从零开始:Linux环境下如何制作静态库与动态库
个人主页:chian-ocean
文章专栏-Linux
前言
动静态库是编程中两种主要的库类型,它们用于帮助开发者复用已有的代码,而不需要每次都从头开始编写。它们的主要区别在于链接和加载的时机、方式以及使用场景
库
库就是一些已经写好并且经过测试的功能模块,你只需要在自己的程序中“借用”这些功能,而无需重新做同样的工作。这样不仅节省了时间,还能提高代码的质量和稳定性。
库的形式
库的形式主要有两种,分别是 静态库 和 动态库。它们的区别在于程序如何使用这些库,以及库文件在程序中的存储方式。
静态库 (Static Library)
静态库是在程序编译时就被链接到可执行文件中的库,所有的库代码会被嵌入到最终生成的程序中。程序在运行时不再依赖外部的库文件。
文件扩展名:
- Linux/Unix 系统:
.a
(archive) - Windows 系统:
.lib
动态库 (Dynamic Library)
动态库是在程序运行时加载的库,程序并不会将库的代码嵌入到程序中,而是在程序启动时,或者在程序运行时动态加载需要的库文件。
文件扩展名:
- Linux/Unix 系统:
.so
(Shared Object) - Windows 系统:
.dll
(Dynamic Link Library)
总结:
特性 | 静态库 | 动态库 |
---|---|---|
链接时机 | 编译时链接,库代码被嵌入到程序中 | 运行时链接,程序在执行时动态加载库 |
可执行文件大小 | 程序文件较大,因为库代码被包含在其中 | 程序文件较小,只包含对库的引用,库的代码在外部 |
依赖关系 | 不依赖外部库文件,所有代码在可执行文件中 | 依赖外部库文件,程序必须确保运行时找到对应的库文件 |
共享 | 每个程序都包含自己需要的库代码,不共享 | 多个程序可以共享同一个库文件,节省内存和磁盘空间 |
更新 | 库文件更新时需要重新编译程序 | 库文件更新时,无需重新编译程序,只需要确保兼容性 |
性能 | 程序启动较快,因为所有代码都已经包含在内 | 程序启动时需要加载库文件,可能稍慢,且可能会有额外的内存管理开销 |
静态库
静态库的制作
**静态库(Static Library)**是一个打包了多个目标文件(.o
文件)或其他库文件的归档文件。它可以在编译时链接到程序中,生成最终的可执行文件。静态库的扩展名通常为 .a
(在 Unix/Linux 系统上)。
编写源文件: 创建包含函数实现的 .c
文件,例如 math.c
。
- 简单的加减乘除。
#include "mymath.h" int errno = 0 ;
int add(int x,int y)
{ return x + y;
}
int sub(int x,int y)
{ return x - y;
}
int mul(int x,int y)
{ return x * y;
}
int div(int x,int y)
{ if(y == 0) { errno = -1; return -1; } return x / y;
}
编写头文件: 创建包含函数实现的 .c 函数声明
#pragma once
#include <stdio.h>
extern int errno; int add(int x,int y);
int sub(int x,int y);
int mul(int x,int y);
int div(int x,int y);
编写Makefile:创建自动化构建文件
# 定义静态库的名称
lib=libmath.a # 生成静态库 libmath.a 的规则
# 依赖 mymath.o 文件,并将其打包成静态库
$(lib): mymath.o # 使用 ar 命令将目标文件 mymath.o 添加到静态库 libmath.a 中ar -rc $@ $^# 编译 mymath.c 文件为 mymath.o 目标文件的规则
mymath.o: mymath.c # 使用 gcc 编译 mymath.c 文件为目标文件 mymath.ogcc -c $^# 定义伪目标 clean,它用于清理构建产生的文件
.PHONY: clean
clean: # 删除所有目标文件 (.o) 和库文件 (lib*)rm -rf *.o lib* # 定义伪目标 output,它用于创建输出目录并复制必要的文件
.PHONY: output
output: # 创建 lib/include 目录mkdir -p lib/include # 创建 lib/libmymath 目录mkdir -p lib/libmymath # 将所有头文件复制到 lib/include 目录cp *.h lib/include # 将静态库 (.a 文件) 复制到 lib/libmymath 目录cp *.a lib/libmymath
静态库的使用
#include "mymath.h" // 包含自定义的头文件 mymath.hint main() {printf("add(1 + 1) = %d\n", add(1, 1));printf("sub(1 + 1) = %d\n", sub(1, 1));printf("mul(1 + 1) = %d\n", mul(1, 1));printf("div(1 + 1) = %d\n", div(1, 1));return 0;
}
写一个代码利用自己写的库;
- 此时的静态库在
/lib/libmymath
的路径下。 - 头文件在
/lib/include
的路径下。 - 可执行程序在
/mian
的目录下。
库路径和头文件路径只有用户知道
gcc main.c -I ../lib/include/ -L ../lib/libmymath/ -lmymath
-
gcc main.c
:使用gcc
编译器来编译main.c
文件。 -
-I ./lib/include/
:这个选项告诉编译器在./lib/include/
目录中查找头文件 (*.h
)。-I
后面跟着的是头文件所在的目录。 -
-L ./lib/libmymath/
:这个选项告诉编译器在./lib/libmymath/
目录中查找库文件 (*.a
或*.so
),-L
后面跟的是库文件所在的目录。 -
-lmymath
:这个选项告诉编译器链接libmymath
库。编译器会自动查找并链接名为libmymath.a
或libmymath.so
的库文件。注意,lib
前缀和.a
后缀会被自动省略。
库路径和头文件路径在系统路径下
/usr/lib64 #库的系统默认路径
/usr/include #头文件的系统默认路径
这时候我们仅仅需要手动连接库就好了。
gcc main.c -lmymath
动态库
动态库的制作
- 把静态库的的方法做成动态库。
编写Makefile:创建自动化构建文件
# 定义变量dy_mymath,表示生成的动态库文件名
dy_mymath = libmymath.so# 生成动态库 libmymath.so 目标
# 该目标依赖于 mymath.o 文件
$(dy_mymath): mymath.o# 使用gcc命令生成动态库,-shared 表示生成共享库,-o 用于指定输出文件# $@ 代表目标文件(这里是 libmymath.so),$^ 代表所有依赖文件(这里是 mymath.o)gcc -shared -o $@ $^# 生成目标文件 mymath.o
# 该目标依赖于 mymath.c 文件
mymath.o: mymath.c# 使用gcc编译源文件 mymath.c 生成目标文件 mymath.o# -fPIC 生成位置无关代码(适用于动态库),-c 只编译源文件,不进行链接# $^ 代表依赖文件(这里是 mymath.c)gcc -fPIC -c $^# 声明 clean 为伪目标,表示 make clean 是一个命令,而不是文件
.PHONY: clean# clean 目标,用于清理生成的目标文件和动态库文件
clean:# 删除所有目标文件 (.o) 和共享库文件 (.so)# -rf 强制删除,不询问确认rm -rf *.o *.so
动态库的使用
库路径和头文件路径只有用户知道
gcc main.c -I ../ -L ../ -lmymath
-
-I../
:此选项指定了头文件路径,告诉编译器去../
目录下查找头文件。 -
-L../
:此选项指定了库文件路径,告诉链接器去../
目录下查找库文件。 -
-lmymath
:告诉编译器链接libmymath.so
动态库。链接器会自动在路径中查找名为libmymath.so
的动态库文件。
库路径和头文件路径在系统路径下
/usr/lib64 #库的系统默认路径
/usr/include #头文件的系统默认路径
这时候我们仅仅需要手动连接库就好了。
gcc main.c -lmymath
执行可执行程序的时候就会报错:
./a.out: error while loading shared libraries: libmymath.so: cannot open shared object file: No such file or directory
这个错误表明 动态库 libmymath.so
无法被加载,通常是因为系统在运行时无法找到该动态库。
动态库的加载
-
将动态库加载到
lib64
系统路径下,拷贝到系统默认搜索的路径的下面 -
软链接到
lib64
的系统路径下。
sudo ln -s /home/ocean/linux/file/lib_dyn/libmymath.so /lib64
将其软连接到系统路径下。
- 运行程序时指定动态库路径: 如果运行时无法找到动态库,使用
LD_LIBRARY_PATH
来指定动态库的位置(临时)。
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/ocean/linux/file/lib_dyn
- 在
/etc/ld.so.conof.d
建立自己的动态库的路径配置文件,然后执行ldconfig
进行刷新。
- 同样也可以进行动态库的加载。
相关文章:

