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

从零开始: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.alibmymath.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 无法被加载,通常是因为系统在运行时无法找到该动态库。

动态库的加载

  1. 将动态库加载到lib64系统路径下,拷贝到系统默认搜索的路径的下面

  2. 软链接到lib64的系统路径下。

sudo ln -s /home/ocean/linux/file/lib_dyn/libmymath.so /lib64

在这里插入图片描述

将其软连接到系统路径下。

在这里插入图片描述

  1. 运行程序时指定动态库路径: 如果运行时无法找到动态库,使用 LD_LIBRARY_PATH 来指定动态库的位置(临时)。
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/ocean/linux/file/lib_dyn

在这里插入图片描述

  1. /etc/ld.so.conof.d建立自己的动态库的路径配置文件,然后执行ldconfig进行刷新。

在这里插入图片描述

  • 同样也可以进行动态库的加载。

相关文章:

从零开始:Linux环境下如何制作静态库与动态库

个人主页&#xff1a;chian-ocean 文章专栏-Linux 前言 动静态库是编程中两种主要的库类型&#xff0c;它们用于帮助开发者复用已有的代码&#xff0c;而不需要每次都从头开始编写。它们的主要区别在于链接和加载的时机、方式以及使用场景 库 库就是一些已经写好并且经过测试…...

【智能体Agent】ReAct智能体的实现思路和关键技术

基于ReAct&#xff08;Reasoning Acting&#xff09;框架的自主智能体 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相关笔记

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

QT-绘画事件

实现颜色的随时调整&#xff0c;追加橡皮擦功能 widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QColor> #include <QPoint> #include <QVector> #include <QMouseEvent> #include <QPainter> #include <Q…...

鸿蒙NEXT开发-端云一体化开发

注意&#xff1a;博主有个鸿蒙专栏&#xff0c;里面从上到下有关于鸿蒙next的教学文档&#xff0c;大家感兴趣可以学习下 如果大家觉得博主文章写的好的话&#xff0c;可以点下关注&#xff0c;博主会一直更新鸿蒙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光数据集&#xff08;cervical spine X-ray dataset&#xff09; 一.颈椎X光&#xff08;1248张原始图像&#xff0c;无处理&#xff0c;jpg格式&#xff09; 二&#xff0e;颈椎X光&#xff08;1000张原始图像&#xff0c;无处理&#xff0c;jpg格式&#xff09; 此数据…...

(动态规划 完全背包 零钱兑换)leetcode 322

本题为完全背包 与01背包的区别是 物品可以任意取 而01背包只能取一次 这就导致了状态转移方程的不同 1.当放不下:的时候 转移方程是一样的 取0到i-1 物品&#xff0c;背包容量为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的一小步&#xff0c;昇腾芯片的一大步 相信在AI圈的人多多少少都看到了最近的信息&#xff1a;PyTorch最新2.1版本宣布支持华为昇腾芯片&#xff01; 1、 发生了什么事儿&#xff1f; 在2023年10月4日PyTorch 2.1版本的发布博客上&#xff0c;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的使用可以说是特别的频繁&#xff0c;但是官方提供的Tabs使用起来&#xff0c;存在tab选项卡切换动画滞后的问题。 原始动画无法满足产品的UI需求&#xff0c;因此&#xff0c;这篇文章将实现下面页面滑动&#xff0c;tab选项卡实时滑动的动画效果。 实现逻…...

Sass 模块化革命:深入解析 @use 语法,打造高效 CSS 架构

文章目录 前言use 用法1. 模块化与命名空间2. use 中 as 语法的使用3. as * 语法的使用4. 私有成员的访问5. use 中with默认值6. use 导入问题总结下一篇预告&#xff1a; 前言 在上一篇中&#xff0c;我们深入探讨了 Sass 中 import 语法的局限性&#xff0c;正是因为这些问题…...

【渗透测试】反弹 Shell 技术详解(一)

反弹 Shell 技术详解 一、前置知识 反弹 shell&#xff08;Reverse Shell&#xff09;是一种技术&#xff0c;攻击者利用它可以在远程主机上获得一个交互式的命令行接口。通常情况下&#xff0c;反弹 shell 会将标准输入&#xff08;stdin&#xff09;、标准输出&#xff08;…...

