Build 如何正确使用make与并行构建?

Build 如何正确使用make与并行构建?,build,parallel-processing,makefile,build-automation,Build,Parallel Processing,Makefile,Build Automation,我在make中遇到了并行构建的问题,即有这个定义 rmlink: $(RM) $(ALIB) $(RM) $(BLIB) $(RM) $(CLIB) $(RM) $(DLIB) $(RM) $(ELIB) mklink: ln -sf $(ALIB_WITHPATH) $(ALIB) ln -sf $(BLIB_WITH_PATH) $(BLIB)

我在make中遇到了并行构建的问题,即有这个定义

 rmlink:
         $(RM) $(ALIB)
         $(RM) $(BLIB)
         $(RM) $(CLIB)
         $(RM) $(DLIB)
         $(RM) $(ELIB)

 mklink:
         ln -sf $(ALIB_WITHPATH) $(ALIB)
         ln -sf $(BLIB_WITH_PATH) $(BLIB)
         ln -sf $(CLIB_WITH_PATH) $(CLIB)
         ln -sf $(DLIB_WITH_PATH) $(DLIB)
         ln -sf $(E_LIB) $(ELIB)
使用
make
启动构建,我将构建这些目标

$ make
/bin/rm -f libA.so
/bin/rm -f libB.so
/bin/rm -f libC.so
/bin/rm -f libD.so
/bin/rm -f libE.so
ln -sf ../libA.so libA.so
ln -sf ../libB.so libB.so
ln -sf ../libC.so libC.so
ln -sf ../libD.so libD.so
ln -sf ../libE.so libE.so
但是,使用并行构建和
make-j2
(或更多)启动它,我会得到:

$ make -j 2
/bin/rm -f libA.so
ln -sf ../libB.so libB.so
/bin/rm -f libB.so
/bin/rm -f libC.so
/bin/rm -f libD.so
ln -sf ../libD.so libD.so
/bin/rm -f libE.so
ln -sf ../libA.so libA.so
ln -sf ../libC.so libC.so
ln -sf ../libE.so libE.so
g++: libB.so: No such file or directory
在这种特殊情况下,它会删除我指向
libB.so的链接,并且不会再次创建它-破坏了有效的构建

如何修复此问题以启动并行构建

编辑

mklink
target添加类似的内容似乎可以解决问题:

mklink: rmlink

请评论这是否是正确的方法。

在考虑并行构建时,make仅通过先决条件列表决定构建的顺序。如果没有将目标FOO定义为目标BAR的先决条件,那么make可以随意同时构建FOO和BAR

请记住,将两个目标列为同一目标的先决条件(如
target:FOO-BAR
)只意味着FOO和BAR必须在目标之前构建。这并不意味着FOO和BAR之间有任何关系。因此,如果你有:

foo: rmlink mklink
然后make可以同时自由运行rmlink和mklink。如果您希望在mklink启动之前始终完成rmlink,则必须声明它们之间的一种特权关系,如:

mklink: rmlink
当然,请记住,您必须确保mklink目标是任何需要这些链接存在的链接器目标的先决条件


这里可能有更多的错误,但是考虑到您显示的makefile部分以及您提出的问题,应该可以解决它。

您没有显示以rmlink和mklink为先决条件的规则。然而,从并行性的角度来看,这个makefile存在致命的缺陷。需要明确的是:先决条件关系可以是一段距离,而不必是直接的。因此,例如,如果
A
依赖于
B
,后者依赖于
C
,后者依赖于
D
,则不必明确地将
D
列为
A
的先决条件。Make将理解所需的订购。好的,这似乎解决了我的问题,但现在我有了类似于:
Make[1]:警告:jobserver不可用:使用-j1。将
+'添加到父生成规则。`因为我在我的
makefile
中使用子调用来生成
。这是另一个问题。您应该将这个问题标记为已回答,然后问另一个问题,因为为了确定答案,我们需要查看调用子make的makefile规则。但是,通常会发生这种情况,因为您直接在运行子make的配方中运行
make
。千万不要这样做:在运行子MAKE时,应该始终使用
$(MAKE)
变量。