2012-03-02 42 views
2

鑑於Makefile中的該位:如何在僅限訂單的先決條件內調用功能?

# for pattern matching 
$(OBJDIR) := build 

# just to see if a level of indirection will work 
my_dir = $(dir $(1)) 

$(OBJECTS) : $(OBJDIR)/% : $(HEADERS) $(SRCDIR)/% | % $(dir %) $(call my_dir,%) 
    @echo output-only = $| 

這是一個static pattern ruleorder-only prerequisites

考慮目標「build/utility/debug.js」。上述規則的輸出將是這樣的:

output-only = utility/debug.js ./ 
  • 第一組分,「實用程序/ debug.js」,被適當地從杆(%)複製。
  • 第二個組件「./」是在先決條件列表中調用dir函數的輸出。
  • 第三個組件是一個空字符串,是在先決條件列表中調用我的my_dir函數的輸出。

如果我改變my_dir這樣:

my_dir = $(1) 

輸出保持不變。如果我改變它:

my_dir = "foo" 

然後抱怨沒有規則,使「foo」(這是預期的)。那麼,看起來$(1)my_dir的調用中沒有受到約束。

發生了什麼事?爲什麼我不能將stem傳遞給函數?我有一個解決方法,使用二次擴展,但我想知道爲什麼我不能這樣寫我的規則。

編輯:我是新來的stackoverflow,原諒我,如果這不是事情在這裏完成的方式。正如Alex指出的那樣,我想把$(1)作爲參數傳遞給my_dir

我不知道爲什麼有人建議我要「$」。我不相信$在任何情況下都會擴展到任何事物。

我知道自動變量只在配方中可用。我在前提條件中沒有使用自動變量 - 我正在使用幹線:

每個目標都與目標模式相匹配,以提取名爲stem的目標名稱的一部分。將該詞幹代入每個prereq-patterns中以製作先決條件名稱(每個prereq-pattern中有一個)。 - the manual

的幹可通過例子證明的事實:單獨使用時,而不是在傳遞給函數的莖擴展​​到正確的值。

回答

2

如在this section of the GNU make manual中可以看到的那樣,在讀取階段期間,先決條件列表中的變量和函數引用被立即擴展。這意味着,在任何模式匹配完成之前,所以%還沒有特別的含義;它將被解釋爲兩個函數參考文字$(dir %)$(call my_dir,%)中的文字字符,兩者的結果都是./,它們在配方中對$|的引用進行合併。

我不知道任何其他的解決方法,比你已經發現的,即二次擴展。

+0

感嘆,okay.jpg。 :/ – 2012-03-02 15:36:54

2

注意$1不是一個特殊的變量,擴展到與模式規則(或靜態模式規則)有關的任何有趣的事情。在$(call ...)函數調用的用戶定義的宏的上下文中,$1變量僅具有唯一的行爲。

您想使用$*而不是$1; $*是一個自動變量,擴展到規則目標的主幹。

然而,在化妝的所有版本(包括化妝的POSIX標準清晰度),自動變量(包括$*$<[email protected]$^等)只能在配方的情況下可用。它們在目標或先決條件列表的上下文中不可用。有關更多詳細信息,請參閱GNU make manual section on Automatic Variables

正如你所建議的那樣,有一個由.SECONDEXPANSION僞目標啓用的GNU make-specific功能,它提供了一種避免這種限制的方法。

+0

不完全 - 他實際上希望宏'my_dir'中的'$ 1'是參數。他所犯的錯誤是你提出的另一點,即自動變量只能在配方的上下文中(而不是在目標或先決條件清單中)使用。 – 2012-03-02 06:10:09

+0

請參閱編輯我的問題。 – 2012-03-02 08:23:49

+0

對不起,我專注於'$(dir%)'的前提條件,而不是'$(call my_dir,%)'前提條件。而我的格式是錯誤的,所以'$ *'展開爲'$'。一個不好的答案。無論如何,eriktous給出的推理是正確的:在隱式規則匹配之前,當在** long **中讀取makefile時,target/prereq列表中的所有變量/函數都會立即擴展。這是POSIX所要求的。輔助擴展功能是爲了允許延遲擴展而創建的,直到後來隱式規則匹配時爲止。 – MadScientist 2012-03-02 13:43:17