通过 shell 命令在 Make 中分配宏值

Assigning a macro value in Make from a shell command

I/O 块大小将在我需要编写的 Makefile 中占据显着位置,因此我需要一种方法来计算它。这个脚本做我想要的:

> cat blksz.bash
#!/bin/bash
bsl=$(du --block-size=1 testfile)
bsl=($bsl)
echo ${bsl[0]}

(有人可能有更好的方法,但如果你能忍受我,那并不是问题中最一般的要点。)

我可以从我的 Makefile 中调用它,它工作正常:

> cat Makefile
BLOCKSIZE := $(shell ./blksz.bash)
blocksize:
        echo $(BLOCKSIZE)
> make blocksize
echo 4096
4096

那我觉得这么小的脚本,直接放在Makefile里岂不是更好。但是后来就不行了。

> cat Makefile
BLOCKSIZE := $(shell bsl=$(du --block-size=1 testfile) ; \
               bsl=($bsl) ; \
               echo ${bsl[0]})
blocksize:
        echo $(BLOCKSIZE)
> make blocksize
echo

BLOCKSIZE 从未定义。显然,我在 Makefile 中错误地定义了 shell 命令。谁能告诉我这样做的正确方法?此外,可能有更好的方法来获取块大小,但更广泛的问题是如何从 shell 命令中获取 return 值以便 Makefile 可以看到它可能会再次出现在某个时候,这就是我想要弄清楚的根本。

最后一件事,关于重复的问题,周围有一些类似的问题,但没有什么能完全满足我的要求,AFAICT。我认为不同之处在于我在 shell 命令中使用变量 within,但不知何故它们的内容丢失了。

除非你破解 SHELL=/bin/bash 你的 shell 命令将由 /bin/sh 执行。但是你不需要Bash。

BLOCKSIZE := $(shell du --block-size=1 testfile | awk '{ print $ }')

直接回答你的问题,$ 是一个特殊的字符 make(它引入了 make 变量和函数)所以如果你想将它传递给 shell 你必须将它转义为$$。加上 @tripleee 提到的数组变量在 /bin/sh 中不可用的问题。

所以你的命令必须是:

BLOCKSIZE := $(shell /bin/bash -c 'bsl=$$(du --block-size=1 testfile) ; bsl=($$bsl) ; echo $${bsl[0]}').

就我个人而言,我不喜欢使用 bash 特定的功能,也不喜欢使用 awk,而是 YMMV。执行此 IMO 的更好方法是使用 stat 程序:

BLOCKSIZE := $(shell stat -c %s testfile)

如果您不想 stat,那么另一种方法是:

BLOCKSIZE := ${shell set -- $$(du --block-size=1 testfile); echo $}