python:pymunk + pygame 模拟六边形中小球弹跳运动

向 chat.deepseek.com 提问&#xff1a;编写 python 程序&#xff0c;用 pymunk, 有一个正六边形&#xff0c;围绕中心点缓慢旋转&#xff0c;六边形内有一个小球&#xff0c;六边形的6条边作为墙壁&#xff0c;小球受重力和摩擦力、弹力影响&#xff0c;模拟小球弹跳运动&…...

Windows 图形显示驱动开发-WDDM 3.2-本机 GPU 围栏对象(二)

GPU 和 CPU 之间的同步 CPU 必须执行 MonitoredValue 的更新&#xff0c;并读取 CurrentValue&#xff0c;以确保不会丢失正在进行的信号中断通知。 当向系统中添加新的 CPU 等待程序时&#xff0c;或者如果现有的 CPU 等待程序失效时&#xff0c;OS 必须修改受监视的值。OS …...

23种设计模式之《模板方法模式(Template Method)》在c#中的应用及理解

程序设计中的主要设计模式通常分为三大类&#xff0c;共23种&#xff1a; 1. 创建型模式&#xff08;Creational Patterns&#xff09; 单例模式&#xff08;Singleton&#xff09;&#xff1a;确保一个类只有一个实例&#xff0c;并提供全局访问点。 工厂方法模式&#xff0…...

DEV-C++ 为什么不能调试?(正确解决方案)

为了备战pat考试&#xff0c;专门下载了DEV C&#xff0c;然后懵圈的发现&#xff0c;怎么无法调试(╯□&#xff09;╯︵ ┻━┻ 然后整了半天&#xff0c;终于在网上找到相应的解决方案&#xff01;&#xff01;&#xff01;-> Dev C 5.11 调试初始设置 <- 一共四步…...

【C++设计模式】第五篇:原型模式(Prototype)

注意&#xff1a;复现代码时&#xff0c;确保 VS2022 使用 C17/20 标准以支持现代特性。 克隆对象的效率革命 1. 模式定义与用途​ ​ 核心思想​ ​原型模式&#xff1a;通过复制现有对象​&#xff08;原型&#xff09;来创建新对象&#xff0c;而非通过new构造。​关键用…...

椭圆曲线密码学(ECC)

一、ECC算法概述 椭圆曲线密码学&#xff08;Elliptic Curve Cryptography&#xff09;是基于椭圆曲线数学理论的公钥密码系统&#xff0c;由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA&#xff0c;ECC在相同安全强度下密钥更短&#xff08;256位ECC ≈ 3072位RSA…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具

作者&#xff1a;来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗&#xff1f;了解下一期 Elasticsearch Engineer 培训的时间吧&#xff01; Elasticsearch 拥有众多新功能&#xff0c;助你为自己…...

FFmpeg 低延迟同屏方案

引言 在实时互动需求激增的当下&#xff0c;无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作&#xff0c;还是游戏直播的画面实时传输&#xff0c;低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架&#xff0c;凭借其灵活的编解码、数据…...

CMake基础:构建流程详解

目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/

使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题&#xff1a;docker pull 失败 网络不同&#xff0c;需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

MySQL中【正则表达式】用法

MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现&#xff08;两者等价&#xff09;&#xff0c;用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例&#xff1a; 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...

使用 SymPy 进行向量和矩阵的高级操作

在科学计算和工程领域&#xff0c;向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能&#xff0c;能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作&#xff0c;并通过具体…...

技术栈RabbitMq的介绍和使用

目录 1. 什么是消息队列&#xff1f;2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...

书籍“之“字形打印矩阵(8)0609

题目 给定一个矩阵matrix&#xff0c;按照"之"字形的方式打印这个矩阵&#xff0c;例如&#xff1a; 1 2 3 4 5 6 7 8 9 10 11 12 ”之“字形打印的结果为&#xff1a;1&#xff0c;…...

Windows 下端口占用排查与释放全攻略

Windows 下端口占用排查与释放全攻略​ 在开发和运维过程中&#xff0c;经常会遇到端口被占用的问题&#xff08;如 8080、3306 等常用端口&#xff09;。本文将详细介绍如何通过命令行和图形化界面快速定位并释放被占用的端口&#xff0c;帮助你高效解决此类问题。​ 一、准…...