【问题标题】:Automatic header dependencies with gmake使用 gmake 的自动标头依赖项
【发布时间】:2011-11-13 06:48:00
【问题描述】:

已编辑

我正在尝试重新编译源文件,而不必为 makefile 中的每个 CPP 指定头文件。

我很失望:

#CoreObj1.cpp(and .h)
#CoreObj2.cpp(and .h)

#This is the makefile.

CORE_COMPONENT_OBJECTS = \
  obj/CoreObj1.o \
  obj/CoreObj2.o \

# Objects
obj/%.o: %.cpp obj/%.d
        @mkdir -p obj
        $(CXX) $(CXX_CFLAGS) -c $*.cpp -o $@

# Dependencies
obj/%.d: %.cpp
        @mkdir -p obj
        $(CXX) $(CXX_CFLAGS) -MM -MF $@ $<

DEPS = $(CORE_COMPONENT_OBJECTS:.o=.d)

ifneq ($(MAKECMDGOALS),clean)
-include $(DEPS)
endif   

但是修改一个头文件并不会触发包含它的源文件被重新编译。

注意:事实上,如果我的 .o、.d 和 .cpp 在同一个文件夹中,它就可以工作。但如果我的 .d 和 .o 在 obj/ 文件夹中,则不会触发重新编译。

【问题讨论】:

  • 我通过使用适当的构建系统(如 automake 或 cmake)来处理此类依赖项;)根据我的经验,Makefile 很快变得无法维护。
  • @honk 这取决于项目(大小/复杂性); makefile 变得不可维护,因为程序员很少保持它们的组织和清理,将其作为低优先级任务,而且通常不了解 make 的大部分功能
  • 在您的第四次编辑之后,您的问题缺少问题、问题、错误报告等任何内容......
  • @eriktous:我已经简化了问题,因为我认为我的问题出在多个 makefile 上,但它不适用于单个 makefile。如果您重新阅读(当前)问题,我认为这是有道理的。我也编辑了标题。

标签: build makefile


【解决方案1】:

人们经常有这样的依赖生成规则,但它们确实是不必要的。

第一次构建项目时不需要依赖项,因为它会构建所有源代码。只有后续构建需要前一个构建的依赖项来检测需要重建的内容。

因此,依赖项实际上是编译的副产品。您的规则应如下所示:

#CoreObj1.cpp(and .h)
#CoreObj2.cpp(and .h)

#This is the makefile.

CORE_COMPONENT_OBJECTS = \
  obj/CoreObj1.o \
  obj/CoreObj2.o \

# Objects
obj/%.o: %.cpp
        @mkdir -p obj
        $(CXX) $(CXX_CFLAGS) -c -o $@ -MD -MP -MF ${@:.o=.d} $<

DEPS = $(CORE_COMPONENT_OBJECTS:.o=.d)

ifneq ($(MAKECMDGOALS),clean)
-include $(DEPS)
endif   

附带说明,mkdir -p 不是并行友好的。例如,当两个或多个进程竞相创建/a/b/c//a/b/cc//a/b/ 不存在时,一个mkdir 进程可能会因EEXIST 尝试创建/a/b/ 而失败。

【讨论】:

    【解决方案2】:

    您没有依赖文件作为编译规则的先决条件。应该是这样的:

    #This is the rule for creating the dependency files
    src/%.d: src/%.cpp
        $(CXX) $(CXX_CFLAGS) -MM -MF $(patsubst obj/%.o,obj/%.d,$@) -o $@ $<
    
    obj/%.o: %.cpp %.d
        $(CXX) $(CXXFLAGS) -o $@ -c $<
    
    -include $(SRC:%.cpp=%.d)
    

    最后一个字符串添加了对标头的依赖。

    编辑

    我看你有

    -include $(DEPS)
    

    但请检查 $(warning DEPS = $(DEPS)) 是否真的包含现有文件,否则请忽略这些文件。

    【讨论】:

    • 有趣。但这会从 core_component 收集依赖项吗?
    • 更新:关键是添加了依赖文件,其中包含对headers的依赖
    • 只是想知道您的更新:SRC 来自哪里,您的意思是 %.cpp 而不是 %.c ?
    • SRC 是源文件列表。它应该放在您拥有它的 makefile 中,或者您可以用 $(COMPONENTX_OBJECTS:%.o=%.d) 替换它。只需检查 DEPS 列表是否完整以及 %.d 文件是否正确生成 - 包含所有依赖的标头
    • 到目前为止,我已将问题缩小到单个组件,因为它似乎不适用于单个组件。请查看我编辑的问题。
    【解决方案3】:

    使用SCons/CMake/bjam 解决“头依赖问题”比使用make 更好

    【讨论】:

    • ...成为 bjam 的第 14 个用户。
    猜你喜欢
    • 2011-01-13
    • 2017-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-10
    • 1970-01-01
    • 2017-02-12
    • 2021-01-12
    相关资源
    最近更新 更多