Linux 源文件在不同目录下的 Makefile
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1139271/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Makefiles with source files in different directories
提问by devin
I have a project where the directory structure is like this:
我有一个项目,目录结构是这样的:
$projectroot
|
+---------------+----------------+
| | |
part1/ part2/ part3/
| | |
+------+-----+ +---+----+ +---+-----+
| | | | | | |
data/ src/ inc/ src/ inc/ src/ inc/
How should I write a makefile that would be in part/src (or wherever really) that could comple/link on the c/c++ source files in part?/src ?
我应该如何编写一个可以在部分/src(或任何地方)中完成/链接到部分 c/c++ 源文件的 makefile?/src ?
Can I do something like -I$projectroot/part1/src -I$projectroot/part1/inc -I$projectroot/part2/src ...
我可以做类似 -I$projectroot/part1/src -I$projectroot/part1/inc -I$projectroot/part2/src ...
If that would work, is there an easier way to do it. I've seen projects where there is a makefile in each of the corresponding part? folders. [in this post I used the question mark like in bash syntax]
如果那行得通,有没有更简单的方法来做到这一点。我见过在每个相应部分都有一个 makefile 的项目吗?文件夹。[在这篇文章中,我使用了 bash 语法中的问号]
采纳答案by devin
The traditional way is to have a Makefile
in each of the subdirectories (part1
, part2
, etc.) allowing you to build them independently. Further, have a Makefile
in the root directory of the project which builds everything. The "root" Makefile
would look something like the following:
传统的方法是有一个Makefile
在每个子目录(中part1
,part2
等),使您能够独立构建它们。此外,Makefile
在构建所有内容的项目的根目录中有一个。“根”Makefile
将类似于以下内容:
all:
+$(MAKE) -C part1
+$(MAKE) -C part2
+$(MAKE) -C part3
Since each line in a make target is run in its own shell, there is no need to worry about traversing back up the directory tree or to other directories.
由于 make 目标中的每一行都在自己的 shell 中运行,因此无需担心遍历目录树或其他目录。
I suggest taking a look at the GNU make manual section 5.7; it is very helpful.
我建议查看GNU make 手册第 5.7 节;这是非常有帮助的。
回答by dave4420
If you have code in one subdirectory dependent on code in another subdirectory, you are probably better off with a single makefile at top-level.
如果一个子目录中的代码依赖于另一个子目录中的代码,那么在顶层使用单个 makefile 可能会更好。
See Recursive Make Considered Harmfulfor the full rationale, but basically you want make to have the full information it needs to decide whether or not a file needs to be rebuilt, and it won't have that if you only tell it about a third of your project.
有关完整原理,请参阅递归生成被认为有害,但基本上您希望 make 拥有决定是否需要重建文件所需的完整信息,如果您只告诉它大约三分之一你的项目。
The link above seems to be not reachable. The same document is reachable here:
上面的链接似乎无法访问。可以在此处访问相同的文档:
回答by IlDan
I think it's better to point out that using Make (recursive or not) is something that usually you may want to avoid, because compared to today tools, it's difficult to learn, maintain and scale.
我认为最好指出使用 Make(无论是否递归)通常是您可能想要避免的,因为与今天的工具相比,它很难学习、维护和扩展。
It's a wonderful tool but it's direct use should be considered obsolete in 2010+.
这是一个很棒的工具,但它的直接使用在 2010 年以后应该被视为过时了。
Unless, of course, you're working in a special environment i.e. with a legacy project etc.
当然,除非你在一个特殊的环境中工作,比如一个遗留项目等。
Use an IDE, CMakeor, if you're hard cored, the Autotools.
使用 IDE、CMake或Autotools(如果您是硬核)。
(edited due to downvotes, ty Honza for pointing out)
(由于反对票而编辑,ty Honza 指出)
回答by CodeGoat
The VPATH option might come in handy, which tells make what directories to look in for source code. You'd still need a -I option for each include path, though. An example:
VPATH 选项可能会派上用场,它告诉 make 在哪些目录中查找源代码。不过,您仍然需要为每个包含路径添加一个 -I 选项。一个例子:
CXXFLAGS=-Ipart1/inc -Ipart2/inc -Ipart3/inc
VPATH=part1/src:part2/src:part3/src
OutputExecutable: part1api.o part2api.o part3api.o
This will automatically find the matching partXapi.cpp files in any of the VPATH specified directories and compile them. However, this is more useful when your src directory is broken into subdirectories. For what you describe, as others have said, you are probably better off with a makefile for each part, especially if each part can stand alone.
这将自动在任何 VPATH 指定目录中找到匹配的 partXapi.cpp 文件并编译它们。但是,当您的 src 目录被分成子目录时,这会更有用。对于您所描述的内容,正如其他人所说,您可能最好为每个部分提供一个 makefile,特别是如果每个部分都可以独立。
回答by RC.
You can add rules to your root Makefile in order to compile the necessary cpp files in other directories. The Makefile example below should be a good start in getting you to where you want to be.
您可以向根 Makefile 添加规则,以便在其他目录中编译必要的 cpp 文件。下面的 Makefile 示例应该是让您达到目标的良好开端。
CC=g++ TARGET=cppTest OTHERDIR=../../someotherpath/in/project/src SOURCE = cppTest.cpp SOURCE = $(OTHERDIR)/file.cpp ## End sources definition INCLUDE = -I./ $(AN_INCLUDE_DIR) INCLUDE = -I.$(OTHERDIR)/../inc ## end more includes VPATH=$(OTHERDIR) OBJ=$(join $(addsuffix ../obj/, $(dir $(SOURCE))), $(notdir $(SOURCE:.cpp=.o))) ## Fix dependency destination to be ../.dep relative to the src dir DEPENDS=$(join $(addsuffix ../.dep/, $(dir $(SOURCE))), $(notdir $(SOURCE:.cpp=.d))) ## Default rule executed all: $(TARGET) @true ## Clean Rule clean: @-rm -f $(TARGET) $(OBJ) $(DEPENDS) ## Rule for making the actual target $(TARGET): $(OBJ) @echo "=============" @echo "Linking the target $@" @echo "=============" @$(CC) $(CFLAGS) -o $@ $^ $(LIBS) @echo -- Link finished -- ## Generic compilation rule %.o : %.cpp @mkdir -p $(dir $@) @echo "=============" @echo "Compiling $<" @$(CC) $(CFLAGS) -c $< -o $@ ## Rules for object files from cpp files ## Object file for each file is put in obj directory ## one level up from the actual source directory. ../obj/%.o : %.cpp @mkdir -p $(dir $@) @echo "=============" @echo "Compiling $<" @$(CC) $(CFLAGS) -c $< -o $@ # Rule for "other directory" You will need one per "other" dir $(OTHERDIR)/../obj/%.o : %.cpp @mkdir -p $(dir $@) @echo "=============" @echo "Compiling $<" @$(CC) $(CFLAGS) -c $< -o $@ ## Make dependancy rules ../.dep/%.d: %.cpp @mkdir -p $(dir $@) @echo "=============" @echo Building dependencies file for $*.o @$(SHELL) -ec '$(CC) -M $(CFLAGS) $< | sed "s^$*.o^../obj/$*.o^" > $@' ## Dependency rule for "other" directory $(OTHERDIR)/../.dep/%.d: %.cpp @mkdir -p $(dir $@) @echo "=============" @echo Building dependencies file for $*.o @$(SHELL) -ec '$(CC) -M $(CFLAGS) $< | sed "s^$*.o^$(OTHERDIR)/../obj/$*.o^" > $@' ## Include the dependency files -include $(DEPENDS)
回答by jvriesem
RC's post was SUPER useful. I never thought about using the $(dir $@) function, but it did exactly what I needed it to do.
RC 的帖子非常有用。我从没想过使用 $(dir $@) 函数,但它确实完成了我需要它做的事情。
In parentDir, have a bunch of directories with source files in them: dirA, dirB, dirC. Various files depend on the object files in other directories, so I wanted to be able to make one file from within one directory, and have it make that dependency by calling the makefile associated with that dependency.
在 parentDir 中,有一堆包含源文件的目录:dirA、dirB、dirC。各种文件依赖于其他目录中的目标文件,因此我希望能够从一个目录中创建一个文件,并通过调用与该依赖项相关联的 makefile 来创建该依赖项。
Essentially, I made one Makefile in parentDir that had (among many other things) a generic rule similar to RC's:
本质上,我在 parentDir 中创建了一个 Makefile,它具有(除其他外)一个类似于 RC 的通用规则:
%.o : %.cpp @mkdir -p $(dir $@) @echo "=============" @echo "Compiling $<" @$(CC) $(CFLAGS) -c $< -o $@
%.o : %.cpp @mkdir -p $(dir $@) @echo "=============" @echo "Compiling $<" @$(CC) $(CFLAGS) -c $< -o $@
Each subdirectory included this upper-level makefile in order to inherit this generic rule. In each subdirectory's Makefile, I wrote a custom rule for each file so that I could keep track of everything that each individual file depended on.
每个子目录都包含此上层 makefile 以继承此通用规则。在每个子目录的 Makefile 中,我为每个文件编写了一个自定义规则,以便我可以跟踪每个单独文件所依赖的所有内容。
Whenever I needed to make a file, I used (essentially) this rule to recursively make any/all dependencies. Perfect!
每当我需要创建文件时,我(基本上)使用此规则递归创建任何/所有依赖项。完美的!
NOTE: there's a utility called "makepp" that seems to do this very task even more intuitively, but for the sake of portability and not depending on another tool, I chose to do it this way.
注意:有一个名为“makepp”的实用程序似乎可以更直观地完成这项任务,但为了便携性而不是依赖其他工具,我选择了这种方式。
Hope this helps!
希望这可以帮助!
回答by EhevuTov
all:
+$(MAKE) -C part1
+$(MAKE) -C part2
+$(MAKE) -C part3
This allows for make
to split into jobs and use multiple cores
这允许make
拆分为作业并使用多个内核
回答by dashesy
If the sources are spread in many folders, and it makes sense to have individual Makefiles then as suggested before, recursive make is a good approach, but for smaller projects I find it easier to list all the source files in the Makefilewith their relative path to the Makefilelike this:
如果源文件分布在许多文件夹中,并且像之前建议的那样拥有单独的 Makefile 是有意义的,那么递归 make 是一种很好的方法,但对于较小的项目,我发现将Makefile中的所有源文件及其相对路径列出会更容易到Makefile像这样:
# common sources
COMMON_SRC := ./main.cpp \
../src1/somefile.cpp \
../src1/somefile2.cpp \
../src2/somefile3.cpp \
I can then set VPATH
this way:
然后我可以这样设置VPATH
:
VPATH := ../src1:../src2
Then I build the objects:
然后我构建对象:
COMMON_OBJS := $(patsubst %.cpp, $(ObjDir)/%$(ARCH)$(DEBUG).o, $(notdir $(COMMON_SRC)))
Now the rule is simple:
现在规则很简单:
# the "common" object files
$(ObjDir)/%$(ARCH)$(DEBUG).o : %.cpp Makefile
@echo creating $@ ...
$(CXX) $(CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<
And building the output is even easier:
构建输出更容易:
# This will make the cbsdk shared library
$(BinDir)/$(OUTPUTBIN): $(COMMON_OBJS)
@echo building output ...
$(CXX) -o $(BinDir)/$(OUTPUTBIN) $(COMMON_OBJS) $(LFLAGS)
One can even make the VPATH
generation automated by:
甚至可以VPATH
通过以下方式使生成自动化:
VPATH := $(dir $(COMMON_SRC))
Or using the fact that sort
removes duplicates (although it should not matter):
或者使用sort
删除重复项的事实(尽管这无关紧要):
VPATH := $(sort $(dir $(COMMON_SRC)))
回答by user2763812
I suggest to use autotools
:
我建议使用autotools
:
//##
Place generated object files (.o) into the same directory as their source files, in order to avoid collisions when non-recursive make is used.
//##
将生成的目标文件 (.o) 放在与其源文件相同的目录中,以避免在使用非递归 make 时发生冲突。
AUTOMAKE_OPTIONS = subdir-objects
just including it in Makefile.am
with the other quite simple stuff.
只是将它Makefile.am
与其他非常简单的东西一起包含在内。
Here is the tutorial.
这是教程。
回答by Matheus Vinícius de Andrade
I was looking for something like this and after some tries and falls i create my own makefile, I know that's not the "idiomatic way" but it's a begining to understand make and this works for me, maybe you could try in your project.
我一直在寻找这样的东西,经过一些尝试和失败,我创建了自己的 makefile,我知道这不是“惯用的方式”,但这是理解 make 的开始,这对我有用,也许您可以在您的项目中尝试。
PROJ_NAME=mono
CPP_FILES=$(shell find . -name "*.cpp")
S_OBJ=$(patsubst %.cpp, %.o, $(CPP_FILES))
CXXFLAGS=-c \
-g \
-Wall
all: $(PROJ_NAME)
@echo Running application
@echo
@./$(PROJ_NAME)
$(PROJ_NAME): $(S_OBJ)
@echo Linking objects...
@g++ -o $@ $^
%.o: %.cpp %.h
@echo Compiling and generating object $@ ...
@g++ $< $(CXXFLAGS) -o $@
main.o: main.cpp
@echo Compiling and generating object $@ ...
@g++ $< $(CXXFLAGS)
clean:
@echo Removing secondary things
@rm -r -f objects $(S_OBJ) $(PROJ_NAME)
@echo Done!
I know that's simple and for some people my flags are wrong, but as i said this is my first Makefile to compile my project in multiple dirs and link all of then together to create my bin.
我知道这很简单,对某些人来说我的标志是错误的,但正如我所说,这是我在多个目录中编译我的项目并将所有这些链接在一起以创建我的 bin 的第一个 Makefile。
I'm accepting sugestions :D
我正在接受建议:D