[英]How to use shell commands in Makefile
I'm trying to use the result of ls
in other commands (eg echo, rsync):我正在尝试在其他命令(例如 echo、rsync)中使用
ls
的结果:
all:
<Building, creating some .tgz files - removed for clarity>
FILES = $(shell ls)
echo $(FILES)
But I get:但我得到:
make
FILES = Makefile file1.tgz file2.tgz file3.tgz
make: FILES: No such file or directory
make: *** [all] Error 1
I've tried using echo $$FILES
, echo ${FILES}
and echo $(FILES)
, with no luck.我试过使用
echo $$FILES
、 echo ${FILES}
和echo $(FILES)
,但没有成功。
With:和:
FILES = $(shell ls)
indented underneath all
like that, it's a build command.像这样在下面缩进,
all
是一个构建命令。 So this expands $(shell ls)
, then tries to run the command FILES...
.所以这扩展
$(shell ls)
,然后尝试运行命令FILES...
。
If FILES
is supposed to be a make
variable, these variables need to be assigned outside the recipe portion, eg:如果
FILES
应该是make
变量,则需要在配方部分之外分配这些变量,例如:
FILES = $(shell ls)
all:
echo $(FILES)
Of course, that means that FILES
will be set to "output from ls
" before running any of the commands that create the.tgz files.当然,这意味着在运行任何创建 .tgz 文件的命令之前,
FILES
将被设置为“从ls
输出”。 (Though as Kaz notes the variable is re-expanded each time, so eventually it will include the.tgz files; some make variants have FILES:=...
to avoid this, for efficiency and/or correctness. 1 ) (尽管Kaz 指出变量每次都会重新扩展,因此最终它将包含 .tgz 文件;一些 make 变体具有
FILES:=...
以避免这种情况,以提高效率和/或正确性。1 )
If FILES
is supposed to be a shell variable, you can set it but you need to do it in shell-ese, with no spaces, and quoted:如果
FILES
应该是一个 shell 变量,你可以设置它,但你需要在 shell-ese 中进行,没有空格,并引用:
all:
FILES="$(shell ls)"
However, each line is run by a separate shell, so this variable will not survive to the next line, so you must then use it immediately:但是,每一行都由一个单独的 shell 运行,所以这个变量不会存活到下一行,所以你必须立即使用它:
FILES="$(shell ls)"; echo $$FILES
This is all a bit silly since the shell will expand *
(and other shell glob expressions) for you in the first place, so you can just:这有点傻,因为 shell 首先会为你扩展
*
(和其他 shell glob 表达式),所以你可以:
echo *
as your shell command.作为您的 shell 命令。
Finally, as a general rule (not really applicable to this example): as esperanto notes in comments, using the output from ls
is not completely reliable (some details depend on file names and sometimes even the version of ls
; some versions of ls
attempt to sanitize output in some cases).最后,作为一般规则(并非真正适用于此示例):正如世界语在评论中指出的那样,使用
ls
中的output并不完全可靠(一些细节取决于文件名,有时甚至取决于ls
的版本;某些版本的ls
尝试在某些情况下对 output 进行消毒)。 Thus, as l0b0 and idelic note, if you're using GNU make you can use $(wildcard)
and $(subst...)
to accomplish everything inside make
itself (avoiding any "weird characters in file name" issues).因此,作为l0b0和idelic注释,如果您正在使用 GNU make,则可以使用
$(wildcard)
和$(subst...)
来完成make
自身内部的所有操作(避免任何“文件名中的奇怪字符”问题)。 (In sh
scripts, including the recipe portion of makefiles, another method is to use find... -print0 | xargs -0
to avoid tripping over blanks, newlines, control characters, and so on.) (在
sh
脚本中,包括 makefile 的配方部分,另一种方法是使用find... -print0 | xargs -0
来避免被空格、换行符、控制字符等绊倒。)
1 The GNU Make documentation notes further that POSIX make added ::=
assignment in 2012 . 1 GNU Make 文档进一步指出 POSIX make 在 2012 年添加了
::=
赋值。 I have not found a quick reference link to a POSIX document for this, nor do I know off-hand which make
variants support ::=
assignment, although GNU make does today, with the same meaning as :=
, ie, do the assignment right now with expansion.我没有为此找到指向 POSIX 文档的快速参考链接,我也不知道哪些变体支持
::=
赋值,尽管 GNU make
今天支持,与:=
具有相同的含义,即进行赋值现在随着扩张。
Note that VAR:= $(shell command args...)
can also be spelled VAR.= command args...
in several make
variants, including all modern GNU and BSD variants as far as I know.请注意,
VAR:= $(shell command args...)
也可以拼写为VAR.= command args...
在几个make
变体中,包括据我所知的所有现代 GNU 和 BSD 变体。 These other variants do not have $(shell)
so using VAR.= command args...
is superior in both being shorter and working in more variants.这些其他变体没有
$(shell)
因此使用VAR.= command args...
在更短和在更多变体中工作方面更胜一筹。
Also, in addition to torek's answer: one thing that stands out is that you're using a lazily-evaluated macro assignment.此外,除了 torek 的回答之外:突出的一件事是您正在使用延迟评估的宏分配。
If you're on GNU Make, use the :=
assignment instead of =
.如果您使用的是 GNU Make,请使用
:=
赋值而不是=
。 This assignment causes the right hand side to be expanded immediately, and stored in the left hand variable.此赋值导致右侧立即展开,并存储在左侧变量中。
FILES := $(shell ...) # expand now; FILES is now the result of $(shell ...)
FILES = $(shell ...) # expand later: FILES holds the syntax $(shell ...)
If you use the =
assignment, it means that every single occurrence of $(FILES)
will be expanding the $(shell...)
syntax and thus invoking the shell command.如果使用
=
赋值,则意味着$(FILES)
的每次出现都将扩展$(shell...)
语法,从而调用 shell 命令。 This will make your make job run slower, or even have some surprising consequences.这将使您的 make 作业运行得更慢,甚至会产生一些令人惊讶的后果。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.