从零开始:Linux环境下如何制作静态库与动态库
个人主页:chian-ocean 文章专栏-Linux 前言 动静态库是编程中两种主要的库类型,它们用于帮助开发者复用已有的代码,而不需要每次都从头开始编写。它们的主要区别在于链接和加载的时机、方式以及使用场景 库 库就是一些已经写好并且经过测试…...
【智能体Agent】ReAct智能体的实现思路和关键技术
基于ReAct(Reasoning Acting)框架的自主智能体 import re from typing import List, Tuplefrom langchain_community.chat_message_histories.in_memory import ChatMessageHistory from langchain_core.language_models.chat_models import BaseChatM…...

Java进阶:Zookeeper相关笔记
概要总结: ●Zookeeper是一个开源的分布式协调服务,需要下载并部署在服务器上(使用cmd启动,windows与linux都可用)。 ●zookeeper一般用来实现诸如数据订阅/发布、负载均衡、命名服务、集群管理、分布式锁和分布式队列等功能。 ●有多台服…...

QT-绘画事件
实现颜色的随时调整,追加橡皮擦功能 widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QColor> #include <QPoint> #include <QVector> #include <QMouseEvent> #include <QPainter> #include <Q…...

鸿蒙NEXT开发-端云一体化开发
注意:博主有个鸿蒙专栏,里面从上到下有关于鸿蒙next的教学文档,大家感兴趣可以学习下 如果大家觉得博主文章写的好的话,可以点下关注,博主会一直更新鸿蒙next相关知识 目录 端云一体化开发基本概念 传统架构 端云一…...

