gcc的简单介绍
预处理(cpp)
把文本文件中的预处理指令全部展开,包括头文件包含,宏替换
gcc test.c -o test.i -E
编译(ccl)
编译预处理文件,生成对应硬件平台的汇编代码
gcc test.i -o test.s -S
汇编(as)
编译汇编代码,翻译为对应处理器的二进制机器码(生成二进制文件可重定向目标文件)
gcc test.s -o test.o -c
链接库
生成可执行文件
gcc test.o -o test -lc //链接标准的c库
gcc test.o -o test -v //查看当前编译链接的过程
对于上述编译过程,重点关注最后一步库文件的链接(gcc test.o -o hello -lc):链接实际上是将多个.o文件合并在一起的过程。这些 *.o 文件合并前是 ELF 格式,合并后也是 ELF 格式。
ELF代表Executable and Linkable Forma,是一种对可执行文件、目标文件和库使用的文件格式,跟Windows下的PE文件格式类似。ELF格式是是UNIX系统实验室作为ABI(Application Binary Interface)而开发和发布的,早已经是Linux下的标准格式了
ELF主要包括三种类型文件:
可重定位文件(relocatable):编译器和汇编器产生的.o文件,被Linker所处理
可执行文件(executable):Linker对.o文件进行处理输出的文件,进程映像
共享对象文件(shared object):动态库文件.so
ELF格式的合并,实际上就是将多个文件中各自对应的段合并在一起,形成一个统一的ELF文件。
在此过程中,必然需要对各个 *.o 文件中的静态数据(包括常量)、函数入口的地址做统一分配和管理,这个过程就叫做 重定位,因此未经链接的单独的 *.o 文件又被称为可重定位文件,经过链接处理合并了相同的段的文件称为可执行文件。
readelf -S test.o //显示节区表内的所有信息,包括每个节的属性
readelf -h test.o //显示在ELF文件头里包含的所有信息
readelf -s test.o //显示符号表的信息,包含静态符号表(.symtab)和动态符号表(.dynsym)
静态库和动态库
静态库在程序编译链接时,会被完整地复制到可执行文件中。
通常以.a(在 Unix/Linux 系统下)或.lib(在 Windows 系统下)为文件扩展名。它实际上是一组目标文件(.o文件)的归档集合,包含了多个函数和变量的编译后的代码。
动态库在程序运行时才被加载到内存中,供程序调用,在 Unix/Linux 系统下通常以.so为扩展名,在 Windows 系统下通常以.dll为扩展名。动态库在磁盘上是独立的文件,包含可执行代码和数据,这些代码和数据在程序运行时可以被多个程序共享。
静态库命名规范
lib库名.后缀
对于动态库而言,在后缀后面还经常会带着版本号
lib库名.后缀.版本号
制作静态库
首先写自己的C文件,例如编写a.c和b.c包含已经封装好的函数
然后编译a.c和b.c
gcc a.c -o a.o -c
gcc b.c -o b.o -c
将编译完的.o文件合并为一个静态链接库
ar crs libx.a a.o b.o
查看静态链接库中的*.o文件
ar -t libx.a
删除静态链接库中的*.o文件
ar d libx.a b.o
像静态库中增加*.o文件
ar r libx.a b.o
提取静态库中*.o文件
ar x libx.a
提取静态库中指定*.o文件
ar x libx.a a.o
静态库的调用,在主函数调用静态库的头文件,#include “xx.h"
编译时用gcc main.c -L./ -lxx -lyy //-L./指定在当前目录下,-l指定库名
制作动态库
gcc a.c -o a.o -c -fPIC
gcc b.c -o b.o -c -fPIC
gcc -shared -fPIC -o libx.so a.o b.o
运行动态库
动态库的最大特征,就是编译链接后程序并不包含动态库的代码,这些程序会在每次运行时,动态地去寻找并定位其所依赖的库文件中的模块,这是他们为什么被称为动态库的原因。也就是说,如果程序运行时找不到动态库,运行就会失败
为了解决找不到动态库的问题,假设我的库路径在/home/loading/lib
有两种解决方法
1、编译时预告
gcc main.c -o main -L. -lx -Wl,-rpath=/home/loading/lib/ //-Wl选项用于将后面的参数传递给链接器
2、将动态链接库路径添加到系统变量中
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/loading/lib