2016-11-24 87 views
2

我的makefile失敗。我的想法是從某個文件中提取文件並將它們放在一個臨時目錄中。然後將它rsync到一個源目錄。由於rsync只在文件更改時更新,因此除非必要,否則源目錄中的makefile不會重新制作。我已經分離出以下問題:Makefile多目標vs分離目標給出不同的結果

.PHONY: extract clean 

FILES = filea1.cc filea2.cc filea3.cc      \ 
     filea1.hh filea2.hh filea3.hh      \ 
     filea1.py filea2.py filea3.py      \ 
     dir-cc/filea1.cc dir-cc/filea2.cc dir-cc/filea3.cc \ 
     dir-cc/filea1.hh dir-cc/filea2.hh dir-cc/filea3.hh \ 
     dir-py/filea1.py dir-py/filea2.py dir-py/filea3.py 

PATTERN := $(sort $(addprefix build/%., $(patsubst .%,%,$(suffix $(FILES))))) 

extract: $(addprefix build/, $(FILES)) 

$(PATTERN): 
    mkdir -p $(dir [email protected]); echo "hello!" > [email protected] 

#build/%.cc:;mkdir -p $(dir [email protected]); echo "hello!" > [email protected] 
#build/%.hh:;mkdir -p $(dir [email protected]); echo "hello!" > [email protected] 
#build/%.py:;mkdir -p $(dir [email protected]); echo "hello!" > [email protected] 

temp: 
    echo $(PATTERN) 

clean: 
    rm -rf build 

這樣做使溫度得到 '編譯/%CC編譯/%HH建立/%PY',而是 '使提取物',無法使所有的文件:

build: 
dir-cc dir-py filea1.cc filea2.cc filea3.cc 

build/dir-cc: 
filea1.cc filea2.cc filea3.cc 

build/dir-py: 
filea1.py filea2.py filea3.py 

hh文件丟失。令人難以置信的是,在實際工作中,cc文件丟失了。總之,註釋掉$(模式),並移除了註釋,所以在上面的代碼中的目標是獨立的,並得到所有的文件:

build: 
dir-cc filea1.cc filea1.py filea2.hh filea3.cc filea3.py 
dir-py filea1.hh filea2.cc filea2.py filea3.hh 

build/dir-cc: 
filea1.cc filea1.hh filea2.cc filea2.hh filea3.cc filea3.hh 

build/dir-py: 
filea1.py filea2.py filea3.py 

因爲一切都必須在實際工作中自動和規則對於所有目標都是一樣的(所以我不應該重新輸入),我非常喜歡第一個版本。我閱讀手冊,但我爲什麼要這樣做感到困惑。我正在使用GNU Make 4.1。

回答

1

它在Pattern Intro節的最後一段解釋:

模式規則可能有一個以上的目標。與一般規則不同,這不具有許多具有相同先決條件和配方的不同規則。如果一個模式規則有多個目標,就知道規則的配方負責製作所有的目標。該配方僅執行一次以製作所有目標。

您不能編寫具有許多不同模式目標的模式規則,例如make會爲每個目標運行一次配方。這不是它的工作原理。

你能做到這一點,您很簡單的例子:

FILETYPES := $(sort $(suffix $(FILES))) 

$(foreach T,$(FILETYPES),$(eval build/%$T: ; mkdir -p $$(@D); echo "hello!" > [email protected])) 
+0

Duh。謝謝。幫助很多。儘管如此,仍然令人困惑。這個配方似乎已經運行了不止一次,因爲這個配方可以解釋mkdir -p build /;回聲「你好!」 > build/filea1.cc mkdir -p build /;回聲「你好!」 > build/filea2.cc mkdir -p build /;回聲「你好!」 > build/filea3.cc mkdir -p build/dir-cc /;回聲「你好!」 > build/dir-cc/filea1.cc ... – user2747939

+0

當然,它對每個_matching pattern_都運行一次。也就是說,它會爲'build/filea1.cc'運行一次,但希望一次運行這個配方也會在目標列表中創建其他模式:'build/filea1.hh'和'build/filea1.py ',所以它不會試圖單獨建立這些。但是make並不認爲運行該模式會創建可能與這些模式匹配的所有可能文件。 – MadScientist

+0

好的,所以它可能會這樣說,對於遇到這種情況的其他人:模式規則可能有多個目標。與一般規則不同,這不具有許多具有相同先決條件和配方的不同規則。如果一個模式規則具有多個目標,則在每次運行配方時,make假定在該配方的該運行中的多個目標列表中匹配的所有目標都已建立。應該注意的是,配方實際上確實構建了所有這些目標,因爲只能嘗試構建任何目標一次。 – user2747939

0

有一個很好的解決方法:使用普通(非模式)多目標 規則$(FILES):;rule並定義模式中的特定變量值調整 的規則到文件擴展名。