2010-03-10 60 views
8

我正在嘗試爲我的Makefiles創建一個通用構建模板,有點像他們在eval documentation中討論的那樣。

我似乎無法得到通配符函數在eval中工作。我遇到的基本代碼看起來像這樣。

SRC_DIR = ./src/ 

PROG_NAME = test 

define PROGRAM_template 
    $(1)_SRC_DIR = $(join $(SRC_DIR), $(1)/) 
    $(1)_SRC_FILES = $(wildcard $$($(1)_SRC_DIR)*.c) 
endef 

$(eval $(call PROGRAM_template, $(PROG_NAME))) 

all: 
    @echo $(test_SRC_DIR) 
    @echo $(test_SRC_FILES) 
    @echo $(wildcard $(wildcard $(test_SRC_DIR)*.c) 

當我運行與這,輸出

./src/test 

[correct list of all .c files in ./src/test/] 

基本上,內PROGRAM_template通配符通話不被我希望它eval'd。通話結果爲空列表。
雖然正在評估聯合調用。

那麼,我做錯了什麼?我的猜測是

$$($(1)_SRC_DIR) 

是不正確的,但我無法弄清楚正確的做法。

編輯 一旦解決了這個問題,我花了很長時間才用eval來打另一個問題。 我張貼它作爲一個新的問題,在 Workaround for GNU Make 3.80 eval bug

回答

10

你需要加倍逃避幾乎所有的函數和變量,當您使用eval。在大多數情況下,不必需要雙重轉義的函數參數(因爲call函數將完全展開它們)。在這種情況下,您在技術上不需要雙重轉義joinSRC_DIR,但如果您在使用eval時總是雙重轉義所有變量和函數,它將簡化您的生活。

您需要雙重轉義的原因是當使用eval時,擴展發生兩次eval函數本身執行擴展,然後當塊最後被解析爲makefile語法(即,實際評估時)時再次擴展

你寫的方式,wildcard被調用的字符串文字$(test_SRC_DIR)*.c。如果你願意,你可以在你的版本中用info代替wildcard,看看會發生什麼。

你需要暫緩實際調用wildcard,直到第二膨脹,使得它的說法是$(test_SRC_DIR)擴張的結果。

試試這個:

SRC_DIR = ./src/ 

PROG_NAME = test 

define PROGRAM_template 
    $(1)_SRC_DIR = $$(join $$(SRC_DIR),$(1)/) 
    $(1)_SRC_FILES = $$(wildcard $$($(1)_SRC_DIR)*.c) 
endef 

$(eval $(call PROGRAM_template,$(PROG_NAME))) 

all: 
    @echo $(test_SRC_DIR) 
    @echo $(test_SRC_FILES) 
    @echo $(wildcard $(test_SRC_DIR)*.c) 

編輯:張貼在此之後,我想我會更好地測試它,以確保它的實際工作。在這樣做的時候,我發現了另一個問題。調用函數時,應避免在逗號和參數之間放置空格。它導致一個字面空格字符被前置到傳遞給該函數的參數,並導致意想不到的結果。我刪除了我的版本中函數調用後的逗號(雖然這對調用join來說不是問題,但我只是因爲這是一個很好的習慣纔去掉了這個空間)。

+0

謝謝! 我正準備評論它沒有用,然後我回來看到你的編輯。 看起來像 $(1)_SRC_DIR = $$(join $$(SRC_DIR),$(1)/) 也符合我的要求,但對於$(通配符)行,您需要$$。 – bengineerd 2010-03-11 02:20:27

+0

@bengineerd:是的,我已經澄清了我的答案。你不需要'join'和'SRC_DIR'上的雙重轉義,因爲只需一次擴展就可以完全擴展。但是,就像我說的那樣,只是總是使用雙重轉義,這會讓生活更輕鬆。當他們不需要時,他們不會傷害任何東西。 – 2010-03-11 02:23:43