使用Makefile+Clang编译时,如何单规则同时遍历$(obj)与$(src)列表?
解决Makefile中同时遍历目标文件和源文件列表的问题
先指出你原代码里的两个问题:
src_files = $(notdir ($src))多了一层括号,正确写法是$(notdir $(src))- 原规则
$(obj): $(src)会让每个目标文件依赖所有源文件,编译时还把所有源文件传给clang,导致所有代码被打包到同一个.o文件里,完全不符合编译单个源文件生成对应目标文件的预期。
要实现每个目标文件对应单个源文件的编译,用静态模式规则是最直接的方案,既能遍历目标列表,又能精准匹配对应的源文件:
修正后的完整Makefile
# 自动获取src目录下所有.c文件 src = $(wildcard src/*.c) # 直接把src路径转换为build目录下的.o文件,省去中间变量更简洁 obj = $(src:src/%.c=build/%.o) .PHONY: all clean all: $(obj) # 静态模式规则:每个build/%.o对应src/%.c $(obj): build/%.o : src/%.c # 确保build目录存在,避免第一次编译报错 @mkdir -p build # $< 表示当前目标对应的源文件,$@ 表示当前目标文件 clang $(clang_options) -c $< -o $@ clean: rm -rf build
关键说明
- 静态模式规则
$(obj): build/%.o : src/%.c会逐个匹配$(obj)里的每个目标(比如build/main.o),自动关联对应的源文件src/main.c - 自动变量
$<展开为当前目标对应的单个源文件,$@展开为当前目标文件,完美实现目标与源文件的一一对应遍历 @mkdir -p build用于自动创建build目录,避免因目录不存在导致编译失败,@符号是让这条命令不在终端输出
如果不想用静态模式,也可以用普通模式规则,效果完全一致:
build/%.o: src/%.c @mkdir -p build clang $(clang_options) -c $< -o $@
内容的提问来源于stack exchange,提问作者WKali
相关产品推荐
相关产品推荐

