并行执行make的虚假目标

时间:2014-08-11 09:15:19

标签: linux shell makefile

make工具的手册页说 -

虚假目标有用性的另一个例子是与make的递归调用相结合(有关更多信息,请参阅make的递归使用)。在这种情况下,makefile通常包含一个变量,该变量列出了要构建的多个子目录。处理此问题的一种方法是使用一个规则,其配方是子目录上的shell循环,如下所示:

 SUBDIRS = foo bar baz

 subdirs:
         for dir in $(SUBDIRS); do \
           $(MAKE) -C $$dir; \
         done

然而,这种方法存在问题。首先,此规则会忽略在子make中检测到的任何错误,因此即使一个目录失败,它也会继续构建其余的目录。这可以通过添加shell命令来记录错误并退出来解决,但是即使使用-k选项调用make也会这样做,这是不幸的。其次,也许更重要的是,你不能利用make并行构建目标的能力(参见并行执行),因为只有一个规则。

通过将子目录声明为虚假目标(您必须这样做,因为子目录显然始终存在;否则它不会被构建)您可以删除这些问题:

 SUBDIRS = foo bar baz

 .PHONY: subdirs $(SUBDIRS)

 subdirs: $(SUBDIRS)

 $(SUBDIRS):
         $(MAKE) -C $@

 foo: baz

此处我们还声明,在baz子目录完成之后才能构建foo子目录;在尝试并行构建时,这种关系声明尤为重要。

有人可以解释上面提到的第二个代码如何实现并行执行? 我不明白Phony Targets是如何帮助的?

4 个答案:

答案 0 :(得分:1)

让我用简单的语言说出来,你会得到一些想法

arved提到的-j2选项可以告诉make文件运行两个并行线程。 如果两个目标是独立的,则检查目标及其依赖性,然后可以并行构建它们。

让我展开第二个makefile并将其写成简单

SUBDIRS = foo bar baz

 .PHONY: subdirs $(SUBDIRS)

 subdirs: $(SUBDIRS)

 bar:
          $(MAKE) -C bar
 baz:
          $(MAKE) -C baz 

 foo: baz
          $(MAKE) -C foo

现在看上面的案例

  1. bar和baz依赖于什么,所以它们可以并行构建

  2. foo取决于baz所以它不能与bar或baz平行构建

  3. 因此,在上述情况下,您确保make文件使用并行构建文件的能力。

    现在拿你提到的第一个make文件

     SUBDIRS = foo bar baz
    
     subdirs:
             for dir in $(SUBDIRS); do \
               $(MAKE) -C $$dir; \
             done
    

    所以,如果你没有提到。上面代码的.PHONY目标对你来说很棘手,但是会失去构建并行的能力。 仔细观察。只有一个目标subdirs运行三个循环。所有三个循环将一个接一个地运行,因此没有并行性。

    记住拇指规则。如果目标彼此独立,Make可以使用并行构建,因此它可以构建独立的目标并行而没有任何依赖性问题

答案 1 :(得分:0)

如果你没有将子目录标记为假冒,那将检查名为foo的文件是否存在并立即将目标标记为已完成,因为目录“foo”存在

标记它PHONY确保即使存在文件也始终重建目标。

虽然在示例1中,只能使用一个make进程来顺序构建所有目录,但在示例2中,make -j2将导致bar和baz目标并行构建。

答案 2 :(得分:0)

这个想法是使子目标成为目标,因此make可以并行地“构建”它们。它们之间没有依赖关系,有一个明确的规则是必须要做什么来“构建”它们,make可以同时处理多个。 For循环将按顺序逐个构建所有内容,迭代后迭代。

Phony只是一种技术性,我们需要它,因为否则make会看到有一些名称为subdir的东西,并且它很久以前被修改过,所以没有必要做。如果有人创建名为all的文件,则必须将cleanall等声明为虚假。

答案 3 :(得分:0)

当目标列出多个先决条件时,可以实现并行:

all: a b c

a: a.c
b: b.c
c: c.c

由于 a b c 所有行中列出的先决条件,因此可以并行运行命令。构建先决条件后,可以执行所有规则。所以:

$ make -j3 all

将允许并行构建3个先决条件。

.PHONY:目标声明会阻止:

$ make -t 

创建一个零长度目标。