开发者

Preventing two make instances from executing the same target (parallel make)

I trying to make parallel make work on our build server. I am running into a very frequent problem here that two instances of make trying to make two different targets, say A and B, nearly simultaneously try to make a target which is required by both, say C.

As both instances try to make C together in different instances, C make fails for either of them since one making of C requires some files to be moved here and there and either one of these instances ends up moving or deleting an already created file.

Is there is common construct that I can use to prevent a re-entry into a makefile if the target is already being made ?

Update:

Ok let me put it this way : My application requires A.lo and B.lo to be present. These A.lo and B.lo are libraries which also link against C.lo. So the rules look like

app.d : A.lo B.lo (other lo s)

(do linking)

In some other directory say A (which will house A.lo) :

A.lo : C.lo (other .o s and .lo s)

(do linking)

In some other directory say B (which will house B.lo) :

B.lo : C.lo (other .o s and .lo s)

(do linking)

So in effect while making app.d make forks off 开发者_开发百科two parallel makes for targets A.lo and B.lo. Upon entering directories A and B make forks off another two threads for target C.lo independently and at times both of these are linking C.lo at the same time, which causes one of them to fail with some weird errors like file not recognized (since it may be written onto by other linker instance)

How should I go about solving this? It is not possible to create A.lo and B.lo without C.lo linked against them.


This may sound a little, well, obvious, but the simplest solution is just to arrange for C to be built explicitly before either A or B. That way when the recursive makes for A and B run, C will already be up-to-date, and neither will bother trying to build it.

If your toplevel makefile looks like this:

all: buildA buildB
buildA:
    $(MAKE) -C A

buildB:
    $(MAKE) -C B

You can extend it like this:

all: buildA buildB
buildA: buildC
    $(MAKE) -C A

buildB: buildC
    $(MAKE) -C B

buildC:
    $(MAKE) -C C

You didn't give a lot of detail about your specific build, so probably this won't just drop-in and work, but hopefully you get the idea.


I solve this problem using the "mkdir" technique:

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"

I would be happy to see a more elegant solution, though.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