GNU Make+GCC:为静态模式规则生成的文件自动生成依赖
解决GNU Make自动生成文件的依赖顺序问题
核心问题在于首次构建时,自动生成的依赖文件(.d)尚未存在,Make不知道编译目标(如main.obj)依赖自动生成的头文件(如bar.h),导致编译先于文件生成执行。以下是无需手动添加依赖的解决方案:
1. 标记自动生成的文件
先明确所有通过静态模式规则生成的源文件和头文件,方便后续统一管理:
# 列出所有自动生成的文件 GENERATED_FILES := bar.c bar.h foo.c foo.h
2. 完善生成文件的静态模式规则
确保静态模式规则能正确匹配并生成目标文件,比如假设用generate.py脚本根据前缀生成.c和.h:
# 静态模式规则:匹配所有GENERATED_FILES,调用生成脚本 $(GENERATED_FILES): %: generate.py python3 $< $(basename $*)
3. 给编译规则添加顺序依赖
使用order-only依赖(| 分隔),让Make在编译任何.obj文件前,先确保所有自动生成的文件已就绪。这种依赖只会控制执行顺序,不会因为生成文件更新而触发不必要的编译:
# 编译规则:添加order-only依赖保证生成文件先存在 %.obj: %.c | $(GENERATED_FILES) $(CC) $(CFLAGS) -c $< -o $@ -MMD -MP -MF $*.d
4. 保留自动依赖生成逻辑
继续沿用mad-scientist的自动依赖方案,包含生成的.d文件,让后续构建能基于精确的依赖关系执行:
# 包含自动生成的依赖文件 -include $(OBJS:.obj=.d)
完整示例Makefile
CC := gcc CFLAGS := -Wall -O2 DEPFLAGS := -MMD -MP -MF $*.d # 自动生成的文件列表 GENERATED_FILES := bar.c bar.h foo.c foo.h # 目标文件列表 OBJS := main.obj bar.obj foo.obj all: my_program # 链接可执行文件 my_program: $(OBJS) $(CC) $(CFLAGS) $^ -o $@ # 编译规则:order-only依赖确保生成文件先就绪 %.obj: %.c | $(GENERATED_FILES) $(CC) $(CFLAGS) $(DEPFLAGS) -c $< -o $@ # 生成文件的静态模式规则 $(GENERATED_FILES): %: generate.py python3 $< $(basename $*) # 包含自动依赖文件 -include $(OBJS:.obj=.d) clean: rm -f $(OBJS) $(OBJS:.obj=.d) $(GENERATED_FILES) my_program
优化(可选):精准匹配生成文件
如果生成文件和编译目标一一对应(如bar.obj对应bar.c/bar.h),可以用.SECONDEXPANSION实现更精准的依赖,避免一次性生成所有文件:
.SECONDEXPANSION: %.obj: %.c | $$(filter $(basename $*).c $(basename $*).h, $(GENERATED_FILES)) $(CC) $(CFLAGS) $(DEPFLAGS) -c $< -o $@
这种方式下,编译bar.obj时只会先生成bar.c/bar.h,而非所有生成文件,适合生成文件数量较多的场景。
内容的提问来源于stack exchange,提问作者emacs drives me nuts
相关产品推荐
相关产品推荐

