静态库
N个程序,需要使用同一个静态库,会加载这个库N次.(可以看成宏函数)
动态库(共享库)
N个程序,需要使用同一个共享库,这个库只有一份可以在连接时加载到各个程序.(其实可以看成函数调用)
计算机嘛,无非时间换空间,空间换时间.
时间要求高就静态库,空间要求高就共享库.没有特定要求时函数宏函数,当然选函数了.也就是动态库.
GCC常用命令
GCC编译过程:预处理,编译,汇编,链接
预处理 gcc -E xxx.c -o xxx.i 生成展开头文件宏替换等(这个叫什么不记得了)
编译 gcc -S xxx.i -o xxx.s 生成汇编文件
汇编 gcc -c xxx.s -o xxx.o 生成目标文件
链接 gcc xxx.o -o test.out 生成可执行文件
其他命令
-I 指定头文件路径
-g gdb调试
-Wall 显示所有警告信息
-D 加入宏定义
案例
头文件
源文件
main函数
静态库制作与使用
命令
ar rcs libxxx.a xxx.o
libxxx.a 约定的东西,敲代码嘛,别搞.
制作静态库
使用gcc -c *.cpp 生成 .o 二进制文件
使用ra rcs libcalc.a *.o生成库文件
静态库使用
这步不需要,只是这个问题会经常出现说一下
gcc
是通过collect2
间接调用ld,然后通过ld完成连接作用.(其实就是告诉链接阶段的错误)
-I 指定头文件路径,当然在头一目录下可以不使用
如果C语言可以没有头文件,直接和库一起编译就可以,因为C语言的灵活性,编译器会给为声明的函数添加隐式声明(***但是,这个隐式声明不一定正确(隐式声明的返回值是int固定的))
C++相对C来说灵活度会降低抛弃了函数的隐式声明(这其中的好坏人云亦云嘛,C的强大,python的火爆就是完美演绎),没有头文件中的函数声明,编译会直接不通过
静态库可执行文件大小
动态库制作与使用
动态库制作
首先也是需要.o文件
但是这个.o文件不同,
众所周知函数就是地址,main函数根据地址偏移量来确定调用哪个函数.
而动态库是运行到该库的时候才会加载该函数地址(也就是说程序没有执行到该库main并不知道这个库的地址)所以这个地址是先预留的,之后把预留的地址替换为动态库地址(也就是需要生成于地址无关的库)
这块是编译原理的内容.
使用 g++ -c -fPIC *.cpp 生成无关地址的.o文件
使用 g++ -shared - o libxxx.so *.o 制作动态库
使用动态库
使用 g++ xxx.cpp -lxxx -Lxxx 来遍历动态库 -l(指定库名不要lib和.so) -L(指定库的路径)
链接器和动态链接器
链接器 作用于链接阶段,需要人为指定
动态链接器 作用于运行阶段,是系统指定的(上面错误原因也就是因为,系统指定下没有我们的库)
解决动态库报错
export LD_LIBRARY_PATH=动态库的目录路径
但是这种方式只是一次性的,如果把当前终端关闭在打开就会失效(原因也很简单变量在内存中嘛,当前程序都结束了,变量自然也就没了)
可以将上面那句条件到配置文件中,经过shell脚本之后配置文件无非也就是要给脚本嘛,虽然不能全都看懂但是大概还是可以的.
添加之后保存运行脚本sh ./bashrc
注意使用绝对路径,还有我上面的代码是相对路径编译的,也需要重新编译一下.
还可以直接把库放进标准库里
ldd是查看库的连接
当然方法不只这些,就不一一介绍了