如何使用单个Makefile构建存放于子文件夹中的多个C应用程序
你遇到的首次编译链接失败的核心原因是:wildcard函数在Makefile的解析阶段就会执行,此时编译生成.o文件的步骤还没运行,所以第一次执行时拿到的结果为空,第二次运行时.o已经生成在磁盘上,才能正常匹配到文件。
另外你最初写的$(OBJ): $(SRC)规则也存在逻辑问题:所有.o文件会依赖全部.c文件,只要修改任意一个.c,所有.o都会重新编译,不符合增量编译的需求。
不需要为每个子文件夹单独编写Makefile,修正后的单顶层Makefile即可正常运行,完整代码如下:
EXAMPLES := hello_world example1 example2 # 自动扫描所有.c文件 SRC := $(wildcard */*.c) OBJ := $(SRC:.c=.o) # 生成每个例子的最终输出路径:格式为 目录名/目录名 OUT := $(foreach e,$(EXAMPLES),$(e)/$(e)) CC := gcc # 可自行补充链接参数,比如LDFLAGS += -lm LDFLAGS ?= # 最终目标:编译所有示例 all: $(OUT) # 通用编译规则:单个.c生成对应.o,支持增量编译 %.o: %.c $(CC) -c $< -o $@ # 通用链接规则:筛选对应目录下的所有.o链接生成最终二进制 %/%: $(OBJ) $(CC) $(filter $(dir $@)%.o,$^) -o $@ $(LDFLAGS) # 清理规则 clean: rm -f $(OUT) $(OBJ) # 声明伪目标,避免和目录下的同名文件冲突 .PHONY: all clean
修正点说明
- 用通用模式规则
%.o: %.c替代原来的全量依赖规则,实现增量编译:单个.c文件修改只会触发对应.o的重编译 - 保留你之前验证过的filter筛选逻辑,该逻辑在规则执行阶段才会展开,此时所有.o已经编译完成,不会出现空值问题,能正确筛选出对应目录下的所有.o文件用于链接
- 新增
.PHONY伪目标声明,避免当目录下存在名为all、clean的文件时,make执行异常
内容的提问来源于stack exchange,提问作者DegH
相关产品推荐
相关产品推荐

