动,静态库(与linux有关)

news2024/11/24 19:48:32

1.一些与本章标题无关的补充内容

当我们修改文件内容的时候,有可能会修改文件的属性。比如:可能会更改文件的大小属性。

我们在通过指令查看文件的时间相关属性时会往往观察到这样的现象:Access(访问时间,之前有具体讲过)没有及时修改。

在较新的linux中,Access时间往往不会立刻更新,经过一定的时间间隔OS才会更新。

当然既然提到了这个时间属性,这里便在补充一点:当我们使用makefile的时候其,你所要make的文件能否被编译成可执行文件就是看modify时间有没有发生改变。

2.动静态库的基本概念

2.1linux下动静态库的基础认知

静态库是一种包含多个目标文件(Object Files)的归档文件,这些目标文件在链接阶段被合并到最终的可执行文件中。静态库的文件扩展名通常为.a,例如libexample.a

动态库是一种在程序运行时动态加载的库,它们在程序启动时或运行时按需加载。动态库的文件扩展名通常为.so(例如libexample.so),或者带有版本号(例如libexample.so.1.0)。

2.2静态编译和动态编译

静态编译是指将所有需要的库都打包进可执行文件中,这样在运行时就不需要依赖任何外部库。在静态编译的情况下,可执行文件的体积会比较大,但是可以保证程序的可移植性和稳定性。此外,静态编译还可以避免由于共享库版本不一致或缺失而导致的兼容性问题。

动态编译是指在运行程序时,程序需要依赖一些共享库才能正常工作,这些共享库通常是系统已经安装好的动态链接库(.so文件)。在动态编译的情况下,程序只需要编译链接自己的代码,而不需要将所有依赖的共享库都打包进可执行文件中。这样可以节省空间,同时也方便了共享库的更新和维护。

在我们之前学过的makefile中加入-static可以静态编译,不过一般的服务器可能没有内置语言的静态库,而只有动态库。

2.3linux下库的命名方式

在这里插入图片描述

在 Linux 下,库有三种常见的名称(上图为完整名称):

  1. 完整名称(Full name):以 lib 开头,以 .so 结尾,比如 libc.so、libstdc++.so 等。它通常包含库的版本信息和其他细节,这是库文件的实际名称。
  2. 简称(Short name)或 soname:去掉 lib 前缀和 .so 后缀(版本信息也去掉)的名称,比如 c、stdc++ 等。这通常用于编译和链接时指定库。
  3. 链接名称(Link name):是指库的软链接或硬链接的名称。比如 libc.so 的一个链接可能叫做 libc-2.28.so。

3.库的制作

3.1一些小思考

库的本质就是一堆二进制函数,可我们如何得知一个库给我们提供了什么方法?

首先一套完整的库包括以下几个成分:

1.库文件本身

2.头文件.h(会说明库中暴露出来方法的基本使用)

3.说明文档

在我们以前的项目中我们都习惯把函数的实现和声明分开写,这样可以方便我们制作库,并且保证私密性。

3.2makefile中实现静态库

如图:

在这里插入图片描述

在linux同一目录下创建5个文档(红色字为文档名)

当使用gcc编译mytest.c时,我们需要输入以下指令(gcc只看得到声明,看不到实现):

在这里插入图片描述

​ 若我们想将自己的代码给别人使用,按照上面的方法即可(给予原文件以及头文件)

​ 如果我不想这么做可以将其打包成静态库(原理就是提供.o文件打包成库)

下面提供两种写法:

第一种(不推荐):

在这里插入图片描述

  1. obj = mytest.o add.o sub.o:这一行定义了一个变量 obj,它包含了需要编译的对象文件的名称。

  2. mytest: $(obj):这一行指定了可执行文件 mytest 依赖于变量 obj 中列出的所有对象文件。如果 obj 中任何一个对象文件发生更改,那么就需要重新编译 mytest。

  3. gcc -o $@ $^:这一行是构建可执行文件 mytest 的命令。它使用 gcc 编译器,将所有依赖项(在这里是 obj 中列出的对象文件)链接在一起,并将输出文件命名为 $@(在这里是 mytest)。

  4. %.o: %.c:%代表匹配任意长度的字符串。所以这个规则的意思是:任意名称的目标文件(以.o结尾),依赖于同名的源文件(以.c结尾)。

  5. gcc -c $<:这一行是构建对象文件的命令。使用gcc编译器编译依赖项(%.c文件),生成目标文件(%.o文件),但不进行链接。

    make之后的实际效果图:
    在这里插入图片描述

第二种:
libmymath.a:sub.o add.o   //库名为libmymath.a
   ar -rc $@ $^          //使用 ar 工具,执行 -rc 选项来创建或更新库文件,并将所有依赖项(在这里是                             sub.o 和 add.o)添加到库中。
%.o:%.c
   gcc -c $<             

在这里插入图片描述

(ar -tv 静态库名 可查看静态库)

完整形态:

libmymath.a:sub.o add.o   
   ar -rc $@ $^                                    
%.o:%.c
   gcc -c $<   

.PHONY:clean
clean:
   rm -rf *.o output libmymath.a

