当たり前かもしれないがわからなかった
結論
callするときは、以下のように書く
$(foreach NUM,$(NUMS),$(eval $(call MACRO,$(NUM))))
以下のように書いてはいけない (引数に前スペースが入ってしまう)
$(foreach NUM, $(NUMS), $(eval $(call MACRO, $(NUM))))
^
(引数以外に前スペースはあってもいいが、統一感出すためについでに消している)
経緯
以下のようなMakefileを書いた
NUMS = 1 2
define BUILD
build/foo-$(1): src/foo-$(1).cpp
g++ $$^ -o $$@
endef
$(foreach NUM, $(NUMS),$(eval $(call BUILD, $(NUM))))
make foo-1
と打ってみると以下のように何も実行されなかった
Makefile:8: 警告: ターゲット 'build/foo-' のためのレシピを置き換えます
Makefile:8: 警告: ターゲット 'build/foo-' のための古いレシピは無視されます
make: *** ターゲット 'build/foo-1' を make するルールがありません. 中止.
make -np
で確認すると以下のように、スペースが入っているようだった
1: src/foo- 1.cpp # foo-と1の間にスペースが入っている
# 暗黙ルールの探索は行われませんでした.
# 修正時刻がチェックされることはありません.
# ファイルは更新されていません.
# 実行するレシピ (ファイル 'Makefile', 8 行目):
g++ $^ -o $@
最初は、マクロ内でbuild/foo-$(trim $(1))
とやったり、call
関数内で$(call BUILD,$(trim $(NUM)))
とやったりした(こちらは無意味だった)が、以下のスペース削除に落ち着いた
$(foreach NUM,$(NUMS),$(eval $(call BUILD,$(NUM))))
もちろん、make foo-1
の実行結果は期待通りになった
g++ src/foo-1.cpp -o build/foo-1
余談
上の事象を再現しようとして、以下のようにしていた
- ディレクトリ構成 (Makefileとソースコードを同じディレクトリ直下においた)
test/ ├ foo-1.cpp ├ foo-2.cpp └ Makefile
- Makefile (前スペースあり)
NUMS = 1 2 define BUILD foo-$(1): foo-$(1).cpp g++ $$^ -o $$@ endef $(foreach NUM, $(NUMS),$(eval $(call BUILD, $(NUM))))
make foo-1
の実行すると、警告はでるが、コンパイルはしてくれる
Makefile:8: 警告: ターゲット 'foo-' のためのレシピを置き換えます
Makefile:8: 警告: ターゲット 'foo-' のための古いレシピは無視されます
g++ foo-1.cpp -o foo-1
(コンパイルしてくれるのはいいが、再現できないので困っていた)
参考
- https://tex2e.github.io/blog/makefile/functions (改めて確認すると、ちゃんと前スペース削除していた)