make,makefile和程序的编译链接过程

原创 2016年06月02日 12:00:18

一,Linux下程序运行过程
1,在一个目录下新建三个文件:main.c hello.c hello.h分别编写他们如下图:
小程序学习编译链接执行过程
2,想要让这个程序执行起来,就必须对上面的三个文件分别进行编译链接执行,如下图:
目标文件的编译,生成.o文件
链接生成可执行文件mian,并执行main
通过上面这个过程。我们可以大致总结一下gcc编译器把目标文件经过预处理,编译,汇编,链接生成可执行文件的过程和命令:
(1)预处理(宏替换,删除注释和多余的空白字符,条件编译,文件包含):
预处理过程
其中选项-E进行查看,这个选项的作用是让gcc在预处理结束后停止编译
过程。
选项-o是指目标文件,.i文件为已将完成预处理过程的C原始程序。
(2)编译(gcc检查代码规范性,是否有语法错误,生成汇编):
编译
其中选项-S进行查看,这个选项只进行编译而不进行汇编,生成.s文件。
(3)汇编(生成机器可识别代码,将编译生成的.s文件转成.o二进制目标代码):
汇编
(4)链接(生成可执行文件或库文件):
在成功编译后,就进入了链接的阶段,这里涉及到一个重要的概念:函数库查看上面的小程序会发现里面并没有定义printf函数的实现,并且在预编译阶段包含进去的“stdio.h”里面也只有它的声明,而没有定义函数的实现。那么printf实在哪里实现的呢?
其实系统把对这些函数的实现都做到名字为libc.so.6的库文件中去了,在没有特别指定时,gcc会到系统默认的路径“/user/lib”下面进行查找,并且链接到lib.so.6库函数中去,这样就能实现printf函数了,这也就是链接的作用。
函数库分为两种:静态库和动态库。静态库是指在编译链接时将库文件的代码全部加入到可执行文件里,因此生成的文件比较大,但在执行过程中就不会再用到库文件了,后缀名一般为.a;动态库和它相反,在编译链接过程中并没有将库文件加入到可执行文件里面去,而是在程序执行时由运行时链接文件加载库,这样可以节省系统的开销,后缀名一般为.so。上面提到的libc.so.6就是动态库,所以也就可以得到gcc在编译时默认使用动态库。完成链接过程,gcc就可以生成可执行文件main了。
链接
(5)执行:
”./可执行文件名“就可以执行这个程序啦,输出结果如下图:
执行
二,make和makefile
1,对make和makefile的理解
像上面提到的那样,要把一个程序执行起来首先要经过编译生成中间文件(.o文件)(在编译时编译器只检查程序语法,函数,变量是否被声明,如果函数没有被声明,编译器会给出警告,但还是会生成.o文件。在链接时链接器会在所有的.o文件里寻找函数的实现,如果没有找到,那就会报链接错误码,就类似与这种:Link2001错误)再经过链接生成可执行文件,这样在小程序里看起来没什么,但在大型的工程里这却是非常艰难烦躁的过程,你必须记住所有中间文件的文件名,才能方便在链接时用到它们,但如果程序里出现了一点小bug,那么上面的过程都要重新来过。这样效率实在太低了,所以就出现了makefile和make。
一个工程中的源文件不计其数,其按类型,功能,模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件要先编译,哪些后编译,哪些需要重新编译,甚至进行更复杂的功能操作。makefile就像一个shell脚本一样,其中也可以执行操作系统的命令。makefile带来的好处就是“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
make和makefile的区别:
make:是一个命令工具。
makefile:是一个存放编译方法的文件。
2,书写makefile的格式和规则
make命令执行时,需要一个Makefile文件,告诉make需要怎样去编译和链接程序。下面是makefile的书写规则:
(1)如果这个工程没有被编译过,那么我们的所有C文件都要编译并被链接。
(2)如果这个工程的某几个C文件被修改,那么我们只编译被修改的C文件,并链接目标程序。
(3)如果这个工程的头文件被改变了,那么我们需要编译引用了这几个头文件的C文件,并链接目标程序。
Makefile文件(形式1)
Makefile文件(形式2)
注意:
在定义好依赖关系后,后续的那一行定义了如何生成目标文件的操作系统命令,一定要以一个Tab键作为开头。记住,make并不管命令是怎么工作的,他只管执行所定义的命令。
clean不是文件,是一个动作名词,make clean用它来清除所有的目标文件,以便于进行重编译。
clean的两种写法
加@和不加@的对比
3,make是怎么工作的?
(1)make会在当前目录下找名字叫“Makefile”或“makefile”的文件。
(2)如果找到,它会找文件中的第一个目标文件,在上面的例子中,他会找到“hello”这个文件,并把这个文件作为最终的目标文件。
(3)如果hello文件不存在,或是hello所依赖的后面的 .o 文件的文件修改时间要比hello这个文件新,那么,他就会执行后面所定义的命令来生
成hello这个文件,这个也就是重编译。
(4)如果hello所依赖的.o文件也存在,那么make会在当前文件中找目标为.o文件的依赖性,如果找到则再根据那一个规则生成.o文件。(这
有点像一个堆栈的过程)
(5)当然,你的.c文件和.h文件是存在的啦,于是make会生成 .o 文件,
然后再用 .o 文件声明make的终极任务,也就是执行文件hello了。
make会一层一层去找文件的依赖关系,直到最终编译出第一个目标文件,如果过程中出现了错误(被依赖的文件找不到等),make会直接退出并报错。而对于所定义的命令的错误,或是编译不成功,make根本不理。make只管文件的依赖性,即如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,make就不工作啦。
好啦,就说这么多啦,有关make和makefile的其他内容后面会继续完善的,有很多不足的地方希望小伙伴们帮忙指正。

