Bash

GNU Makefile 中的程序替換

  • January 14, 2021

在 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 時shbash將在 POSIX 模式下執行(就像POSIXLY_CORRECT已定義,或者它以 開頭--posix)。

在這種模式下,不存在程序替換。

解決方案:

  1. 使用顯式臨時文件:
all:
   command1 >tmpfile
   command2 | diff tmpfile -
   rm -f tmpfile
  1. 使用bash -c內聯腳本:
all:
   bash -c 'diff <(command1) <(command2)'
  1. 將 Makefile 變數定義SHELL/bin/bash(或系統上的任何路徑bash):
SHELL=/bin/bash

如果您想要便攜性,請使用第一個解決方案。如果您對 的依賴沒問題bash,請選擇第二個。如果您另外不需要關心非 GNUmake實現,請使用第三個。


關於設置SHELL: POSIX 標準規定 Makefiles 中的執行檔應由system()C 庫函式呼叫make。這個函式不保證使用SHELL環境變數(事實上,標準不鼓勵這樣做)。該標準還說設置 Makefile 變數SHELL不應該影響環境變數 SHELLmake然而,在我所知道的大多數實現中,Makefile 變數SHELL將用於執行命令。

該實用程序的基本原理中make的建議是使用bash -c

省略了歷史MAKESHELL特徵和其他實現提供的相關特徵。make在某些實現中,它用於讓使用者覆蓋要用於執行make命令的 shell。這令人困惑;對於可移植make的,shell 應該由 makefile 編寫者選擇。此外,makefile writer 不能要求使用備用 shell,並且仍然認為 makefile 是可移植的。雖然可以標準化指定備用 shell 的機制,但現有實現不同意這種機制,並且 makefile 編寫者已經可以通過在規則中為目標指定 shell 名稱來呼叫備用 shell;例如:

python -c "foo"

引用自:https://unix.stackexchange.com/questions/356535