gpt4 book ai didi

linux - 当 eval 创建规则时 Makefile 中的目标顺序

转载 作者:太空狗 更新时间:2023-10-29 12:14:45 28 4
gpt4 key购买 nike

我写了一个 Makefile,它使用了与 here 相似的想法.也就是说,我定义了一组目录并使用 foreachdefine 我在每个目录中构建了所有对象。我的 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)

我总是使用 -j32 参数运行 make 命令。通常它工作正常,但在某些情况下,我从 Makefile 中得到一个错误,它自己说 No rule to make target with the first object file name in $(all_objs) list program_name 需要

寻找 here问题很明显。由于我使用的是 -j,因此 make 命令似乎在扩展 foreach 创建的规则之前开始评估 program_name。我试图在规则中编写 foreach 这样我就可以保证 program_nameforeach 之间的执行顺序但是后来我得到了错误 先决条件不能在配方中定义

知道如何解决这个问题吗?我也许可以使用两步 make 来解决这个问题,即首先使用 make objs 构建 $(all_objs) ,然后使用 将它们链接在一起code>make prog 但我更喜欢这一切都发生在一个命令中,我觉得我错过了一些简单的事情。请指教。

最佳答案

这可能有效,但我还没有测试过:

# ...

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 , EvaluatingExecuting行。

--- 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在不应该运行的时候运行。在我的例子中,输出是:

GNU Make 3.82
Built for x86_64-apple-darwin14.3.0
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Reading makefiles...
Executing shell command: find . -type d
Call compile_rule: compile_rule .
Evaluating: ./%.foo: ./%.txt
@echo build $@ from $<
Call compile_rule: compile_rule ./1
Evaluating: ./1/%.foo: ./1/%.txt
@echo build $@ from $<
Call compile_rule: compile_rule ./2
Evaluating: ./2/%.foo: ./2/%.txt
@echo build $@ from $<
Updating goal targets....
File `program' does not exist.
File `1/1.foo' does not exist.
Must remake target `1/1.foo'.
Invoking recipe from Makefile:11 to update target `1/1.foo'.
File `2/2.foo' does not exist.
Must remake target `2/2.foo'.
Invoking recipe from Makefile:11 to update target `2/2.foo'.
File `prereq' does not exist.
Must remake target `prereq'.
Successfully remade target file `prereq'.
build 1/1.foo from 1/1.txt
File `program' does not exist.
build 2/2.foo from 2/2.txt
File `program' does not exist.
Must remake target `program'.
Invoking recipe from Makefile:9 to update target `program'.
link program w/args 1/1.foo 2/2.foo

关于linux - 当 eval 创建规则时 Makefile 中的目标顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29719561/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com