C/C++过程编译的过程
- .o文件,目标文件,使用gcc或g++编译器,相当于obj文件,保存了编译的时候引用到的符号(函数,全局变量等),这些符号在链接的时候需要使用到
- .so文件,shared object共享库(对象),相当于dll动态链接库;
- .a文件,archive归档包,静态库,多个.o文件打包结果,相当于lib静态链接库
- .la文件。libtool archive文件,是libtool自动生成的共享库文件
1、预处理:展开头文件、宏定义和条件编译处理等
gcc -E source.c -o source.i #生成source.i文件
2、编译:将处理后为念翻译成汇编代码的过程
gcc -S source.i #默认生成source.s文件
3、汇编:将上一步的汇编代码翻译成对应的二进制机器码的过程
gcc -c source.s #生成source.o文件
4、链接:将生成目标文件和其引用的各种符号生成一个完整的可执行程序;链接时会有虚拟内存的重定向。
gcc -o main main.o -Wl,-rpath=. atoi.so.1
在链接的时候,我们可以通过-Wl,-rpath=sopath
来指定运行时加载动态库的路径;
5、.a文件的生成
ar rc libhello.a hello.o
该命令将hello.o添加到静态库文件libhello.a,ar命令就是用来创建、修改库的,也可以从库中提出单个模块,参数r表示在库中插入或者替换模块,c表示创建一个库,
-Wl: 表示后面的参数将传给link程序ld,gcc编译时候的链接实际上是调用ld进行的
gcc -fPIC -shared -o atoi.so.1 atoi.c
-share
该选项指定生成动态连接库(让连接器生成T类型的导出符号表,有时候也生成弱连接W类型的导出符号,后面介绍nm
工具的时候再说),不用该标志外部程序无法连接。相当于一个可执行文件。
-fPIC
表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的
在linux 下可以使用ldd
命令来查看某个可执行文件需要链接哪些共享库(动态库),并可以确定这些要链接的共享库在本机中的位置
动态库和静态库连接时搜索路径的顺序
静态库
1、ld先去找gcc命令中参数-L
2、再找gcc的环境变量LIBRARY_PATH(用法:LIBRARY_PATH= path)
3、再找默认的目录 /lib /usr/lib /usr/local/lib
动态库
1、ld先去找gcc命令中的参数-L
2、环境变量LD_LIBRARY_PATH(LD_LIBRARY_PATH=path)
3、配置文件/etc/ld.so.conf中的动态链接库路径(若修改/etc/ld.so.conf文件,运行/sbin/ldconfig)
4、默认的目录/lib /usr/lib
头文件
1、去-I(id大写)指定的路径
2、源代码中(#include)的头文件路径
3、/usr/include
4、/usr/local/include
当静态链接库和动态链接库重名时,gcc优先使用动态链接库
-I(大写的i) :指定头文件的搜索路径
-l(小写的L)库名
-L库搜索目录