在 bash 提示符下,可以使用伪文件执行 diff:
diff <(echo test) <(echo test)
将其按原样添加到 Makefile 中失败:
all:
diff <(echo test) <(echo test)
错误(提示:/bin/sh 指向该系统上的/bin/bash):
/bin/sh: -c: line 0: syntax error near unexpected token `('
/bin/sh: -c: line 0: `diff <(echo test) <(echo test)'
这是什么意思?有没有办法在不使用临时文件的情况下仍然比较两个输出?
答案1
/bin/sh
可能bash
在您的系统上,但当作为 调用时sh
,bash
将以 POSIX 模式运行(就好像POSIXLY_CORRECT
已定义,或者以 启动--posix
)。
在此模式下,不存在进程替换。
解决方案:
使用显式临时文件:
all: command1 >tmpfile command2 | diff tmpfile - rm -f tmpfile
使用
bash -c
内联脚本:all: bash -c 'diff <(command1) <(command2)'
将 Makefile 变量定义
SHELL
为(或系统上的/bin/bash
任何路径):bash
SHELL=/bin/bash
如果您想要便携性,请选择第一个解决方案。如果您可以接受对 的依赖bash
,请选择第二个。如果您另外不需要关心非 GNUmake
实现,请使用第三种。
关于设置SHELL
: POSIX 标准规定 Makefile 中的可执行文件应该system()
由 .c 库函数调用make
。该函数不保证使用SHELL
环境变量(事实上,标准不鼓励这样做)。该标准还详细说明设置 Makefile 变量SHELL
不应影响环境变量 SHELL
。然而,在我所知道的大多数实现中make
,Makefile 变量SHELL
将用于执行命令。
中的建议make
该实用程序的基本原理是使用bash -c
:
历史
MAKESHELL
特征以及其他make
实现提供的相关特征被省略。在某些实现中,它用于让用户覆盖用于运行make
命令的 shell。这很令人困惑;对于便携式make
,shell 应由 makefile 编写者选择。此外,makefile 编写者不能要求使用备用 shell 并仍然认为 makefile 是可移植的。虽然可以标准化指定备用 shell 的机制,但现有的实现并不同意这种机制,并且 makefile 编写者已经可以通过在目标规则中指定 shell 名称来调用备用 shell;例如:
python -c "foo"