makefile强制库依赖项排序
makefile enforce library dependency ordering
在构建具有递归依赖关系的库时,我有以下片段:
$(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条戒律:
-
您应该调用
make
来生成target
(或多个目标)或默认目标,这是Makefile中的第一个目标。Makefile中的目标位于:
的左侧 -
有两种目标:真实的和"虚假的"。真正的目标是您想要(重新)创建的实际文件(或目录)。虚假目标是一个抽象的概念,不是一个真实的文件,但它通常意味着一组真实的文件。
-
Makefile中列出的目标也可能具有
%
,在这种情况下,它是一个模式目标,可以匹配多个目标,真实或虚假。 -
源是未列为目标的文件,并且在调用
make
之前已经存在。 -
目标"取决于"
:
之后、目标之后写入的"先决条件" -
真正的目标必须有一个"配方",它是目标行下的shell脚本。配方应该只写一个文件,并且只能写一个目标文件。目标文件应在配方中称为
$@
。如果配方写入多个文件,请将其分解为单个目标的多个配方。
配方可能会读取许多文件:这些文件必须列为先决条件。
-
一个虚假的目标不能有配方。
-
虚假目标可以依赖于其他虚假目标、真实目标或来源。真正的目标必须只依赖于真正的目标或来源。一切最终(递归地)只依赖于源。
-
你不应该在食谱中递归调用
make
,除非是在一种情况下,也只有一种情况:你有一些子目录,它完全是自己构建的,没有读取任何外部的源或目标
在这种特殊情况下,你应该有一个虚假的目标子目录和配方:
.PHONY: subdirectory
subdirectory:
$(MAKE) -C $@
- 如果您想使用其他makefile,但不满足上述异常,请使用
include
注意:我并不是说你不能在违反这些原则的情况下编写正确的Makefile。你可以,有时也是必要的。但要做到这一点,你必须知道自己在做什么,并理解更先进的概念。您不应该以这种方式开始学习,而是首先按照上述原则开始编写Makefile。
- 如何从C++中的依赖类型中获得它所依赖的类型
- 二叉排序树无法编译
- 仅使用绝对值对数组进行排序,并在C++中显示实际值
- C++选择排序算法中的逻辑错误
- 使用C++程序合并排序没有得到正确的输出
- 计算排序向量的向量中唯一值的计数
- 排序算法c++
- 使用2个键的cpp-stl::优先级队列排序不正确
- 将结构向量排序为子组
- 在c++中尝试对对象数组进行排序时,出现std:bad_alloc错误
- 如何对点云数据进行排序
- 对字符串进行排序时,在c++中处理sort()
- 是否有类似std::lower_bound的函数,而不需要排序/分区输入
- 将--whole archive链接器选项与CMake和具有其他库依赖项的库一起使用
- 将依赖名称显式标记为类型名和模板的奇怪之处
- C++依赖标头排序
- makefile强制库依赖项排序
- C++std列表排序使用自定义比较器,该比较器依赖于对象实例的成员变量
- 当无法重新排序时,依赖成员初始化
- 使用循环依赖检测进行依赖排序