makefile から複数のmakefile を呼び出した場合の動作


環境：

  * OS : CentOS 7
  * make : GNU Make 3.82

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

[code]

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

そこで質問があります。

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

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

以上、よろしくお願いします。




`make`(1) はタスクの各行のコマンドライン(=シェルスクリプト)全体の終了コードが 0
かそうでないかによって後続のタスクを実行するかどうか判断します。よって、以下のターゲット `test` は `echo done` に到達して成功します。

[code]

    test:
        false; true
        echo done
    
[/code]

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

[code]

    $ sh -c 'true'; echo $?
    0
    $ sh -c 'false'; echo $?
    1
    $ sh -c 'true; false'; echo $?
    1
    $ sh -c 'false; true'; echo $?
    0
    
[/code]

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

[code]

    all:
        @for d in $(TARGET_LIST); do $(MAKE) -C $$d || exit $$?; done
    
[/code]

余談ですが `Makefile` 中で `make` を起動したい場合は `make` よりは `$(MAKE)` を記述したほうがベターです。`make`
で `Makefile` を駆動したときは `make` に、`/path/to/your/local/bin/make` で駆動したときは
`/path/to/your/local/bin/make` に置き代わるので。




`make`(1) はタスクの各行のコマンドライン(=シェルスクリプト)全体の終了コードが 0
かそうでないかによって後続のタスクを実行するかどうか判断します。よって、以下のターゲット `test` は `echo done` に到達して成功します。

[code]

    test:
        false; true
        echo done
    
[/code]

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

[code]

    $ sh -c 'true'; echo $?
    0
    $ sh -c 'false'; echo $?
    1
    $ sh -c 'true; false'; echo $?
    1
    $ sh -c 'false; true'; echo $?
    0
    
[/code]

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

[code]

    all:
        @for d in $(TARGET_LIST); do $(MAKE) -C $$d || exit $$?; done
    
[/code]

余談ですが `Makefile` 中で `make` を起動したい場合は `make` よりは `$(MAKE)` を記述したほうがベターです。`make`
で `Makefile` を駆動したときは `make` に、`/path/to/your/local/bin/make` で駆動したときは
`/path/to/your/local/bin/make` に置き代わるので。

