2014-03-31 59 views
0

我試圖設置一個Makefile來處理來自一組源的兩個不同的目標,並且我有點超出了我的元素。它絕大多數工作正常,但我的依賴結構被破壞,因此我不得不每次都進行完整的重新編譯。有削減下來示例如下:基於目標的Makefile中的不同依賴位置

first: OBJDIR = obj 
second: OBJDIR = obj-2 

SRCS = $(wildcard src/*.cc) 

OBJECTS = $(patsubst %.cc,$(OBJDIR)/%.o,$(SRCS)) 

first: CFLAGS = -g -Wall -Wextra -std=c++11 -MMD 
second: CFLAGS = -g -Wall -Wextra -std=c++11 -MMD -DCOMPILE_FLAG 

$(OBJDIR)/%.o: %.cc 
    @mkdir -p $(OBJDIR)/src 
    clang++ -c $(CFLAGS) -o $(OBJDIR)[email protected] $< 

#DEPENDENCIES AREN'T WORKING PROPERLY 
-include $(OBJECTS:.o=.d) 

first: $(OBJECTS) 
    clang++ -o gen/first $(OBJECTS) 

second: $(OBJECTS) 
    clang++ -o gen/second $(OBJECTS) 

如果我將first:可執行代下@echo $(OBJECTS:.o=.d)(或因爲它是在編譯步驟中使用),它正確地擴展到/obj/src/filename.d。但是,當它在包含行中時,它僅顯示爲/src/filename.d。顯然.d文件不存在於該位置,所以它找不到它們並執行完整的重新編譯。

Makefiles並不是我經驗豐富的東西,所以如果有更好的方法來完成上述任何事情,我就會全神貫注。但關鍵點是能夠從同一個源擁有兩組目標文件和兩組依賴項。

-

要澄清的最終目標是什麼,我是一組用於建立兩個獨立的可執行文件,通過#ifdef小號處理的差異源文件。

我想從makefile結構中得到的是帶有兩個目標的單個makefile。每個目標都會生成自己的.o/.d文件,以便在對源進行更改時,我可以運行make firstmake second以生成兩個新的可執行文件,而無需從頭開始重新編譯所有文件。我之前通過使用兩個獨立的makefile來處理這個問題,但這似乎是錯誤的。

回答

0

你已經錯過了關鍵的一句相關GNU make manual瞄準特定的變量:

與自動變量,這些值僅是一個目標的配方內獲得

這意味着您無法在目標列表或先決條件列表中使用特定於目標的變量:此處使用的任何變量始終都具有全局值,並且永遠不會具有目標特定值。類似地,include行將在讀入makefile時被解析:這裏根本沒有目標上下文,因此全局值被使用。此外,任何時候當你在一個makefile文件中看到ANY規則正在創建一個不完全是[email protected]的文件,而是對其進行一些修改時,這是一個紅旗,你知道你有一個問題:-o $(OBJDIR)[email protected]是錯誤的。

一般來說,這個makefile有很多錯誤,但並不完全清楚你在這裏要做什麼。也許如果你退後一步並描述你想達到的目標,我們可以給你一些指示。

+0

啊,是的,我顯然做到了。這就回答了爲什麼它不起作用的主要問題。至於其他方面,我對你的最後一段並不感到驚訝。請參閱我的編輯進一步澄清。 –

0

我相信答案只是重新思考我這樣做的方式。我已經重寫Makefile文件如下(修剪出任何東西無關),從MadScientist閱讀了大量的Makefile文件,並考慮到一些意見後:

CC  = clang++ 
SRCS = $(wildcard src/*.cc) 
OBJECTS = $(patsubst %.cc,$(OBJDIR)/%.o,$(SRCS)) 
CFLAGS = -g -Wall -Wextra -std=c++11 -MMD 

.PHONY: all clean run 

all: $(EXECUTABLE) 

-include $(OBJECTS:.o=.d) 

$(EXECUTABLE): $(OBJECTS) 
    @mkdir -p gen 
    $(CC) -o gen/$(EXECUTABLE) $(OBJECTS) 

$(OBJDIR)/%.o: %.cc 
    @mkdir -p $(@D) 
    $(CC) -c $(CFLAGS) $(CMDFLAGS) -o [email protected] $< 

clean: 
    rm -rf obj obj-2 gen 

run: 
    cd gen && ./$(EXECUTABLE) 

從那裏,我做了幾個別名我。bash_profile:

alias mfirst="make OBJDIR=obj EXECUTABLE=first" 
alias msecond="make OBJDIR=obj-2 CMDFLAGS=-DCOMPILE_FLAG EXECUTABLE=second" 

因爲變量現在設置在任何目標規範之外,所以一切都很好。它將目標文件和依賴關係分開,並且別名仍允許快速使用(例如,包括mfirst run)。

隨意指出這裏的任何缺陷,但我對結果相當滿意。