除某些规则外,并行执行Makefile

除某些规则外,并行执行Makefile,makefile,jobs,Makefile,Jobs,我有一个复杂的makefile,里面有很多食谱。我希望运行它们时,除了生成我的对象文件之外,没有并行执行。我注意到.NOTPARALLEL目标不能接受任何先决条件,否则它将更容易解决我的问题 我的第一个猜测是使用一个不存在的名为“.PARALLEL”的目标,我会将对象文件称为依赖项,如下所示: SRC=$(wildcard *.c) OBJ=$(SRC:.c=.o) .PARALLEL: $(OBJ) %.o: %.c gcc –c –o$@ $< -M

我有一个复杂的makefile,里面有很多食谱。我希望运行它们时,除了生成我的对象文件之外,没有并行执行。我注意到.NOTPARALLEL目标不能接受任何先决条件,否则它将更容易解决我的问题

我的第一个猜测是使用一个不存在的名为“.PARALLEL”的目标,我会将对象文件称为依赖项,如下所示:

SRC=$(wildcard *.c)
OBJ=$(SRC:.c=.o)           

.PARALLEL: $(OBJ)

%.o: %.c
    gcc –c –o$@ $< -M

a.out: $(OBJ)
    gcc –o$@ $^
SRC=$(通配符*.c)
OBJ=$(SRC:.c=.o)
.PARALLEL:$(OBJ)
%.o:%.c
gcc–c–o$@$<-M
a、 输出:$(OBJ)
gcc–o$@$^
我发现一个更实用的解决方案是使用中间目标。但是,由于MyObjects没有依赖项,make将始终调用MyObjects并重新创建a.out

%.o: %.c
    $(CC) –c –o$@ $< -M

MyObjects: 
    $(MAKE) -j $(OBJ)

a.out: MyObjects
    $(CC) –o$@ $(OBJ)
%.o:%.c
$(CC)–c–o$@$<-M
对象:
$(制造)-j$(OBJ)
a、 输出:MyObject
$(CC)–o$@$(OBJ)
为了避免这种情况,我发现没有什么比使用虚拟文件更好的了。我写了这个例子来说明它:

NAMES = 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

SRC = $(addsuffix .c, $(NAMES))
OBJ = $(patsubst %.c,%.o,$(SRC))
DUM = $(addsuffix .dummy,$(OBJ))

all: a.out

$(SRC):%.c: 
    touch $@

$(OBJ):%.o: %.c
    cp $< $@
    touch $(addsuffix .dummy, $@)

$(DUM):
    $(MAKE) -j8 $(OBJ)

a.out: $(DUM) $(OBJ)
    zip $@ $(OBJ)    

clean: 
    -rm *.o
    -rm *.out
    -rm *.c 
    -rm *.dummy 
NAMES=12345678910112131416
SRC=$(addsuffix.c,$(名称))
OBJ=$(patsubst%.c、%.o、$(SRC))
DUM=$(addsuffix.dummy,$(OBJ))
全部:a
$(SRC):%
触碰$@
$(OBJ):%.o:%.c
cp$<$@
touch$(addsuffix.dummy,$@)
美元(达姆):
$(制造)-j8$(OBJ)
a、 输出:$(DUM)$(OBJ)
zip$@$(OBJ)
清洁:
-rm*.o
-rm*.out
-rm*.c
-rm*.dummy
我相信这不是我能得到的最好的解决方案。我很乐意得到一些帮助


另外,疯狂科学家,谢谢你的建议

这确实不对:

MyObjects: $(OBJ)
        $(MAKE) -j $(OBJ)
这意味着make在尝试构建
MyObjects
目标之前,将首先尝试更新所有
$(OBJ)
文件。一旦这些都完成了,它将尝试通过递归调用make来重新构建
MyObjects
目标。显然那不是你想要的。另外,您正在使用基本上是“无限并行”的
-j
,并且(如果您有足够的对象文件)可能会使您的系统崩溃

你想要这样的东西:

MyObjects:
        $(MAKE) -j5 $(OBJ)
NAMES = 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

SRC = $(addsuffix .c,$(NAMES))
OBJ = $(patsubst %.c,%.o,$(SRC))

all: recurse

