今天写C语言的时候,我突然遇到需要做一个项目.以前没有接触过,通过简单的了解,Windows下可以通过IDE来进行共同编译 vs就是很好的选择.
而我们今天讨论的重点是如何在Linux中进行多文件编译,一般简单的项目会有三个文件 (xxx.c ,xxx.c,xxx.h)其中一个执行程序主要功能,一个描述抽象数据类型的函数,一个进行函数原型的声明,在Linux下,大家都是手动达人,我们在编译的时候是需要把怎么编译都写出来,比如编译顺序,那个文件和那个文件进行链接,那些文件在什么情况下需要重新编译等等,或者一些更加复杂的操作,用来写这些具体操作的文件就是这个项目的makefile.
而且,我们在写好了一个makefile之后就可以自动编译了,只需用一个make命令就行.而且更加建议先学了makefile之后用IDE,因为学习了mmakefile之后你就对其中怎样把编程语言变成可执行程序有了更加深刻的理解,基础更加扎实.好了,接下来我们就来一起看看怎么写Makefile,
我是以c语言作为源码,编译器是Ubuntu 下默认的gcc.
首先我们来聊聊有关程序的编译和链接 无论是 C、 C++、还是 pas,首先要把源文件编译成中间代码文件,在 Windows 下也就是 .obj 文件,UNIX 下是 .o 文件,即 Object File,这个动作叫做编译( compile)。然后再把大量的 Object File合成执行文件,这个动作叫做链接( link),windows下大部分的IDE都将这两个动作结合成一个并且集合到一个快捷键上,这样对初学者友好但是对于深刻理解缺有点缺陷。
Makefile就是一个怎样编译多文件的脚本,我们写好之后在终端下输入make 这个命令就可以开始编译了.
target ... : prerequisites ... command ... ...
形如这样的就是一个Makefile,其中 target 也就是一个目标文件,可以是 Object File,也可以是执行文件。还可以是一个标签( Label)。prerequisites 就是,要生成那个 target 所需要的文件或是目标。command 也就是 make 需要执行的命令。(任意的 Shell 命令)
这 是 一 个 文 件 的 依 赖 关 系 , 也 就 是 说 , target 这 一 个 或 多 个 的 目 标 文 件 依 赖 于prerequisites 中 的 文 件 , 其 生 成 规 则 定 义 在 command 中 。 说 白 一 点 就 是 说 ,prerequisites 中如果有一个以上的文件比 target 文件要新的话, command 所定义的命令就会被执行。这就是 Makefile 的规则。
好了,我说完了,Makefile的核心内容就是这样了,
这就是一个实例,其中film 就是编译之后要生成的文件,它依赖的就是后面的film4.c ,list.c和list.h这三个文件.
make 的具体工作方式是这样,当你在默认界面或者是终端中输入了make命令之后,
make 会在当前目录下找名字叫“ Makefile”或“ makefile”的文件
如果找到,它会找文件中的第一个目标文件( target),在上面的例子中,他会找到“ film”这个文件,并把这个文件作为最终的目标文件。
如果 film 文件不存在,或是 film 所依赖的后面的文件的文件修改时间要比film这个文件新,那么,他就会执行后面所定义的命令来生成 film这个文件。
好了,这样就通过编译器生成了film 这个文件.
Makefile中还可以使用变量,让我们看这样一个例子,
edit : main.o kbd.o command.o display.o \ insert.o search.o files.o utils.o cc -o edit main.o kbd.o command.o display.o \ insert.o search.o files.o utils.o main.o : main.c defs.h cc -c main.c kbd.o : kbd.c defs.h command.h cc -c kbd.c command.o : command.c defs.h command.h cc -c command.c display.o : display.c defs.h buffer.h cc -c display.c insert.o : insert.c defs.h buffer.h cc -c insert.c search.o : search.c defs.h buffer.h cc -c search.c files.o : files.c defs.h buffer.h command.h cc -c files.c utils.o : utils.c defs.h cc -c utils.c clean : rm edit main.o kbd.o command.o display.o \ insert.o search.o files.o utils.o
我们可以看到[.o]文件的字符串被重复了两次,如果我们的工程需要加入一个新的[.o]文
件,那么我们需要在两个地方加,但如果 makefile 变得复杂,那么我们就有可能会忘掉一个需要加入的地方,而导致编译失败所以,为了 makefile 的易维护,在 makefile 中我们可以使用变量。 makefile 的变量也就是一个字符串,理解成 C语言中的宏可能会更好。比如,我们声明一个变量,叫 objects, OBJECTS, objs, OBJS, obj, 或是 OBJ,反
正不管什么啦,只要能够表示 obj 文件就行了。我们在 makefile 一开始就这样定义:
objects = main.o kbd.o command.o display.o \ insert.o search.o files.o utils.o
于是,我们就可以很方便地在我们的 makefile 中以“ $(objects)”的方式来使用这个变
量了,于是我们的改良版 makefile 就变成下面这个样子:
objects = main.o kbd.o command.o display.o \ insert.o search.o files.o utils.o edit : $(objects) cc -o edit $(objects) main.o : main.c defs.h cc -c main.c kbd.o : kbd.c defs.h command.h cc -c kbd.c command.o : command.c defs.h command.h cc -c command.c display.o : display.c defs.h buffer.h cc -c display.c insert.o : insert.c defs.h buffer.h cc -c insert.c search.o : search.c defs.h buffer.h cc -c search.c files.o : files.c defs.h buffer.h command.h cc -c files.c utils.o : utils.c defs.h cc -c utils.c clean : rm edit $(objects)
如果有新的.o文件加入,我们只用在开始的变量声明中修改就可以了.
最后我告诉大家一下Makefile的书写规则
它的语法就是下面这个样子
targets : prerequisites command ...
或是这样:
targets : prerequisites ; command command ...
targets 是文件名,以空格分开,可以使用通配符。一般来说,我们的目标基本上是一个文件,但也有可能是多个文件。command 是命令行,如果其不与“ target:prerequisites”在一行,那么,必须以[Tab键]开头,如果和 prerequisites 在一行,那么可以用分号做为分隔。(见上)prerequisites 也就是目标所依赖的文件(或依赖目标)。如果其中的某个文件要比目标文件要新,那么,目标就被认为是“过时的”,被认为是需要重生成的。这个在前面已经讲过了。如果命令太长,你可以使用反斜框(‘ \’)作为换行符。 make 对一行上有多少个字符没有限制。规则告诉 make 两件事,文件的依赖关系和如何成成目标文件。
一般来说, make 会以 UNIX 的标准 Shell,也就是/bin/sh 来执行命令。
好了,简单的Makefile的就到这,看过这个之后大家就学会在linux下进行件简单的工程的编译,如果想要对于Makefile进行系统的学习可以去参考一下相关的书籍.