我写了一个makefile,希望它可以像这样按顺序生成文件
1.out
2.out
3.out
生成文件
TOUCH := $(shell for n in 'seq 1 3'; do echo $$n ;done)
.PHONY: test
test:
@$(TOUCH)
[确定]结果:
1
2
3
但是,当我用触摸替换 echo 时,
TOUCH := $(shell for n in 'seq 1 3'; do touch $$n.out ;done)
[错]结果:
1
seq
3.out
答案 0 :(得分:5)
你似乎在这里混合了两个完全独立的结构。
VARIABLE := value
会将value
分配给变量。
VARIABLE := $(shell echo value)
将使用shell生成字符串,然后将该字符串分配给VARIABLE
。当解析Makefile
时,即在Make尝试实际执行任何配方之前,会发生这种情况。
我想你正在寻找这个:
TOUCH := for n in $$(seq 1 3); do touch $$n.out; done
.PHONY: test
test:
@$(TOUCH)
当然也可以内联;
.PHONY: test
test:
@for n in $$(seq 1 3); do touch $$n.out; done
更好的设计是让Make in掌控,但是:
.PHONY: test
test: 1.out 2.out 3.out
%.out:
@touch $@
(就个人而言,我会在任何地方都省略@
前缀,这样你就可以看到发生了什么。如果输出有问题,一旦调试了东西就运行make -s
。)
答案 1 :(得分:2)
这里有很多问题。
您在shell代码中使用单引号而不是反引号。单引号创建字符串。反引号执行命令。
因此,当您编写for n in 'seq 1 3'; do echo $$n; done
shell正在执行的操作是循环遍历单个字符串“seq 1 3”的列表而不是数字1,2和3。
这导致TOUCH
的值为“seq 1 3”。
当您在规则TOUCH
上展开@$(TOUCH)
时,该行变为@seq 1 3
,然后shell将为您执行并输出
1
2
3
但不是你想的原因。 (删除前导@
,你会看到它。)
如果我们查看非工作示例,请提供该信息
TOUCH := $(shell for n in 'seq 1 3'; do touch $$n.out ;done)
并使用循环体touch $$n.out
并将$$n
替换为字符串“seq 1 3”以获取touch seq 1 3.out
。
这会让我们进行$(shell)
调用,该调用会运行touch seq 1 3.out
并创建您在帖子中列出的文件以及一个空的TOUCH
变量。这解释了为什么(虽然你没有问),你得到make: Nothing to be done for \
测试'as output from running
make`。
我还应明确指出,您echo
/ touch
正在$(shell)
通话期间正在进行,而{strong> 正在{{1}规则执行。这可能不是你想要的。要么不使用简单扩展的test
变量,要么将命令放在变量中运行,不要使用:=
。