簡體   English   中英

makefile 中的多行 bash 命令

[英]Multi-line bash commands in makefile

考慮到每個命令都在自己的 shell 中運行,在 makefile 中運行多行 bash 命令的最佳方法是什么? 例如,像這樣:

for i in `find`
do
    all="$all $i"
done
gcc $all

您可以使用反斜杠進行換行。 但是請注意,shell 接收連接成一行的整個命令,因此您還需要用分號終止某些行:

foo:
    for i in `find`;     \
    do                   \
        all="$$all $$i"; \
    done;                \
    gcc $$all

但是,如果您只想獲取find調用返回的整個列表並將其傳遞給gcc ,則實際上不一定需要多行命令:

foo:
    gcc `find`

或者,使用更傳統的$(command)方法(注意$轉義):

foo:
    gcc $$(find)

如問題所示,每個子命令都在自己的 shell 中運行 這使得編寫非平凡的 shell 腳本有點混亂——但這是可能的! 解決方案是將您的腳本合並為 make 將考慮單個子命令(單行)的內容。

在 makefile 中編寫 shell 腳本的技巧:

  1. 通過替換為$$逃避腳本對$的使用
  2. 通過插入將腳本轉換為單行; 命令之間
  3. 如果要在多行上編寫腳本,請使用\\轉義行尾
  4. 可以選擇以set -e開頭以匹配 make 的規定以在子命令失敗時中止
  5. 這完全是可選的,但您可以用(){}將腳本括起來以強調多行序列的內聚性——這不是典型的 makefile 命令序列

這是一個受 OP 啟發的示例:

mytarget:
    { \
    set -e ;\
    msg="header:" ;\
    for i in $$(seq 1 3) ; do msg="$$msg pre_$${i}_post" ; done ;\
    msg="$$msg :footer" ;\
    echo msg=$$msg ;\
    }

ONESHELL 指令允許編寫要在同一個 shell 調用中執行的多行配方。

all: foo

SOURCE_FILES = $(shell find . -name '*.c')

.ONESHELL:
foo: ${SOURCE_FILES}
    FILES=()
    for F in $^; do
        FILES+=($${F})
    done
    gcc "$${FILES[@]}" -o $@

但是有一個缺點:特殊前綴字符(“@”、“-”和“+”)的解釋不同。

https://www.gnu.org/software/make/manual/html_node/One-Shell.html

當然,編寫 Makefile 的正確方法是實際記錄哪些目標取決於哪些來源。 在微不足道的情況下,建議的解決方案將使foo依賴於自身,但當然, make足夠聰明,可以刪除循環依賴。 但是如果你在你的目錄中添加一個臨時文件,它會“神奇地”成為依賴鏈的一部分。 最好一勞永逸地創建一個明確的依賴項列表,也許通過腳本。

GNU make 知道如何運行gcc以從一組.c.h文件中生成可執行文件,所以也許您真正需要的就是

foo: $(wildcard *.h) $(wildcard *.c)

只調用命令有什么問題?

foo:
       echo line1
       echo line2
       ....

對於您的第二個問題,您需要使用$$來轉義$ ,即bash -c '... echo $$a ...'

編輯:您的示例可以重寫為這樣的單行腳本:

gcc $(for i in `find`; do echo $i; done)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM