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

【Linux】动态库和静态库——动态库和静态库的打包和使用、gcc编译、拷贝到系统默认的路径、建立软连接

文章目录

  • 动态库和静态库
    • 1.静态库和动态库的介绍
    • 2.静态库的打包和使用
      • 2.1生成静态库
      • 2.2使用静态库的三种方式
        • 2.2.1gcc编译
        • 2.2.2拷贝到系统默认的路径
        • 2.2.3建立软连接
    • 3.动态库的打包和使用
      • 3.1生成动态库
      • 3.2使用动态库
      • 3.3解决加载不到动态库的方法

动态库和静态库

1.静态库和动态库的介绍

  静态库和动态库是两种不同的程序库,它们在编译和链接阶段有不同的应用方式和特点。

  静态库(Static Library):

  静态库是在编译时被全部链接到目标程序中,一同生成可执行文件,所以生成的可执行文件较大,但运行时不需要链接其他库。静态库的后缀通常为.a或.lib。在程序发布时,通常只需要提供静态库和可执行文件,而不需要源代码。

  动态库(Dynamic Library):

  动态库在程序运行时才被加载和链接,所以多个程序可以共享相同的动态库代码,从而节省内存。动态库的后缀通常为.so(Linux)或.dll(Windows)。动态库的代码需要满足能够被加载到不同进程的不同地址,因此需要进行特别的编译处理。动态库在程序运行时由操作系统负责加载和链接,因此如果程序需要更新某个模块,只需要更新相应的动态库即可,而不需要重新编译整个程序。

  静态库和动态库的主要区别在于链接时间和使用方式。静态库在编译时链接到目标程序中,而动态库在程序运行时才被加载和链接。此外,静态库和动态库的打包和分发方式也不同,静态库需要和可执行文件一起发布,而动态库只需要提供动态库文件即可。

  静态库(后缀为 .a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库。

  动态库(后缀为 .so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。

            

2.静态库的打包和使用

  静态库的打包原理基于链接器的工作原理,将各个目标文件中的代码和符号合并到一起,以便在其他项目中进行使用。先将所有目标文件(.c文件)编译为(.o文件),然后把目标文件(.o文件)打包在一起,生成一个或多个静态库文件。 这个过程通常使用ar命令(在Linux和类Unix系统中)或lib命令(在Windows系统中)完成。

  打包过程中,需要将所有的目标文件组织到一个归档文件中,形成静态库。这个归档文件是一个持久的数据库,包含了目标文件的名称、创建时间和修改时间等信息。在链接阶段,链接器会从静态库中提取需要的目标文件,将其链接到最终的可执行文件中。

  

2.1生成静态库

  我们假设使用mymath.c和mymath.h模拟为静态库。下面是制作和打包静态库的过程。

  假设我们的main.c想要编译外部的两个源文件和头文件(mymath.c和mymath.h)。

  mymath.h

#pragma once#include <stdio.h>extern int myerrno;int add(int x, int y);
int sub(int x, int y);
int mul(int x, int y);
int div(int x, int y);

  
  mymath.c

#include "mymath.h"int myerrno = 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){myerrno = 1;return -1;}return x / y;
}

  
  main.c

#include "mymath.h"
//#include "myinc/mymath.h"int main()
{extern int myerrno;//printf("1+1=%d\n", add(1,1));int n=div(10,0);//C语言实例化是从右向左,所以myerrno输出的是0printf("10/0=%d, errno=%d\n", n, myerrno);//gcc默认的链接方式是动态链接//没有动态库就默认使用静态库链接return 0;
}  

  

  经过下面的make操作,生成.a静态库文件。

在这里插入图片描述

static-lib=libmymath.a//将我们静态库的名称命名为static-lib$(static-lib):mymath.o//如何使用mymath.o构建static-libar -rc $@ $^//构建静态库 目标文件 依赖文件
mymath.o:mymath.c//如何使用mymath.c构建mymath.ogcc -c $^//编译到.o文件.PHONY:clean//伪目标
clean:      //清除所有的.o  .a  和static-lib文件rm -rf *.o *.a static-lib.PHONY:output//打包文件
output:mkdir -p static-lib/include//创建目录includemkdir -p static-lib/my-static-lib//创建目录my-static-libcp *.h static-lib/include//拷贝所有.h文件到includecp *.a static-lib/my-static-lib//拷贝所有.a文件到my-static-lib

  

  此时的文件为,我们进行make操作:

在这里插入图片描述

  

  我们可以看到生成了mymath.o文件和我们需要的打包好的静态库libmymath.a文件。此时我们就需要使用这个静态库libmymath.a了。

在这里插入图片描述
  

  顺带着打包一下,将.h和.a文件放入一个static-lib文件中。

在这里插入图片描述
在这里插入图片描述

  

2.2使用静态库的三种方式

2.2.1gcc编译

  当前的文件下输入 gcc main.c -I ./头文件的路径 -L ./库文件的路径 -l 链接库的名称 即可生成我们的可编译程序。

在这里插入图片描述
  

  注意上面的代码所含的内容缺一不可:

  缺少头文件和库文件,链接出错。

在这里插入图片描述
  
  缺少库文件,链接出错。

在这里插入图片描述

  
  找不到链接库的名称,链接出错。

在这里插入图片描述

  
  虽然链接出错,但是仍然可以汇编为.o文件。

在这里插入图片描述

  

2.2.2拷贝到系统默认的路径

  拷贝文件到系统路径同样可以实现静态库的使用:

  sudo cp static-lib/include/mymath.h /usr/include/

   sudo cp static-lib/my-static-lib/libmymath.a /lib64/libmymath.a

在这里插入图片描述
  

  gcc 无法直接编译我们的main.c文件还是需要我们告诉编译器其中的静态库的名字才可以,-l mymath

在这里插入图片描述
  

  但是一般不推荐,这样会对我们系统的路径造成污染,删除:

在这里插入图片描述

  

2.2.3建立软连接

  软链接应用广泛,可以快速找到.h和.c文件。

  使用时,main函数的头文件要修改为文件的路径。

//#include "mymath.h"
#include "myinc/mymath.h"//使用软链接时编译

  软链接includesudo ln -s /home/wu1/study_liunx/2024_1_23动静态库测试/static-lib/include /usr/include/myinc

  软链接.a静态库sudo ln -s /home/wu1/study_liunx/2024_1_23动静态库测试/static-lib/my-static-lib/libmymath.a /lib64/libmymath.a

  解除链接:sudo unlink/usr/include/myinc sudo unlink/lib64/libmymath.a

在这里插入图片描述

            

3.动态库的打包和使用

  动态库的打包原理是将多个相对独立的部分按照模块化的方式拆分成不同的文件,并在程序运行时才将这些模块链接在一起形成一个完整的程序。与静态库不同,动态库不会将所有代码和数据都包含在最终的可执行文件中,而是在程序运行时由操作系统动态加载到内存中。

  打包动态库时,需要将各个目标文件(.o文件)编译为动态库文件(.so文件),以便在程序运行时被加载和链接。 这个过程通常使用gcc命令,并指定-fPIC-shared选项,以便生成位置无关代码和共享库。

  

3.1生成动态库

  和上面生成的.a类似,动态库是后缀为.so的文件,我们下面使用mylog.h mylog.c myprint.h myprint.c进行动态库的打包实现。

  main.c

#include "mylog.h"
#include "myprint.h"int main()
{Print();Log("这是一个动态库打包的测试");return 0;
}  

  
  mylog.h

#pragma once#include <stdio.h>void Log(const char*);

  
  mylog.c

#include "mylog.h"void Log(const char*info)
{printf("Warning: %s\n", info);
}

  
  myprint.h

#pragma once#include <stdio.h>void Print();

  
  myprint.c

#include "myprint.h"void Print()
{printf("hello new world!\n");printf("hello new world!\n");printf("hello new world!\n");printf("hello new world!\n");
}

  

  经过下面的make操作,生成.so静态库文件。
在这里插入图片描述

dy-lib=libmymethod.so//将我们动态库的名称命名为dy-lib.PHONY:all//伪目标为dy-lib文件
all: $(dy-lib)$(dy-lib):mylog.o myprint.o//将mylog.o和myprint.o文件打包为动态库文件gcc -shared -o $@ $^//形成共享库(可执行程序加载内存)mylog.o:mylog.c//将.c文件编译为.o文件gcc -fPIC -c $^//-fPIC产生与位置无关码
myprint.o:myprint.cgcc -fPIC -c $^.PHONY:clean//伪目标删除操作
clean:rm -rf *.o *.so dy-lib.PHONY:output//打包动态库
output:mkdir -p dy-lib/includemkdir -p dy-lib/my-dy-libcp *.h dy-lib/includecp *.so dy-lib/my-dy-lib

  

  此时的文件为,我们进行make操作:

在这里插入图片描述
  

  我们将我们的头文件和.so文件打包为了dy-lib文件。

在这里插入图片描述

在这里插入图片描述
  

3.2使用动态库

  和上面使用静态库一样,我们链接头文件和库文件,而且找到链接库的名称即可。

  gcc main.c -I ./dy-lib/include/ -L ./dy-lib/my-dy-lib -l mymethod

  

  但是在链接的时候,会报错。因为动态库在哪里也要告诉系统——加载器,加载同样也需要过程。

在这里插入图片描述
  

  进行动态库的软链接,ldd成功找到链接。

在这里插入图片描述

  

  运行成功。

在这里插入图片描述

  

3.3解决加载不到动态库的方法

  1.拷贝到系统默认的库路径 /lib64 /usr/lib64/

  2.在系统默认的库路径 /ib64 /usr/lib64/下建立软连接

  3.将自己的库所在的路径,添加到系统的环境变量LD LIBRARY PATH中

  4. /etc/ld.so.conf.d 建立自己的动态库路径的配置文件,然后重新ldconfiq即可

  实际情况,我们用的库都是别人的成熟的库,都采用直接安装到系统的方式。

相关文章:

【Linux】动态库和静态库——动态库和静态库的打包和使用、gcc编译、拷贝到系统默认的路径、建立软连接

文章目录 动态库和静态库1.静态库和动态库的介绍2.静态库的打包和使用2.1生成静态库2.2使用静态库的三种方式2.2.1gcc编译2.2.2拷贝到系统默认的路径2.2.3建立软连接 3.动态库的打包和使用3.1生成动态库3.2使用动态库3.3解决加载不到动态库的方法 动态库和静态库 1.静态库和动…...

【Redis】Redis有哪些适合的场景

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;Redis ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 &#xff08;1&#xff09;会话缓存&#xff08;Session Cache&#xff09; &#xff08;2&#xff09;全页缓存&#xff08;FPC…...

uniapp上传音频文件到服务器

视频教程地址&#xff1a; 【uniapp录音上传组件&#xff0c;将录音上传到django服务器】 https://www.bilibili.com/video/BV1wi4y1p7FL/?share_sourcecopy_web&vd_sourcee66c0e33402a09ca7ae1f0ed3d5ecf7c uniapp 录制音频文件上传到django服务器保存到服务器 &#xf…...

C#-正则表达式

1.C#功能点&#xff1a; 验证格式&#xff1a;通过正则表达式&#xff0c;我们可以检查一个字符串是否符合特定的格式要求&#xff0c;例如验证邮箱、电话号码、身份证号码等。 查找和提取&#xff1a;我们可以使用正则表达式来查找字符串中符合特定模式的部分&#xff0c;并将…...

【word】论文、报告:①插入图表题注,交叉引用②快速插入图表目录③删改后一键更新

【word】①插入图表题注&#xff0c;②删改后一键更新 写在最前面插入题注交叉引用修改插入题注的文字格式快速插入图表目录 插入题注后有删改&#xff0c;实现编号一键更新 &#x1f308;你好呀&#xff01;我是 是Yu欸 &#x1f30c; 2024每日百字篆刻时光&#xff0c;感谢你…...

Spring Security 的TokenStore三种实现方式

博主介绍&#xff1a;✌专注于前后端领域开发的优质创作者、秉着互联网精神开源贡献精神&#xff0c;答疑解惑、坚持优质作品共享。本人是掘金/腾讯云/阿里云等平台优质作者、擅长前后端项目开发和毕业项目实战&#xff0c;深受全网粉丝喜爱与支持✌有需要可以联系作者我哦&…...

微信小程序 图片自适应高度 宽度 完美适配原生或者uniapp

-- - - - 查了一下百度看到网上图片高度自适应的解决方案 基本是靠JS获取图片的宽度进行按比例计算得出图片高度。 不是很符合我的需求/ 于是我脑瓜子一转 想到一种新的解决方案 不用JS计算也能完美解决。 我写了一个组件&#xff0c;直接导入可以使用。 - - - 1.新…...

Go语言基础之反射

1.变量的内在机制 Go语言中的变量是分为两部分的: 类型信息&#xff1a;预先定义好的元信息。值信息&#xff1a;程序运行过程中可动态变化的。 2.反射介绍 反射是指在程序运行期间对程序本身进行访问和修改的能力。程序在编译时&#xff0c;变量被转换为内存地址&#xff…...

MySQL十部曲之六:数据操作语句(DML)

文章目录 前言语法约定DELETEINSERTSELECT查询列表SELECT 选项子句FROMWHEREORDER BYGROUP BYHAVINGWINDOWLIMITFOR SELECT ... INTO连接查询CROSS JOIN和INNER JOINON和USINGOUTER JOINNATURE JOIN 子查询标量子查询使用子查询进行比较带有ANY、IN或SOME的子查询带有ALL的子查…...

Quartus生成烧录到FPGA板载Flash的jic文件

简要说明&#xff1a; Altera的FPGA芯片有两种基本分类&#xff0c;一类是纯FPGA&#xff0c;另一类是FPGASoc&#xff08;System on chip)&#xff0c;也就是FPGAHPS&#xff08;Hard Processor System&#xff0c;硬核处理器&#xff09;&#xff0c;对应两种Flash烧录方式&a…...

CSS 多色正方形上升

<template><view class="loop cubes"><view class="item cubes"></view> <!-- 方块1 --><view class="item cubes"></view> <!-- 方块2 --><view class="item cubes"></vie…...

《HelloGitHub》第 94 期

兴趣是最好的老师&#xff0c;HelloGitHub 让你对编程感兴趣&#xff01; 简介 HelloGitHub 分享 GitHub 上有趣、入门级的开源项目。 https://github.com/521xueweihan/HelloGitHub 这里有实战项目、入门教程、黑科技、开源书籍、大厂开源项目等&#xff0c;涵盖多种编程语言 …...

uniapp 实现路由拦截,权限或者登录控制

背景&#xff1a; 项目需要判断token&#xff0c;即是否登录&#xff0c;登录之后权限 参考uni-app官方&#xff1a; 为了兼容其他端的跳转权限控制&#xff0c;uni-app并没有用vue router路由&#xff0c;而是内部实现一个类似此功能的钩子&#xff1a;拦截器&#xff0c;由…...

[GXYCTF2019]BabySQli1

单引号闭合&#xff0c;列数为三列&#xff0c;但是没有期待的1 2 3回显&#xff0c;而是显示wrong pass。 尝试报错注入时发现过滤了圆括号&#xff0c;网上搜索似乎也没找到能绕过使用圆括号的方法&#xff0c;那么按以往爆库爆表爆字段的方法似乎无法使用了 在响应报文找到一…...

【架构】Docker实现集群主从缩容【案例4/4】

实现集群主从缩容【4/4】 接上一节&#xff0c;在当前机器为4主4从的架构上&#xff0c;减缩容量为3主3从架构。即实现删除6387和6388. 示意图如下&#xff1a; 第一步&#xff1a;查看集群情况&#xff08;第一次&#xff09; redis-cli --cluster check 127.0.0.1:6387roo…...

【ArcGIS微课1000例】0097:栅格重采样(以数字高程模型dem为例)

Contents 1. 最邻近法(Nearest Neighbor)2. 双线性内插法(Bilinear Interpolation)3. 三次卷积法(Cubic Convolution)4. ArcGIS重采样工具(Resample)5. 注意事项栅格/影像数据进行配准或纠正、投影等几何变换后,像元中心位置通常会发生变化,其在输入栅格中的位置不一…...

【技术分享】Ubuntu 20.04如何更改用户名

产品简介 本文适用于所有RK3568/RK3588平台产品在Ubuntu 20.04系统上如何更改用户名&#xff0c;本文以IDO-EVB3588开发板为例&#xff0c;在ubuntu20.04系统上修改用户名industio为usernew。 IDO-EVB3588开发板是一款基于RK3588平台的产品。该开发板集成了四核Cortex-A76和四…...

LabVIEW振动信号分析

LabVIEW振动信号分析 介绍如何使用LabVIEW软件实现希尔伯特-黄变换&#xff08;Hilbert-Huang Transform, HHT&#xff09;&#xff0c;并将其应用于振动信号分析。HHT是一种用于分析非线性、非平稳信号的强大工具&#xff0c;特别适用于旋转机械等复杂系统的振动分析。开发了…...

清理Docker环境

清理Docker环境&#xff1a;有时&#xff0c;Docker环境可能会出现一些问题&#xff0c;导致网络连接故障。您可以尝试清理Docker环境并重新启动。可以尝试运行以下命令&#xff1a; 复制 docker-compose down docker system prune -a docker-compose up docker-compose up 和…...

oracle等保测评

实战|等保2.0 Oracle数据库测评过程 一、身份鉴别 a) 应对登录的用户进行身份标识和鉴别,身份标识具有唯一性,身份鉴别信息具有复杂度要求并定期更换; sysdba是Oracle数据库的最高权限管理员。通常使用sqlplus或PL/SQL 管理软件进行管理,PL/SQL 为第三方管理软件,但S…...

