56581
環境：

  * OS : CentOS 7
  * make : GNU Make 3.82

トップの makefile は以下のようになっており、SUB1,SUB2,SUB3 のmakefile を呼び出すようになっていたとします。  
SUB1,SUB2,SUB3 の makefile には C ソースをコンパイルするだけの単純なものとします。

```

    TARGET_LIST=SUB1 SUB2 SUB3
    
    all:
        @for d in $(TARGET_LIST); do make -C $$d; done
    
```

そこで質問があります。

  * (1) この状態で、SUB1 内でコンパイルエラーが発生した場合、SUB2,SUB3  
が実行されてしまいますが実行されるのが通常の動作なのでしょうか？(make -k した状態に見える）

  * (2) そもそも (1) の状態になることが異常で、なにかしら makefile に記載ミスがあるのでしょうか？
  * (3) makefile から makefile を呼び出した場合は、エラー発生時の停止条件はどうのような扱いとなるのでしょうか？(exit 1;？等の扱いを別途考慮し、makeifle を記載するべき？）

以上、よろしくお願いします。
CC BY-SA 4.0
2019-07-12T01:23:00.407
56575
2019-07-15T08:41:39.547
2019-07-15T08:41:39.547
3061
13909
question
makefile
makefile から複数のmakefile を呼び出した場合の動作
(1) ループの停止処理を書いていないので停止しないのが通常の動作となります。  
ループ for を処理しているのは make ではなくシェルになります。シェルの for 文はループ内で実行されている make
コマンドが成功しようがしまいがループを進めるため停止しません。

(2) 異常ではありません。

(3) シェルのfor文でループするのであれば実行結果を判定してエラーなら停止する処理を自分で記述する必要があります。

別の方法としてはシェルのフープを使わずに、以下のように make のターゲットとして記述すればSUB2のmakeコマンドが失敗した時点で停止し、SUB3
のビルドを実行しないかと思います。

```

    all: subtask1 subtask2 subtask3
    
    subtask1:
        make -C SUB1 
    
    subtask2:
        make -C SUB2 
    
    subtask3:
        make -C SUB3 
    
```
CC BY-SA 4.0
2019-07-12T02:05:11.533
56579
2019-07-12T02:05:11.533
27410
56575
answer
`make`(1) はタスクの各行のコマンドライン(=シェルスクリプト)全体の終了コードが 0
かそうでないかによって後続のタスクを実行するかどうか判断します。よって、以下のターゲット `test` は `echo done` に到達して成功します。

```

    test:
        false; true
        echo done
    
```

`sh` で確認するならこんな感じ:

```

    $ sh -c 'true'; echo $?
    0
    $ sh -c 'false'; echo $?
    1
    $ sh -c 'true; false'; echo $?
    1
    $ sh -c 'false; true'; echo $?
    0
    
```

よってタスクである 1 つのシェルスクリプト中にシェルでループするとき、ループ中でのエラーで失敗させたい場合はループを中断かつ終了コードを 0
以外にしてやる必要があります。こんな感じ:

```

    all:
        @for d in $(TARGET_LIST); do $(MAKE) -C $$d || exit $$?; done
    
```

余談ですが `Makefile` 中で `make` を起動したい場合は `make` よりは `$(MAKE)` を記述したほうがベターです。`make`
で `Makefile` を駆動したときは `make` に、`/path/to/your/local/bin/make` で駆動したときは
`/path/to/your/local/bin/make` に置き代わるので。
CC BY-SA 4.0
2019-07-12T03:04:14.810
56581
2019-07-12T04:21:23.880
2019-07-12T04:21:23.880
3061
3061
56575
answer