我想构建一个应用程序,我有多个模块存储在多个目录中。我决定遵循this的想法,即在每个目录中都有一个makefile然后合并它。但是 - 作为初学者程序员 - 我仍然没有看到如何做到这一点。首先,这种“部分”的makefile是怎样的。它们不能具有main函数,因为每个二进制文件只能有一个,但是当我尝试编译它时,gcc会抱怨对main的未定义引用。其次,我不知道如何将所有这些模块组合在一起。
我将不胜感激任何帮助,但请尽量保持简单的答案。 Makefile对我来说仍然是一个黑魔法。
答案 0 :(得分:25)
在使用makefile执行任何操作之前,必须知道如何在没有makefile的情况下执行此操作。
由于您使用的是gcc,我假设您的源代码是C ++。
您还没有告诉我们您的目录结构是什么样的,所以我假设您在两个目录中有三个源文件:primary/main.cc
,other/foo.cc
和other/bar.cc
。 (我们稍后可以处理foo.h
之类的标头文件。)并且您想要构建myApp
。
第1步:手工操作
要在一个命令中执行此操作,您可以使用:
gcc -Wall primary/main.cc other/foo.cc other/bar.cc -o myApp
这将编译三个源文件并将二进制对象链接到可执行文件myApp
。
第2步:在片中进行(除非你能让上一步完美地运作,否则不要尝试这样做。)
您可以采用中间步骤,将源文件编译为二进制目标文件,而不是使用一个命令构建:
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
(即primary/makefile
)中写一个makefile,如下所示:
main.o:
gcc -Wall -c main.cc -o main.o
(来自gcc...
的空格是TAB。)
现在试试这个:
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
第5步:使用多个Makefile (在完成上一步之前,不要尝试这样做。)
写一个other/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
make
cd ..
make
第6步:使用一个调用他人的Makefile (在你完成上一步工作之前不要尝试这个。)
编辑顶级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
但在尝试更精简之前,你应该让这些makefile工作并理解它们。