建站提交历史文章,原文写作时间 2023 年 2 月前后。

静态库与动态库制作

介绍

  • 库文件是计算机上的一类文件,可以把它当作是一个代码仓库,可以为程序提供变量、函数和类。

  • 库文件与可执行文件差别不大,但是库文件不能直接运行。

  • 库分为两种:静态库动态库(共享库),静态库在编译时写入可执行文件,动态库在执行时读入内存。

  • 库具有代码保密部署与分发方便的优势。

静态库

  • 命名规范:Linux:libxxx.a,Windows:libxxx.lib

静态库制作

​ 首先自行安装ar工具。

​ 假设我们的项目包括:main.chead.hadd.csub.cmul.cdiv.c

head.c文件位于include目录下,add.csub.cmul.cdiv.c位于lib目录下。

1
2
3
$ gcc -c add.c sub.c mul.c div.c  // 生成目标代码: add.o sub.o mul.o div.o
$ ar src libcalc.a *.o // 建立静态库. s-索引, r-将文件插入备存文件中, c-建立备存文件, 库文件名: libcalc.a
$ gcc main.c -o main -L . -l calc // 打包程序(即使静态库在同一目录, 也需要-L)

静态库优缺点

  • 优点

    • 静态库打包在应用程序中,加载速度快。

    • 静态库提供单一文件,移植方便。

    • 适用于小体积库。

  • 缺点

    • 消耗系统资源,重复占用内存。
    • 更新、部署麻烦。

动态库

  • 命名规范:Linuxlibxxx.soWindows:libxxx.dll

动态库制作

1
2
3
$ gcc -c -fpic add.c sub.c mul.c div.c  // 生成目标代码: add.o sub.o mul.o div.o, 目标代码与位置无关
$ gcc -shared *.o -o libcalc.so // 建立动态库, 库文件名: libcalc.so
$ gcc main.c -o main -L . -l calc // 打包程序(即使静态库在同一目录, 也需要-L)

注意:此时启动程序./test将出现file not found错误,因为动态库路径没有被找到。

动态库路径搜索原理

  • 动态库在编译阶段仅写入描述信息,在程序运行时载入内存。

  • 当系统需要载入动态库时,通过库名与绝对路径定位动态库,绝对路径由动态载入器查找。

  • 对于elf格式的应用程序,查找优先级为:

    DT_RPATH\to 环境变量LD_LIBRARY_PATH \to /etc/ld.so.cache文件 \to /lib/usr/lib目录。

添加动态库路径

  • 方法一:配置环境变量

    注:LD_LIBRARY_PATH跟随终端,重启终端将会重置。

1
2
3
4
$ cd .  // 切换至 libcalc.so 所属目录, 此处为 . , 即为打包时 -L 目录
$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD // 向 LD_LIBRARY_PATH 追加 PWD 路径, PWD 也是环境变量为当前目录
$ cd . // 切换至 main 所属目录, 此处为 .
$ ldd main // 检查动态库依赖关系, 如正确操作, 无 not found
  • 方法二:配置/etc/ld.so.cache文件

    注:/etc/ld.so.cache为二进制文件,无法直接修改。

1
2
3
4
$ sudo vim /etc/ld.so.conf  // 编辑 /etc/ld.so.conf 文件需要管理员权限
// 在末行添加 库绝对路径, 保存并退出
$ sudo ldconfig // 重新配置 ld.so.cache 文件, 实际上将 ld.so.conf 加载为 ld.so.cache 文件
$ ldd main // 检查动态库依赖关系, 如正确操作, 无 not found
  • 方法三:配置~/.bashrc文件(不推荐)

    注:~/.bashrc为终端启动配置,因此配置结束需重启终端。

1
2
3
4
$ vim ~/.bashrc  // 编辑 .bashrc 文件
// 在末行添加 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:库绝对路径, 保存并退出
// 重启终端并切换至 main 所属目录
$ ldd main // 检查动态库依赖关系, 如正确操作, 无 not found
  • 方法三:添加至/lib/usr/lib目录(不推荐)

    注意:容易意外覆盖重要文件

1
2
$ mv libcalc.so /lib  // 或 mv libcalc.so /usr/lib
$ ldd main // 检查动态库依赖关系, 如正确操作, 无 not found

动态库优缺点

  • 优点
    • 实现系统资源共享。
    • 更新、部署方便。
    • 动态库加载时刻可控制。
    • 适用于大体积库。
  • 缺点
    • 加载速度相比于静态库较慢。
    • 发布程序需提供相关库。