2017-02-02 24 views
-1

我試圖建立一個GNU讓Canned Recipe,就像這樣:爲什麼我不能建立在GNU的變量使「定義」指令

define this-will-fail 
my_var=1 
$(info your variable is $(my_var)) 
endef 

$(this-will-fail) 

這將導致一個錯誤*** missing separator. Stop.

然而,以下按預期工作:

define why-does-this-work 
$(eval my_var=1) 
$(info your variable is $(my_var)) 
endef 

$(why-does-this-work) 

印刷your variable is 1

我正在查看AOSP's build system,並經常看到evaldefine搭配使用的用法。這兩個項目之間有什麼關係,爲什麼在使用define時爲什麼不能「正常」創建變量?

+0

罐裝配方文件片段,而不是Make(實際上,Make context中的「recipe」這個詞總是意味着「規則的shell代碼部分」)。 –

+0

@MichaelLivshin謝謝,那是我需要清除所有混亂的珍聞。如果您想將其作爲「答案」發佈,我會很樂意接受 – Hamy

回答

0

答案從簡單的點與大後果莖 - 一個makefile,有兩種方言,1)make語言本身和2)您使用的東西,如調用gcc的shell語言。

正常使「規則」語法的提醒:

targets : prerequisites 
     recipe 

雖然make目標和先決條件是使 語法,在配方中的東西是在shell語法,不作語法

這就解釋了爲什麼你不能做這樣分配的東西使變量作爲配方的一部分,像這樣:

all: the_dependencies_of_all 
    this_will_not_work := because_the_shell_does_not_know_what_this_line_means 

在shell語法位,使不三種特殊的文本操作,然後將剩餘的字符串逐字地傳遞給殼。這三個步驟是

  1. 處理逃脫換行符(如反斜線後跟換行符)
  2. 運行任何使函數(如$(filter ....)$(eval ..)
  3. 擴展任何使目標變量(如[email protected]

在正常情況下,這個3步 - 然後shell過程每個配方行發生一次,所以你的makefile配方的每一行都運行在不同的shell中(因此爲什麼有些調用make會產生許多/bin/sh子流程)。

上面的操作#2解釋了爲什麼您可以在配方中使用eval以在配方中添加一些make語法。 Eval將變成一個空字符串,這將不會導致shell的問題,但make會評估你的語句中的字符串,所以像變量定義這樣的東西是可能的。

這個評估發生的確切時刻有點棘手 - 這似乎是在變量首次展開時發生的,它本身取決於您在makefile中引用該變量的位置。也許有人可以多一點,澄清這一點,因爲當發生這種情況一直使用該-j標誌並行

更多信息運行多個配方系化妝的調用後果:

相關問題