目录
二、linux项目自动化构建工具(make/makefile)
一、gcc/g++编译器
1.程序的翻译过程
一个程序的翻译过程可以分为四步:预处理、编译、汇编、链接
(1)预处理
在预处理中,程序会执行“头文件展开、去注释、宏替换、条件编译”等工作,为了更加直观的显示,假设我们现在有test.c文件,里面包含下图的程序:
现在我们执行“gcc -E test.c -o test.i”命令。该命令会将对应test.c文件执行完预处理后就结束,并将处理好后的文本内容放入test.i文件中
打开test.i后,前面的内容大部分人都看不懂,但是没有关系。我们直接翻到该文件的最后,此时就会看到以下内容:
与上图我们写的代码相比较,就可以看到,注释,条件编译和宏之类的内容就已经不见了,此时还留着的就是和代码强相关的内容
(2)编译
编译简单来讲,就是将预处理过后的“纯C语言”转化成汇编语言。此时我们输入“gcc -S test.c -o test.s”命令,该命令会在文件执行完汇编后结束并将结果放入test.s文件:
虽然上面的内容我们看不懂,但依然可以看出来这是汇编语言
(3)汇编
对于这一步有些可能会感到奇怪,既然c转汇编在编译阶段已经完成了,那汇编要干嘛呢?我们要知道,汇编语言并不是最原生的语言,在计算机底层,是以0,1信号来执行的。而汇编这一步,就是将汇编语言转成二进制机器语言,将汇编文件转换成二进制目标文件
我们输入“gcc -c tst.c -o test.o”命令,就会在文件执行完汇编后结束,并将结果放入test.o文件中:
此时显示的是乱码,我们是看不懂的。但我们可以执行“od test.o”命令,以二进制的形式查看:
(4)链接
虽然此时我们已经有了二进制目标文件,但该文件我们此时依然无法执行。因为虽然我们写了这份代码,但代码中调用的c标准库中的函数还没有实现。而链接就是将我们写好的代码与c标准库中对应的代码合起来,使得我们调用的函数可用。
此时我们直接执行“gcc test.c”命令,就会直接帮我们生成对应的可执行程序
要注意的是,预处理用的命令是“-E”,生成的文件后缀是“.i”;编译用的命令是“S”,生成的文件后缀是“.s”;汇编用的命令是“-c”,生成的文件后缀是“.o”
2.动态库与静态库
(1)动态链接和静态链接
在了解动态库和静态库之前,我们先来了解动态链接和静态链接。为了更容易理解,我们在这里举一个例子。
我们假设现在有一所学校。然后你现在作为一名住宿生,放假期间都是呆在宿舍里面。然后学校里面有一个食堂。在平时,我们呆在宿舍里面可以做很多事情,比如学习,睡觉等。如下图:
但是当你学习或者娱乐一段时间后,觉得饿了,想要吃饭,但是宿舍里面没有饭可以吃,因此我们就必须离开宿舍沿着一定的路线来到食堂吃饭。吃完饭后再回到宿舍做自己的事。如下图:
而这里面的宿舍就可以看做一个程序;食堂则可以看成是一个库。学习,睡觉等活动就是这个程序需要完成的工作。而前往食堂就是在进行库函数跳转:
学习和睡觉这些活动程序可以依赖自身的代码完成,但是吃饭却不行。因此此时程序就去到库里面执行库里面的代码,在库里面执行完后再返回。
但是我们怎么知道食堂的位置在哪里呢?当我们入学时,都会有老师或者引导人员告诉你食堂的位置,这些老师和引导人员就可以看成是编译器里面的链接器,将库的位置告诉程序,程序到对应的位置去找。而程序从自己所处的位置到库里面执行代码的过程就是“动态链接”
然后有一天,学校发通知说食堂需要装修更新,暂时停运了。但是为了解决学生的吃饭问题,于是学校给每个宿舍都发了食堂里面的炒锅和菜,现在我们要吃饭时就不需要去食堂了,而是直接在宿舍自己做就行了。