2013-02-24 65 views
11

摘要:
我使用GNU使(3.81)類Unix系統上,我碰到的一個問題,即$(wildcard, pattern)功能無法找到一個由(可能/顯然是?)先前執行的配方生成的文件,而其他程序(例如ls)能夠驗證它的存在。我想知道爲什麼通配符函數沒有返回任何東西,當它被擴展(到空字符串)時,以及如何找到它生成的文件。GNU使通配符功能無法找到運行時生成的文件

測試案例:
下面的測試案例說明了這個問題。
Makefile文件內容:

.PHONY: build clean 

test: 
    @echo "Creating test file 'test'." 
    @echo "this is a test file" > test 

build: test 
    @echo "Directory contents:" 
    @ls 
    @echo "Test file contents:" 
    @cat test 
    @echo "Wildcard output:" 
    @echo $(wildcard test) 

clean: 
    @rm -f test 

運行生成文件的兩倍(當時清理)顯示,僅在第二輪做它檢測所創建的文件。
輸出:

Creating test file 'test'. 
Directory contents: 
makefile test 
Test file contents: 
this is a test file 
Wildcard output: 

Directory contents: 
makefile test 
Test file contents: 
this is a test file 
Wildcard output: 
test 

重現:
保存在一個空的目錄生成文件,然後運行 ​​「make構建,使建設,使清潔」。

研究:
其中一個目標的先決條件是處理independent of the order in which they appear in the list after the colon,因此,如果要定義在他們處理的順序明確的相互依存關係的先決條件,必須引入的順序。

但是,我不認爲我可以剝奪依賴關係了; build取決於testtest對應於不存在並由其配方生成的文件。我推測它會在build的配方處理時出現。

根據我對製作文件解析的瞭解,配方內的通配符函數在處理之前不應展開。但是,我清楚地看到內置make功能的輸出和通過shell訪問的常見實用程序的輸出之間的區別,所以這種推測可能是錯誤的,但我還沒有遇到任何好的解釋發生在這裏,甚至不在GNU make手冊中。

N.B.這個問題的目的只是爲了理解與這個問題有關的通配符函數的工作原理;有一個實際的用例,我從中提煉出這個淡化版本,但我對這種情況更感興趣。

回答

4

GNU化妝執行其中任何之前擴大了目標的命令所有。在這種情況下,「擴展」的意思是「用所有變量的值(遞歸)替換所有變量的引用,並評估任何函數的引用。」當然,$(wildcard)是函數引用。由於擴展發生在任何命令執行之前,當然文件test找不到 - 它還沒有被創建。第二次運行構建時,已經存在test,因此$(wildcard)可以找到它。

關於你聲明的順序前提條件處理:技術上 GNU化妝不作任何有關訂單的保證,但實際講prereqs處理左到右,儘管試圖通過純粹主義者改變(唯一的目的是與沒有完全指定依賴關係的人打交道),GNU make的可能性實際上會改變實現的細節,而這個可能性非常小。 但是你只能真的依靠系列構建中的那個排序。如果你並行地運行這個版本,那麼事情會變得有點棘手:GNU make does仍然按照從左到右的順序處理prereqs,但它不再等待一個在開始下一個之前完成,所以實際上他們可能看起來是以隨機或「任意」順序處理的,這取決於inter-prereq依賴關係,這就是爲什麼指定這些依賴關係是一個好習慣。