Linux使用第三方库链接的使用方式——静态式

2023-11-10

 

目录

二.第三方库为静态库时:

       方法1:  两个窗口去分别模拟两个窗口公司A(客户端),公司B(服务端)的视角案例实现

提前插播一条指令:生成静态库文件的指令:

       方法2——优化:该方法在上述方法1的第10步后开始进行:

这里强调一个问题:


今天我们来学习将第三方库作为动静态库去链接生成可执行文件的使用方式。

        之前我发过一篇关于使用动静态链接生成可执行文件的文章,里面简单的介绍了一下动静态链接的指令实现和动静态库的区别认识,有兴趣的伙伴们可以看看。

 Linux——gcc/g++编译器_橙予清的zzz~的博客-CSDN博客https://blog.csdn.net/weixin_69283129/article/details/130820057?spm=1001.2014.3001.5501        有了上面对动静态库基本知识的铺垫,接下来我将详细说明一个问题:当我们在写好一个源.c/cpp文件时,该如何使用第三方库的多种方式。

        首先,我先来写两个简单类型的头文件和函数实现,用于测试:

        如上,我写了加法和减法的俩个函数实现。

        然后我在测试main.c文件中包含了这俩函数的头文件,以便于使用Add和Sub函数。

然后就是对这些.c文件进行汇编链接,生成可执行文件:

 

执行结果:

        如上,这是我们一般情况下自产自销的写出文件后,汇编链接形成可执行文件。但若是在公司企业的话,就不一样了。

        举个例子公司A将某某项目外包给了公司B,该公司的程序员只写出了main.c文件,将指定要求的多个函数交给公司B去实现。公司B实现好后,将这些函数的.o文件和.h文件打包给了公司A,公司A的程序员收到后,立即将main.c文件汇编链接公司B的函数实现,完成了项目。 

         这里有几个问题需要解答一下:

        1.函数的生成也是从.c形式开始,一步步进行预处理成为.i文件---->编译成为.s文件---->汇编成为.o重定向二进制目标文件。而我们写的这些.c文件就是经过这三步形成.o类型文件,最终将这些.o文件链接起来生成.exe可执行文件(这是对于Windows系统来说的,因为Windows系统很重视文件的后缀类型,而对于Linux系统来说,文件后缀不重要)。

       

       

        2.为什么公司B在打包时只给了公司A函数的.o目标文件和.h头文件,却唯独不给函数的.c文件呢?

        因为外面做函数的公司不愿给客户源代码!!!对方不想让客户知道方法底层的实现,若是客户知道了底层的实现,就会掌握相应的技术方法和原理,这对做函数的公司来说是得不偿失的!所以只给出.o类型文件有两种原因:

        a.是为了增加安全性,因为给客户.o二进制目标文件,客户也无法破译出底层实现的原理,.o文件中全是二进制数据——打开是一堆乱码,没法用!

        b.客户只需要将自己的main.c文件生成.o文件,直接将对方提供的.o文件进行链接即可生成可执行文件。

        3. .h文件很重要,缺少了.h文件,那些函数就无法使用,也无法生成.o文件。所以我们必须同时拥有.o目标文件和.h头文件才能完成main.c的链接生成.exe文件

 

但假如项目是个几万行的代码,且公司B给提供的.o/.h文件有数百个呢,那么我们在链接的时候是不是得一个一个的输入这些文件进行链接,那不得累死吗?

        这时静态库的作用就体现出来了!案例的整个步骤如下:对方公司将提供给我们的所有.o文件和h文件也各自集合起来,打成一个压缩包(zip或者tgz形式的)——库文件,然后发布出去,我们在接收后需要进行解压然后获取,直接使用gcc指令链接即可。

         强调一下:我们平常使用gcc编译器写的C代码,都需要#include<stdio.h>,里面写的printf、return 0;等语句函数都是使用系统自带的libC库方法和库头文件,所以我们不需要主动进行链接,但若是使用第三方库却不行,需要主动链接。——为后面案例的第11步埋下了伏笔!

 我们就是依赖这两个东西才能写成功C代码并运行。


