我写了一个makefile,希望它可以像这样顺序生成文件
1.out
2.out
3.out
makefile
TOUCH := $(shell for n in 'seq 1 3'; do echo $$n ;done)
.PHONY: test
test:
@$(TOUCH)
[确定]取得结果:
1
2
3
但是,当我用touch替换echo时,
TOUCH := $(shell for n in 'seq 1 3'; do touch $$n.out ;done)
[错误]产生结果:
1
seq
3.out
您似乎在这里混合了两个完全独立的结构。
VARIABLE := value
将value
分配给变量。
VARIABLE := $(shell echo value)
将使用外壳程序生成一个字符串,然后将该字符串分配给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负责:
.PHONY: test
test: 1.out 2.out 3.out
%.out:
@touch $@
((我个人会在所有地方都省略@
前缀,这样您就可以看到发生了什么。调试完东西后,如果输出困扰您,请使用make -s
运行。)
这里有很多问题。
您在外壳程序代码中使用单引号而不是反引号。单引号创建字符串。反引号执行命令。
因此,当您编写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
替换为字符串“ seq 1 3”以获取$$n
。
这将为我们提供一个touch seq 1 3.out
调用,该调用运行$(shell)
并创建您在帖子中列出的文件和一个空的touch seq 1 3.out
变量。这就解释了为什么(尽管您没有要求)却得到TOUCH
test'make: Nothing to be done for \
make`。
我还应该明确指出,您的as output from running
/ echo
运行是在touch
调用期间完成的,而not在$(shell)
规则执行期间完成了。那可能不是您想要的。不要使用简单扩展的test
变量,也不要将命令放在变量中运行,也不要使用:=
。