2011-04-22 115 views
5

我使用define來創建一個宏。但是,在定義構造中,我無法創建變量。分配一個變量不會導致錯誤,但是當我稍後嘗試使用它時,它的值是空的。在makefile宏中定義變量(定義)

例如

####################################################### 
## JIDL_RULE 
## Macro to build and install PHP and JS files 
## from idl.json files 
####################################################### 
## param $(1) Full path to idl.json file 
## param $(2) Path to directory to copy PHP file into (relative to where make is run from) 
## param $(3) Path to directory to copy JS file into (relative to where make is run from) 
########################################################## 
define JIDL_RULE 
# Create the output directory if it doesn't exist 
$(2): 
    mkdir -p $(2) 

$(3): 
    mkdir -p $(3) 

# Rule to generate a PHP file. Notice that we have to prepend `pwd` 
$(call GENERATED_FILE,$(1),$(2),php): $(1) 
    $(PHPHOME)/bin/php -f $(JIDL2PHP) -- `pwd`/$$< $(DATADEF_HOME) > [email protected] 

# Rule to generate a JS file 
$(call GENERATED_FILE,$(1),$(3),js): $(1) 
    $(PHPHOME)/bin/php -f $(JIDL2JS) -- `pwd`/$$< $(DATADEF_HOME) > [email protected] 

# Add those generated files to the all target 
all:: $(call GENERATED_FILE,$(1),$(2),php) $(call GENERATED_FILE,$(1),$(3),js) $(2) $(3) 

# Remove generated files on clean: 
clean:: 
    -$(RM) -f $(call GENERATED_FILE,$(1),$(2),php) $(call GENERATED_FILE,$(1),$(3),js) 

# Rules to install generated files 
$(call PHP_RULE, $(call GENERATED_FILE,$(1),$(2),php)) 
$(call JS_RULE, $(call GENERATED_FILE,$(1),$(3),js)) 
endef 

您可以從上面的代碼中看到我複製線

$(call GENERATED_FILE,$(1),$(2),php)$(call GENERATED_FILE,$(1),$(3),js)從多個地方。所以,我想創建兩個變量作爲宏觀前兩個語句,就像這樣:

PHP_OUT_FILE := $(call GENERATED_FILE,$(1),$(2),php) 
JS_OUT_FILE := $(call GENERATED_FILE,$(1),$(3),js) 

但是,如果我嘗試以後(還是內部的定義)使用它們,就像$(PHP_OUT_FILE)$(JS_OUT_FILE),變量是空的。我很想能夠從我的宏中刪除重複項。我做錯了嗎?這不可能嗎?還有另一種方法可以做到嗎?

同時測試真題答案

我試圖eriktous的伊勢紫藤的做法,他們都「工作」。兩者都不會創建私有變量,只有全局變量,我可以,我只需要小心碰撞變量,我不能做任何遞歸調用(我沒有計劃)。

eriktous的方法存在的問題是,添加$$使得變量在外部被評估,也就是說,$$被輸出爲單個$並且只有在目標被調用時才被評估。因此,調用宏兩次將覆蓋它。

伊斯紫藤的方法確實做了我需要的。調用eval可以確保變量立即被聲明,因此在宏被撤銷時它是可用的並且被宏擴展。這確實意味着我無法在宏中將其設置爲兩個不同的值,但我也可以。

這是我用來測試它

define TEST 
$(eval INNERVAR := Blah $(1)) 
inner:: 
    echo Using EVAL: INNERVAR = $(INNERVAR) 
    echo 

endef 

define TEST2 
INNERVAR2 := Blah $(1) 
inner:: 
    echo Using double dollar sign: INNERVAR2 = $$(INNERVAR2) 
    echo 
endef 

$(eval $(call TEST,TEST_1_A)) 
$(eval $(call TEST,TEST_1_B)) 
$(eval $(call TEST2,TEST_2_A)) 
$(eval $(call TEST2,TEST_2_B)) 

inner:: 
    echo is that var really private? $(INNERVAR) 
    echo is that var really private? $(INNERVAR2) 

makefile文件而這裏的輸出:我ommitted是運行,以使其更容易看到報表作出的呼應。

Using EVAL: INNERVAR = Blah TEST_1_A 

Using EVAL: INNERVAR = Blah TEST_1_B 

# Calling the macro twice overwrites the global variable and since 
# it's not expanded immediately, calling the macro with different params 
# will output the last value that we set the variable to 
Using double dollar sign: INNERVAR2 = Blah TEST_2_B 
Using double dollar sign: INNERVAR2 = Blah TEST_2_B 

# As expected, the variables are not private to the macro. 
is that var really private? Blah TEST_1_B 
is that var really private? Blah TEST_2_B 
+0

爲什麼你不能使用更容易的模式規則來實現相同的任何特殊原因?好吧,這並不能回答這個問題,但我認爲你想找到一個解決方案來構建這些東西...... :) – 0xC0000022L 2011-04-22 00:15:28

+1

要解釋爲什麼,它不會幫助回答問題。我不是在尋求解決實際問題的幫助。只是一種在定義中定義局部變量的方法:) – 2011-04-22 00:22:09

+0

@STATUS_ACCESS_DENIED:讓我試着回答你的問題,也許不完全; idl.json文件位於多個文件夾中,不會複製到它們所在的文件夾中。每次對宏的調用都必須指定輸出目錄。請不要問我這是爲什麼:) – 2011-04-22 15:41:39

回答

9

是否將eval應用於如下所示的任務解決問題?

$(eval PHP_OUT_FILE := $(call GENERATED_FILE,$(1),$(2),php)) 
$(eval JS_OUT_FILE := $(call GENERATED_FILE,$(1),$(3),js)) 

希望這有助於

+0

它確實工作,真棒,謝謝,看我編輯與eriktous的方法比較。 – 2011-04-22 15:17:44

+0

謝謝,很高興幫助:-) _eriktous_的解決方案很有趣。 在稍有不同的情況下會有所幫助。 – 2011-04-22 19:42:37

5

我一直在這個實驗了一下,我想我現在明白make如下評價的順序。
伊勢紫藤提供了一個解決您的問題,我認爲應該工作。另一個是在引用變量時簡單地添加第二個$,如下所示:$$(PHP_OUT_FILE)

+0

這幾乎可以工作......如果我只調用一次宏,請參閱編輯以獲得解釋。我仍然非常感謝投入。 – 2011-04-22 15:17:27