GNU Make:如何编写忽略目录差异的通用编译规则
解决Makefile模式规则中目标与源文件目录不匹配的问题
你当前的Makefile中,%.obj: %.src模式规则仅能匹配同一目录下同名的.src和.obj文件。但像foo.obj对应/some/dir/1/foo.src这类目标与源文件不在同一目录的情况,因为路径不匹配,规则无法触发,只能重复编写每个目标的编译逻辑,既冗余又难维护。
以下是两种简洁易维护的解决方案:
方案1:使用vpath指定源文件搜索路径
GNU Make的vpath指令可以为特定后缀的文件指定搜索目录,结合原有模式规则即可实现跨目录匹配:
default: exe # 指定.src文件的搜索目录,按顺序查找 vpath %.src /some/dir/1 /some/dir/2 . %.obj: %.src # dummy compiler @echo link $< to $@ cat $< > $@ exe: main.obj foo.obj bar.obj # dummy linker @echo link $^ to $@ cat $^ > $@ # 无需再单独编写每个.obj的依赖规则,vpath会自动匹配对应目录下的源文件
说明:vpath %.src /some/dir/1 /some/dir/2 .告诉Make,当需要查找.src文件时,依次在/some/dir/1、/some/dir/2和当前目录(.)中搜索。这样foo.obj会自动匹配到/some/dir/1/foo.src,无需手动声明依赖。
方案2:使用静态模式规则(适合明确所有目标文件的场景)
如果所有.obj目标是明确的,可以用静态模式规则直接绑定目标与源文件的匹配关系:
default: exe # 定义所有需要编译的.obj文件 OBJ_FILES := main.obj foo.obj bar.obj # 静态模式规则:对每个%.obj,匹配对应目录下的同名.src文件 $(OBJ_FILES): %.obj: # 提取目标文件名(去掉.obj后缀) SRC_NAME := $(notdir $@:.obj=.src) # 在指定目录中搜索对应源文件(可根据实际目录扩展) SRC_FILE := $(wildcard /some/dir/1/$(SRC_NAME) /some/dir/2/$(SRC_NAME) ./$(SRC_NAME)) @echo link $(SRC_FILE) to $@ cat $(SRC_FILE) > $@ exe: $(OBJ_FILES) # dummy linker @echo link $^ to $@ cat $^ > $@
说明:$(notdir $@:.obj=.src)提取出目标的纯文件名(比如foo.obj转为foo.src),再通过wildcard在指定目录中搜索该文件,实现跨目录的文件名匹配。
内容的提问来源于stack exchange,提问作者Alexander Foken
相关产品推荐
相关产品推荐

