Bash
GNU Makefile 中的程序替換
在 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)'
這是什麼意思,有沒有辦法在不使用臨時文件的情況下仍然區分兩個輸出?
/bin/sh
可能bash
在您的系統上,但是當呼叫 as 時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 標準規定 Makefiles 中的執行檔應由system()
C 庫函式呼叫make
。這個函式不保證使用SHELL
環境變數(事實上,標準不鼓勵這樣做)。該標準還說設置 Makefile 變數SHELL
不應該影響環境變數SHELL
。make
然而,在我所知道的大多數實現中,Makefile 變數SHELL
將用於執行命令。省略了歷史
MAKESHELL
特徵和其他實現提供的相關特徵。make
在某些實現中,它用於讓使用者覆蓋要用於執行make
命令的 shell。這令人困惑;對於可移植make
的,shell 應該由 makefile 編寫者選擇。此外,makefile writer 不能要求使用備用 shell,並且仍然認為 makefile 是可移植的。雖然可以標準化指定備用 shell 的機制,但現有實現不同意這種機制,並且 makefile 編寫者已經可以通過在規則中為目標指定 shell 名稱來呼叫備用 shell;例如:
python -c "foo"