makefile强制库依赖项排序

makefile enforce library dependency ordering

本文关键字:排序 依赖 makefile      更新时间:2023-10-16

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

$(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是假的,但我不明白为什么它实际上重建了所有内容)。如何在不必每次都重新生成所有内容的情况下,为了并行生成的目的强制执行正确的顺序?

我将向您介绍如何设置makefile以保证:

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

b。正确地并行工作。

有些人已经要求一些"好的原则",所以他们来了。

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

10条戒律:

  1. 您应该调用make来生成target(或多个目标)或默认目标,这是Makefile中的第一个目标。Makefile中的目标位于: 的左侧

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

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

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

  5. 目标"取决于":之后、目标之后写入的"先决条件"

  6. 真正的目标必须有一个"配方",它是目标行下的shell脚本。配方应该只写一个文件,并且只能写一个目标文件。目标文件应在配方中称为$@

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

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

  7. 一个虚假的目标不能有配方。

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

  9. 你不应该在食谱中递归调用make,除非是在一种情况下,也只有一种情况:你有一些子目录,它完全是自己构建的,没有读取任何外部的源或目标
    在这种特殊情况下,你应该有一个虚假的目标子目录和配方:

.PHONY: subdirectory subdirectory: $(MAKE) -C $@

  1. 如果您想使用其他makefile,但不满足上述异常,请使用include

注意:我并不是说你不能在违反这些原则的情况下编写正确的Makefile。你可以,有时也是必要的。但要做到这一点,你必须知道自己在做什么,并理解更先进的概念。您不应该以这种方式开始学习,而是首先按照上述原则开始编写Makefile。