You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 14:58:09