大模型——股票分析AI工具开发教程
大模型——股票分析AI工具开发教程 在本教程中,我们将利用Google Gemini 2.0 Flash模型创建一个简单但有效的股票分析器。 你是否曾被大量的股票市场数据所淹没?希望有一个私人助理来筛选噪音并为您提供清晰、可操作的见解?好吧,你可以自己构建一个,而且由于 Python 的强…...

nexus 实现https 私有镜像搭建
1、安装nexus 1.1 安装JDK17 rpm -ivh jdk-17.0.13_linux-x64_bin.rpm 1.2 下载安装包解压到指定目录 tar zxvf nexus-3.77.2-02-unix.tar.gz -C /usr/local 2、运行nexus 默认8081端口 cd /usr/local/nexus-3.77.2-02 && bin/nexus start 3、配置nexus私有docker 镜…...

颈椎X光数据集(cervical spine X-ray dataset)
颈椎X光数据集(cervical spine X-ray dataset) 一.颈椎X光(1248张原始图像,无处理,jpg格式) 二.颈椎X光(1000张原始图像,无处理,jpg格式) 此数据…...

(动态规划 完全背包 零钱兑换)leetcode 322
本题为完全背包 与01背包的区别是 物品可以任意取 而01背包只能取一次 这就导致了状态转移方程的不同 1.当放不下:的时候 转移方程是一样的 取0到i-1 物品,背包容量为j的最优值 else 2.放得下:就是取 0到i-1 物品,背包容量为j的最优值和 “0到i的[j-w[i]]v…...

【AI大模型】DeepSeek + Kimi 高效制作PPT实战详解
目录 一、前言 二、传统 PPT 制作问题 2.1 传统方式制作 PPT 2.2 AI 大模型辅助制作 PPT 2.3 适用场景对比分析 2.4 最佳实践与推荐 三、DeepSeek Kimi 高效制作PPT操作实践 3.1 Kimi 简介 3.2 DeepSeek Kimi 制作PPT优势 3.2.1 DeepSeek 优势 3.2.2 Kimi 制作PPT优…...

Pytorch的一小步,昇腾芯片的一大步
Pytorch的一小步,昇腾芯片的一大步 相信在AI圈的人多多少少都看到了最近的信息:PyTorch最新2.1版本宣布支持华为昇腾芯片! 1、 发生了什么事儿? 在2023年10月4日PyTorch 2.1版本的发布博客上,PyTorch介绍的beta版本…...

rabbitmq-amqp事务消息+消费失败重试机制+prefetch限流
1. 安装和配置 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency><dependency> <groupId>com.fasterxml.jackson.core</groupId> <arti…...

