如何使用Makefile中的shell命令(How to use shell commands in

2019-06-23 09:39发布

我试图使用的结果ls在其他命令(例如回声,rsync的):

all:
    <Building, creating some .tgz files - removed for clarity>
    FILES = $(shell ls)
    echo $(FILES)

但我得到:

make
FILES = Makefile file1.tgz file2.tgz file3.tgz
make: FILES: No such file or directory
make: *** [all] Error 1

我已经尝试使用echo $$FILESecho ${FILES}echo $(FILES) ,没有运气。

Answer 1:

附:

FILES = $(shell ls)

下面缩进all这样的,它是一个构建命令。 所以这个扩展$(shell ls)然后尝试运行命令FILES ...

如果FILES应该是一个make的变量,这些变量需要的配方部分,例如外被分配:

FILES = $(shell ls)
all:
        echo $(FILES)

当然,这意味着FILES将被设置为“从输出ls ”运行任何创建.tgz的文件的命令之前 。 (虽然作为卡兹指出变量每次再膨胀,这样最终会包括.tgz的文件;有的使变种有FILES := ... ,以避免这种情况,为了提高效率和/或正确性1)。

如果FILES应该是一个shell变量,你可以设置它,但你需要做的是在壳ESE,没有空格,并引用:

all:
        FILES="$(shell ls)"

然而,每一行由单独的shell中运行,所以这个变量将无法生存到下一行,这样,那么你必须立刻使用它:

        FILES="$(shell ls)"; echo $$FILES

这毕竟是一个有点傻,因为外壳将扩大*你(和其他壳水珠表达式)摆在首位,所以你可以:

        echo *

作为你的shell命令。

最后,作为一般规则(不是真的适用于本示例):作为世界语在评论中指出,使用从输出ls不是完全可靠的(一些细节依赖于文件名,有时甚至版本的ls ;某些版本的ls尝试消毒在某些情况下输出)。 因此, l0b0和idelic的注意,如果你使用GNU让你可以使用$(wildcard)$(subst ...)来完成这里的一切都make自己(避免“在文件名字符怪异”的问题的话)。 (在sh脚本,包括生成文件的配方部分,另一种方法是使用find ... -print0 | xargs -0以避免绊倒坯料,换行,控制字符,等等)。


1 的GNU制作文件进一步指出,POSIX使加::=分配在2012年 。 我还没有找到一个快速参考链接到了这个POSIX文件,也不知道离手这make变种支持::=分配,虽然GNU做出今天这样,有相同的含义:= ,即做作业现在与扩张。

需要注意的是VAR := $(shell command args...)也可以拼VAR != command args...在几个make变体,包括所有的现代GNU和BSD据我所知变种。 这些其他变体没有$(shell)因此使用VAR != command args...在这两个长度较短在更多的变种工作优越。



Answer 2:

此外,除了托雷克的回答是:有一点突出的是,您使用的是惰性计算宏观分配。

如果你在使用GNU make,使用:=赋值,而不是= 。 这种分配导致右侧被立即展开,并存储在左边的变量。

FILES := $(shell ...)  # expand now; FILES is now the result of $(shell ...)

FILES = $(shell ...)   # expand later: FILES holds the syntax $(shell ...)

如果使用=赋值,这意味着每一个出现$(FILES)将扩展$(shell ...)语法,因此调用shell命令。 这会让你的化妆工作运行速度较慢,甚至有一些令人惊讶的结果。



文章来源: How to use shell commands in Makefile