recurse: non-parallel-targets
        $(MAKE) -j8 a.out PARALLEL=true

ifneq($(PARALLEL),true)
.NOTPARALLEL:
endif

%.o: %.c
        cp $< $@

a.out: $(OBJ)
        zip $@ $(OBJ)

init: $(SRC)

clean: 
        -rm *.o
        -rm *.out

.PHONY: all clean init
至于你关于重建目标的第二个问题,如果没有具体的例子,我们无法提供帮助。通常发生这种情况是因为您的规则编写不正确,并且它们实际上没有更新您告诉它们的目标。例如,您有一个目标
recipe\u a
,但是
recipe\u a
的规则会更新一些其他目标,而不是
recipe\u a

我将根据你的第二个问题补充几点说明。也许如果你在这之后没有得到它,你应该把它从StackOverflow上取下来,并寻求帮助-make@gnu.org邮件列表,或者考虑打破这一点,并询问几个特定的StAcExpLoad问题。 首先,为什么您看到make[1]:“15.o”是最新的。对于递归make中的每个文件:因为make总是为命令行上的每个目标打印该消息,所以如果您运行
make1.o2.o3.o…
(无论您是否使用
-j
,或者您使用的
-j
的值是多少),您将为每个不需要重建的目标获得该消息。就像您自己从命令行运行相同的
make
命令一样

第二,为什么不获取
a.out是最新的
,因为
a.out
不是最新的。它取决于
build
目标,并且文件
build
不存在,因此它已过期,因此每次都必须重新生成。这意味着依赖于
build
目标的任何东西,比如
a.out
,每次都必须重新生成。这解释了为什么它总是重新运行
zip
命令

第三,
all.c
的行为是因为,如果您创建一个像
%.c:
这样的模式规则,并且没有任何先决条件,那么它会告诉make,它可以通过运行该命令来创建任何扩展名为
.c
的文件。嗯,您要求make构建的目标之一是
all
目标。由于您没有将其声明为
.PHONY
目标,make尝试构建它。通常,该尝试会失败,因为make找不到任何知道如何构建
all
的规则,因此不会发生任何事情,但在您告诉make如何从无到有地构建
.c
文件(无先决条件)之后,然后,当make想要构建
all
时,它会查看其预定义规则的内部数据库,并看到一个模式规则
%:%.c
,它告诉make如何从具有相同名称的源文件构建可执行文件(在UNIX系统上,可执行文件没有任何后缀,如
.exe
:它们只是
make
cc
等),因此,
make
尝试运行这些规则,但失败了

对于任何您不希望实际创建的目标,如
all
clean
等,您应该声明它们为
。虚假的
,因此make不会尝试创建它们

至于你的问题,我认为最简单的方法是将zip文件的整个构建下推到递归make中,而不是只在递归make中构建对象。类似于这样:

MyObjects:
        $(MAKE) -j5 $(OBJ)
NAMES = 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

SRC = $(addsuffix .c,$(NAMES))
OBJ = $(patsubst %.c,%.o,$(SRC))

all: recurse

recurse: non-parallel-targets
        $(MAKE) -j8 a.out PARALLEL=true

ifneq($(PARALLEL),true)
.NOTPARALLEL:
endif

%.o: %.c
        cp $< $@

a.out: $(OBJ)
        zip $@ $(OBJ)

init: $(SRC)

clean: 
        -rm *.o
        -rm *.out

.PHONY: all clean init
NAMES=12345678910112131416
SRC=$(addsuffix.c,$(名称))
OBJ=$(patsubst%.c、%.o、$(SRC))
全部:递归
递归:非并行目标
$(MAKE)-j8 a.out PARALLEL=true
ifneq($(并行),真)
.不平行:
恩迪夫
%.o:%.c
cp$<$@
a、 输出:$(OBJ)
zip$@$(OBJ)
初始化:$(SRC)
清洁:
-rm*.o
-rm*.out
.冒牌货:都是干净的

我一直将“Parralell”改为“parallel”;您的
makefile
包含
。Parralell:
如果这就是您所拥有的,可能会解释问题。我不明白您在说什么。我上面的示例只调用了一个递归make,因为
MyObject
是一个目标。那一个递归的