如何编写Makefile实现双扩展名通用目标匹配与路径映射?
问题描述
我需要定义形如a.ext1.new_ext、a.ext2.new_ext、b.ext1.new_ext这类通用目标,它们分别依赖a.ext1、a.ext2、b.ext1等文件。现有的示例规则都是重复的,想改成通用规则:
a.ext1.new_ext: a.ext1 compiler --input a.ext1 --output a.ext1.new_ext a.ext2.new_ext: a.ext2 compiler --input a.ext2 --output a.ext2.new_ext b.ext1.new_ext: b.ext1 compiler --input b.ext1 --output b.ext1.new_ext b.ext2.new_ext: b.ext2 compiler --input b.ext2 --output b.ext2.new_ext ...
补充说明:从根目录./调用Makefile,依赖文件位于./src/folder,输出文件需生成到./build/folder。我写的Makefile无法正常工作:
SRC := $(shell find ./src -type f \( -name '*.ext1' -or -name '*.ext2' \)) OBJ := $(patsubst ./src%, ./build%, $(SRC)) OBJ := $(addsuffix .new_ext, $(OBJ)) # 无法正常工作的规则 %.new_ext: % mkdir -p $(dir $@) compiler --input $< --output $@
解决方案
方案1:静态模式规则(推荐)
静态模式规则适合这种已明确源文件和目标文件列表的场景,能精准对应依赖与目标:
# 查找src目录下所有.ext1和.ext2文件 SRC := $(shell find ./src -type f \( -name '*.ext1' -o -name '*.ext2' \)) # 将src路径替换为build路径,得到目标文件的基础路径 OBJ_BASE := $(patsubst ./src%, ./build%, $(SRC)) # 给基础路径添加.new_ext后缀,得到最终目标文件列表 OBJ := $(addsuffix .new_ext, $(OBJ_BASE)) # 默认目标:构建所有输出文件 all: $(OBJ) # 静态模式规则:每个build下的.new_ext文件依赖对应的src下的源文件 $(OBJ): ./build/%.new_ext: ./src/% # 确保目标文件所在目录存在 mkdir -p $(dir $@) # 执行编译命令,$<是依赖文件路径,$@是目标文件路径 compiler --input $< --output $@
方案2:通用路径模式规则
如果偏好更通用的模式写法,可以直接在规则中明确路径前缀,让Make正确匹配跨目录的依赖与目标:
SRC := $(shell find ./src -type f \( -name '*.ext1' -o -name '*.ext2' \)) OBJ_BASE := $(patsubst ./src%, ./build%, $(SRC)) OBJ := $(addsuffix .new_ext, $(OBJ_BASE)) all: $(OBJ) # 匹配build目录下所有带.new_ext后缀的文件,依赖src目录下对应路径的源文件 ./build/%.new_ext: ./src/% mkdir -p $(dir $@) compiler --input $< --output $@
原代码失效原因
原规则%.new_ext: %的问题在于:
当目标是./build/folder/a.ext1.new_ext时,%会被匹配为./build/folder/a.ext1,但Make会去寻找这个路径下的依赖文件,而实际依赖文件在./src/folder/a.ext1,路径不匹配导致规则无法触发。
内容的提问来源于stack exchange,提问作者Denisof
相关产品推荐
相关产品推荐

