Makefile 在多个目录中生成文件
我想建立一个应用程序,我有多个模块存储在多个目录。我决定遵循这个想法,即在每个目录中都有一个makefile,然后合并它。但是,作为一个初学者程序员,我仍然不知道如何做到这一点。首先,这样的“局部”生成文件是什么样子的。它们不能有main函数,因为每个二进制只能有一个,尽管当我试图编译它时,gcc会抱怨对main的引用未定义。其次,我不知道把所有这些模块放在一起会是什么样子Makefile 在多个目录中生成文件,makefile,Makefile,我想建立一个应用程序,我有多个模块存储在多个目录。我决定遵循这个想法,即在每个目录中都有一个makefile,然后合并它。但是,作为一个初学者程序员,我仍然不知道如何做到这一点。首先,这样的“局部”生成文件是什么样子的。它们不能有main函数,因为每个二进制只能有一个,尽管当我试图编译它时,gcc会抱怨对main的引用未定义。其次,我不知道把所有这些模块放在一起会是什么样子 我将非常感谢任何帮助,但请尽量保持你的答案简单。Makefiles对我来说仍然是一种黑魔法。在你能用makefile做任何
我将非常感谢任何帮助,但请尽量保持你的答案简单。Makefiles对我来说仍然是一种黑魔法。在你能用makefile做任何事情之前,你必须知道没有makefile怎么做 <> P>因为你使用的是GCC,我会假设你的源代码是C++。 您还没有告诉我们您的目录结构是什么样子,所以我假设您在两个目录中有三个源文件:
primary/main.cc
、other/foo.cc
和other/bar.cc
。(我们以后可以处理像foo.h
这样的头文件)并且您想要构建myApp
第一步:用手做
要在一个命令中执行此操作,可以使用:
gcc -Wall primary/main.cc other/foo.cc other/bar.cc -o myApp
这将编译三个源文件,并将二进制对象链接到可执行文件myApp
第二步:分步完成(在前一步完全完成之前不要尝试)
您可以采取中间步骤,将源文件编译为二进制对象文件,而不是使用一个命令进行构建:
gcc -Wall -c primary/main.cc -o primary/main.o
gcc -Wall -c other/foo.cc -o other/foo.o
gcc -Wall -c other/bar.cc -o other/bar.o
这将产生alpha/main.o
、beta/foo.o
和beta/bar.o
。编译器不会抱怨foo
和bar
缺少main()
函数,因为对象文件不需要函数。然后将对象链接到一个可执行文件中:
gcc -Wall primary/main.o other/foo.o other/bar.o -o myApp
第3步:在本地进行(在上一步能够完美工作之前,不要尝试此操作。)
与上一步一样,我们在primary/
和other/
中操作:
cd primary
gcc -Wall -c main.cc -o main.o
cd ../other
gcc -Wall -c foo.cc -o foo.o
gcc -Wall -c bar.cc -o bar.o
cd ..
gcc -Wall primary/main.o other/foo.o other/bar.o -o myApp
第4步:使用Makefile(在上一步工作正常之前,不要尝试此操作。)
我们可以让一个makefile执行步骤1,但这并不是真正必要的。在primary
中编写一个makefile(即primary/makefile
),如下所示:
main.o:
gcc -Wall -c main.cc -o main.o
(gcc…的fromt中的空白是一个选项卡。)
现在试试这个:
cd primary
make
cd ../other
gcc -Wall -c foo.cc -o foo.o
gcc -Wall -c bar.cc -o bar.o
cd ..
gcc -Wall primary/main.o other/foo.o other/bar.o -o myApp
cd primary
make
cd ../other
make
cd ..
make
第5步:使用多个makefile(在前一步完全正常工作之前,不要尝试此操作。)
编写一个其他/makefile
:
both: foo.o bar.o
foo.o:
gcc -Wall -c foo.cc -o foo.o
bar.o:
gcc -Wall -c bar.cc -o bar.o
以及顶部目录中的一个makefile,您正在该目录中构建myApp
:
myApp:
gcc -Wall primary/main.o other/foo.o other/bar.o -o myApp
现在试试这个:
cd primary
make
cd ../other
gcc -Wall -c foo.cc -o foo.o
gcc -Wall -c bar.cc -o bar.o
cd ..
gcc -Wall primary/main.o other/foo.o other/bar.o -o myApp
cd primary
make
cd ../other
make
cd ..
make
第6步:使用一个调用其他文件的Makefile(在上一步工作正常之前,不要尝试此操作)
编辑顶部生成文件:
myApp:
cd primary; make
cd other; make
gcc -Wall primary/main.o other/foo.o other/bar.o -o myApp
现在试试:
make
如果所有这些都有效,那么您拥有的就是一个粗糙但有效的makefile系统。当您准备好卸下训练轮时,有许多改进是可能的
编辑:
如果一个子目录中有许多源文件(例如,other/
),并且您不想手动在顶层makefile中维护列表,那么有几种方法可以处理它。这是一个:
OTHER_SOURCES := $(wildcard other/*.cc)
OTHER_OBJECTS := $(OTHER_SOURCES:.cc=.o)
myApp:
cd primary; make
cd other; make
gcc -Wall primary/main.o $(OTHER_OBJECTS) -o myApp
但是,在尝试进一步优化之前,您应该让这些生成文件正常工作并理解它们。感谢您提供的精彩教程!如果每个模块目录中有大量的文件怎么办?写第六步的最后一行会让人非常恼火。有解决办法吗?例如,将所有.o文件合并到每个目录中,或者告诉makefile从给定目录中获取所有.o文件?您也可以使用
-C
来更改目录并读取该目录中的makefile。@Aif:是的,我使用-C
,但我试图保持原始状态。正如我所说,许多改进是可能的。(我听说,-C
实际上并不符合POSIX…)回答得真棒!很好的分步解释:)可能重复