文章目录
- 库文件
- 静态库
- 动态库/共享库
- 区别
库文件
- 库文件是计算机上的一类文件,可以简单的将库文件看作一种代码仓库,提供给使用者可直接使用的变量、类、函数。
- 库不能单独运行
- 静态库在程序链接阶段把静态库中的代码直接复制到了程序中,每个程序需要使用到该静态库时都要链接一次。
- 动态库在程序链接阶段代码不会复制到程序中,而是程序在运行时由系统动态加载到内存中供程序调用,不同程序调用动态库可以直接加载到内存调用即可。
- 库的好处是代码保密以及方便部署和分发,采用了封装的思想隐藏具体属性和实现细节,向用户提供可以使用的接口(例如函数、类)。
静态库
- 静态库在程序链接阶段把静态库中的代码直接复制到了程序中
- 制作静态库需要使用ar将.o文件打包生成.a库文件,例如
ar rcs libbag.a a.o b.o
即将a.o b.o
文件打包生成静态库bag,lib是默认库前缀不可改变,r、c、s分别表示将文件插入备份文件中、建立备份文件、索引
- 使用静态库:将
libbag.a
库文件以及相应的头文件拷贝至当前文件,在编译时使用-I
指定include头文件所在目录以及使用-l
指定使用的库的名字(不包含前缀)-L
指定库所在的路径例如g++ main.cpp -o app.out -I ../head/ -l bag -L ../lib/
动态库/共享库
- 在程序链接阶段没有复制到程序中,而是程序在运行时由系统动态加载到内存中供程序调用。
- 制作动态库需要先获得和位置无关的.o文件使用
-fpic
即可g++ -c -fpic a.cpp b.cpp
再使用g++ -shared
将.o文件打包生成.so例如g++ -shared a.o b.o -o libcalc.so
即将a.o b.o
文件打包生成动态库calc,lib是默认库前缀不可改变。 - 使用动态库:将
libcalc.so
库文件以及相应的头文件拷贝至当前文件,在编译时使用-I
指定include头文件所在目录以及使用-l
指定使用的库的名字(不包含前缀)-L
指定库所在的路径例如g++ calc.cpp -o app.out -I ../head/ -l calc -L ../lib/
,此时编译通过但无法运行,因为动态库是动态加载到内存中的,虽然指定了路径但是并没有加载到程序中,无法识别该动态库,可以通过ldd命令检查动态库的依赖关系ldd app.out
发现该动态库并没有依赖,所以还需要定位共享库文件,通过动态载入器获取绝对路径先后搜索elf中DT_RPATH->环境变量LD_LIBRARY_PATH->...
可以通过变更环境变量的方式正常执行 - 变更环境变量LD_LIBRARY_PATH:临时方式为
export LD_LIBRARY_PATH = $(LD_LIBRARY_PATH):/home/linux/lib //export更改环境变量,$(LD_LIBRARY_PATH)为旧值冒号后为新值
,此时可通过echo $(LD_LIBRARY_PATH)
或者ldd app.out
查看是否更改,更改后即可运行。
永久改变需要对.bashrc
文件进行更改,将export LD_LIBRARY_PATH = $(LD_LIBRARY_PATH):/home/linux/lib
插入,再对文件进行刷新. .bashrc
区别
静态库在程序链接阶段把静态库中的代码直接复制到了程序中,每个程序需要使用到该静态库时都要链接一次。程序加载快,但是很消耗资源,部署麻烦。
动态库在程序链接阶段代码不会复制到程序中,而是程序在运行时由系统动态加载到内存中供程序调用,不同程序使用动态库可以直接使用加载到内存的动态库中即可,实现进程间资源的共享。