我有一个复杂的makefile,有很多食谱。除了生成我的对象文件之外,我想在没有并行执行的情况下运行它们。我注意到.NOTPARALLEL目标不能采取任何先决条件,否则它将更容易解决我的问题。
我的第一个猜测是使用名为“.PARALLEL”的不存在的目标,我将其中提到的对象文件作为这样的依赖:
SRC=$(wildcard *.c)
OBJ=$(SRC:.c=.o)
.PARALLEL: $(OBJ)
%.o: %.c
gcc –c –o$@ $< -M
a.out: $(OBJ)
gcc –o$@ $^
我发现一个更实用的解决方案是使用中间目标。但是,由于MyObjects没有依赖项,因此make将始终调用MyObjects并重新创建a.out。
%.o: %.c
$(CC) –c –o$@ $< -M
MyObjects:
$(MAKE) -j $(OBJ)
a.out: MyObjects
$(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
我确信这不是我能得到的最佳解决方案。我很乐意得到一些帮助。
P.S。 MadScientist,谢谢你的建议。
答案 0 :(得分:2)
这真的不对:
MyObjects: $(OBJ)
$(MAKE) -j $(OBJ)
这意味着在尝试构建MyObjects
目标之前,它将首先尝试更新所有$(OBJ)
个文件。一旦完成,它将尝试通过递归调用make来重建它们来构建MyObjects
目标。显然这不是你想要的。另外,你使用的-j
基本上是“无限平行”,很可能(如果你有足够的目标文件)让你的系统瘫痪。
你想要这样的东西:
MyObjects:
$(MAKE) -j5 $(OBJ)
至于你关于尝试重建目标的第二个问题,如果没有某种具体的例子,我们就无法提供帮助。通常会发生这种情况,因为您的规则编写错误,而且实际上并没有更新您告诉他们的目标。例如,您有一个目标recipe_a
,但recipe_a
的规则更新了其他一些目标,而不是recipe_a
。
我会根据你的第二个问题添加一些笔记。可能如果你在此之后没有得到它,你应该从StackOverflow上取下它并在help-make@gnu.org邮件列表上询问,或者考虑打破这个并询问几个特定的StackOverflow问题。
首先,为什么你看到 make [1]:'15 .o'是最新的。对于递归make中的每个文件:因为make总是为命令中的每个目标打印该消息如果您运行make 1.o 2.o 3.o ...
(无论您是否使用-j
或使用-j
的价值无关紧要),您都会收到针对每个目标的消息需要重建。就像您自己从命令行运行相同的make
命令一样。
其次,为什么你没有得到a.out is up to date
,因为a.out
不是最新的。它取决于build
目标,文件build
不存在,因此它已过时,因此必须每次重建。这意味着每次都必须重建依赖于build
目标的任何内容,例如a.out
。这解释了为什么它总是重新运行zip
命令。
第三,使用all.c
的行为是因为如果您创建了一个没有先决条件的%.c:
之类的模式规则,那就告诉它可以通过运行创建一个.c
扩展名的任何文件那个命令。那么,您要求构建的目标之一是all
目标。由于您没有将其声明为.PHONY
目标,因此请尝试构建它。通常,尝试失败是因为make无法找到任何知道如何构建all
的规则,所以没有任何反应,但是在你告诉make如何从无到有(无先决条件)构建.c
文件之后,那么当make想要构建all
时,它会在其预定义规则的内部数据库中查找并查看模式规则% : %.c
,它告诉如何从具有相同名称的源文件构建可执行文件(在UNIX系统上)可执行文件没有.exe
之类的任何后缀:它们只是make
或cc
等等。)因此,make
尝试运行这些规则但它们会失败。
对于您不希望实际创建的任何目标,例如all
,clean
等,您应该声明它们为.PHONY
,因此make不会尝试建立他们。
至于你的问题。我认为最简单的事情是将zip文件的整个构建推送到递归make中,而不是仅尝试在递归make中构建对象。像这样:
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