【HarmonyOS Next】自定义Tabs
背景 项目中Tabs的使用可以说是特别的频繁,但是官方提供的Tabs使用起来,存在tab选项卡切换动画滞后的问题。 原始动画无法满足产品的UI需求,因此,这篇文章将实现下面页面滑动,tab选项卡实时滑动的动画效果。 实现逻…...

Sass 模块化革命:深入解析 @use 语法,打造高效 CSS 架构
文章目录 前言use 用法1. 模块化与命名空间2. use 中 as 语法的使用3. as * 语法的使用4. 私有成员的访问5. use 中with默认值6. use 导入问题总结下一篇预告: 前言 在上一篇中,我们深入探讨了 Sass 中 import 语法的局限性,正是因为这些问题…...
【渗透测试】反弹 Shell 技术详解(一)
反弹 Shell 技术详解 一、前置知识 反弹 shell(Reverse Shell)是一种技术,攻击者利用它可以在远程主机上获得一个交互式的命令行接口。通常情况下,反弹 shell 会将标准输入(stdin)、标准输出(…...

python:pymunk + pygame 模拟六边形中小球弹跳运动
向 chat.deepseek.com 提问:编写 python 程序,用 pymunk, 有一个正六边形,围绕中心点缓慢旋转,六边形内有一个小球,六边形的6条边作为墙壁,小球受重力和摩擦力、弹力影响,模拟小球弹跳运动&…...
Windows 图形显示驱动开发-WDDM 3.2-本机 GPU 围栏对象(二)
GPU 和 CPU 之间的同步 CPU 必须执行 MonitoredValue 的更新,并读取 CurrentValue,以确保不会丢失正在进行的信号中断通知。 当向系统中添加新的 CPU 等待程序时,或者如果现有的 CPU 等待程序失效时,OS 必须修改受监视的值。OS …...
23种设计模式之《模板方法模式(Template Method)》在c#中的应用及理解
程序设计中的主要设计模式通常分为三大类,共23种: 1. 创建型模式(Creational Patterns) 单例模式(Singleton):确保一个类只有一个实例,并提供全局访问点。 工厂方法模式࿰…...

DEV-C++ 为什么不能调试?(正确解决方案)
为了备战pat考试,专门下载了DEV C,然后懵圈的发现,怎么无法调试(╯□)╯︵ ┻━┻ 然后整了半天,终于在网上找到相应的解决方案!!!-> Dev C 5.11 调试初始设置 <- 一共四步…...
【C++设计模式】第五篇:原型模式(Prototype)
注意:复现代码时,确保 VS2022 使用 C17/20 标准以支持现代特性。 克隆对象的效率革命 1. 模式定义与用途 核心思想 原型模式:通过复制现有对象(原型)来创建新对象,而非通过new构造。关键用…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...

视频字幕质量评估的大规模细粒度基准
大家读完觉得有帮助记得关注和点赞!!! 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用,因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型(VLMs)在字幕生成方面…...

3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...

基于IDIG-GAN的小样本电机轴承故障诊断
目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) 梯度归一化(Gradient Normalization) (2) 判别器梯度间隙正则化(Discriminator Gradient Gap Regularization) (3) 自注意力机制(Self-Attention) 3. 完整损失函数 二…...

免费数学几何作图web平台
光锐软件免费数学工具,maths,数学制图,数学作图,几何作图,几何,AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...

macOS 终端智能代理检测
🧠 终端智能代理检测:自动判断是否需要设置代理访问 GitHub 在开发中,使用 GitHub 是非常常见的需求。但有时候我们会发现某些命令失败、插件无法更新,例如: fatal: unable to access https://github.com/ohmyzsh/oh…...

C++--string的模拟实现
一,引言 string的模拟实现是只对string对象中给的主要功能经行模拟实现,其目的是加强对string的底层了解,以便于在以后的学习或者工作中更加熟练的使用string。本文中的代码仅供参考并不唯一。 二,默认成员函数 string主要有三个成员变量,…...

链式法则中 复合函数的推导路径 多变量“信息传递路径”
非常好,我们将之前关于偏导数链式法则中不能“约掉”偏导符号的问题,统一使用 二重复合函数: z f ( u ( x , y ) , v ( x , y ) ) \boxed{z f(u(x,y),\ v(x,y))} zf(u(x,y), v(x,y)) 来全面说明。我们会展示其全微分形式(偏导…...