问题描述
在构建具有递归依赖性的库时,我有这个片段:
In building a library that has recursive dependencies, I have this fragment:
$(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
,库建立在一个坏的顺序,因为我实际上没有任何依赖顺序规则集,这导致大量未定义的引用。
This works if I run make
. Everything builds as expected in the correct order. But if I run make -jN
, the libraries build in a bad order because I don't actually have any dependency ordering rules set, which leads to lots of undefined references.
如果我添加规则:
$(OBJECTS) : $(DEPENDENCIES)
然后运行make每次重建每个库,不管更改( DEPENDENCIES
是虚假的,但我不明白为什么它实际重建一切)。
then running make rebuilds every library every time, regardless of changes (DEPENDENCIES
is phony, but I don't understand why it actually rebuilds everything). How can I enforce the correct orderings for the purposes of parallel build while not having to rebuild everything every time?
推荐答案
我要去的地方给你一般指导如何设置makefile以保证:
I am going to give you general guidelines how to setup makefiles to guaranteee:
a。重建,只有那是必要的,和
a. rebuild that and only that which is necessary, and
b。正确地使用并行性。
b. correctly work with parallelism.
有些人已经问过一些好的原则,所以在这里。
Some people already had asked for some "good principles", so here they are.
使用这些原则重写您的makefile,并确保您能正常工作。
Rewrite your makefile with these principles and you are guaranteed to work correctly.
10条诫命: p>
The 10 Commandments:
-
您必须调用
make
才能创建目标
(或目标)或默认目标,这是您的Makefile中的第一个目标。您的Makefile中的目标位于的左侧:
Thou shalt invoke
make
to make atarget
(or targets) or a default target, which is the first target in thy Makefile. Targets in thy Makefile are on the left side of:
目标有两种:real和假。真正的目标是要(重新)创建的实际文件(或目录)。假目标是一个抽象的概念,而不是真正的文件,但它通常意味着一组真实文件。
There are two kinds of targets: real and "phony". A real target is an actual file (or directory) that you want to (re)create. A phony target is an abstract concept, not a real file, but it typically means a group of real files.
Makefile中列出的目标也可能有一个%
A target listed in the Makefile may also have a %
, in which case it is a pattern target, which can match multiple targets, real or phony.
来源是未列为目标的文件,而且在
Sources are files that are not listed as targets, and are already present before make
is invoked.
在之后写入的先决条件
A target "depends" on "prerequisites" which are written after the :
, after the target
真正的目标必须有一个recipe,这是目标行下的shell脚本。配方应该只写一个文件和一个文件,目标文件。目标文件应在配方内引用 $ @
。
A real target must have a "recipe", which is a shell script under the target line. The recipe should only write one file and one file only, the target file. The target file should be referred as $@
inside the recipe.
如果配方写入多个文件,
If the recipe writes multiple files, break it down to multiple recipes for single targets.
配方可能会读取许多文件:这些文件必须作为先决条件列出。
The recipe may read many files: these must be listed as prerequisites.
虚假目标不得有食谱。
A phony target must not have a recipe.
虚假目标可以依赖于其他虚假目标,真实目标或来源。真正的目标必须只依赖于真实的目标或源。一切最终(递归)只取决于来源。
A phony target can depend on other phony targets, real targets, or sources. A real target must only depend on real targets, or sources. Everything eventually (recursively) depends on sources only.
您不能在食谱中递归调用 make
,除了一种情况和一种情况:thou有一个子目录,它自己完全构建,而不会读取任何你的源或目标本身之外。
在这个特殊情况下,你应该有一个假目标子目录和配方:
Thou shalt not call make
recursively in recipes, except in one case and one case only: thou hast some subdirectory that builds completely by itself, without reading any of thy sources or targets outside of itself.
In that exceptional case, thou shalt have a phony target subdirectory and the recipe:
.PHONY:子目录
子目录:
$(MAKE) C $ @
- 如果要使用其他makefile,不满足上述异常,
include
他们。
- If you want to use other makefiles, but do not satisfy the above exception,
include
them.
注意:我不是说你不能在违反这些原则的情况下写一个正确的Makefile。你可以,有时是必要的。但是要做到这一点,你必须知道你在做什么,并理解更高级的概念。你不应该开始学习这种方式,但首先开始写Makefiles遵循上述原则。
Note: I am not saying you can't write a correct Makefile while violating these principles. You can and sometimes it is necessary. But to do that you have to know what you are doing and understand more advanced concepts. You should not start learning that way, but first start writing Makefiles following the above principles.
这篇关于makefile强制库依赖性排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!