静态库与共享库
静态库,.a结尾
制作静态库:将.o文件制作成静态库文件
ar rcs libmylib.a file1.o
rcs表示创建索引
库名libmylib.a,一般以lib开头再加自己定的库名,后缀.a表示
这是一个静态库名。
ar rcs libmylib.a a.o b.o c.o
相当于把a.o b.o c.o三个文件打包到一个库里面,
库名叫libmylib.a
在使用gcc时,要注意其参数的顺序,-l是链接器
查看静态库里面有哪些目标文件用指令nm 静态库名(如libmylib.a)
gcc编译添加静态库:
gcc main.c lib/libmylib.a -o app
上面意思是,编译main.c,并链接静态库libmylib.a,生成可执行程序app.
共享库,.so结尾
win环境下共享库以dll结尾,Linux环境下是以.so结尾。
gcc -fpic -c a.c 意思是将a.c编译但不连接,生成a.o
fpic参数含义是相对地址,在内存中与具体位置无关,
静态库使用的目标文件也用-fpic设置。
gcc -shared -Wl -o libmylib.so a.o b.o
这一句是将a.o,b.o做成一个叫libmylib.so的共享库(动态库)
共享库的三种名字
- real name,真名,即libmylib.1.10,记录了主版本号1,次版本号10,共享库源文件
- so name,记录主版本号,判断程序运行阶段所需共享库主版本号是否与so name里面的版本号相同,指向real name的链接,一般命令行gcc使用
- link name ,表明库名,只是指向real name的源文件,一般用于Makefile,在编写Makefile时,里面会需要添加许多库,使用链接来指定共享库很方便,当原先的库更新为2.0版本后,只需改掉link指向即可,不需要改makefile的内容。link name即在命令行中ln -s 定义的软连接。
采用偏移地址而不是绝对地址,偏移地址保证代码执行还在库里面,而不是跳转到绝对地址跑到库外面了。
命令ldd,可查看程序依赖关系,如写的test.c编译生成可执行文件app,查询app,查询的库依赖关系可用ldd app查询。
gcc main.c libmylib.so.1.10 -o app
编译main.c ,同时链接libmylib.so.1.10动态库,
生成可执行文件app,
运行app时会报错,找不到库libmylib.so.1.10,这是因为没有把共享库目录添加到配置文件中,所以需要修改配置文件。
修改配置文件添加共享库目录
sudo vim /etc/ld.so.conf
打开如下:
1 include /etc/ld.so.conf.d/*.conf
2
直接添加一行共享库所在目录保存即可,再更新配置文件
sudo ldconfig -v
在更新过后,会在写入的目录地址共享库目录下生成一个指向
共享库原文件的软连接,这软连接是方便配置文件寻找
gcc -share -Wl,soname,libmylib.so.1 -o libmylib.so.1.10 a.o b.o
指令里面设定了so name(libmylib.so.1,指向源文件的符号链接),
当配置共享库配置文件更新后会和
real name(libmylib.so.1.10,源文件)一起生成,命令行内链接
一般使用so name
ln -s libmylib.so.1.10 libmylib.so
手动生成link name
静态库与共享库对比
以main.c,静态库libmylib.a,共享库libmylib.so为例:
静态库:
gcc main.c libmylib.a -o test
首先,main.c编译为目标文件main.o,接下来为链接过程,静态库libmylib.a链接到main.o,一起组成为test,即main.o + libmylib.a -->test,所以静态库是编译到可执行程序内的,不管程序拷贝到那台电脑都可以运行,因为库已经在程序内了。
所以静态库链接的程序,体积庞大,但是移植性好
共享库(动态库)
gcc main.c libmylib.so.1 -o test
首先,main.c编译为目标文件main.o,接下来为链接过程,与静态库不同,共享库并不是将库本身链接到main.o一起生成可执行文件,而是生成一个符号记录表和依赖共享库版本(即程序共享库依赖关系信息)和main.o一起组成test可执行文件,当test程序运行时,它到链接部分会通过前面的依赖关系信息去系统内寻找共享库并执行,所以共享库移植性不好,程序必须在有共享库的系统内运行。
共享库也叫动态库,程序链接动态库,程序体积小,但移植性差