Makefile 如何使用make';s--具有子曲面的作业? 我的C++项目的构建时间非常大。它由一系列子项目(库)组成,在文件系统文件夹中结构化。我想用make的--jobs(-j)参数来加速并行构建。正确的做法是什么?文档中说,使用subdir进行并行构建有一些技巧

Makefile 如何使用make';s--具有子曲面的作业? 我的C++项目的构建时间非常大。它由一系列子项目(库)组成,在文件系统文件夹中结构化。我想用make的--jobs(-j)参数来加速并行构建。正确的做法是什么?文档中说,使用subdir进行并行构建有一些技巧,makefile,jobs,Makefile,Jobs,根目录中的Makefile如下所示: ... all: $(MAKE) -C DirA $(MAKE) -C DirB ... DirA中的Makefile: all: $(MAKE) -C SubDirA $(MAKE) -C SubDirB $(MAKE) -C SubDirC 在DirB中: all: $(MAKE) -C SubDirD $(MAKE) -C SubDirE $(MAKE) -C SubDirF 等等。

根目录中的Makefile如下所示:

...
all:
    $(MAKE) -C DirA
    $(MAKE) -C DirB
...
DirA中的Makefile:

all:
    $(MAKE) -C SubDirA
    $(MAKE) -C SubDirB
    $(MAKE) -C SubDirC
在DirB中:

all:
    $(MAKE) -C SubDirD
    $(MAKE) -C SubDirE
    $(MAKE) -C SubDirF

等等。叶子文件夹中的Makefiles非常简单,只包含构建指令,没有任何技巧。

您可以按原样使用这些Makefiles将
-j
添加到
make
,这样您将获得一些并行性,但无法获得最大的并行性。问题是make只会并行化目标:显然(通常)在同一个目标中并行运行多个命令是行不通的

因此,在顶层make将连续运行
$(make)-C DirA
,然后运行
$(make)-C DirB
。当make builds
DirA
时,它将首先连续运行
$(make)-C subdra
,然后运行
$(make)-C SubDirB
,等等。最后,当make进入
子分区时,它将在那里并行构建目标。这很好,如果构建目录的顺序很重要,您可能需要做些什么,除了make有时可以开始处理
SubDirB
目标,但不会,直到
SubDirA
中的所有目标完成

处理子目录的更好方法是使用生成规则:

SUBDIRS := DirA DirB
all: $(SUBDIRS)
$(SUBDIRS):
        $(MAKE) -C $@
.PHONY: $(SUBDIRS)
子目录也是如此。注意:您必须包括
.PHONY

由于每个目录都是一个单独的目标,因此如果使用
-j
,make现在可以并行调用它们

哦,如果某些子目录的某些内容依赖于其他子目录,您可以在makefile中显式声明该依赖关系,以便了解它:

SUBDIRS := SubDirA SubDirB SubDirC SubDirD
all: $(SUBDIRS)
$(SUBDIRS):
        $(MAKE) -C $@
.PHONY: $(SUBDIRS)

SubDirA: SubDirD

等等。

非常感谢,我很快会查一查。顺便说一句,如果目录名包含空格怎么办?例如“dira”。我应该如何处理它?Mb加引号或转义为\\?您不能使用包含空格的路径,本质上是带make的。@QtRoS,如果您的目录名包含空格(我不建议这样做,但您可能会被卡住),那么您就不能给规则赋予与目录相同的名称。因此,每个子目录都有一个规则,而不是像上面那样有一个单一的模式规则。如果目录名中没有目标的合法字符(例如,
),则可以使用变量替换,如
$(MAKE)-C$(subst.',@)
。但实际上,不要这样做。如果在目标或先决条件中唯一需要空格的时间是在这个子目录的情况下,那么您可以这样做;正如托比所说,除了方便之外,没有其他理由认为虚假目录目标必须与实际目录同名。但通常这些路径也会泄漏到“正常”目标或先决条件(头文件路径等)中,这是不容易实现的。尽可能避免。你会更高兴的。