for makefile中的shell循环

时间:2014-11-20 02:49:04

标签: makefile

我写了一个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

2 个答案:

答案 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变量,要么将命令放在变量中运行,不要使用:=