
在 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"