.PHONY:output
output:
   mkdir output
   cp -rf *.h output
   cp -rf libmymath.a output
       
.PHONY:install     //安装到某处 
install:
   cp *.h /user/include
   cp libmymath.a/lib64

在这里插入图片描述

将output文件创建好后,重新命名成lib(此时的lib和mytest.c都在lesson2文件下)

输入如图指令:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zXv7Py52-1685974570404)(C:\Users\山野村居\Documents\Tencent Files\1641229318\FileRecv\MobileFile\3DDEB61892F295752B6DC9A63B8676EB.png)]

这里为什么需要指明这些选项,我们正常写代码为什么编译时不需要指明这些选项?

​ 之前的库,在系统的默认路径下:/lib64,/user/lib,/user/include等编译器是能识别这些路径的。

换句话说如果我不想带这些选项,可以将这些东西拷贝到默认路径下,不过一般不推荐这么做

(上面的这种过程其实就是一般软件的安装过程 )

3.3makefile中形成动态库
#形成一个动态链接的共享库
libmytham.so:add.o sub.o
	gcc -shared -o $@ $^
#产生.o目标文件,程序内部的地址方案是:与位置无关,库文件可以在内存的任何位置加载,而且不影响和其他程序的关联性
%.o:%.c
	gcc -fPIC -c $<
	
.PHONY:clean
clean:
	rm -f libmymath.so *.o

.PHONY:lib
lib:
	mkdir lib
	cp *.h lib
	cp libmymath.so lib

使用刚才上面演示的gcc的方法编译mytest.c后虽然能编译成功,但是却会报错,为什么呢?

程序运行的时候需要动态库,但是当我上面gcc编译完时我所提供的寻找的位置已经消失了,此时加载器需要在运行的时候,告知系统,我们的库在哪里。而刚刚上面的静态库却不需要,因为已经直接拷贝进去了。

如何解决呢?

在库所在的文件导入一个环境变量LD_LIBRARY_PATH(比如路径lib下里面有add.h sub.h libmymath.so , 将环境变量放入这个lib里面就行),代码为:$ export LD_LIBRARY_PATH=绝对路径 当然这么搞下次退出环境变量就消失了,之前这点有讲过。

或者可以 ldconfifig 配置/etc/ld.so.conf.d/,ldconfifig更新

[root@localhost linux]# cat /etc/ld.so.conf.d/bit.conf 
 /root/tools/linux
 [root@localhost linux]# ldconfig
3.4总结

如果只提供静态库,我们只能将我们的库,静态链接到我们的程序当中。

如果只提供动态库,我们只能将我们的库采用动态链接。

如果此时只有动态库,是无法在makefile中加入 -static进行静态链接的。

如果提供了两种库,当我们使用gcc和g++时候会优先选择动态库。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/613534.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++ string的简单应用

C语言的字符串 C的字符串 头文件&#xff1a; #include<string.h> //c #include<string> //C #include<cstring> //C 比较string的大小 两个string对象相加 使用字符串对象来存放字符串 两个string对象相加 string str "Hello,"; st…

求取平面参数

