makefile的本质
以我的理解,makefile就像一个代码工程的骨架一样,将不同文件下的不同源代码文件串联在一起。当你想编译时,你只要在控制台上输入make命令,就能完成整个工程的自动编译,连接。make是一个解释makefile文件的工具。很多用IDE编写过程序的初学者可能会一脸懵逼,makefile是什么鬼,到底有什么用啊。其实IDE工具已经帮你在后台完成了makefile的工作。
为什么需要makefile
下面我将通过举例说明:
###举例###
####关于程序的编译和链接####
在实验之前,先介绍一个基础知识。
一般来说,无论是C还是C++,首先要把源文件编译成中间代码文件,在Windows下也就是 .obj 文件,UNIX下是 .o 文件,即 Object File,这个动作叫做编译(compile),一般来说,每个源文件都应该对应于一个中间目标文件(O文件或是OBJ文件)。然后再把大量的Object File合成执行文件,这个动作叫作链接(link)。
编译时,编译器需要的是语法的正确,函数与变量的声明的正确。对于后者,通常是你需要告诉编译器头文件的所在位置(头文件中应该只是声明,而定义应该放在C/C++文件中),只要所有的语法正确,编译器就可以编译出中间目标文件。
链接时,主要是链接函数和全局变量,所以,我们可以使用这些中间目标文件(O文件或是OBJ文件)来 链接我们的应用程序。链接器并不管函数所在的源文件,只管函数的中间目标文件(Object File),在大多数时候,由于源文件太多,编译生成的中间目标文件太多,而在链接时需要明显地指出中间目标文件名,这对于编译很不方便,所以,我们要给 中间目标文件打个包,在Windows下这种包叫“库文件”(Library File),也就是 .lib 文件,在UNIX下,是Archive File,也就是 .a 文件。
实验环境
windows虚拟机上的ubuntu(linux系统)。
实验目标
编译生成一个多文件小程序。
实验步骤
首先在任意目录下建一个demo文件夹。在文件夹里面新建三个文件,分别是:add.h,add.c,main.c
- main.c
#include<stdio.h>
#include"add.h"
void main(void)
{
int sum;
sum=add(6,9);
printf("%d",sum);
}
- add.c
#include"add.h"
int add(int a,int b)
{
return a+b;
}
- add.h
int add(int a,int b);
接下来我们使用ubuntu的gcc编译器来对这个应用进行编译:
首先打开控制台,进入到demo目录下,输入编译连接命令:gcc main.c add.c -o app
生成app可执行文件:然后输入./app
这是在控制台上输出结果15。
试想一下,如果这个工程有几百个文件,你每次编译时需要在gcc后面输入多少个字符,是不是特别麻烦,这是我们可以采用第二种方法,编写makefile文件,然后用make解释makefile,自动调用编译器和连接器生成可执行文件。
在demo下新建一个文件:makefile
- makefile
app :add.o main.o
cc -o app add.o main.o
add.o :add.c add.h
cc -c add.c
main.o:main.c add.h
cc -c main.c
然后打开控制,进入到demo目录下,输入make
命令(如果没有make,自己装一下),紧接着,make将会运行makefile文件生成可执行程序app,然后在控制输入./app
,输出结果15.
两种方式都能达到目的,但是当文件多时,谁优谁劣,一目了然。
补充
关于makefile文件的编写,我就不赘述了,如有兴趣,可以自行百度。
makefile基于两个重要东西
- 依赖关系,依赖关系定义了如果你要建立一个目标,有什么是必须做的
- 时间先后:根据文件的时间,make程序判断那些东西发生了变化,然后根据前面定义的依赖关系把依赖于这些文件的目标重新建立一遍
以上所有内容,已经实测过,如有问题,欢迎指出。