linux之kylin系统nginx的安装

一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源&#xff08;HTML/CSS/图片等&#xff09;&#xff0c;响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址&#xff0c;提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容&#xff0c;我认为是AI开发里面非常重要的内容。它在AI开发里无处不在&#xff0c;当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗"&#xff0c;或者让翻译模型 "将这段合同翻译成商务日语" 时&#xff0c;输入的这句话就是 Prompt。…...

工业安全零事故的智能守护者:一体化AI智能安防平台

前言&#xff1a; 通过AI视觉技术&#xff0c;为船厂提供全面的安全监控解决方案&#xff0c;涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面&#xff0c;能够实现对应负责人反馈机制&#xff0c;并最终实现数据的统计报表。提升船厂…...

Spring Boot 实现流式响应(兼容 2.7.x)

在实际开发中&#xff0c;我们可能会遇到一些流式数据处理的场景&#xff0c;比如接收来自上游接口的 Server-Sent Events&#xff08;SSE&#xff09; 或 流式 JSON 内容&#xff0c;并将其原样中转给前端页面或客户端。这种情况下&#xff0c;传统的 RestTemplate 缓存机制会…...

Java如何权衡是使用无序的数组还是有序的数组

在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建

制造业采购供应链管理是企业运营的核心环节&#xff0c;供应链协同管理在供应链上下游企业之间建立紧密的合作关系&#xff0c;通过信息共享、资源整合、业务协同等方式&#xff0c;实现供应链的全面管理和优化&#xff0c;提高供应链的效率和透明度&#xff0c;降低供应链的成…...

