静态库与动态库区别
静态库会链接时将静态库中所有内容会放到程序代码区
动态库会随着程序的执行,将使用到的函数放在程序的动态库加载区
静态库
在 Linux 中静态库以 lib 作为前缀,以.a 作为后缀,中间是库的名字自己指定即可,即: libxxx.a
在 Windows 中静态库一般以 lib 作为前缀,以 lib 作为后缀,中间是库的名字需要自己指定,即: libxxx.lib
生成静态库
-
1.需要将源文件进行汇编,得到 .o 文件,需要使用参数 -c
$ gcc 源文件(*.c) -c
-
2.将得到的 .o 进行打包,得到静态库
$ ar rcs 静态库的名字(libxxx.a) 原材料(*.o)
-
3.发布静态库
提供头文件 **.h 提供制作出来的静态库 libxxx.a
使用静态库
编译的时候指定库信息
-L: 指定库所在的目录(相对或者绝对路径)
-l: 指定库的名字, 掐头(lib)去尾(.a) ==> calc
$ gcc main.c -o app -L ./ -l calc
动态库
在 Linux 中动态库以 lib 作为前缀,以.so 作为后缀,中间是库的名字自己指定即可,即: libxxx.so
在 Windows 中动态库一般以 lib 作为前缀,以 dll 作为后缀,中间是库的名字需要自己指定,即: libxxx.dll
生成动态库
1.将源文件进行汇编操作,需要使用参数 -c, 还需要添加额外参数 -fpic /-fPIC
$ gcc 源文件(*.c) -c -fpic
2.将得到的.o 文件打包成动态库,还是使用 gcc, 使用参数 -shared 指定生成动态库 (位置没有要求)
$ gcc -shared 与位置无关的目标文件(*.o) -o 动态库(libxxx.so)
3.发布动态库和头文件
head.h
libxxx.so
使用动态库
动态库编译
编译时指定库的路径和名称
$ gcc main.c -o app -L./ -lxxx
生成的程序中只有需要的动态库名称,并没有动态库路径
使用动态库程序执行
动态链接器会搜索程序内的动态库,搜索顺序按照优先级如下
1.可执行文件内部的 DT_RPATH 段
2.系统的环境变量 LD_LIBRARY_PATH
3.系统动态库的缓存文件 /etc/ld.so.cache
4.存储动态库 / 静态库的系统目录 /lib/, /usr/lib 等
按照以上四个顺序,依次搜索,找到之后结束遍历,最终还是没找到,动态连接器就会提示动态库找不到的错误信息。
通过ldd 程序名
可以知道程序中需要的动态库是否加载成功
动态库连结失败解决方法
方案 1: 将库路径添加到环境变量 LD_LIBRARY_PATH 中
用户级别: ~/.bashrc —> 设置对当前用户有效
系统级别: /etc/profile —> 设置对所有用户有效
export LIBRARY_PATH=$LIBRARY_PATH:动态库的绝对路径
让修改的配置文件生效
修改了用户级别的配置文件,关闭当前终端,打开一个新的终端配置就生效了
修改了系统级别的配置文件,注销或关闭系统,再开机配置就生效了
不想执行上边的操作,可以执行一个命令让配置重新被加载
修改的是哪一个就执行对应的那个命令
source 可以简写为一个 . , 作用是让文件内容被重新加载
$ source ~/.bashrc (. ~/.bashrc)
$ source /etc/profile (. /etc/profile)
方案 2: 更新 /etc/ld.so.cache 文件
找到动态库所在的绝对路径(不包括库的名字)比如:/home/robin/Library/
使用 vim 修改 /etc/ld.so.conf 这个文件,将上边的路径添加到文件中 (独自占一行)
1.打开文件
$ sudo vim /etc/ld.so.conf
2.添加动态库路径, 并保存退出
更新 /etc/ld.so.conf 中的数据到 /etc/ld.so.cache 中
必须使用管理员权限执行这个命令
$ sudo ldconfig
方案 3: 拷贝动态库文件到系统库目录 /lib/ 或者 /usr/lib 中 (或者将库的软链接文件放进去)
库拷贝:sudo cp /xxx/xxx/libxxx.so /usr/lib
创建软连接:sudo ln -s /xxx/xxx/libxxx.so /usr/lib/libxxx.so