簡體   English   中英

Makefile中shell命令的使用方法

[英]How to use shell commands in Makefile

我正在嘗試在其他命令(例如 echo、rsync)中使用ls的結果:

all:
    <Building, creating some .tgz files - removed for clarity>
    FILES = $(shell ls)
    echo $(FILES)

但我得到:

make
FILES = Makefile file1.tgz file2.tgz file3.tgz
make: FILES: No such file or directory
make: *** [all] Error 1

我試過使用echo $$FILESecho ${FILES}echo $(FILES) ,但沒有成功。

和:

FILES = $(shell ls)

像這樣在下面縮進, all是一個構建命令。 所以這擴展$(shell ls) ,然后嘗試運行命令FILES...

如果FILES應該是make變量,則需要在配方部分之外分配這些變量,例如:

FILES = $(shell ls)
all:
        echo $(FILES)

當然,這意味着在運行任何創建 .tgz 文件的命令之前FILES將被設置為“從ls輸出”。 (盡管Kaz 指出變量每次都會重新擴展,因此最終它將包含 .tgz 文件;一些 make 變體具有FILES:=...以避免這種情況,以提高效率和/或正確性。1

如果FILES應該是一個 shell 變量,你可以設置它,但你需要在 shell-ese 中進行,沒有空格,並引用:

all:
        FILES="$(shell ls)"

但是,每一行都由一個單獨的 shell 運行,所以這個變量不會存活到下一行,所以你必須立即使用它:

        FILES="$(shell ls)"; echo $$FILES

這有點傻,因為 shell 首先會為你擴展* (和其他 shell glob 表達式),所以你可以:

        echo *

作為您的 shell 命令。

最后,作為一般規則(並非真正適用於此示例):正如世界語在評論中指出的那樣,使用ls中的output並不完全可靠(一些細節取決於文件名,有時甚至取決於ls的版本;某些版本的ls嘗試在某些情況下對 output 進行消毒)。 因此,作為l0b0idelic注釋,如果您正在使用 GNU make,則可以使用$(wildcard)$(subst...)來完成make自身內部的所有操作(避免任何“文件名中的奇怪字符”問題)。 (在sh腳本中,包括 makefile 的配方部分,另一種方法是使用find... -print0 | xargs -0來避免被空格、換行符、控制字符等絆倒。)


1 GNU Make 文檔進一步指出 POSIX make 在 2012 年添加了::=賦值 我沒有為此找到指向 POSIX 文檔的快速參考鏈接,我也不知道哪些變體支持::=賦值,盡管 GNU make今天支持,與:=具有相同的含義,即進行賦值現在隨着擴張。

請注意, VAR:= $(shell command args...)也可以拼寫為VAR.= command args...在幾個make變體中,包括據我所知的所有現代 GNU 和 BSD 變體。 這些其他變體沒有$(shell)因此使用VAR.= command args...在更短在更多變體中工作方面更勝一籌。

此外,除了 torek 的回答之外:突出的一件事是您正在使用延遲評估的宏分配。

如果您使用的是 GNU Make,請使用:=賦值而不是= 此賦值導致右側立即展開,並存儲在左側變量中。

FILES := $(shell ...)  # expand now; FILES is now the result of $(shell ...)

FILES = $(shell ...)   # expand later: FILES holds the syntax $(shell ...)

如果使用=賦值,則意味着$(FILES)的每次出現都將擴展$(shell...)語法,從而調用 shell 命令。 這將使您的 make 作業運行得更慢,甚至會產生一些令人驚訝的后果。

暫無
暫無

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

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