make和makefile以及程序的编译和链接过程

一,Linux下程序运行过程  1,在一个目录下新建三个文件:main.c hello.c hello.h分别编写他们如下图:    2,想要让这个程序执行起来,就必须对上面的三个文件分别进行编...

makefile的链接顺序

1. 你有一个library或者是可执行文件,你可以这样查看他的依赖关系: readelf -dldd工具 2.查看某个. c文件引用了那些头文件   gcc -M    :查...

Makefile 连接库文件的方法

Linux的静态库是以.a结尾的,要连接静态库有两种方法,一种是在编译命令最后直接加上库路径/库名称。例如你的库在绝对目录/lib/libtest.a下面 你就可以这样来编译 $(CC) $(CF...

Makefile经典教程(掌握这些足够)

makefile很重要       什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professio...
  • ruglcc
  • ruglcc
  • 2012年07月31日 15:28
  • 445087

使用make命令编译项目文件入门

使用make命令编译项目文件入门 目录: 一、make命令的运行过程 二、基本gcc编译命令 三、简单Makefile文件的编写 四、实例 一、make命令的运行过程    ...

Makefile之关于程序的编译和链接

关于程序的编译和链接 —————————— 在此,我想多说关于程序编译的一些规范和方法,一般来说,无论是C、C++、还是pas,首先要把源文件编译成中间代码文件,在Windows下也就是.ob...
  • l_nan
  • l_nan
  • 2014年06月05日 09:32
  • 1807

make:一个非常重要的编译命令

无论是在Linux还是在Unix环境中,make都是一个非常重要的编译命令。不管是自己进行项目开发还是安装应用软件,我们都经常要用到make或make install。利用make工具,我们可以将大型...

gmake和make 的区别

这几天在做qtopia的移植发现还有个gmake,不清楚和make的区别,所以查来看看,并记下来,方便查找。~~~~~~~~~~~~~~~~gmake是GNU Make的缩写。Linux系统环境下的m...

教会你如何编写makefile文件

最近一直在学习makefile是如何编写的。     当我们写的程序文件比较少的时候,敲入gcc /g++,当你在大型工程中,在一个个编译文件的话,你可能就会很郁闷。linux有一个自带的make命...
  • wallwind
  • wallwind
  • 2011年09月19日 20:47
  • 29945

使用autoconf生成Makefile并编译工程

这里我会用一个例子来说明怎么用autoconf工具生成规范的Makefile并且编译工程
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:make,makefile和程序的编译链接过程
举报原因:
原因补充:

(最多只允许输入30个字)