2012-02-13 104 views
0

我正在嘗試創建一個Makefile以便在子目錄中生成目標文件,而不是讓它們在src /文件夾中。 下面是該項目的結構:使用Makefile在子目錄中生成目標文件

Trunk 
- Server 
    - src/ 
    - include/ 
- Common 
    - src/ 
    - include/ 

Makefile文件位於Trunk/Server。源文件位於無論是在Server/srcCommon/src,所以Makefile中目前有這樣的事情:

SRC  =  src/main.cpp     \ 
        src/Network.cpp    \ 
        ../Common/src/SQLManager.cpp \ 
        ../Common/src/Utils.cpp 

我woud喜歡把生成的目標文件在各自obj文件夾,因此Trunk/Server/objTrunk/Common/obj。我怎樣才能做到這一點?我發現了許多方法來在子目錄中生成目標文件(vpath,patsubst等等),但我無法讓它們中的任何一個適用於此文件夾組織。

編輯:如果有一種方法可以將所有的目標文件放入Server/obj/,那也可以。

下面是完整的Makefile文件(減去一些源文件和鏈接庫): EDIT2:更新與迪迪埃Trosset的變化

CXX    =  g++ 

RM    =  rm -vf 

NAME   =  Server 

SRC    =  src/main.cpp     \ 
         src/Network.cpp    \ 
         ../Common/src/SQLManager.cpp \ 
         ../Common/src/Utils.cpp 

OBJ    =  $(subst src/,obj/, $(subst .cpp,.o, $(SRC))) 

LDFLAGS   =  -lpthread -lm 

CPPFLAGS  =  -std=c++0x -pedantic -Wextra -Wall -Wconversion -Iinclude -I../Common/include 

all: Server 

%.o: %.cpp 
     $(CXX) $< -o [email protected] 

Server: $(OBJ) 
     $(CXX) -o $(NAME) $(OBJ) $(LDFLAGS) 

clean: 
     $(RM) $(OBJ) *~ 

fclean: clean 
     $(RM) $(NAME) 

re: fclean Server 

.PHONY: all clean fclean Server 
+0

這樣的問題幾乎每隔一週就會被問到。您是否嘗試過搜索,如果可以,您能解釋爲什麼/如何回答這些問題不適合您? – eriktous 2012-02-13 14:13:20

+0

我曾嘗試搜索,並閱讀這些答案:http://stackoverflow.com/questions/5178125/gnu-make-how-to-get-object-files-in-separate-subdirectory,http:// stackoverflow.com/questions/231229/how-to-generate-a-makefile-with-source-in-sub-directories-using-just-one-makefil。但是文件夾結構不完全相同,Makefile通常根本不起作用(找不到'.cpp',錯誤的命令行...) – Jukurrpa 2012-02-13 14:21:16

+0

另一個問題:爲什麼你認爲這個問題出現了經常這樣做,爲什麼你認爲Makefile通常不起作用?這個方案只有固有的問題;模式規則因爲需要在正確的目錄前面加上前綴而崩潰。爲了保持你的Makefile和你自己的理智,不要這樣做。堅持[Paul的第三條Makefiles規則](http://mad-scientist.net/make/rules.html),或者遷移到更高級的構建系統。 – eriktous 2012-02-13 15:11:14

回答

2

根據這些定義,subst應該用來替代目錄的src部分,和文件擴展名。

OBJ = $(subst src/,bin/,$(subst .cpp,.o,$(SRC))) 

然後,你必須添加新的模式規則來編譯你的源文件。 (你必須編寫每個目錄下你的源文件是一個模式規則。)

obj/%.o: src/%.cpp 
     $(CXX) -c $< -o [email protected] 

../Common/obj/%.o: ../Common/src/%.cpp 
     $(CXX) -c $< -o [email protected] 
+0

我試過了(在'subst'後刪除多餘的逗號後),它似乎使GCC在'obj /'中查找'.cpp'文件而不是'src /'...我得到了一個'no rule使目標錯誤。 – Jukurrpa 2012-02-13 13:03:27

+0

@Jukurrpa感謝您的逗號。另外,你的Makefile的其餘部分是什麼。你在這裏張貼的是不夠的!你需要其他目標,至少要鏈接你的對象。 – 2012-02-13 16:17:10

+0

是的,我沒有指定'通常'的規則,例如調用'$(OBJ)',然後鏈接所有對象。我可以將它們添加到我原來的帖子,如果這可以幫助您找到解決方案:) – Jukurrpa 2012-02-14 12:46:13

0

我不知道這會工作,但我會嘗試這樣的:

OBJ := $(join $(addsuffix ../obj/,$(dir $(SRC))),$(notdir $(SRC)) 
# or, as Didier suggested: 
# OBJ := $(subst src/,obj/,$(SRC)) 

%.o: ../src/%.cpp 
    $(CXX) $< -o [email protected] 
+0

我得到了與Didier Trosset的方法相同的錯誤。它使GCC在'obj /'文件夾中尋找'.cpp'文件。 – Jukurrpa 2012-02-13 13:26:22

0

這不是清楚你正在嘗試做什麼,但這應該接近:

OBJ = $(subst src/,obj/,$(SRC:.cpp=.o)) 

obj/%.o : src/%.cpp 
    $(CXX) $< -o [email protected] 

../Common/obj/%.o : ../Common/src/%.cpp 
    $(CXX) $< -o [email protected] 
+1

我想,你的意思是'%.cpp'而不是'* .cpp',不是嗎? – 2012-02-14 19:39:50

+0

@EldarAbusalimov,Ack!是。謝謝。 – Beta 2012-02-14 20:18:54

+0

這適用於位於'src /'中的文件,但不適用於'../ Common/src'中的文件。我試圖將源文件和規則的路徑更改爲'./src/',因此兩者之間沒有歧義,但它不起作用。 – Jukurrpa 2012-02-15 13:39:21