运行 具有多个作业的构建(例如:-j8)似乎会与 Autotools 生成的 Makefile 产生竞争
Running a build with multiple jobs (e. g.: -j8) seems to produce a race with Autotools-generated Makefiles
假设我有一个简单的 Autotools 项目,仅包含一个源文件(例如:amhello)。
现在,由于某种原因,尽管在生成的 Makefile
中 all
和 check
目标之间存在直接依赖关系,但似乎也存在竞争,因此 运行
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
也总是成功,导致整个项目正在构建。
- 为什么如此成熟的构建系统仍然产生
Makefile
的种族?
- 鉴于
all
是 check
的先决条件,make check
与 make all check
有何不同?
问题 #1 的答案是,我想,没有人 运行 会同时在命令行上同时使用 all
和 check
。这不是通常的使用模型,因此即使出现问题,人们也不会注意到。
正如您所指出的,它没有用,因为 make check
无论如何都会以正确的顺序首先构建 all
。
我认为 automake 生成的 makefile 始终假定并要求向初始 make
调用提供一个且仅一个“顶级”目标。
我期望第二个问题的答案与这些 makefile 使用递归 make 这一事实有关。即顶层make调用没有check: all
。它有 check: check-recursive
和 all: all-recursive
,因此这些规则可以 运行 并行。他们每个人都调用一个子制作过程,而子制作 运行ning check-recursive
知道它不能 运行 与 all
目标并行检查 it 是 运行ning,另一个 submake 运行ning all-recursive
不知道其他一些 make 实例也在构建 all
同一目录。
假设我有一个简单的 Autotools 项目,仅包含一个源文件(例如:amhello)。
现在,由于某种原因,尽管在生成的 Makefile
中 all
和 check
目标之间存在直接依赖关系,但似乎也存在竞争,因此 运行
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
也总是成功,导致整个项目正在构建。
- 为什么如此成熟的构建系统仍然产生
Makefile
的种族? - 鉴于
all
是check
的先决条件,make check
与make all check
有何不同?
问题 #1 的答案是,我想,没有人 运行 会同时在命令行上同时使用 all
和 check
。这不是通常的使用模型,因此即使出现问题,人们也不会注意到。
正如您所指出的,它没有用,因为 make check
无论如何都会以正确的顺序首先构建 all
。
我认为 automake 生成的 makefile 始终假定并要求向初始 make
调用提供一个且仅一个“顶级”目标。
我期望第二个问题的答案与这些 makefile 使用递归 make 这一事实有关。即顶层make调用没有check: all
。它有 check: check-recursive
和 all: all-recursive
,因此这些规则可以 运行 并行。他们每个人都调用一个子制作过程,而子制作 运行ning check-recursive
知道它不能 运行 与 all
目标并行检查 it 是 运行ning,另一个 submake 运行ning all-recursive
不知道其他一些 make 实例也在构建 all
同一目录。