makefile 目标中的 foreach 和消音器

foreach & silencer in a makefile target

我在 makefile 中为特定目标使用 foreach。

my_Target:
    $(foreach x,$(MY_TARGET_DIRS), @echo "  BUILD   $(x)";$(Q)$(MAKE) --directory=$(x) LIB_DIR=$(MY_LIB_DIR) $(MY_TARGET_RULES); )

这是为了调用包含 MY_TARGET_DIRS 的每个指定目录的 makefile,在打印字符串以告知正在进行的构建之后。

Q变量定义如下:

# Silent per default, 'make V=1' shows all compiler calls. 
ifneq ($(V),1)
    Q := @
endif

如果定义了 V=1,则 make 命令会变得冗长。

对于 V=1,输出日志为:

make my_Target V=1 
BUILD   /dir1
make[1]: Entering directory `/dir1'
make[1]: Nothing to be done for `elf'.
make[1]: Nothing to be done for `bin'.
make[1]: Leaving directory `/dir1'
/bin/sh: @echo: command not found
make[1]: Entering directory `/dir2'
make[1]: Nothing to be done for `elf'.
make[1]: Nothing to be done for `bin'.
make[1]: Leaving directory `/dir2'

而如果我不定义V=1,输出日志是:

make my_Target 
BUILD   /dir1
/bin/sh: @make: command not found
/bin/sh: @echo: command not found
/bin/sh: @make: command not found
make: *** [my_Target] Error 127

如何才能正确获得我想要的行为?

再见!

@ ($(Q))放在菜谱的开头:

my_Target:
    $(Q)$(foreach x,$(MY_TARGET_DIRS), echo "  BUILD   $(x)";$(MAKE) --directory=$(x) LIB_DIR=$(MY_LIB_DIR) $(MY_TARGET_RULES); )

请注意,foreach 将输出单个配方行,而 @ 将应用于所有配方。另一种方法,如果你想更花哨,是为每个目标目录创建一个规则:

MY_TARGET_DIRS_TARGS=$(MY_TARGET_DIRS:%=%/.phony)

my_Target: $(MY_TARGET_DIRS_TARG)

$(MY_TARGET_DIRS_TARGS):
     @echo "  BUILD   $(x)"
     $(Q)(MAKE) --directory=$(x) LIB_DIR=$(MY_LIB_DIR) $(MY_TARGET_RULES);

.PHONY: $(MY_TARGET_DIRS_TARGS)