当前位置: 首页 > news >正文

1.4 编译库:静态库、动态库

一、静态库

1.1 编译静态库

静态库:是将多个.o文件打包成一个归档文件(.a)

源码下载地址:universe.zip

(1)编译源码

gcc -c -o zeus.o zeus.c
gcc -c -o sun.o sun.c
gcc -c -o moon.o moon.c
gcc -c -o earth.o earth.c

(2)将.o文件打成包静态库

ar -rcs libstar.a moon.o sun.o earth.o# ar是Linux归档工具
# -r 如果库中有同名的.o文件,则替换
# -c 如果静态库不存在,则创建。
# -s 为静态库生成或更新索引

(3)使用静态库

poseidon.c 内容如下:

#include "sun.h"
#include "moon.h"
#include "earth.h"
#include <stdio.h>
int main()
{printf("poseidon do something \r\n");sun_rotate();moon_rotate();earth_rotate();return 0;
}
# 1.编译
gcc -c poseidon.c# 2.链接静态库
gcc -o poseidon poseidon.o -static -L./ -lstar # 通过-L指定库路径gcc -o poseidon poseidon.o libstar.a # 通过库完整名称来指定

1.2 封装静态库

封装静态库:在静态库基础上,增加一些功能代码,再重新打包静态库。

封装静态库流程

  • 将新增的.c文件编译成.o文件
  • 将静态库解压:ar -x
  • 将所有的.o文件重新打包成静态库

项目代码:handes.zip

(1)编译新增代码

gcc -c -o dog.o dog.c
gcc -c -o pig.o pig.c

(2)解压原静态库

# libstar.a会解压出:earth.o、moon.o、sun.o
ar -x libstar.a

(3)重新打包

ar -rcs libpower.a earth.o moon.o sun.o dig.o pig.o

注意

  • 不能直接把libstar.a和新.o文件一起打包,否则会有问题。
  • 静态库不是纯ELF文件,而是多个ELF文件的合并,所以必须先解压再打包

二、动态库

2.1 编译动态库

动态库:多个程序共用,共享节省磁盘空间。

源码下载地址:universe.zip

(1)编译源码

gcc -c -o sun.o sun.c
gcc -c -o moon.o moon.c
gcc -c -o earth.o earth.c 

(2)编译动态库

# 编译动态库 -fPIC 生成位置无关的代码,-shared生成动态库
gcc -fPIC -shared -o libstar.so sun.o moon.o earth.o

(3)使用动态库

# 链接动态库
gcc -c zeus.c
gcc -o zeus zeus.o libstar.so  # 运行报错,找不到libstar.so,因为Linux默认不从当前目录加载动态库。
./zeus# 可以设置环境变量 再运行
export LB_LIBRARY_PATH=./:$LB_LIBRARY_PATH
./zeus

2.2 显式使用动态库

问题:当静态库和动态库存在同名符号时,会导致符号冲突。
如:

  • 静态库A(依赖C标准库libc.a)和 动态库B(依赖C标准库libc.so)
  • 现在程序program需要同时链接A和B库。
  • A和B存在相同的符号(函数)就会导致符号冲突

解决方法正常链接静态库,动态库在代码中显式调用。

zeus.c 的代码:

  #include <stdio.h>#include<dlfcn.h>int main(int argc, char **argv){// 动态库的句柄void *handle;// 动态库中函数的地址int (*sun_rotate)();// 打开动态库handle = dlopen("/home/oem/Desktop/dev/cpp/universe/libstar.so", RTLD_LAZY);if (!handle) {fprintf(stderr, "%s\n", dlerror());return 1;}// 获取函数的地址sun_rotate = dlsym(handle, "sun_rotate");if (!sun_rotate) {fprintf(stderr, "%s\n", dlerror());return 1;}// 调用函数printf("zeus2 do something\n");(*sun_rotate)();// 关闭动态库dlclose(handle);return 0;}

编译和链接

# 会提示一个警告,但不影响运行
gcc -c zeus.c
gcc -c zeus zeus.o -ld -static

2.3 封装静态库为动态库

封装静态库成动态库:在已有的静态库基础上,增加一些功能代码,并封装成新动态库。

封装动态库流程

  • 将新增的.c文件编译成.o文件
  • 将静态库解压:ar -x
  • 将所有.o文件重新链接成动态库。

项目代码:handes.zip

(1)编译新增代码

gcc -c -o dog.o dog.c
gcc -c -o pig.o pig.c

(2)解压原静态库

# libstar.a会解压出:earth.o、moon.o、sun.o
ar -x libstar.a

(3)重新打包

gcc -fPIC -shared -o libpower.so dog.o pig.o moon.o earth.o sun.o

2.4 混合使用静态库与动态库

编译器支持同时链接静态库和动态库:

  • -Wl,-Bstatic 指定后续库静态链接。
  • -Wl,-Bdynamic 指定后续库动态链接。

示例项目

  • 项目用到动态库libstar.so和静态库libcook.a
  • 动态库存储在:/usr/local/star/lib
  • 静态库存储在:/usr/lib
gcc -c theseus.c
gcc -o theseus theseus.o -Wl,-Bstatic -lcook -Wl,-Bdynamic -L/usr/local/star/lib -lstar
#  静态库不使用-L指定库路径的原因,是/usr/lib系统默认的库路径

注意:避免同一库同时静态和动态链接,防止冲突。

http://www.lqws.cn/news/195445.html

相关文章:

  • 精益数据分析(94/126):30/10/10用户参与法则与定价策略的科学制定
  • leetcode1971. 寻找图中是否存在路径-easy
  • MyBatis
  • 【Go语言基础【7】】条件语句
  • Emacs定制:编译
  • OpenLayers 地图定位
  • 如何在CloudCompare中打开pcd文件
  • pyinstaller打包遇到报错,和pathlib冲突
  • 全球长序列高分辨率光合有效辐射(PAR)(1984-2018)
  • 汉诺塔问题深度解析
  • WebDB:一款免费高效的数据库开发工具
  • MAX3490
  • 关于嵌入式系统的知识课堂(一)
  • 008-C++String
  • 华为云Flexus+DeepSeek征文|基于华为云Flexus X和DeepSeek-R1打造个人知识库问答系统
  • 【芯片设计- RTL 数字逻辑设计入门 4.2 -- 组合逻辑赋值 + 时序逻辑状态保持】
  • Unity 中的颜色空间
  • CentOS 7 如何安装llvm-project-10.0.0?
  • solidity中sar和>>的区别
  • 新版双紫擒龙、紫紫红黄、动能二号源码指标源码公式讲解
  • Linux 初始化与服务管理全解析:rc.d、systemctl与service对比
  • 《ERP原理与应用教程》第3版习题和答案
  • 高等数学》(同济大学·第7版)第二章第一节“导数的概念“
  • 软件测试:质量保障的基石与未来趋势
  • 技术突破与落地应用:端到端 2.0 时代辅助驾驶TOP10 论文深度拆解系列【第一篇(排名不分先后)】
  • leetcode_206 反转链表
  • 【设计模式-5】设计模式的总结
  • 【办公类-104-01】20250606通义万相50分一天用完,通义万相2.1专业版测试
  • Guava LoadingCache 使用指南
  • Beckhoff(倍福)PLC 顺控程序转换条件解读