2012-02-13 128 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

相关问题