GNU Makefile使用eval函数引入子makefile时输出异常如何解决
问题根源
- 配方(目标下的执行语句)中的变量默认是执行阶段延迟展开的,你用了全局的
SRC变量存储每个模块的源文件,后续循环对SRC的修改会覆盖之前的值,所有目标执行时都会取最终的SRC值,而非定义目标时对应模块的SRC值。 foreach的循环变量名和被遍历的列表变量同名(都叫TEST_PROGRAM),会覆盖原始的测试程序列表,导致遍历逻辑异常。- 你用了
-include引入子Makefile,加了减号后如果对应路径的子Makefile不存在,Make会直接忽略错误不会提示,导致对应模块的SRC没有被重新赋值,复用了之前模块的SRC值,这也是你第二个模块输出ABC、第三个模块输出DAB和预期不符的直接原因。
解决方法
- 给每个模块目标绑定目标专属变量,将当前模块的
SRC值固定到对应目标上,不受后续全局SRC修改的影响。 - 修改
foreach的循环变量名,避免和被遍历的列表变量重名。 - 临时把
-include改成include调试,确认每个模块对应的子Makefile路径正确、存在,调试完成后可以根据需求改回-include。 - 确认各子Makefile的赋值符合预期:
unit-tests/AnotherSampleFileToUT/Makefile中赋值SRC += DAB,unit-tests/None/Makefile中不赋值SRC或者显式写SRC :=。
注意:Makefile中目标对应的执行语句(recipe)必须以Tab字符开头,不能使用空格缩进,否则会触发语法错误。
修改后完整代码
SRC := include unit-tests/makefile define COLLECT_TEST_PROGRAMS # 每次处理新模块先清空SRC SRC := # 引入当前模块的Makefile,调试阶段可以把-去掉排查文件存在性问题 -include unit-tests/$(1)/Makefile # 给当前目标绑定专属的SRC变量,固定当前的SRC值 $(1): SRC := $(SRC) $(1): @/bin/echo @echo The Module is $(1) @/bin/echo $(SRC) Compile += $(1) endef #COLLECT_TEST_PROGRAMS # 循环变量改用prog,避免和原列表TEST_PROGRAM重名 $(foreach prog,$(TEST_PROGRAM),$(eval $(call COLLECT_TEST_PROGRAMS,$(prog))) ) all: $(Compile) @/bin/echo @/bin/echo Compiled Programs: $(Compile)
内容的提问来源于stack exchange,提问作者Teodor Iksinski
相关产品推荐
相关产品推荐

