Linux 开发系列笔记 - 静态库与动态库制作

68 阅读2分钟

静态库与动态库制作

介绍

  • 库文件是计算机上的一类文件,可以把它当作是一个代码仓库,可以为程序提供变量、函数和类。
  • 库文件与可执行文件差别不大,但是库文件不能直接运行。
  • 库分为两种:静态库动态库(共享库),静态库在编译时写入可执行文件,动态库在执行时读入内存。
  • 库具有代码保密部署与分发方便的优势。

静态库

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

静态库制作

首先自行安装ar工具。 假设我们的项目包括:main.chead.hadd.csub.cmul.cdiv.chead.c文件位于include目录下,add.csub.cmul.cdiv.c位于lib目录下。

$ 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)

静态库优缺点

  • 优点
    • 静态库打包在应用程序中,加载速度快。
    • 静态库提供单一文件,移植方便。
    • 适用于小体积库。
  • 缺点
    • 消耗系统资源,重复占用内存。
    • 更新、部署麻烦。

动态库

  • 命名规范:Linux:libxxx.so,Windows:libxxx.dll

动态库制作

$ 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跟随终端,重启终端将会重置。
$ 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为二进制文件,无法直接修改。
$ 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为终端启动配置,因此配置结束需重启终端。
$ vim ~/.bashrc  // 编辑 .bashrc 文件
// 在末行添加 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:库绝对路径, 保存并退出
// 重启终端并切换至 main 所属目录
$ ldd main  // 检查动态库依赖关系, 如正确操作, 无 not found
  • 方法三:添加至/lib/usr/lib目录(不推荐)。 注意:容易意外覆盖重要文件
$ mv libcalc.so /lib  // 或 mv libcalc.so /usr/lib
$ ldd main  // 检查动态库依赖关系, 如正确操作, 无 not found

动态库优缺点

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