Gnu-Make

在 makefile 配方中找不到變數

  • August 20, 2020

為什麼這個簡單的食譜不起作用?

.PHONY: test
test:
   foo := $(shell ls | grep makefile) ;\
   echo $(foo)

結果是

$> make test
makefile:65: warning: undefined variable 'foo'
foo := makefile ;\
echo 
/bin/sh: 1: foo: not found

那麼,據我了解,該變數foo已正確設置為 value makefile,但之後不能使用?但是,它是一個單行命令,在同一個 shell 中執行?

但是,這有效

@$(eval export foo := $(shell ls | grep makefile)) \
echo $(foo)

所以我猜想第一個例子中的變數是不可訪問的,因為在我們嘗試echo?

如果我再深入一點,如何完成這項工作

.PHONY: test
test:
   @$(eval export files = $(shell ls))
   for f in $(files) ; do \
       t = $(ls | grep $$f) ; \
       echo $$t;\
   done

我看了你的循環……這裡引用:

.PHONY: test
test:
   @$(eval export files = $(shell ls))
   for f in $(files) ; do \
       t = $(ls | grep $$f) ; \
       echo $$t;\
   done

所以……$(eval ... )在make中執行一個命令。

$(shell ls)在 shell 中執行命令ls,並替換它的輸出。

因此,由 執行的命令$(eval ... )類似於export files = file file2 makefile source.c. 此命令生成一個名為 files 的 make 變數並將其導出到子 make。因此,可能不需要導出。

整個$(eval ... )可能會被替換為files = $(wildcard *) 並且它可能會使用:=並被放置在規則之外。

for循環,四行,在 shell 中執行。完成的第一件事是替換 make 變數和函式。奇怪的是$(ls | grep $$f)。由於 ls 不是一個 make 函式,這將嘗試擴展一個未定義的變數。這是一個空字元串。如果這是外殼的$(...)運算符,則需要將 $ 加倍。 $$擴展為$$(files)基於評估擴展。

這變成(使用我之前的範例):

for f in file file2 makefile source.c ; do
   t =
   echo $t;
done

乍一看,這可能會呼應四個空行,但不是。該命令t =實際執行程序t並將等號作為參數傳遞。 t可能不存在。因此,我們得到 t 不是有效程序的四個錯誤,每個錯誤後跟一個空行(除非 t 在其他地方定義)。

更接近您想要的東西可能是:

files := $(wildcard *)
.PHONY: test
test:
   for f in $(files) ; do \
       t=$$(ls | grep $$f) ; \
       echo $$t ; \
   done

這將輸出:

file file2
file2
makefile
source.c

請注意,第一行列出了兩個文件,因為它們的名稱中都包含“文件”。如果這不是您想要的,您可以考慮:

files := $(wildcard *)
.PHONY: test
test:
   for f in $(files) ; do \
       echo $$f ; \
   done

甚至(可能是 GNU 特定的):

files := $(wildcard *)
.PHONY: test
test:
   $(foreach f, $(files), echo $f ; )

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