我经常发现Bash语法非常有用,例如进程替换,比如diff <(sort file1) <(sort file2)
。
在Makefile中是否可以使用这样的Bash命令?我想到了这样的东西:
file-differences:
diff <(sort file1) <(sort file2) > $@
在我的GNU Make 3.80中,这将会出现错误,因为它使用
sh
而不是bash
来执行命令。来自GNU Make文档,
5.3.2 Choosing the Shell
------------------------
The program used as the shell is taken from the variable `SHELL'. If
this variable is not set in your makefile, the program `/bin/sh' is
used as the shell.
在您的makefile顶部添加SHELL:= /bin/bash
,然后您就可以开始了。
顺便说一句:您也可以为一个目标执行此操作,至少对于GNU Make而言。每个目标都可以有自己的变量分配,如下所示:
all: a b
a:
@echo "a is $$0"
b: SHELL:=/bin/bash # HERE: this is setting the shell for b only
b:
@echo "b is $$0"
这会输出:
a is /bin/sh
b is /bin/bash
请参阅文档中的“目标特定变量值”了解更多详细信息。该行可以放置在Makefile的任何位置,不必紧接在目标之前。
man
提供报价。谈论一下时间。 :P - SiddharthaRTSHELL=/bin/bash
。 - Yauhen Yakimovich/usr/bin/env bash
,它将使用 PATH 中的 bash
。但如果仅是 SHELL := bash
呢? - CMCDragonkai$(info $(SHELL))
将始终显示make将调用的shell,而不是调用shell的SHELL
环境变量的值。如果info
打印/bin/bash
,那么这意味着在您的makefile中的某个地方,您已经将makefile变量SHELL
设置为/bin/bash
,并且这就是make在调用recipes时使用的shell。 - MadScientist您可以直接调用bash
,使用-c
标志:
bash -c "diff <(sort file1) <(sort file2) > $@"
当然,你可能无法将重定向指向变量$@,但是当我尝试这样做时,我得到了-bash:$@:ambiguous redirect
的错误消息,所以在深入研究之前,你可能需要注意一下这个问题(虽然我使用的是bash 3.2.x版本,所以你的版本可能会有所不同)。
还有一种方法也可以使用,就是在目标代码的第一行这样放置:
your-target: $(eval SHELL:=/bin/bash)
@echo "here shell is $$0"
您可以在Makefile中直接调用bash,而不使用默认的shell:
bash -c "ls -al"
改为:
ls -al
make
忽略环境变量 SHELL 的值。 - choroba如果可移植性很重要,您可能不想在Makefile中依赖特定的shell。并非所有环境都有bash可用。
sh
的名称调用时,Bash以兼容模式(set -o posix
)运行。 OP试图使用的功能——进程替换,在此模式下不可用。 - Charles Duffy这不是对问题的直接回答,makeit 是一个带有 bash 语法的受限 Makefile 替代品,在某些情况下可能很有用 (我是作者)
基本思想是在脚本末尾使用 while
循环:
while [ $# != 0 ]; do
if [ "$(type -t $1)" == 'function' ]; then
$1
else
exit 1
fi
shift
done
https://asciinema.org/a/435159
/bin/sh: -c: line 0: syntax error near unexpected token
('`。 - David