2011-06-07 114 views
1

我正在嘗試使用遞歸make來消除像多個CFLAGS變量這樣的變量,每個目標都有一個變量。只有一個遞歸級別,這裏沒有發生瘋狂的目錄樹遍歷。我只想將我的對象文件轉儲到其特定目標文件夾中。遞歸問題

到目前爲止,我已經想出了一些非常優雅的東西(編輯:好吧,它比我以前的單一makefile解決方案更優雅,哪個方法太重複了!),但不幸的是不起作用。

我認爲,通過發佈格式在這裏,它會明白什麼是我想要做的。

# ./makefile 
.PHONY: all clean 

export CC = g++ 
export INCLUDE = -I ../include/ 
export SRC = Main.cpp Graphics.cpp Thread.cpp Net.cpp Otherstuff.cpp 
export LINKEROPT = -lglew32 -lopengl32 -lsdl -lws2_32 -lglu32 -lmorelibraries 

test: 
    $(MAKE) -f make.unittest 

all: 
    $(MAKE) -f make.unittest 
    $(MAKE) -f make.debug 
    $(MAKE) -f make.release 

clean: 
    -rm -rf build_* *.exe 
# I am on windows so the targets are .exe's 

這裏是文件make.debug:

### sub-makefile for the debug build target. Contains target specific build settings. 
DIRNAME = build_debug 
TARGETNAME = program_debug 
TARGETDESCR = DEBUG 
CFLAGS = -Wextra -Wall -O0 -g3 -DDEBUG 

### EVERYTHING AFTER THIS POINT IS A TEMPLATE 
# my goal is to have as much of my makefile code being "reusable" as possible 
# so that I can easily add targets. 

OBJ = $(patsubst %.cpp,$(DIRNAME)/%.o,$(SRC)) 
DEPS = $(patsubst %.cpp,$(DIRNAME)/%.d,$(SRC)) 
-include $(DEPS) 

# default behavior. Set up the build directory. Then build the debug target. 
all: $(DIRNAME) $(TARGETNAME) 

# this is the build dir 
$(DIRNAME): 
    mkdir $(DIRNAME) 

$(DIRNAME)/%.o: %.cpp 
    @echo -e "Compiling for $(TARGETDESCR): $< --> [email protected]" 
    $(CC) $(CFLAGS) $(INCLUDE) -c $< -o [email protected] 
    @echo -e "Generating dependencies: $< --> $(patsubst %.o,%.d,[email protected])" 
    $(CC) $(CFLAGS) $(INCLUDE) -MM -MT [email protected] -MF $(patsubst %.o,%.d,[email protected]) $< 
    # I realize there is a way to generate the deps while compiling in one pass 
    # but I'll figure it out later 

$(TARGETNAME): $(OBJ) 
    @echo -e "Linking $(TARGETDESCR): [email protected]" 
    $(CC) -L ../lib/win32/ -o [email protected] $(OBJ) $(LINKEROPT) 

正如你所看到的,我可以很快用自己的一套CFLAGS通過複製在子Makefile中添加一個新的構建目標和稍微修改它,然後在主makefile中添加一些條目。

所以這裏的問題是,它無法識別文件中的更改。只有當我編輯Main.cpp時,它纔會重新編譯build_debug/Main.o。我真的不確定我能從哪裏開始弄清楚什麼是不正確的。

+0

'main.d'是否按預期包含在內?修改該文件並在文件末尾添加'$(info included main.d ...)',並確保在嘗試重新構建時看到該消息。另外,請驗證.d文件包含您希望它包含的所有內容,並且所有路徑都是正確的。 – bta 2011-06-07 17:20:47

+0

要生成依賴關係並在一次編譯中添加'-MD'選項(http://www.gnu.org/software/gcc/news/dependencies.html)。 – bta 2011-06-07 17:30:31

回答

2

我創造了一個怪物。

當我在that other post中建議遞歸製作時,它是處理一個特殊的 - 非常奇怪的包含問題。我不贊同遞歸式純粹是邪惡的教條,但它確實有缺點,不應該被用作治癒所有的東西。

首先,讓我們消除一個不好的(和正在進行的)冗餘源。在你的makefile爲主,而不是

$(MAKE) -f make.debug 

使用

$(MAKE) -f makefile.sub DIRNAME = build_debug TARGETNAME = program_debug TARGETDESCR = DEBUG CFLAGS = -Wextra -Wall -O0 -g3 -DDEBUG 

其中makefile.sub是你的各種子的makefile的 「模板」 部分。我知道這看起來不像是一種改進,但這樣你只有一個子makefile,而不是N.(我也認爲你使用了太多的特定於目標的變量,但我們可以在以後討論它。)

一旦你適應了這一點,你可以在makefile.sub使用target-specific variables,所以在主makefile文件,你可以用

all: 
    $(MAKE) -f makefile.sub unittest debug release 

更換

all: 
    $(MAKE) -f makefile.sub DIRNAME=build_unittest ... 
    $(MAKE) -f makefile.sub DIRNAME=build_debug ... 
    $(MAKE) -f makefile.sub DIRNAME=build_release ... 

目前尚不清楚對我有什麼問題,你」重新識別文件中的變化(w如果Main.cc沒有改變,那麼母雞應該重建build_debug/Main.o?),但這可能是遞歸使用make的直接後果(參見上文的「缺點」),我們可以在不太痛苦的情況下修復它。

編輯:

在你的子生成文件,把all規則-include前行,所以,這將是默認的規則。當你打電話給$(MAKE)時,你沒有指定目標,所以Make選擇默認的目標,這通常是(無論哪個先來的)。 %.d文件的內容具有規則的形式,所以如果您include他們第一,其中一個(即build_debug/Main.o: Main.cpp)將贏得。

+0

謝謝Beta :) – 2011-06-07 16:38:48

+0

好吧,它似乎沒有識別什麼時候的東西改變。如果我刪除構建目錄中的每個目標文件,它們都會被重建。但是如果我刪除其中的一半,它不會認爲任何錯誤。直到我刪除Main.o(我懷疑這是因爲它是列表中的第一個元素)。此時Main.o被編譯。其餘的仍然失蹤。沒有鏈接發生。真的沒有任何意義。 – 2011-06-07 20:16:02