平面方程AXBYCZD0 变换一下-> A/DX B/DYC/DZ -1 该方程满足Axb 其中A为, x为,b为-1单位阵 求解代码如下: /* comment plane equation: Ax By Cz D 0 convert to: A/D*x B/D*y C/D*z -1 solve: A0*x0 b0 where A0_i [x_i, y_i, z_i], x0 [A/D, B/D, C/D]^T,…

逆向汇编与反汇编——基本数据类型

-1&#xff1a;0xFFFFFFFF 为什么内存使用补码来存储数据&#xff1f; 》因为CPU的设计只有加法器&#xff0c;没有减法&#xff0c;需要使用补码来实现减法 大端&#xff1a;数值的高位放到内存的低字节 小端模式验证&#xff1a;78 78 浮点型&#xff1a;单精度float和双精…

创建类构造器

类的创建 构造器 作用&#xff1a;给类赋值 类实际可分为&#xff1a;构造器属性方法 构造器的重载 重载&#xff1a;方法名相同&#xff0c;参数类型不同 一定要有空构造器&#xff01;&#xff01;&#xff01; TIP&#xff1a;this.指代当前创建对象

数据结构与算法系列之希尔排序

&#x1f497; &#x1f497; 博客:小怡同学 &#x1f497; &#x1f497; 个人简介:编程小萌新 &#x1f497; &#x1f497; 如果博客对大家有用的话&#xff0c;请点赞关注再收藏 &#x1f31e; 希尔排序 希尔排序法又称缩小增量法。希尔排序法的基本思想是&#xff1a;先选…

Python读写mat文件(使用scipy.io)

在matlab中&#xff0c;数据可保存为mat文件&#xff0c;使用save和load命令可进行读写操作。而在Python中&#xff0c;也可以对mat文件进行读写。 一、由matlab向Python传数据&#xff08;Python读取mat文件&#xff09; 第一步&#xff1a;使用matlab创建变量并保存至mat文…

某程序员——我应届毕业,年薪23万...

马士兵教育线下训练营第1期 已经圆满结束啦~ 不了解训练营的伙伴 有的在观望、有的在好奇 训练营真的能学到东西吗&#xff1f; 出去了之后能找到工作吗&#xff1f; 不如看看那些参加过的人是怎么说的 或许&#xff0c;你会对我们、对训练营 会有更深入的了解...... 0…

计算机视觉:转置卷积

转置卷积 文章目录 转置卷积基本操作填充、步幅和多通道性质 转置卷积&#xff08;Transposed Convolution&#xff09;&#xff0c;也称为反卷积&#xff08;Deconvolution&#xff09;&#xff0c;是卷积神经网络&#xff08;CNN&#xff09;中的一种操作&#xff0c;它可以将…

排他网关-部署流程定义

类&#xff1a;com.roy.ActivitiGatewayExclusive /*** 部署流程定义*/Testpublic void testDeployment(){ // 1、创建ProcessEngineProcessEngine processEngine ProcessEngines.getDefaultProcessEngine(); // 2、得到RepositoryService实例RepositoryService…

剑指offer刷题笔记--题目11-20

1-旋转数组的最小数字&#xff08;11&#xff09; 主要思路&#xff1a; 一次旋转将最后一个元素移动最前面&#xff0c;由于数组最开始是升序的&#xff0c;因此数组的大部分元素都应该保持升序的状态&#xff08;n1<n2<...<n3>n4<n5<...<n6&#xff09;…

JAVA练习小游戏——贪吃蛇小游戏 PLUS版

目录 基础版本 新增内容 1.添加START开始界面 2.新增背景音乐 3.添加SCORE计分 4.新增游戏机制 代码实现 实机演示 基础版本 JAVA练习小游戏——贪吃蛇小游戏_timberman666的博客-CSDN博客https://blog.csdn.net/timberman666/article/details/131046742?spm1001.201…

xshell使用技巧小节

文章目录 1. 输出日志文件2. 快捷键设置3. 使用ctrlv按键4. 快速命令 1. 输出日志文件 需求&#xff1a;我们使用xshell时会经常需要把xshell中的内容打印到文件中&#xff0c;或者因为内容过多&#xff0c;xshell界面无法显示先显示出的内容&#xff0c;或者需要明确记录文件…

AlterNET Studio v9.0 Crack

AlterNET Studio v9.0 改进了代码编辑器、表单设计器和 Python LSP 解析器。 2023 年 6 月 5 日 - 11:22新版本 特征 代码编辑器 编辑器中添加了 Microsoft Visual Studio 主题。现在包括一个放大镜区域&#xff0c;可以更轻松地浏览文档的内容。带有 alpha 通道的图像现在用于…

汽车电子AUTOSAR之EcuM模块

目录 前言 正文 EcuM模块总体介绍 主要功能 总状态机&#xff08;Flexible 与 Fixed&#xff09; Startup Sequence STARTUP I STARTUP II RUN Sequence RUN II RUN III ShutDown Sequence ShutDown Target Go Sleep Go OFF I Go OFF II Sleep Sequence Sleep…

如何从平面图或蓝图为 ROS 创建地图

如何从平面图或蓝图为 ROS 创建地图 在本教程中&#xff0c;我将向您展示如何从平面图或蓝图为 RViz&#xff08;ROS 的 3D 可视化程序&#xff09;创建地图。为 RViz 创建地图是使机器人能够在环境中自主导航的重要步骤。 我们经常使用机器人的激光雷达来构建地图。这很好&am…

【openeuler】Yocto embedded sig例会 (2023-01-12)

Yocto & embedded sig例会 (2023-01-12)_哔哩哔哩_bilibili

群智能算法-模拟退火

一.基本理念 模拟退火算法(Simulated Annealing,简称SA) 的思想最早是由Metropolis等提出的.其出发点就是基于物理中固体物质的退火过程与一般的组合优化问题之间的相似性。模拟退火法是一种通用的优化算法&#xff0c;其物理退火过程由以下三部分组成。 加温过程&#xff1a;我…

AutoHand插件使用指南

一、设置 1.软件包设置 Auto Hand 包括四个内置的输入选项。AutoHand不直接管理输入,而是包含各种脚本,充当所选输入系统和Auto Hand之间的桥梁。 这里只介绍OpenXR(Action Based),首先作如下设置: 我这里用的是HTC Vive Pro: 找到并导入AutoHand插件中的OpenXR这个包:…

java错题记录(一)

一、观察下类代码&#xff0c;输出正确的是 String s1 "coder"; String s2 "coder"; String s3 "coder" s2; String s4 "coder" "coder"; String s5 s1 s2; System.out.println(s…

SELD2022:(一)数据集收集与组织详解

前言&#xff1a;声音事件检测与定位&#xff08;SELD&#xff09;作为DCASE挑战赛的子任务&#xff0c;从2019年开始已经举办了好几届。该子任务的目标也从2022年开始由原来的在仿真数据集上设计更优声学模型&#xff0c;过渡到了在真实数据集上进行模型优化。相对而言&#x…