2011-03-04 334 views
4

我試圖排除的main.cpp文件從文件列表進行編譯通過下面的規則來定義:Makefile。如何從編譯中排除一個特定的文件?

$(TMPDIRPATH)%.o: %.cpp 
    @echo compile $< 
ifneq ($(notdir $<), main.cpp) 
     @$(COMPILE.cpp) $(OUTPUT_OPTION) $< 
endif 

這種「ifneq」條件計算結果始終爲true,這是奇怪的。我究竟做錯了什麼?有沒有更好的方法來從明確的規則中排除一個文件?

回答

5

那是不是做的最好的辦法,但如果你沿着這些路線去做,把它寫成一個shell的條件,不使用GNU使條件語句:

$(TMPDIRPATH)%.o: %.cpp 
    @echo compile $< 
    @if [ $(notdir $<) != main.cpp ]; \ 
    then $(COMPILE.cpp) $(OUTPUT_OPTION) $<; \ 
    fi 

延續標記(反斜槓)是必要的。分號也是如此。在Shell被調用來解釋它們之前,前綴爲$的值將被擴展make。你可能不希望回聲在哪裏。您可能需要:

$(TMPDIRPATH)%.o: %.cpp 
    @if [ $(notdir $<) != main.cpp ]; \ 
    then echo compile $<; \ 
     $(COMPILE.cpp) $(OUTPUT_OPTION) $<; \ 
    fi 

我期望這樣做的方式是與要編譯的文件列表。使用任何通配符機制會導致在添加額外文件時出現問題 - 其他測試或不屬於系統的雜散文件。


的評論說, 「但GNU Make使用手冊說:ifneq應該工作。」

ifneq將工作,如果它被正確定位,這意味着'不作爲與規則相關的命令的一部分縮進'。你可以,因此,喜歡寫東西(一個令人吃驚壞的榜樣,但我的大腦的弗裏茨):

ifneq (${CFLAGS}, -Wall) 
CFLAGS += -Wall 
endif 

file1.o: file1.c 
    ${CC} ${CFLAGS} -c $< 

但當ifneq縮進作爲的問題,它只是其實並不是一個命令在make運行shell來處理命令時在系統上找到。

+0

它的工作原理。但我對「ifneq」業務感到十分困惑。它應該按照gnu make手冊工作。感謝您的提示。不幸的是,我不知道哪些文件是相關的,不能明確地指定它們。這不是我的項目。只是試圖振興許多月前的構建腳本。謝謝一堆。 – bioffe 2011-03-04 05:12:20

+0

@bioffe:我試圖解釋答案中的額外信息。 – 2011-03-04 05:24:53

+0

我想到了縮進方面,並在我的代碼中修復了它。它不會失敗,但總是評估爲真。剛剛幾分鐘前更新了這個問題。 – bioffe 2011-03-04 05:40:48

2

Make並沒有真正有效的方法來處理規則中的條件。你可以把有條件的命令,但在這種情況下,有一個更清潔的方式:

$(TMPDIRPATH)main.o: 
    @echo compile $< (but not really) 

$(TMPDIRPATH)%.o: %.cpp 
    @echo compile $< 
    @$(COMPILE.cpp) $(OUTPUT_OPTION) $< 

編輯:
我不知道你沒有一個main.cpp。解決方法很簡單:刪除main.cpp作爲main.o規則的先決條件(我已將其刪除)。現在makefile不需要它,並且不會嘗試構建它。

但是你仍然在運行規則,這意味着某些東西仍然在嘗試構建main.o,作爲明確的目標或其他某些東西的先決條件。這是混亂的症狀,對makefile的這種改變不會修復。如果您告訴我們更多有關情況的信息,也許我們可以提出更好的解決方案。什麼要求main.o?你有沒有main.o?您打電話給Make時指定了什麼目標?

+0

make:***目標'main.cpp'沒有規則,'tmp/main.o'需要。停止。 命令/ usr/bin/make失敗,退出代碼2 – bioffe 2011-03-04 04:55:44

+0

我真的不太瞭解'Make'。看起來這個腳本想要馬上執行main.cpp。我用'$(TMPDIRPATH)main.o:%.cpp'修復了這個規則,但是它無論如何都不處理main.cpp的情況。 – bioffe 2011-03-04 05:07:24

4

當make啓動並分析makefile時,ifneq行僅被評估一次。在這種情況下,$<爲空。

要獲得不同的行爲,針對通過您的模式規則相匹配的目標,你可以不喜歡

$(TMPDIRPATH)%.o: %.cpp 
    @echo compile $< 
    @$(if $(filter main.cpp,$<),$(COMPILE.cpp) $(OUTPUT_OPTION) $<) 

東西它可以幫助你在makefile作爲喜歡思考ifneq$(if)之間的差異C代碼中的#ifif()之間的差異。但是,退一步說,如果您不希望main.cpp按照此規則進行編譯,那麼您可能希望提供一個明確的規則,其中$(TMPDIRPATH)main.o作爲其目標,這將始終優於模式規則。或者,如果您不希望$(TMPDIRPATH)main.o在處得到,那麼您應該在:的正確視線範圍內尋找規則,然後將其從中刪除。

+0

感謝您分享Makefile內部工作 – bioffe 2011-03-04 20:23:43

8

爲什麼不嘗試使用filter-out text function如果您使用的是GNU Make。

返回文本中與模式字不匹配的所有以空格分隔的單詞,刪除匹配一個或多個單詞的單詞。這與過濾器功能完全相反。

例如,給定:

objects=main1.o foo.o main2.o bar.o 
mains=main1.o main2.o 

下面生成包含所有對象「主」不是文件的列表:

$(filter-out $(mains),$(objects)) 
+1

「返回文本中與模式字不匹配的所有以空格分隔的單詞,並刪除匹配一個或多個單詞的單詞。」這是最乾淨的答案 - 如果您將鏈接網站上的示例添加到答案中,這將非常有用。 – aaren 2014-12-21 21:54:32

+0

是@aaren我會更新我的答案 – 2014-12-22 17:31:42

相關問題