如何编写适用于所有子文件夹的Makefile规则?
多同结构子目录的Makefile构建解决方案
目录结构
tests |- test1 |- file1 |- file2 |- test2 |- file1 |- file2
需求
编写Makefile规则,同时处理test1、test2等子目录,生成的my_program目标文件与依赖的file1、file2处于相同子目录中。
错误尝试及问题分析
尝试1:模式规则报错
TESTS = test1 test2 .PHONY : all all: $(addsuffix /my_program, $(TESTS)) %/my_program : %/file1 %/file2 clang $< -o $@
错误信息:
No rule to make target `AddStruct/my_program', needed by `all'. Stop.
问题:若报错中出现AddStruct,大概率是TESTS变量包含了不存在的目录;另外命令中使用$<仅会传入第一个依赖文件,编译会遗漏file2。
尝试2:通配符规则导致冗余编译
*/my_program : */file1 */file2 clang $< -o $@
问题:Make会将所有*/file1和*/file2作为依赖,生成所有可能的组合编译命令(如用test2的文件编译test1的目标),不符合需求。
尝试3:依赖列表使用自动化变量报错
*/my_program : $(@D)/file1 $(@D)/file2 clang $< -o $@
错误信息:
make: *** No rule to make target `(@D)/file1', needed by `test1/my_program'. Stop.
问题:$(@D)是自动化变量,仅能在规则的命令部分使用,无法在依赖列表中解析,Make会将其当作字面量文件名处理,导致找不到文件。
正确解决方案
使用Make的模式规则(%匹配),配合正确的自动化变量:
TESTS = test1 test2 .PHONY : all all: $(addsuffix /my_program, $(TESTS)) # 模式规则:%匹配子目录名,如test1、test2 %/my_program : %/file1 %/file2 clang $^ -o $@
说明
%作为通配符匹配子目录前缀,比如目标test1/my_program会匹配%为test1,依赖自动对应test1/file1和test1/file2;$^代表所有依赖文件,确保file1和file2都被传入clang编译;- 若之前报错是因为
TESTS中包含不存在的目录,只需修正TESTS变量为实际存在的子目录即可。
内容的提问来源于stack exchange,提问作者Santiago Cuellar
相关产品推荐
相关产品推荐