二.第三方库为静态库时:

       方法1:  两个窗口去分别模拟两个窗口公司A(客户端),公司B(服务端)的视角案例实现:

        

        1.首先,先创建makefile自动化构建工具,以遍书写指令:

        2.其次,这是客户端的目录视角,该目录只有客户自己写的main.c的文件,他正在等待着公司B的函数文件传来:

        3.以下便是服务端的目录执行视角,公司B已经做好了客户需要的函数实现.c文件和头文件:

 

提前插播一条指令:生成静态库文件的指令:

        ar -rc (生成的静态库文件名) (所要依赖的文件名)

        解析:ar代表archive,意为把…存档; 把…归档。

        4.然后,公司B将.c函数文件全都生成为.o文件,使用ar -rc将相应的.o文件全都集合生成静态库文件lib_math.a:

5.使用makefile自动化工具创建指令:

 output的指令解析:通过创建一个递归目录,将.a文件和.h文件放在相应的位置中——打包。

6.执行打包命令:

 7.将打包好的文件进行压缩:tar czf指令为压缩指令:

         之后,公司B就可以将做好的安装包发送到客户的邮箱中,客户便可以从中获取到里面的库文件和头文件。

        

 8.以下便是客户端的目录视角,客户下载安装包——其实下载的本质就是拷贝!

 9.客户开始解压安装包:tar xzf为解压指令:

 10.查看是否成功安装:

 从图片上看,表明成功安装。

 11.下载完后,便可以开始链接生成可执行文件了:

上图错误分析:在链接过程中发现链接错误,说系统没有找到MyAdd.h。不对啊,客户心想:我不是把安装包下载好并和main.c放在同一目录下了吗,为什么编译器说没有找到?

        

        因为在案例说明前面埋下的那个伏笔!这是第三方库,需要主动链接头文件的所在路径!

        解决方法如下:在后面加上:-I 头文件的路径

        上图错误分析:但是链接后发现头文件的问题解决了,又出现了不认识第三方库函数的问题。这表明不仅第三方的头文件需要链接,而且第三方的库文件也需要链接!

        解决方法如下:在后面加上:-L 库文件的路径 

                                  在后面加上:-l 库文件的名称

       

        为什么还要加上库文件的名称?gcc在编译的过程中只会从被指定的路径中寻找系统自带的头文件和库文件,而第三方的库文件它压根不会去主动找,只能由你提示告诉编译器相关的路径和名称!

        上图错误解决方法:-l链接方式有问题,需要去除静态库文件libmy_math.a的前缀lib和后缀.a!

        如下:

 最终链接运行成功!

        以上就是使用静态库作为第三方库的一种方法,看起来是相当的复杂啊~,这是因为我们没有将包中的头文件和库文件放在系统指定的路径下,所以需要增加很多繁琐的步骤。

方法2——优化:该方法在上述方法1的第10步后开始进行:

11、将解压后的目录文件进行拷贝转移到gcc编译器默认寻找的路径下:

gcc编译器的默认寻找头文件、库文件路径:

        通过上图步骤,我们已将库文件和头文件成功的安装到了gcc指定的路径下,这样做的好处就在于不用像方法1那种主动链接,gcc会自动找到! 

12.最后一步: 

 也得要去链接并且标明去掉静态库文件的前缀和后缀。然后就大功告成了!!!


