源文件在不同目录中的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语法中的问号]
传统的方法是在每个子目录( part1
, part2
等)中都有一个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
与其他非常简单的东西。
这里是教程 。