GNU Makefile中的进程替换


11

在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)'

这是什么意思,有没有办法在不使用临时文件的情况下仍然比较两个输出?

Answers:


20

/bin/sh可能bash在您的系统上,但是当以调用时shbash将以POSIX模式运行(就像POSIXLY_CORRECT已定义,或以开头--posix)。

在这种模式下,不存在进程替换。

解决方案:

all:
    command1 >file1
    command2 >file2
    diff file1 file2
    rm -f file1 file2

选择:

all:
    bash -c "diff <(command1) <(command2)"

或者只是将Makefile变量定义SHELL/bin/bash

SHELL=/bin/bash

如果您想要可移植性,请选择第一个解决方案。如果可以bash,请选择第二个。如果您另外不需要关心非GNU make实现,请使用第三个。


关于设置SHELL:POSIX标准指出Makefiles中的可执行文件应该用system()C库函数调用make。不能保证此函数使用SHELL环境变量(实际上,标准不建议这样做)。该标准还说,设置Makefile变量SHELL不应影响环境变量 SHELL。在make我所知道的大多数实现中,Makefile变量SHELL将用于执行命令。

实用程序的基本原理中make的建议是使用bash -c

省略了历史MAKESHELL特征以及其他make实现提供的相关特征。在某些实现中,它用于让用户覆盖要用于运行make命令的外壳。这令人困惑;对于便携式计算机make,外壳应由makefile编写器选择。此外,makefile编写器不能要求使用备用shell,而仍然认为makefile可移植。尽管可以规范化指定备用shell的机制,但现有的实现方法在这种机制上并不一致,makefile编写者可以通过在目标规则中指定shell名称来调用备用shell。例如:

python -c "foo"


有没有一种方法可以bash在不使用临时文件的情况下调用Makefile或其他任何针对diff问题的解决方案?
约翰内斯

只需使用两个临时文件,这或多或少是过程替换方法在幕后所做的。
Kusalananda

3
您也SHELL可以/bin/bash在Makefile中设置为。
斯蒂芬·基特

1
@Johannes Kusalananda's在回答中添加了信息,这很棒,因为它提供了许多选项以及可以使用它们的情况。我希望您接受这个答案...(但我很感激!)
Stephen Kitt

2
使用SHELL变量不符合POSIX的信息非常有帮助。也许还是更好用bash -c
约翰内斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.