在makefile中,我使用define
指令定义变量。该变量将包含我想要执行的可配置命令列表。
我希望此变量获取文件列表(例如.foo
个文件)。这些文件是在makefile执行期间创建的。例如makefile:
MY_VAR = $(wildcard *.foo)
define MY_VAR2
echo $(1) $(MY_VAR)
endef
foo: create_files
$(call MY_VAR2, ls)
rm -f *.foo
create_files:
touch foo.foo
touch bar.foo
我没有得到预期的结果。似乎MY_VAR2
在声明时进行评估。
有没有办法获得理想的行为?
修改
正确指出的$(shell)
MY_VAR2
命令适用于上面的示例。但是,它不适用于下面的示例。此示例的主要区别在于新文件是在MY_VAR = $(wildcard *.foo)
TEST_VAR = $(shell ls *.foo)
define MY_VAR2
@touch foo.foo
@touch bar.foo
@echo "MY_VAR" $(1) $(MY_VAR)
@echo "TEST_VAR" $(1) $(TEST_VAR)
endef
foo:
$(call MY_VAR2, ls)
@rm -f *.foo
内创建的。
{{1}}
我可以通过添加规则来解决上述问题。有更简单的方法吗?
答案 0 :(得分:2)
我在这里假设你在这里使用GNU Make。我想你可以得到所希望的 结果使用GNU Make提供的“shell”内置函数。
以下是make文件摘要,演示了如何获得结果:
MY_VAR = $(wildcard *.foo)
TEST_VAR = $(shell ls *.foo)
define MY_VAR2
@echo "MY_VAR" $(1) $(MY_VAR)
@echo "TEST_VAR" $(1) $(TEST_VAR)
endef
foo: create_files
$(call MY_VAR2, ls)
@rm -f *.foo
create_files:
@touch foo.foo
@touch bar.foo
为目标“foo”运行上述make文件的结果是:
MY_VAR ls
TEST_VAR ls bar.foo foo.foo
因此, shell 函数的演示使用得到了理想的结果。
来自GNU make文档:
shell
函数执行与反引号(''')相同的函数
shell:它确实命令扩展。这意味着它将shell作为参数
命令并计算命令的输出。唯一的处理工具就是
结果是将每个换行符(或回车符/换行符对)转换为单个空格。
... 的
通过调用shell函数运行的命令在扩展函数调用时运行。
...
files:= $(shell echo .c)
将文件设置为' .c'的扩展。除非make使用一个非常奇怪的shell,否则就有了
结果与'$(通配符* .c)'相同(只要存在至少一个'.c'文件)。
所以我认为使用递归扩展变量(= form)和 shell 来运行你 可以得到理想的结果。
答案 1 :(得分:2)
在我看来,你正在滥用make,试图在make中编写一个shell脚本。
如果编写shell脚本,请编写shell脚本。您可以按顺序执行命令,并且可以在执行每一行时知道存在哪些文件。
touch foo.foo
touch bar.foo
your-command `ls *.foo`
另一方面,如果你想使用make,那么就有了规则和依赖关系,如果你采用make方式思考,你甚至不需要使用define。
foo: create_files
your-command $(wildcard *.foo)
rm -f *.foo
create_files:
touch foo.foo
touch bar.foo
答案 2 :(得分:1)
4.4.3功能通配符
通配符扩展在规则中自动发生。但是,通常不会在设置变量时或在函数的参数内部进行通配符扩展。如果要在这些位置进行通配符扩展,则需要使用通配符函数
您可以在eval
函数周围工作。
这些创建的文件应该是另一个规则的依赖项,以便依赖图是正确的。
参考文献:
答案 3 :(得分:0)
您可以尝试过滤命令吗?您可以找到示例here。
答案 4 :(得分:0)
如何使用include?
重点是make需要两次执行。
首先,你需要让make创造它想要的东西,
然后你将让make在第二遍之后解析生成的规则
执行第一条规则。
define MY_VAR2
echo $(1) $(MY_VAR)
$(1) $(MY_VAR)
endef
-include .listoffiles
foo: create_files
$(call MY_VAR2, ls -al)
rm -f *.foo .listoffiles
create_files: .listoffiles
.listoffiles:
touch foo.foo
touch bar.foo
@echo "MY_VAR = \$$(wildcard *.foo)" > $@
我认为它只是做你想要的
双通评估并不意味着你必须输入两次。
它将通过make自动完成。
% make -f test.mk
touch foo.foo
touch bar.foo
echo ls -al bar.foo foo.foo
ls -al bar.foo foo.foo
ls -al bar.foo foo.foo
-rw-rw-r-- 1 yo-hei clearusers 0 Jan 8 08:44 bar.foo
-rw-rw-r-- 1 yo-hei clearusers 0 Jan 8 08:44 foo.foo
rm -f *.foo .listoffiles
答案 5 :(得分:0)
如何在shell中进行扩展而不是make?
MY_VAR = $$(ls *.foo)
define MY_VAR2
@echo $(1) $(MY_VAR)
endef
foo: create_files
$(call MY_VAR2, ls)
@rm -f *.foo
create_files:
@touch foo.foo
@touch bar.foo
double-$将允许shell扩展文件搜索部分。我不禁同意其他有关更优雅的方式的帖子,但这是一个选择。
也适用于你的第二个例子:
MY_VAR = $(wildcard *.foo)
TEST_VAR = $$(ls *.foo)
define MY_VAR2
@touch foo.foo
@touch bar.foo
@echo "MY_VAR" $(1) $(MY_VAR)
@echo "TEST_VAR" $(1) $(TEST_VAR)
endef
foo:
$(call MY_VAR2, ls)
@rm -f *.foo