如何基于Makefile中两组关联变量生成对应编译规则
如何基于Makefile中两组关联变量生成对应编译规则
兄弟,你这个问题我刚学Makefile的时候也踩过一模一样的坑!核心问题就是你用的自动模式规则没处理好路径前缀的替换,导致Make傻乎乎地去build目录下找.c源文件,可咱们的源文件明明在source目录里啊!
先给你直接上能跑的解决方案,再慢慢给你拆解为啥这么写:
SOURCE_DIR := ./source BUILD_DIR := ./build C_FILES := $(shell find $(SOURCE_DIR) -name '*.c') # 这里修正了patsubst的匹配模式,补全斜杠才能正确识别路径 BIN_FILES := $(patsubst $(SOURCE_DIR)/%.c,$(BUILD_DIR)/%, $(C_FILES)) # 关键的静态模式规则,专门处理路径映射 $(BIN_FILES): $(BUILD_DIR)/%: $(SOURCE_DIR)/%.c @mkdir -p $(@D) # 先自动创建目标文件所在的目录,避免目录不存在报错 cc $< -o $@ all: $(BIN_FILES) # 再加个clean规则方便编译后清理 clean: rm -rf $(BUILD_DIR)
给你拆解下重点:
- 先修正了
BIN_FILES的生成规则:你原来的$(SOURCE_DIR)%.c少了个斜杠,改成$(SOURCE_DIR)/%.c才能正确匹配source/ch01/hello.c这种完整路径,替换成build/ch01/hello - 核心的静态模式规则
$(BIN_FILES): $(BUILD_DIR)/%: $(SOURCE_DIR)/%.c:$(BUILD_DIR)/%是目标的匹配模式,比如build/ch01/hello会把%匹配成ch01/hello- 对应的依赖就是
$(SOURCE_DIR)/%.c,也就是source/ch01/hello.c,完美对应上源文件的真实路径
- 加了
@mkdir -p $(@D):$(@D)是Make的自动变量,代表目标文件的目录部分(比如build/ch01),这个命令会自动创建所有需要的子目录,避免因为目录不存在导致编译失败
为啥你之前的写法不行?因为%:%.c这种自动模式规则是把整个目标字符串直接加上.c当依赖,比如目标是build/ch01/hello,它就会去找build/ch01/hello.c,完全没考虑源文件在另一个目录下的情况,自然就错了。
用静态模式规则就刚好解决了路径前缀替换的问题,把build前缀的目标对应到source前缀的源文件,完美实现你要的“一对一对编译”的需求。
备注:内容来源于stack exchange,提问作者Ranvir
相关产品推荐
相关产品推荐

