GCC编译过程和Linux的动静态库
基于Centos 7
首先我们抛出一个问题:为什么我们可以在我们的Linux或Windows上运行我们的C/C++或者其他类型的开发呢?
因为在Windows下安装了vs这样的集成环境,Linux下安装了gcc这样的编译器,基于这样的环境我们才可以进行编译,但是更重要的是我们也下载了库文件和头文件。
编译型语言:安装开发包一定是下载安装的头文件和库文件。
Windows:
他会在你安装IDE型软件时下载到你的Windows中。
Linux:
C/C++程序执行时需要进行四个过程
1.预处理
1.1去注释
很简单就是将注释的内容删除
1.2头文件展开
就是将包含的头文件展开
1.3条件编译
举个例子:
在下载vs等类似软件时,我们可以看到有好几种版本,类似社区版和专业版。
答案是当然不要,我们是只要添加不同的条件进行控制编译就可以。这就是条件编译。
1.4宏替换
就是将定义的宏进行替换
我们可以使用 命令:gcc -E filename.c -o filename.i 将文件停留在只进行预处理的阶段。
filename.c->filename.i
我们可以看到就是这样进行上述四个操作。
2.编译
形成汇编代码
使用命令:gcc -S filename.c -o filename.s 将文件停留在进行编译的过程中。
filename.i->filename.s
3.汇编
将汇编文件形成可重定位二进制文件,简称为目标文件,在vs的环境下生成的后缀为.obj
使用命令为gcc -c filename.c -o filename.o 将文件停留在汇编的过程中。
filename.s->filename.o
由于是二进制文件,所以是乱码。
但可通过readelf -S 命令查看:
4.链接
虽然此时文件已经是二进制文件,但是还是不能执行,需要链接库文件才能实现。
如下:
hello程序调用了printf函数,它存在于一个名为printf.o的单独的预编译好了的目标文件中,而这个文件必须以某种方式合并到我们的hello.o程序中。连接器(ld)就负责处理这种合并。结果就得到了hello文件,它是一个可执行目标文件(或者称为可执行文件),可以被加载到内存中,由系统执行。(链接程序运行需要的一大堆目标文件,以及所依赖的其它库文件,最后生成可执行文件)。
**就使用gcc filename.c -o filename **即可
5.库文件
linux下编程c语言是使用C语言标准库。C语言的标准库定义了诸如printf函数的实现方法。
5.1库的种类
5.1.1动态库
对于默认的机器下,一般只会安装动态库,需要手动安装静态库。
Linux:.so后缀为动态库
Windows:.dll后缀为动态库
如libc.so.xxx lib是标准的意思,c是c语言,xxx是版本号
ldd:ldd用来打印或者查看程序运行所需的共享库(访问共享对象依赖关系)
因为动态库就是共享库,许多的程序都依赖动态库,如果动态库缺失会造成很多程序无法进行。
5.1.2静态库
编译器在使用静态库的时候,会将实现方法拷贝在目标可执行文件中。该程序以后就不依赖静态库。
Linux:.a后缀为静态库
Windows:.lib后缀为静态库
在编译器进行编译形成可执行文件时,默认先采用动态库链接,所以我们需要加上**-static**进行静态链接
5.1.3两者对比
a.1如果没有静态库,我们就要进行静态链接,行不行呢?答案是不行
a.2如果没有动态库,只有静态库,而且gcc可以找到,能不能编译成可执行文件呢?答案是可以的
-static本质:是改变优先级
a.3文件编译的时候不一定是纯的动态库或者静态库,而是混合的。
b.动静态库的优缺点:
动态库优点:共享库,节省资源(磁盘空间、内存空间、网络空间)动态缺点:一旦缺失,会致使多个程序无法运行
静态库优点:不依赖库,程序可以正常运行。
静态库缺点:消费资源(磁盘空间、内存空间、网络空间)
b.动静态库的优缺点:
动态库优点:共享库,节省资源(磁盘空间、内存空间、网络空间)动态缺点:一旦缺失,会致使多个程序无法运行
静态库优点:不依赖库,程序可以正常运行。
静态库缺点:消费资源(磁盘空间、内存空间、网络空间)