我尝试在我们的构建服务器上进行并行make。我在这里遇到一个非常频繁的问题,即试图制造两个不同目标的两个实例,例如A和B,几乎同时尝试制作两者都需要的目标,比如C。
由于两个实例都试图在不同的实例中一起制作C,因此C make使其中任何一个失败,因为制作C需要在此处移动某些文件,并且其中一个实例最终移动或删除已创建的文件。
如果已经制作目标,是否有可用于阻止重新进入makefile的常用构造?
好的,让我这样说吧: 我的申请要求A.lo和B.lo出席。这些A.lo和B.lo是与C.lo相关联的库。 因此规则看起来像
app.d:A.lo B.lo(其他人)
(做连结)
在其他一些目录中说A(将容纳A.lo):
A.lo:C.lo(其他.o s和.lo s)
(做连结)
在其他一些目录中说B(将容纳B.lo):
B.lo:C.lo(其他.o s和.lo s)
(做连结)
因此实际上在制作app.d制作叉子时,两个平行的制作目标A.lo和B.lo. 一旦进入目录A和B,就会独立地为目标C.lo关闭另外两个线程,并且有时这两个线程同时链接C.lo,这导致其中一个失败,出现一些奇怪的错误,如文件无法识别(因为它可能被其他链接器实例写入)
我该如何解决这个问题?如果没有C.lo链接它们,就不可能创建A.lo和B.lo.
答案 0 :(得分:2)
这可能听起来有点,明显,但最简单的解决方案就是安排在C
或{{1}之前明确构建A
}。这样,当递归使B
和A
运行时,B
已经是最新的,并且都不会尝试构建它。
如果你的toplevel makefile看起来像这样:
C
您可以像这样扩展它:
all: buildA buildB
buildA:
$(MAKE) -C A
buildB:
$(MAKE) -C B
你没有详细介绍你的具体构建,所以可能这不仅仅是插入和工作,但希望你能得到这个想法。
答案 1 :(得分:1)
我使用“mkdir”技术解决了这个问题:
SHELL = /bin/bash
all: targetC targetD
targetC: targetA
............
targetD: targetB
............
targetA targetB: source
-mkdir source.lock && ( $(command) < source ; rm -r source.lock )
$(SHELL) -c "while [ -d source.lock ] ; do sleep 0.1 ; done"
但我很乐意看到更优雅的解决方案。