ETLCloud可能遇到的问题有哪些?常见坑位解析

数据集成平台ETLCloud&#xff0c;主要用于支持数据的抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;和加载&#xff08;Load&#xff09;过程。提供了一个简洁直观的界面&#xff0c;以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

【配置 YOLOX 用于按目录分类的图片数据集】

现在的图标点选越来越多&#xff0c;如何一步解决&#xff0c;采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集&#xff08;每个目录代表一个类别&#xff0c;目录下是该类别的所有图片&#xff09;&#xff0c;你需要进行以下配置步骤&#x…...

Angular微前端架构:Module Federation + ngx-build-plus (Webpack)

以下是一个完整的 Angular 微前端示例&#xff0c;其中使用的是 Module Federation 和 npx-build-plus 实现了主应用&#xff08;Shell&#xff09;与子应用&#xff08;Remote&#xff09;的集成。 &#x1f6e0;️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...

用机器学习破解新能源领域的“弃风”难题

音乐发烧友深有体会&#xff0c;玩音乐的本质就是玩电网。火电声音偏暖&#xff0c;水电偏冷&#xff0c;风电偏空旷。至于太阳能发的电&#xff0c;则略显朦胧和单薄。 不知你是否有感觉&#xff0c;近两年家里的音响声音越来越冷&#xff0c;听起来越来越单薄&#xff1f; —…...