【问题标题】:Assigning variables in Makefile recipe在 Makefile 配方中分配变量
【发布时间】:2022-01-02 16:29:37
【问题描述】:

在我的一个 Makefile 配方中,我想创建一个临时文件,将该文件的名称传递给一个 shell 命令,并将该命令的输出分配给一个 make 变量,以便以后可以使用它。对于我的生活,我无法让它工作。

出于调试的目的,我试图将问题归结为我能想到的最简单的目标:

.PHONY: foo
foo:
    $(eval TMPFILE = $(shell mktemp -p ./))
    dd if=/dev/random of=${TMPFILE} bs=1 count=512
    $(eval FOO = $(shell wc -c ${TMPFILE}))
    @echo FOO: ${FOO}

会发生什么:

❯ make foo
dd if=/dev/random of=./tmp.K1au4WrZ76 bs=1 count=512
512+0 records in
512+0 records out
512 bytes copied, 0.00287818 s, 178 kB/s
FOO: 0 ./tmp.K1au4WrZ76

不知何故,wc 认为文件是空的。但是当我检查 TMPFILE 时,它有 512 个字节,正如预期的那样:

❯ wc -c tmp.K1au4WrZ76
512 tmp.K1au4WrZ76

谁能告诉我这里发生了什么以及如何正确地做到这一点?

谢谢 菲尔

更新:根据答案,我将这个目标放在一起,它可以按需要工作:

.PHONEY: foo
.ONESHELL:
foo:
    set -e
    TMPFILE=`mktemp -p ./`
    dd if=/dev/random of=$$TMPFILE bs=1 count=512
    FOO=`wc -c $$TMPFILE`
    @echo FOO: $$FOO

谢谢!

【问题讨论】:

    标签: variables makefile gnu-make


    【解决方案1】:

    Make 总是先展开整个配方(配方的所有行),然后再启动任何 shell 命令。因此,您的所有eval 等操作都会在任何shell 命令(例如dd)运行之前调用。

    【讨论】:

    • 谢谢——这解释了很多!所以这意味着我可能不得不纯粹在 shell 端实现它。可能为此目标使用 .ONESHELL 并使用 shell 变量而不是 make 变量。但如果我这样做,只有最后一行失败时,配方才会失败——对吗?
    • 是的,除非您编写的 shell 命令立即失败。您可以通过编写由&& 分隔的命令而不是;(如foo && bar && baz)或将set -e 添加到脚本的开头来做到这一点。或者在每个命令后添加|| exit 1。基本上,此时它与 make 无关:它是你编写 shell 脚本的方式。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-25
    • 1970-01-01
    相关资源
    最近更新 更多