2015-04-22 60 views
1

我試圖理解GNU make的多行define指令,但我不能。例如:GNU make中的多行定義

define A 
1 
2 
endef 
all: 
    @echo W=$(word 1,$(A)) 

運行make產生一個結果我期望的最小:

W=1 
make: 2: Command not found 
make: *** [all] Error 127 

似乎的$(A)那部分具有$(word)功能外溢出。

這是一個錯誤或預期的行爲?如果「泄漏」是故意的,它是如何起作用的?

P.S. Linux/x64上的GNU make v3.81

回答

2

$(word)函數在空間上分割。不是空格,空格。

您的A宏中沒有空格,因此沒有任何分隔。

1行或2行上的前導空格中添加尾部空格,您將得到預期的行爲。

這在GNU make 3.81,3.82,4.0和4.1的一些快速測試中是一致的。

你看到「溢出」的原因就像你所說的那樣,是因爲定義被擴展了。它是從字面上擴展的,換行符和全部。 (Think template expansion。)

因此,將定義擴展到$(word 1,...)的調用中,然後將結果(包括換行符在內的整個定義)展開到配方模板中,最後以兩行作爲配方執行。

考慮這樣一個宏:

define somecommands 
echo foo 
echo bar 
echo baz 
endef 

all: 
    $(somecommands) 

什麼你希望發生在這裏? all的正文有多少行?這裏運行多少個shell?什麼命令被執行?答案是三行,三個shell和三個echo命令。

如果換行不計算在內,那麼你將有效地在一個命令運行echo foo echo bar echo baz並獲得foo echo bar echo baz作爲輸出,而不是預期(和有用得多)foobarbaz在三個不同的線路。

+0

我不是詢問'$(word)'函數。我要求解釋'make:2:Command not found'錯誤信息。我對如何/爲什麼「2」出現在函數外面並進入make的執行流程感興趣。這是我所問的問題。 – Dummy00001

+0

您問過「$(A)'的部分溢出$(word)函數外部」。我只是回答了這個問題......雖然我現在看到答案沒有在我寫的內容中得到充分解釋(儘管它在那裏)。等一下。 –

+0

不,這不是一個真正的答案。這基本上是官方(主題模糊)文件的推斷,根本沒有解決含糊不清的問題。我開始認爲這只是實現多行定義時的一個錯誤。例如,嘗試在'echo'命令的末尾添加分號並查看錯誤消息的更改方式。 (如果在Linux下,使用'strace -ff -e execve'運行以查看它的所有榮耀中的廢話。) – Dummy00001

4

這裏要記住的是,使將每個配方存儲爲單個遞歸變量。當使決定它必須運行你的配方時,它展開該變量。 製作然後將每個行傳遞到單獨的shell中,如果其中任何一個shell執行返回錯誤,則會停止。

在你的例子中,在運行任何東西之前使擴展@echo W=$(word 1,$(A))

  1. $(A)成爲1¶2(不知道這是什麼看起來像你的瀏覽器,但我使用表示換行符)
  2. 現在,1¶2是一個單詞儘可能使而言,所以$(word 1,1¶2)自然會擴大到1¶2(你能看到這裏還在哪裏嗎?)
  3. 這留下使與字符串@echo W=1¶2。盡責地將第一行傳遞給shell(沒有@,因爲這對而言是特殊的,使得)。該shell執行echo W=1
  4. 使執行2新的殼。
  5. 第二個shell聲稱它找不到命令2

所以,是的,預期的行爲。

[警告:在輕微簡化上面,我粉飾位,其中使能夠在的Elid外殼和調用命令本身如果字符串中有沒有shell字符]