Linux 静态库动态库的制作命令及示例
静态库和动态库
在Linux中静态库以lib作为前缀, 以.a作为后缀, 中间是库的名字自己指定即可, 即: libxxx.a
在Windows中静态库一般以lib作为前缀, 以lib作为后缀, 中间是库的名字需要自己指定, 即: libxxx.lib
生成静态链接库
1将源文件进行汇编, 得到 .o 文件, 需要使用参数 -c $ gcc *.c -c
2将得到的 .o 进行打包, 得到静态库 $ ar rcs 静态库的名字(libxxx.a) 原材料(*.o)
3发布静态库 1. 提供头文件 **.h 2. 提供制作出来的静态库 libxxx.a
静态库制作示例
#一创建文件 #main.c #include <stdio.h> #include "head.h" int main() { add(); div(); } #add.c #include "head.h" void add() { printf("a+b = c\n"); } #div.c #include "head.h" void div() { printf("a-b = c\n"); } #head.h #ifndef _HEAD_H_ #define _HEAD_H_ #include <stdio.h> void add(); void div(); #endif
#二 创建静态库 #1 生成.o文件 gcc add.c div.c -c #2制作静态库 ar rcs libcalu.a add.o div.o
#3 使用静态库
gcc main.c -o cal -L./ -lcalu
-L: 指定库所在的目录(相对或者绝对路径)-l: 指定库的名字, 静态库的名字指去掉头部的(lib)和尾部的(.a) 剩下部分
生成动态链接库
生成动态链接库直接使用
gcc命令并且需要添加-fPIC(-fpic)以及-shared参数。
-fPIC 或 -fpic参数的作用是使得 gcc 生成的代码是与位置无关的,也就是使用相对位置。-shared参数的作用是告诉编译器生成一个动态链接库。
动态库制作示例
# 1. 将.c汇编得到.o, 需要额外的参数 -fpic或-fPIC $ gcc add.c div.c mult.c sub.c -c -fpic -I ./include/ #-I指出头文件相对位置 # 2. 将得到 .o 打包成动态库, 使用gcc , 参数 -shared $ gcc -shared add.o div.o mult.o sub.o -o libcalc.so # 3. 发布库文件和头文件 1. head.h 2. libcalc.so
动态库的使用
# 1. 拿到发布的动态库 `head.h libcalc.so # 示例目录: . ├── head.h ==> 函数声明 ├── libcalc.so ==> 函数定义 └── main.c ==> 函数测试 #2 在编译的时候指定动态库相关的信息: 库的路径 -L, 库的名字 -l $ gcc main.c -o app -L./ -lcalc #直接执行 ./app 会报错, 提示找不到动态库,还要进行下面操作
问题分析:可执行程序被执行起来之后:
程序执行的时候会先检测需要的动态库是否可以被加载,加载不到就会提示上边的错误信息
当动态库中的函数在程序中被调用了, 这个时候动态库才加载到内存,如果不被调用就不加载
动态库的检测和内存加载操作都是由动态连接器来完成的
动态连接器搜索顺序
-
可执行文件内部的 DT_RPATH 段
-
系统的环境变量
LD_LIBRARY_PATH -
系统动态库的缓存文件
/etc/ld.so.cache -
存储动态库/静态库的系统目录
/lib/,/usr/lib等
解决方案
方案1: 将库路径添加到环境变量 LD_LIBRARY_PATH 中 找到相关的配置文件 用户级别: ~/.bashrc —> 设置对当前用户有效 或者系统级别: /etc/profile —> 设置对所有用户有效 使用 vim 打开配置文件, 在文件最后添加这样一句话 export LD_LIBRARY_PATH=动态库的相对路径/绝对路径
让修改的配置文件生效 1修改了用户级别的配置文件, 关闭当前终端, 打开一个新的终端配置就生效了 2修改了系统级别的配置文件, 注销或关闭系统, 再开机配置就生效了 如果不想执行上边的操作, 可以执行一个命令让配置重新被加载 # 修改的是哪一个就执行对应的那个命令 # 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
验证
$ ldd 可执行程序名 # 举例: $ ldd app linux-vdso.so.1 => (0x00007ffe8fbd6000) libcalc.so => /home/robin/Linux/3Day/calc/test/libcalc.so (0x00007f5d85dd4000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5d85a0a000) /lib64/ld-linux-x86-64.so.2 (0x00007f5d85fd6000) ==> 动态链接器, 操作系统提供
优缺点比较
3.1 静态库 优点: 静态库被打包到应用程序中加载速度快 发布程序无需提供静态库,移植方便 缺点: 相同的库文件数据可能在内存中被加载多份, 消耗系统资源,浪费内存 库文件更新需要重新编译项目文件, 生成新的可执行程序, 浪费时间。 3.2 动态库 优点: 可实现不同进程间的资源共享 动态库升级简单, 只需要替换库文件, 无需重新编译应用程序 程序猿可以控制何时加载动态库, 不调用库函数动态库不会被加载 缺点: 加载速度比静态库慢, 以现在计算机的性能可以忽略 发布程序需要提供依赖的动态库

浙公网安备 33010602011771号