这里强调一个问题:

       知识拓展:

         file指令该指令可以识别文件类型的命令,通过查看文件的头部信息来获取文件类型。它不支持扩展名。同时,file命令还可以列出文件辨识结果、详细显示指令执行过程、文件名中的文件类型、mime类型的字符串等。 

        我们使用file指令去识别这个生成的可执行文件Myfile.exe时,发现它是dynamically linked(动态链接的形式),为什么?我们使用的不是静态库吗?静态库应该是使用静态链接进行啊!

       1. gcc编译器是专门用来写C语言的,它只认识指定路径下的库文件,我们写的静态库文件虽然也被识别到了,但是我们的代码中还用到了系统提供的<stdio.h>等动态库,所以该可执行文件依赖的就不仅仅是第三方库一个库了,而且系统提供的默认情况下是动态库,所以依赖的只要有一个动态库,文件显示出来的就是动态链接!

        2.除非该文件依赖的全是静态库,文件才会显示静态链接!!!

        3.gcc默认是动态链接的。


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux使用第三方库链接的使用方式——静态式 的相关文章

  • Linux C++ 错误:未定义对“dlopen”的引用

    我在 Linux 上使用 C Eclipse 工作 并且想要使用一个库 Eclipse 向我显示一个错误 undefined reference to dlopen 你知道解决办法吗 这是我的代码 include
  • 内核驱动程序从用户空间读取正常,但写回始终为 0

    因此 我正在努力完成内核驱动程序编程 目前我正在尝试在应用程序和内核驱动程序之间构建简单的数据传输 我使用简单的字符设备作为这两者之间的链接 并且我已成功将数据传输到驱动程序 但我无法将有意义的数据返回到用户空间 内核驱动程序如下所示 in
  • 如果文件没有行尾字符,则 wc -l 不计算文件的最后一个

    我需要计算 unix 文件的所有行数 该文件有 3 行 但是wc l仅给出 2 个计数 我知道它不计算最后一行 因为它没有行尾字符 任何人都可以告诉我如何计算这一行吗 grep c返回匹配行的数量 只需使用一个空字符串 作为您的匹配表达式
  • 找出Linux上一个进程使用了​​多少内存页

    我需要找出进程分配了多少内存页 每个页面是 4096 进程内存使用情况我在查找正确值时遇到一些问题 当我查看 gome system monitor 时 内存映射下有几个值可供选择 Thanks 这样做的目的是将内存使用量除以页数并验证页大
  • 如何从脚本编辑 /etc/sudoers?

    我需要编辑 etc sudoers从脚本中添加 删除白名单中的内容 假设我有一个可以处理普通文件的命令 我如何将其应用到 etc sudoers 我可以复制并修改它 然后有visudo用修改后的副本替换原始版本 通过提供我自己的脚本 EDI
  • 任何退出 bash 脚本但不退出终端的方法

    当我使用exitshell 脚本中的命令 该脚本将终止终端 提示符 有什么方法可以终止脚本然后停留在终端中吗 我的剧本run sh预计通过直接获取或从另一个脚本获取来执行 编辑 更具体地说 有两个脚本run2 sh as run sh ec
  • 使用 shell 脚本发送 HTML 邮件

    如何使用 shell 脚本发送 HTML 电子邮件 首先 您需要撰写消息 最低限度由这两个标头组成 MIME Version 1 0 Content Type text html 以及适当的消息正文 p Hello world p 获得后
  • 使用 systemctl 获取 systemd 进程的正常运行时间或停机时间?

    喜欢使用systemctl is active
  • 更新Linux中的包含路径

    我的 my path to file 文件夹中有几个头文件 我知道如何将这些文件包含在新的 C 程序中 但每次我都需要在包含它之前输入头文件的完整路径 我可以在linux中设置一些路径变量 以便它自动查找头文件吗 您可以创建一个 makef
  • Bash:将字符串添加到文件末尾而不换行

    如何将字符串添加到文件末尾而不换行 例如 如果我使用 gt gt 它将添加到文件末尾并换行 cat list txt yourText1 root host 37 echo yourText2 gt gt list txt root hos
  • Ruby:在 Ubuntu 上安装 rmagick

    我正在尝试在 Ubuntu 10 04 上安装 RMagick 看起来here https stackoverflow com questions 1482823 is there an easy way to install rmagic
  • 如何在 Linux 和 C 中使用文件作为互斥体?

    我有不同的进程同时访问 Linux 中的命名管道 并且我想让此访问互斥 我知道可以使用放置在共享内存区域中的互斥体来实现这一点 但作为一种家庭作业 我有一些限制 于是 我想到的是对文件使用锁定原语来实现互斥 我做了一些尝试 但无法使其发挥作
  • 如何从 C++ 程序中重新启动 Linux?

    我有一个 Qt 4 GUI 我需要在下拉菜单中提供一个选项 允许用户选择重新启动计算机 我意识到这对于以其他方式重新启动计算机的能力来说似乎是多余的 但选择需要保留在那里 我尝试使用 system 来调用以下内容 suid root she
  • Linux无法删除文件

    当我找到文件时 我在删除它们时遇到问题 任务 必须找到带有空格的文件并将其删除 我的尝试 rm find L root grep i 但我有错误 rm cannot remove root test No such file or dire
  • Ubuntu Python shebang 线不工作

    无法让 shebang 线在 Ubuntu 中为 python 脚本工作 我每次只收到命令未找到错误 test py usr bin env python print Ran which python usr bin python 在 sh
  • 如何在线程创建和退出时调用函数?

    include
  • vmsplice() 和 TCP

    在原来的vmsplice 执行 有人建议 http lwn net Articles 181169 如果您的用户态缓冲区是管道中可容纳的最大页面数的 2 倍 则缓冲区后半部分成功的 vmsplice 将保证内核使用缓冲区的前半部分完成 但事
  • 在内核代码中查找函数的最佳方法[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我开始浏览内核代码 遇到的一件事是如何跟踪函数调用 结构定义等 有没有一种好的方法可以快速跳转到函数定义并退出 我尝试过 Source N
  • 仅使用containerd(不使用Docker)修剪容器镜像

    如果我刚刚containerd安装在 Linux 系统上 即 Docker 是not安装 如何删除未使用的容器映像以节省磁盘空间 Docker 就是这么方便docker system prune https docs docker com
  • 相当于Linux中的导入库

    在 Windows C 中 当您想要链接 DLL 时 您必须提供导入库 但是在 GNU 构建系统中 当您想要链接 so 文件 相当于 dll 时 您就不需要链接 为什么是这样 是否有等效的 Windows 导入库 注意 我不会谈论在 Win

随机推荐

  • CentOS6 YUM 源失效问题解决办法

    问题描述 Yum 源失效 无法正常使用 Yum 错误信息如下 http mirrors aliyun com centos 6 updates x86 64 repodata repomd xml Errno 14 PYCURL ERROR
  • CentOs 6.5下java 安装

    我们下载jdk 的rpm包到要安装的服务器上 然后要进行下面的工作 1 移除系统自带的jdk 1 查找系统自带的jdk版本 输入命令 rpm qa grep jdk 2 移除系统自带的jdk 输入命令 yum y remove java 1
  • fatal: Not a git repository (or any of the parent directories): .git

    问题描述 解决方案
  • js之事件委托

    在js的事件流模型中 事件的触发分为3个阶段 1 捕获阶段 由外向内传播 寻找目标元素 2 目标阶段 找到事件触发的目标元素 3 冒泡阶段 事件由内向外冒泡 事件委托也被称为事件代理 那么是事件委托呢 用一个例子来说明 div div di
  • 万字详解:Activiti 工作流引擎

    点击上方 芋道源码 选择 设为星标 管她前浪 还是后浪 能浪的浪 才是好浪 每天 10 33 更新文章 每天掉亿点点头发 源码精品专栏 原创 Java 2021 超神之路 很肝 中文详细注释的开源项目 RPC 框架 Dubbo 源码解析 网
  • BART论文要点解读:看这篇就够了

    全称 Denoising Sequence to Sequence Pre training for Natural Language Generation Translation and Comprehension BART来源于Bidi
  • java晋级赛 深入并发编程

    根据黑马java并发编程学习做的笔记 传送门 https www bilibili com video BV16J411h7Rd p 15 java晋级赛 深入并发编程 一 多线程基础 进程与线程 创建线程的方式及运行原理 创建线程的方式
  • 进程调度的控制—文件锁

    前言 在进程之间 我们不能决定应该先去调度哪一个进程 这时候我们就需要对一个文件加锁 来要求那个先来执行 整体文件锁 int flock int fd int operation fd 文件描述符 operation 定义的宏 也就是选项
  • STL标准模板库学习笔记一(STL序列容器)

    目录 STL 容器 STL迭代器 array vector deque功能 list 和 forward list 功能 vector emplace back 和push back 的区别 vector插入函数insert和emplace
  • ST7796S MIPI单通道, 320x480初始化代码

    ST7796S MIPI单通道接口 320x480分辨率初始化代码 代码示例 loadWidthSet 320 loadHeightSet 480 loadHBPSet 180 loadVBPSet 20 loadHFPSet 20 loa
  • 【C语言】统计素数并求和

    改名字了 2022 2 26之前叫 回到正题 由题可知 题目要求在用户自己输入的定整数M和N区间内求出素数的个数 并且对他们求和 要想解决编程题目 首先要知道题目问的是什么 素数一般指质数 质数是指在大于1的自然数中 除了1和它本身以外不再
  • 版本控制之最佳实践(Git版)

    现如今 应该每个开发者都在使用版本控制工具了吧 然而 如果你理解版本控制的基本规则 你便能更好地发挥它的效用 在此 我们汇总了一些最佳实践 希望你在使用Git做版本控制时能够了然于心 得心应手 1 相关的改动才放一起提交 一次提交 git
  • hi35 web服务器

    在hi3516A上移植好的boa嵌入式web服务器代码 boa有61k 一次只能处理一个请求 https download csdn net download ganxiaoyagn000 9239729 appweb Appweb 6 1
  • android 11 存储权限,Android 11存储权限强制申请

    private static final int REQUEST CODE 1024 private void requestPermission if Build VERSION SDK INT gt Build VERSION CODE
  • OC中的基本容器和基本数据类型

    基本数据类型 NSRange 是一个结构体 里面有两个数据成员数据类型都为NSUInteger 就是c语言中的无符号整形 一个是location表示集合的起始地址 另外一个变量是length表示从起始地址开始算多少个元素 NSRange的三
  • CTF-web 简介

    web部分是CTF的重要组成部分之一 素有WEB大魔王之称 题目种类繁多 关键是如何发现漏洞的类型和怎样构造特殊的负载绕过过滤 CTF分为三种模式 解题模式 攻防模式 混合模式 在线工具 https www ctftools com dow
  • JVM运行时数据区

    文章目录 JVM内存结构图 1 运行时数据区域 JDK 1 7 JDK 1 8 1 线程栈 虚拟机栈 2 本地方法栈 3 程序计数器 4 方法区 元空间 5 堆 6 运行时常量池 Runtime Constant Pool 7 直接内存 D
  • 新版MetaMask如何获取当前账户地址

    window addEventListener load async gt Modern dapp browsers if window ethereum let ethereum window ethereum window web3 n
  • C语言中 -> 和 . 的区别

    在C语言中 gt 和 都是用于访问结构体 struct 成员的运算符 但它们的使用场景略有不同 1 gt 运算符用于访问结构体指针的成员 当你有一个指向结构体的指针时 你可以使用 gt 运算符来访问该结构体的成员 例如 struct Per
  • Linux使用第三方库链接的使用方式——静态式

    目录 二 第三方库为静态库时 方法1 两个窗口去分别模拟两个窗口公司A 客户端 公司B 服务端 的视角案例实现 提前插播一条指令 生成静态库文件的指令 方法2 优化 该方法在上述方法1的第10步后开始进行 这里强调一个问题 今天我们来学习将