源文件在不同目录中的Makefile

我有一个项目的目录结构是这样的:

$projectroot | +---------------+----------------+ | | | part1/ part2/ part3/ | | | +------+-----+ +---+----+ +---+-----+ | | | | | | | data/ src/ inc/ src/ inc/ src/ inc/ 

我应该如何编写一个部分在/ src(或真正在哪里)可以在/ c ++源文件/ / src中完成/链接的makefile?

我可以做一些像-I $ projectroot / part1 / src -I $ projectroot / part1 / inc -I $ projectroot / part2 / src …

如果这样做,有没有一个更简单的方法来做到这一点。 我见过每个相应部分都有makefile的项目吗? 文件夹。 [在这篇文章中,我用了bash语法中的问号]

传统的方法是在每个子目录( part1part2等)中都有一个Makefile ,允许您独立构build它们。 此外,在构build一切的项目的根目录中有一个Makefile 。 “根” Makefile将如下所示:

 all: +$(MAKE) -C part1 +$(MAKE) -C part2 +$(MAKE) -C part3 

由于make目标中的每一行都在其自己的shell中运行,所以不必担心遍历目录树或其他目录。

我build议看看GNU make手册第5.7节 ; 这是非常有帮助的。

如果你有一个子目录中的代码依赖于另一个子目录中的代码,那么最好在顶层使用一个makefile。

请参阅“ recursion制作”有害于完整的基本原理,但基本上,您希望获得所需的全部信息来决定是否需要重新构build文件,如果仅告诉其中的三分之一你的项目。

上面的链接似乎无法访问。 同一个文件可以在这里find:

  • aegis.sourceforge.net
  • lcgapp.cern.ch

您可以将规则添加到您的根Makefile以编译其他目录中的必要cpp文件。 下面的Makefile例子应该是一个很好的开始,让你到你想要的地方。

 CC =克++
 TARGET = cppTest
 OTHERDIR = .. / .. / someotherpath /中/项目/ src目录

 SOURCE = cppTest.cpp
 SOURCE = $(OTHERDIR)/file.cpp

 ##结束来源定义
 INCLUDE = -I./ $(AN_INCLUDE_DIR)  
 INCLUDE = -I。$(OTHERDIR)/../ inc
 ##结束更多包括

 VPATH = $(OTHERDIR)
 OBJ = $(join $(addsuffix ../obj/,$(dir $(SOURCE))),$(notdir $(SOURCE:.cpp = .o))) 

 ##修正依赖关系目标是相对于src目录的../.dep
 DEPENDS = $(join $(addsuffix ../.dep/,$(dir $(SOURCE))),$(notdir $(SOURCE:.cpp = .d)))

 ##默认规则执行
全部:$(TARGET)
         @真正

 ##清理规则
清洁:
         @ -rm -f $(TARGET)$(OBJ)$(DEPENDS)


 ##制定实际目标的规则
 $(TARGET):$(OBJ)
         @echo“=============”
         @echo“链接目标$ @”
         @echo“=============”
         @ $(CC)$(CFLAGS)-o $ @ $ ^ $(LIBS)
         @echo  - 链接完成 - 

 ##通用编译规则
 %.o:%.cpp
         @mkdir -p $(dir $ @)
         @echo“=============”
         @echo“编译$ <”
         @ $(CC)$(CFLAGS)-c $ <-o $ @


 ##来自cpp文件的对象文件的规则
 ##每个文件的对象文件放在obj目录中
 ##从实际的源代码目录上升一级。
 ../obj/%.o:%.cpp
         @mkdir -p $(dir $ @)
         @echo“=============”
         @echo“编译$ <”
         @ $(CC)$(CFLAGS)-c $ <-o $ @

 #规则为“其他目录”你将需要一个“其他”目录
 $(OTHERDIR)/../ obj /%。o:%.cpp
         @mkdir -p $(dir $ @)
         @echo“=============”
         @echo“编译$ <”
         @ $(CC)$(CFLAGS)-c $ <-o $ @

 ##制定依赖性规则
 ../.dep/%.d:%.cpp
         @mkdir -p $(dir $ @)
         @echo“=============”
         @echo构build$ *。o的依赖关系文件
         @ $(SHELL)-ec'$(CC)-M $(CFLAGS)$ <|  sed“s ^ $ *。o ^ .. / obj / $ *。o ^”> $ @'

 ##“其他”目录的依赖规则
 $(OTHERDIR)/../。dep /%。d:%.cpp
         @mkdir -p $(dir $ @)
         @echo“=============”
         @echo构build$ *。o的依赖关系文件
         @ $(SHELL)-ec'$(CC)-M $(CFLAGS)$ <|  sed“s ^ $ *。o ^ $(OTHERDIR)/../ obj / $ *。o ^”> $ @'

 ##包含依赖文件
 -include $(DEPENDS)

