我写了一个Makefile,它使用与here类似的想法。也就是说,我定义了一组目录并使用foreach
和define
我在每个目录中构建所有对象。这里我的Makefile看起来粗略
all_dirs := $(shell ...) # long shell command which finds all directories
all_objs := $(shell ...) # long shell command which finds all objects
define compile_rule
$(BUILDDIR)/$(1)/%.o : $(1)/%.cpp
$(CXX) $(CXXFLAGS) -c $< -o $@ -MD -MF $(@:.o=.dep)
endef
$(foreach dir,$(all_dirs:$(BUILDDIR)/%=%),$(eval $(call compile_rule,$(dir))))
all : program_name
program_name: $(all_objs)
$(LD) -o $@ $(all_objs) $(LDFLAGS)
我总是使用make
参数运行-j32
命令。通常它工作正常但在某些情况下我从Makefile中得到一个错误,它自带No rule to make target
$(all_objs)
列表needed by program_name
中的第一个目标文件名。
看here问题很明显。由于我正在使用-j
,因此似乎make命令在扩展program_name
创建的规则之前开始评估foreach
。我尝试在规则中编写foreach
,以便保证program_name
和foreach
之间的执行顺序,但后来我收到错误prerequisites cannot be defined in recipes
。
知道如何解决这个问题吗?我或许可以使用两步制作来解决这个问题,即首先使用类似$(all_objs)
的{{1}}构建make objs
然后将其与make prog
之类的内容链接在一起,但我更喜欢它在一个命令中发生,我有一种感觉,我想念一些简单的东西。请指教。
答案 0 :(得分:2)
这可能有效,但我没有测试过:
# ...
prereq: $(foreach dir ...)
program_name: $(all_objs) | prereq
$(LD) ...
似乎 来处理我的测试设置,但我只测试了一些目录和对象。管道是order-only prerequisite,看起来将for循环放在目标中是可以的。
<强>建议强>
如果您真的想要,可以下载GNU Make 3.82 source,使用patch < function.c.patch
应用下面的补丁,然后使用make --debug=b -j32 ...
调用make并注意Call
,{{ 1}}和Evaluating
行。
Executing
通过这种方式,如果--- function.c 2010-07-13 03:20:39.000000000 +0200
+++ function.c.patched 2015-04-18 20:41:15.000000000 +0200
@@ -1371,6 +1371,8 @@
install_variable_buffer (&buf, &len);
+ DB (DB_BASIC, (_("Evaluating: %s\n"), argv[0]));
+
eval_buffer (argv[0]);
restore_variable_buffer (buf, len);
@@ -1652,6 +1654,11 @@
return o;
}
+ DB (DB_BASIC, (_("Executing shell command:")));
+ for ( char **p=command_argv; *p!=NULL; ++p )
+ DB (DB_BASIC, (_(" %s"), *p));
+ DB (DB_BASIC, (_("\n")));
+
# ifdef __EMX__
/* close some handles that are unnecessary for the child process */
CLOSE_ON_EXEC(pipedes[1]);
@@ -2311,6 +2318,12 @@
--cp;
cp[1] = '\0';
+ DB (DB_BASIC, (_("Call %s:"), fname));
+ for ( char **p=argv; *p!=NULL; ++p )
+ DB (DB_BASIC, (_(" %s"), *p));
+ DB (DB_BASIC, (_("\n")));
+
+
/* Calling nothing is a no-op */
if (*fname == '\0')
return o;
运行时,您实际上可以查看。在我的例子中,输出是:
call compile_rule