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