VPATH选项可能会派上用场,它告诉做什么目录来查找源代码。 不过,您仍然需要为每个包含path指定-I选项。 一个例子:

 CXXFLAGS=-Ipart1/inc -Ipart2/inc -Ipart3/inc VPATH=part1/src:part2/src:part3/src OutputExecutable: part1api.o part2api.o part3api.o 

这将自动在任何VPATH指定的目录中find匹配的partXapi.cpp文件并进行编译。 然而,当你的src目录被分解成子目录时,这会更有用。 正如其他人所说的,对于你所描述的内容,你可能最好用每个部分的makefile,特别是如果每​​个部分都可以独立的话。

如果源文件被分散在多个文件夹中,那么就像之前build议的那样使用单独的Makefiles是合理的,recursionmake是一个好方法,但是对于较小的项目,我发现将Makefile中的所有源文件与它们的相对path到这样的Makefile

 # common sources COMMON_SRC := ./main.cpp \ ../src1/somefile.cpp \ ../src1/somefile2.cpp \ ../src2/somefile3.cpp \ 

然后我可以这样设置VPATH

 VPATH := ../src1:../src2 

然后我build立对象:

 COMMON_OBJS := $(patsubst %.cpp, $(ObjDir)/%$(ARCH)$(DEBUG).o, $(notdir $(COMMON_SRC))) 

现在这个规则很简单:

 # the "common" object files $(ObjDir)/%$(ARCH)$(DEBUG).o : %.cpp Makefile @echo creating $@ ... $(CXX) $(CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $< 

build立输出甚至更容易:

 # This will make the cbsdk shared library $(BinDir)/$(OUTPUTBIN): $(COMMON_OBJS) @echo building output ... $(CXX) -o $(BinDir)/$(OUTPUTBIN) $(COMMON_OBJS) $(LFLAGS) 

甚至可以通过以下方式使VPATH生成自动化:

 VPATH := $(dir $(COMMON_SRC)) 

或者使用sort删除重复的事实(尽pipe这不重要):

 VPATH := $(sort $(dir $(COMMON_SRC))) 

我认为最好指出,使用Make(recursion或不是)通常是你可能想要避免的,因为与现在的工具相比,很难学习,维护和扩展。

这是一个非常棒的工具,但直接使用应该在2010年被认为是过时的。

当然,除非你正在一个特殊的环境中工作,比如一个传统的项目等等。

使用IDE, CMake,或者,如果你辛苦的话, Autotools 。

(由于downvotes编辑,ty洪扎指出)

RC的职位是超级有用的。 我从来没有想过使用$(dir $ @)函数,但它正是我所需要做的。

在parentDir中,有一堆包含源文件的目录:dirA,dirB,dirC。 各种文件依赖于其他目录中的目标文件,所以我希望能够从一个目录中创build一个文件,并通过调用与该依赖关联的makefile来创build依赖关系。

本质上,我在parentDir中创build了一个Makefile(其中包含许多其他内容)的类似于RC的通用规则:

 %.o : %.cpp @mkdir -p $(dir $@) @echo "=============" @echo "Compiling $<" @$(CC) $(CFLAGS) -c $< -o $@ 

每个子目录都包含这个高级makefile,以便inheritance这个通用规则。 在每个子目录的Makefile中,我为每个文件写了一个自定义规则,以便跟踪每个单独文件所依赖的所有内容。

无论何时我需要创build一个文件,我都(基本上)使用这个规则recursion地创build任何/所有的依赖关系。 完善!

注意:有一个名为“makepp”的工具,它似乎更直观地完成了这个任务,但为了便于携带而不依赖于其他工具,我select这样做。

希望这可以帮助!

recursion使用Make

 all: +$(MAKE) -C part1 +$(MAKE) -C part2 +$(MAKE) -C part3 

这允许make分成作业并使用多个核心

我build议使用autotools

//##将生成的目标文件(.o)放在与源文件相同的目录中,以避免使用非recursionmake时的冲突。

 AUTOMAKE_OPTIONS = subdir-objects 

只要将其包含在Makefile.am与其他非常简单的东西。

这里是教程 。