运行 具有多个作业的构建(例如:-j8)似乎会与 Autotools 生成的 Makefile 产生竞争

Running a build with multiple jobs (e. g.: -j8) seems to produce a race with Autotools-generated Makefiles

假设我有一个简单的 Autotools 项目,仅包含一个源文件(例如:amhello)。

现在,由于某种原因,尽管在生成的 Makefileallcheck 目标之间存在直接依赖关系,但似乎也存在竞争,因此 运行

make -j8 all check

可能会导致构建错误:

make  all-recursive
Making check in src
make[1]: Entering directory '/tmp/tmp.2E2WN3dwFg/build'
make[1]: Entering directory '/tmp/tmp.2E2WN3dwFg/build/src'
/usr/bin/gcc -DHAVE_CONFIG_H -I. -I/tmp/tmp.2E2WN3dwFg/src -I..     -g -O2 -MT test-test.o -MD -MP -MF .deps/test-test.Tpo -c -o test-test.o `test -f 'test.c' || echo '/tmp/tmp.2E2WN3dwFg/src/'`test.c
Making all in src
make[2]: Entering directory '/tmp/tmp.2E2WN3dwFg/build/src'
/usr/bin/gcc -DHAVE_CONFIG_H -I. -I/tmp/tmp.2E2WN3dwFg/src -I..     -g -O2 -MT test-test.o -MD -MP -MF .deps/test-test.Tpo -c -o test-test.o `test -f 'test.c' || echo '/tmp/tmp.2E2WN3dwFg/src/'`test.c
mv -f .deps/test-test.Tpo .deps/test-test.Po
/usr/bin/gcc  -g -O2   -o test test-test.o
mv -f .deps/test-test.Tpo .deps/test-test.Po
mv: cannot stat '.deps/test-test.Tpo': No such file or directory
make[2]: *** [GNUmakefile:369: test-test.o] Error 1
make[2]: Leaving directory '/tmp/tmp.2E2WN3dwFg/build/src'
make[1]: *** [GNUmakefile:400: all-recursive] Error 1
make[1]: Leaving directory '/tmp/tmp.2E2WN3dwFg/build'
make: *** [GNUmakefile:320: all] Error 2
make: *** Waiting for unfinished jobs....
make[1]: Leaving directory '/tmp/tmp.2E2WN3dwFg/build/src'
make[1]: Entering directory '/tmp/tmp.2E2WN3dwFg/build'
make[1]: Leaving directory '/tmp/tmp.2E2WN3dwFg/build'

自然地,运行 相同的构建仅使用一个 Make 作业成功:

make -j1 all check

奇怪的是运行

make -j8 check

也总是成功,导致整个项目正在构建。

  1. 为什么如此成熟的构建系统仍然产生 Makefile 的种族?
  2. 鉴于 allcheck 的先决条件,make checkmake all check 有何不同?

问题 #1 的答案是,我想,没有人 运行 会同时在命令行上同时使用 allcheck。这不是通常的使用模型,因此即使出现问题,人们也不会注意到。

正如您所指出的,它没有用,因为 make check 无论如何都会以正确的顺序首先构建 all

我认为 automake 生成的 makefile 始终假定并要求向初始 make 调用提供一个且仅一个“顶级”目标。

我期望第二个问题的答案与这些 makefile 使用递归 make 这一事实有关。即顶层make调用没有check: all。它有 check: check-recursiveall: all-recursive,因此这些规则可以 运行 并行。他们每个人都调用一个子制作过程,而子制作 运行ning check-recursive 知道它不能 运行 与 all 目标并行检查 it 是 运行ning,另一个 submake 运行ning all-recursive 不知道其他一些 make 实例也在构建 all同一目录。