【Linux】动静态库
目录
写在前面的话
如何编写静态库库
编写静态库
ar命令
Makefile自动化形成静态库
如何使用编写的静态库
1.拷贝到系统路径中
2.指定路径搜索
如何编写动态库
编写动态库
完善Makefile
如何使用编写的动态库
指定路径搜索(不可行及原因)
环境变量LD_LIBRARY_PATH
修改配置文件
写在前面的话
本文章主要讲解了动静态库的编写以及使用。在了解静态链接和动态链接的基础上,观看本文的效果会更好。
欢迎阅读我之前写的:动静态链接,里面有关于动态和静态链接的详细介绍,而且也有对动静态库的一些基本认识,欢迎阅读哦.
如何编写静态库
这里我们将编写两个类型的库:动态库(.so) 和 静态库(.a).
编写静态库
静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库.
需要说明:库里不能包含main函数,因为是要别人用的。写main函数的话就会和别人的main函数冲突了.
我现在分别创建了4个文件:mymath.h mymath.c myprint.h myprint.c.
分别写入以下内容:
- mymath.h:
#pragma once #include<stdio.h> extern int addToTarget(int start, int end);//声明函数
- mymath.c
#include "mymath.h" # //这段函数的作用是计算start-end之间的和int addToTarget(int start, int end) { int sum = 0; int i = start; for(i; i <= end; i++){ sum += i; } return sum; }
- myprint.h
#pragma once #include<stdio.h> #include<time.h> extern void Print(const char* str);
- myprint.c
#include "myprint.h" //这段函数功能是输出传入的字符串,后面加上时间戳 void Print(const char* str) {printf("%s[%d]\n",str,(int)(time(NULL))); }
然后我们编写一个main.c文件,来调用这些函数.
#include "myprint.h"
#include "mymath.h" int main()
{ Print("hello,world"); int res = addToTarget(1,100); printf("res: %d\n",res); return 0;
}
指令编译所有.c文件,目标生成my.exe可执行文件:
gcc main.c mymath.c myprint.c -o my.exe
然后我们执行my.exe文件,得到了我们预期的结果:
这只是我们的正常使用,毕竟源代码.c文件就在我们手上。
当我们把.h文件和 .c文件编译成的.o文件,给别人,别人可以用吗?
答案是可以的,我们首先把两个.c文件编译成.o文件:
gcc -o myprint.o -c myprint.c
gcc -o mymath.o -c mymath.c
然后我们换到另一个文件中,把两个.o和两个.h文件复制到这个文件中,然后将main.c也编译成main.o文件,此时我们将这三个.o文件一起编译,形成可执行程序。
gcc main.o mymath.o myprint.o -o my.exe
我们发现照样可以成功运行:
但问题是我们这里有太多的.o文件,发给别人也不方便,而且容易丢失,编译的时候还得都写上,这也未必太麻烦了。
所以此时我们需要把这些.o文件打包,这个打包的过程就是形成静态库的过程.
ar命令
把这些.o文件打包需要用到ar命令,命令格式如下:
ar -[选项] lib+库文件名+.a 所有.o文件
选项这里只说r(replace替换),c(create创建)就可以了,就足以让我们创建静态库了.
其中需要注意的是:要形成的静态库的名字 前缀必须是lib,后缀必须是.a,中间可以随便起名字.
比如我想把所有的.o文件打包成名字叫hello的静态库,指令如下:
ar -rc libhello.a main.o myprint.o mymath.o
这样就形成了.
Makefile自动化形成静态库
有了以上的认知,我们便对一个文件形成静态库的过程有了大概的了解:
.c文件 ---> .o文件 ---> 打包形成静态库
既然是这么一套固定的流程,那么我们完全可以用Makefile来完成这些工作。需要注意的是搞清各个文件的依赖关系,然后再进行编写。所以最后的Makefile编写如下:
libhello.a: mymath.o myprint.o ar -rc libhello.a mymath.o myprint.o
mymath.o : mymath.c gcc -o mymath.o -c mymath.c
myprint.o: myprint.c gcc -o myprint.o -c myprint.c .PHONY:clean
clean: rm -rf *.o libhello.a
这样,我们不需要再手动编译了,直接使用make就好了.
但这样只是将.o文件打包了,还有.h文件,就是通常#include<>的那些,一般都是.h文件
.h声明,然后从.o打包形成的库里面找
所以我们还需要做一件工作:将.h和.o文件规整到一起.在Makefile加入以内容:
.PHONY:hello
hello: mkdir -p hello/lib mkdir -p hello/include cp -rf *.h hello/include cp -rf *.a hello/lib
即创建了三个目录,hello,lib和include,把当前所有的.h文件放到include文件夹中,所有.a库文件放到lib文件夹中。
这里首先把资源全部清理一下,然后make编译形成.o文件,再make hello 形成hello目录,里面包含了两个目录include 和 lib ,分别保存.h文件和库文件.
如何使用编写的静态库
1.拷贝到系统路径中
头文件gcc系统默认搜索路径是:/usr/include
库文件gcc系统默认搜索路径是:/lib64 或者 /usr/lib64
sudo cp hello/include/*.h /usr/include/ //拷贝头文件
sudo cp hello/lib/*.a /lib64 //拷贝库文件
拷贝完成后,我们再次编译main.c
发现还是不行,这是由于我们平常使用的是系统自带的库,而我们编写的是第三方库,所以我们编译时需要指定链接哪一个库.
gcc main.c -lhello
注意,-l后面直接加库的名字,不加前缀lib和后缀.a.
此时我们再编译,便运行成功了.
这种把自己的库拷贝到系统路径下的行为就叫做库的安装.
但是一般不建议采用这种办法。会污染别人已经写好的库。
2.指定路径搜索
我们可以直接在编译的时候加上头文件和库文件的路径.
gcc main.c -I ./hello/include/ -L ./hello/lib/ -lhello
选项:-I(i的大写)表示头文件的搜索路径
-L表示库文件的搜索路径
-l(小写的L)表示在特定路径下,要使用哪一个库.
如何编写动态库
动态库(.so):程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。
编写动态库
同样地,我么也需要先将.c文件编译成.o文件,但此时需要加上选项 -fPIC.
gcc -fPIC -c myprint.c -o myprint.o
gcc -fPIC -c mymath.c -o mymath.o
选项
-fPIC
是指生成位置独立代码(Position Independent Code,PIC)。它通常用于创建可在不同内存地址空间加载的共享库(动态链接库)。具体来说,
-fPIC
选项的作用是告诉编译器生成与位置无关的代码,这些代码可以在内存中的任何位置加载和执行,与共享库的加载地址无关。这是通过使用相对偏移而不是绝对地址来访问全局变量和函数等的。
看不懂没有关系,我们后面会继续细说的.
然后我们需要将这些.o文件它打包成动态库.它没有单独的命令,使用gcc进行打包,但是需要加上 -shared的选项,如下:
gcc -shared myprint.o mymath.o -o libhello.so
这样我们就完成了动态库的打包和编写.
由于流程是固定的,所以我们依然可以使用Makefile来完成。
完善Makefile
首先我们需要先将.c编译诚.o文件,并打包成动态库
然后需要将生成的动态库也放到我们之前创建的lib目录中。
完善后的效果如下(框起来的是新增的内容):
.PHONY:all
all:libhello.so libhello.a libhello.so:mymath_d.o myprint_d.o gcc -shared mymath_d.o myprint_d.o -o libhello.so
mymath_d.o:mymath.c gcc -c -fPIC mymath.c -o mymath_d.o
myprint_d.o:myprint.c gcc -c -fPIC myprint.c -o myprint_d.o libhello.a: mymath.o myprint.o ar -rc libhello.a mymath.o myprint.o
mymath.o : mymath.c gcc -o mymath.o -c mymath.c
myprint.o: myprint.c gcc -o myprint.o -c myprint.c .PHONY:output
output: mkdir -p hello/lib mkdir -p hello/include cp -rf *.h hello/include cp -rf *.a hello/lib cp -rf *.so hello/lib
.PHONY:clean
clean: rm -rf *.o libhello.a output
此时我们即可以形成动态库,也可以形成静态库.
然后此时我们make编译,再make output将文件拷贝到指定目录中.
此时便把动态库也成功放入到lib路径下了.
此时我们便可以利用tar指令打包发送到网上,然后让别人使用了。
如何使用编写的动态库
指定路径搜索(不可行及原因)
首先,静态库中的第一种拷贝到系统路径里这种方法一定是可行的.
第二种方法,这条指令:
gcc main.c -I ./hello/include/ -L ./hello/lib/ -lhello
我们首先要知道,gcc默认使用的是动态链接,即使用动态库.
a.当库中只有静态库时,gcc就只能针对该库进行静态链接.
b.当动静态库同时存在时,默认使用的就是动态库
c.如果动静态库同时存在,强制使用静态库,那就需要再上面指令后面加上 -static
表示的是:摒弃优先使用动态库的原则,而是直接使用静态库的方法.
代码如下:
gcc main.c -I ./hello/include/ -L ./hello/lib/ -lhello -static
我们同样地利用上面那一条指令进行编译生成可执行程序后,我们把可执行程序移动到上一级目录.然后运行它。
此时我们再运行,发现报错了,就是找不到这个共享的文件,这是为什么呢、我们不是已经指定路径了吗,为什么还找不到呢?
我们要明白,动态库是一个独立的文件,动态库可以和可执行程序分批加载!
而我们指定路径是给gcc指定查找的,是告诉了gcc的动态库的路径。
当我们运行和加载的时候,就和gcc没有关系了,所以我们要告诉操作系统或者加载器 这个动态库的路径!
如果此时新来一个进程,也需要用相同的动态库,操作系统只需要将物理内存中动态库数据经过页表映射到对应进程的地址空间 中的共享区的位置,这样代码区的代码遇到动态库中的函数直接去共享区去找。
那为什么静态库不用呢?
静态链接的一旦编译好,就和库没有关系了,因为已经把库中代码拷贝到自己写的C/C++代码中了.即已经在可执行程序中了.
环境变量LD_LIBRARY_PATH
这个是库加载时搜索的路径.我们只需要把我们的库的路径导入到这个环境变量里面即可.
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:你的库文件路径
导入完成后,此时我们便可以成功运行了
但这个方法有一个缺点,就是每次退出后,我们导入的这些环境变量就会清空,下次还需要重新导入,比较麻烦。
修改配置文件
我们既不想在系统中安装我们的库,又想永久保存,那该怎么办呢?
我们只需要在/etc/ld.so.conf.d/路径下 随便创建一个文件.然后vim打开文件,输入你动态库文件路径,然后退出保存即可.
sudo vim /etc/ld.so.conf.d/mylib.conf
然后输入你的库文件路径即可,然后退出,执行重新加载指令
sudo ldconfig
这样也可以照样正常运行了.
到这里动静态库就讲完了,感谢您的阅读哦~
相关文章:

【Linux】动静态库
目录 写在前面的话 如何编写静态库库 编写静态库 ar命令 Makefile自动化形成静态库 如何使用编写的静态库 1.拷贝到系统路径中 2.指定路径搜索 如何编写动态库 编写动态库 完善Makefile 如何使用编写的动态库 指定路径搜索(不可行及原因) 环境变量LD_LIBRARY_PAT…...
《kubernetes权威指南》-第一章学习笔记
1.什么是kubernetes? kubernetes是一个全新的基于容器技术的分布式架构领先方案。 2.为什么要用kubernetes? 使用kubernetes提供的解决方案能够减少30%的开发成本,并且能够将开发人员的精力更加集中于业务本身,同时可以降低系统…...

ubuntu 18.04 磁盘太满无法进入系统
安装了一个压缩包,装了一半提示磁盘空间少导致安装失败。我也没在意,退出虚拟机打算扩展硬盘。等我在虚拟机设置中完成扩展操作,准备进入虚拟机内部进行操作时,发现登录不进去了 shift 登入GUN GRUB设置项的问题 网上都是在开机…...
基于LNMP配置WordPress建站时出现的问题汇总
目录 wordpress上传文件报错问题描述原因分析:解决方案: wordpress裁剪图片报错问题描述原因分析:解决方案: 配置固定链接和伪链接 wordpress上传文件报错 WP内部错误,在上传文件时发生了错误,显示权限不足…...

【Spring Cloud】Gateway的配置与使用
文章目录 前言第一步,创建一个springboot工程第二步,添加依赖第三步,编写yml文件第四步,启动主启动类总结 前言 Gateway其实是springcloud 原生的东西,但是我还是想放在这里讲,因为我们使用nacos时&#x…...

概念、框架简介--ruoyi学习(一)
开始进行ruoyi框架的学习,比起其他的前后端不分离的,这个起码看的清晰一些吧。 这一节主要是看了ruoyi的官方文档后,记录了以下不懂的概念,并且整理了ruoyi框架中的相关内容。 一些概念 前端 store store是状态管理库&#x…...

IDEA的基础使用——【初识IDEA】
IDEA的基础使用——【初识IDEA】 文章目录 IDEA简介前言官网 IDEA的下载与安装选择下载路径勾选自己需要的其余按默认选项进行即可 目录简介安装目录简介 运行Hello WorldIDEA快捷键常用模板模板一:psvm(main)模板二:模板三&#…...

LeetCode刷题总结-动态规划篇
LeetCode刷题总结-动态规划篇 本文总结LeetCode上有动态规划的算法题,推荐刷题总数为54道。具体考点分析如下图: 1.中心扩展法 题号:132. 分割回文串 II,难度困难 2.背包问题 题号:140. 单词拆分 II,难…...

el-table使用xlsx实现导入文件编辑功能
需求:列表根据xlsx文件导入后,和列表进行对比,之后实现编辑功能 1.下载xlsx 我下的是之前的版本,新版不知道兼不兼容,这个包900多k npm install xlsx0.14.5 2.在需要使用表格导入的页面引入 import XLSX from &quo…...
Android9、11 有线网络开关设置
Android9、11 有线网络开关设置 Android9、11 有线网络开关设置_android 以太网开关_峥嵘life的博客-CSDN博客...
【MySQL】mysql问题 | [ERROR] unknown variable ‘column-statistics=0‘
一、说明 1、用到一个开源项目,dbBkTool[asurplus] 2、这个项目用于MySQL定时备份的 3、然后有个执行的时候,发下报错 [ERROR] unknown variable column-statistics0 二、解决 1、把MySQL客户端升级到8.0.19之后,就不报错了 2、column-stat…...

ElasticSearch 7.x
前言 elastic表示可伸缩,search表示查询。所以es的核心即为查询。通常情况下,我们的数据可以分为三类:结构化数据、非结构化数据、半结构化数据。 结构化数据:一般会用特定的结构来组织和管理数据,表现为二维表结构。…...
MVC乱码问题
RequestMapping(value "insert",produces {"text/html;charsetutf-8"}) //前端响应回去加响应头,解决乱码问题,这个还跟JSP响应头还不一样,这是响应的字符串,纯文本,那个前端的是out.Writer()对象ÿ…...

1004. 最大连续1的个数 III
题目描述: 主要思路: 刚看到这个问题首先想到的是二分答案,二分长度,然后利用滑动窗口判断是否可以达成。 class Solution { public:bool find(int x,vector<int> nums, int k){int now0;for(int i0,j0;i<nums.size();…...

【机器学习】西瓜书学习心得及课后习题参考答案—第3章线性模型
过了一遍第三章,大致理解了内容,认识了线性回归模型,对数几率回归模型,线性判别分析方法,以及多分类学习,其中有很多数学推理过程以参考他人现有思想为主,没有亲手去推。 术语学习 线性模型 l…...

面试官问我:一个 TCP 连接可以发多少个 HTTP 请求?我竟然回答不上来...
一道经典的面试题是从 URL 在浏览器被被输入到页面展现的过程中发生了什么,大多数回答都是说请求响应之后 DOM 怎么被构建,被绘制出来。但是你有没有想过,收到的 HTML 如果包含几十个图片标签,这些图片是以什么方式、什么顺序、建…...
树莓派Pico|RP2040|官方文档|在MS Windows上构建“Hello World”及环境配置
9.2. 在MS Windows上构建 在Microsoft Windows 10或Windows 11上安装工具链与其他平台有些不同。然而安装后,RP2040的构建代码基本类似。 警告 官方不支持在Windows 7或8上使用Raspberry Pi Pico,但在Windows 7或8上可以使其工作。 9.2.1. 安装工具…...
全球公链进展| 2023/7/31
一周速览 过去一周,明星项目动态如下: 第114次以太坊核心开发者共识会议:Devnet #8 最早下周推出 Layer2网络Shibarium跨链桥已上线公开测试 Optimism 推出「Law of Chains」v0.1 版本 Sui 通过 SIP#6 ,允许开发人员构建流动…...

Spring源码(三)Spring Bean生命周期
Bean的生命周期就是指:在Spring中,一个Bean是如何生成的,如何销毁的 Bean生命周期流程图 1、生成BeanDefinition Spring启动的时候会进行扫描,会先调用org.springframework.context.annotation.ClassPathScanningCandidateCompo…...

【iOS】Cydia Impactor 错误:file http.hpp; line:37; what: _assert(code == 200)
Cydia Impactor 报错,信息如下 file http.hpp; line:37; what: _assert(code 200)解决方案:Cydia Impactor 已被弃用,切换到sideloadly 即可,亲测成功,并且支持双重验证登录 csdn备份地址 HERE...

【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...

企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...

USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...

MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)
macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 🍺 最新版brew安装慢到怀疑人生?别怕,教你轻松起飞! 最近Homebrew更新至最新版,每次执行 brew 命令时都会自动从官方地址 https://formulae.…...

什么是VR全景技术
VR全景技术,全称为虚拟现实全景技术,是通过计算机图像模拟生成三维空间中的虚拟世界,使用户能够在该虚拟世界中进行全方位、无死角的观察和交互的技术。VR全景技术模拟人在真实空间中的视觉体验,结合图文、3D、音视频等多媒体元素…...