C++ makefile强制执行库依赖项排序

C++ makefile强制执行库依赖项排序,c++,makefile,C++,Makefile,在构建具有递归依赖关系的库时,我有以下片段: $(LIBRARY) : $(OBJECTS) | $(LIBDIR) # objects is all the obj/*.o $(AR) ... obj/%.o : %.cpp obj/%.d $(CC) ... build : $(DEPENDENCIES) $(LIBRARY) $(DEPENDENCIES): $(MAKE) -C $(ROOT)/$@ 如果我运行make,这会起作用。一切都按照正确的顺序按

在构建具有递归依赖关系的库时,我有以下片段:

$(LIBRARY) : $(OBJECTS) | $(LIBDIR) # objects is all the obj/*.o
    $(AR) ... 

obj/%.o : %.cpp obj/%.d
    $(CC) ...

build : $(DEPENDENCIES) $(LIBRARY)

$(DEPENDENCIES):
    $(MAKE) -C $(ROOT)/$@
如果我运行
make
,这会起作用。一切都按照正确的顺序按预期进行构建。但是如果我运行
make-jN
,库的构建顺序就不好,因为我实际上没有任何依赖项排序规则集,这会导致大量未定义的引用

如果我添加规则:

$(OBJECTS) : $(DEPENDENCIES)

然后运行make每次都会重建每个库,而不考虑更改(
DEPENDENCIES
是假的,但我不明白为什么它实际上会重建所有内容)。如何在不必每次都重新生成所有内容的情况下,为并行生成的目的强制执行正确的顺序?

我将为您提供如何设置生成文件的一般指导原则,以确保:

a。重建,并且只重建必要的,以及

b。正确使用并行性

有些人已经要求一些“好原则”,所以他们来了

用这些原则重写你的makefile,你就能保证工作正常

十诫:

  • 您应该调用
    make
    来创建一个
    目标(或多个目标)或一个默认目标,这是您的Makefile中的第一个目标。Makefile中的目标位于

  • 目标有两种:真实的和“虚假的”。实际目标是要(重新)创建的实际文件(或目录)。虚假目标是一个抽象概念,不是真实的文件,但它通常意味着一组真实的文件

  • Makefile中列出的目标也可能有一个
    %
    ,在这种情况下,它是一个模式目标,可以匹配多个目标,真实的或虚假的

  • 源是未列为目标的文件,并且在调用
    make
    之前已经存在

  • 目标“依赖”于“先决条件”,先决条件写在目标后面的

  • 真正的目标必须有一个“配方”,即目标行下的shell脚本。配方应该只写一个文件,并且只写一个文件,即目标文件。目标文件在配方中应称为
    $@

    如果配方写入多个文件,请将其分解为单个目标的多个配方

    配方可能会读取许多文件:这些文件必须作为先决条件列出

  • 虚假目标不得有配方

  • 虚假目标可以依赖于其他虚假目标、真实目标或源。真正的目标必须仅依赖于真正的目标或来源。一切最终(递归地)只依赖于源

  • 你不应该在菜谱中递归调用
    make
    ,只有一种情况除外:你有一个子目录,它完全是自己构建的,没有读取自己之外的任何源或目标。
    在这种例外情况下,你应该有一个虚假的目标子目录和配方:

  • 
    .PHONY:子目录
    子目录:
    $(MAKE)-C$@
    

  • 如果您想使用其他makefiles,但不满足上述例外情况,
    包含它们
    
    注意:我并不是说在违反这些原则的情况下不能编写正确的Makefile。你可以,有时这是必要的。但要做到这一点,你必须知道你在做什么,并理解更先进的概念。您不应该以这种方式开始学习,而是首先按照上述原则开始编写makefile

    @MichaelGrünewald是的!!!谢谢你,你是我的英雄。