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使用第三方库链接的使用方式——静态式 的相关文章

  • ubuntu:升级软件(cmake)-版本消歧(本地编译)[关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我的机器上安装了 cmake 2 8 0 来自 ubuntu 软件包 二进制文件放置在 usr bin cmake 中 我需要将 cmake 版本至少
  • PHP 无法打开流:是一个目录

    非常简单的 PHP 脚本 我在我亲自设置的 Ubuntu Web 服务器上的 EE 模板中运行 我知道这与权限有关 并且我已经将我尝试写入的目录的所有者更改为 Apache 用户 我得到的错误是 遇到 PHP 错误 严重性 警告 消息 fi
  • jq中如何分组?

    这是 json 文档 name bucket1 clusterName cluster1 name bucket2 clusterName cluster1 name bucket3 clusterName cluster2 name bu
  • 查找哪些页面不再与写入时复制共享

    假设我在 Linux 中有一个进程 我从中fork 另一个相同的过程 后forking 因为原始进程将开始写入内存 Linux写时复制机制将为进程提供与分叉进程使用的不同的唯一物理内存页 在执行的某个时刻 我如何知道原始进程的哪些页面已被写
  • ftrace:仅打印trace_printk()的输出

    是否可以只转储trace printk 输出于trace文件 我的意思是过滤掉函数跟踪器 或任何其他跟踪器 中的所有函数 一般来说 您可以在选项目录中关闭选项 sys kernel debug tracing options Use ls显
  • CoAP数据包的大小是多少?

    我是这项技术的新手 有人可以帮助我了解一些疑问吗 Q 1 CoAP数据包的大小是多少 我知道有 4 字节固定标头 但是包括标头 选项和负载在内的最大大小限制是多少 Q 2 有像MQTT那样的Keep Alive的概念吗 它在UDP上工作 它
  • 如何在 Bash 中给定超时后终止子进程?

    我有一个 bash 脚本 它启动一个子进程 该进程时不时地崩溃 实际上是挂起 而且没有明显的原因 闭源 所以我对此无能为力 因此 我希望能够在给定的时间内启动此进程 如果在给定的时间内没有成功返回 则将其终止 有没有simple and r
  • 是否可以创建一个脚本来保存和恢复权限?

    我正在使用 Linux 系统 需要对一组嵌套文件和目录进行一些权限实验 我想知道是否没有某种方法可以保存文件和目录的权限 而不保存文件本身 换句话说 我想保存权限 编辑一些文件 调整一些权限 然后将权限恢复到目录结构中 将更改的文件保留在适
  • Linux 上的用户空间能否实现本机代码的抢占式多任务处理?

    我想知道是否可以在 Linux 用户空间的单个进程中实现本机代码的抢占式多任务处理 也就是说 从外部暂停一些正在运行的本机代码 保存上下文 交换到不同的上下文 然后恢复执行 所有这些都由用户空间精心安排 但使用可能进入内核的调用 我认为这可
  • waitpid() 的作用是什么?

    有什么用waitpid 它通常用于等待特定进程完成 或者如果您使用特殊标志则更改状态 基于其进程 ID 也称为pid 它还可用于等待一组子进程中的任何一个 无论是来自特定进程组的子进程还是当前进程的任何子进程 See here http l
  • 我如何知道 C 程序的可执行文件是在前台还是后台运行?

    在我的 C 程序中 我想知道我的可执行文件是否像这样在前台运行 a out 或者像这样 a out 如果你是前台工作 getpgrp tcgetpgrp STDOUT FILENO or STDIN FILENO or STDERR FIL
  • 使用 Grep 查找两个短语之间的文本块(包括短语)

    是否可以使用 grep 来高亮所有以以下内容开头的文本 mutablePath CGPathCreateMutable 并以以下内容结尾 CGPathAddPath skinMutablePath NULL mutablePath 这两个短
  • Urwid:使光标不可见

    我正在使用 urwid 它是一个用于在 ncurses 中设计终端用户界面的 Python 框架 但有一件事我在 urwid 中无法做到 而这在 Curses 中很容易做到 使光标不可见 现在 选择按钮时光标是可见的 而且看起来很丑 有办法
  • 高效的内存屏障

    我有一个多线程应用程序 其中每个线程都有一个整数类型的变量 这些变量在程序执行期间递增 在代码中的某些点 线程将其计数变量与其他线程的计数变量进行比较 现在 我们知道在多核上运行的线程可能会无序执行 一个线程可能无法读取其他线程的预期计数器
  • 在 Mac OSX 上交叉编译 x86_64-unknown-linux-gnu 失败

    我尝试将我的 Rust 项目之一编译到 x86 64 unknown linux gnu 目标 cargo build target x86 64 unknown linux gnu Compiling deployer v0 1 0 fi
  • 捕获实时流量时如何开启纳秒精度?

    如何告诉 libpcap v1 6 2 将纳秒值存储在struct pcap pkthdr ts tv usec 而不是微秒值 捕获实时数据包时 Note This question is similar to How to enable
  • Capistrano 3 部署无法连接到 GitHub - 权限被拒绝(公钥)

    我使用 Capistrano v3 和 capistrano symfony gem 设置了以下部署脚本 我正在使用 Ubuntu 14 4 部署到 AWS EC2 实例 我正在连接从 AWS 下载的 pem 文件 我的deploy rb中
  • 限制 Imagemagick 使用的空间和内存

    我在 Rails 应用程序上使用 Imagemagick 使用 rmagick 但我的服务器 Ubuntu 不是很大 当我启动转换进程时 Imagemagick 占据了我的服务器 30GB HDD 的所有位置 内存 我想限制内存和 tmp
  • 每个命令都返回“bash:<命令>:找不到命令...”[关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 我刚刚安装了 Scala 并添加了路径gedit bashrc export SCALA HOME home avijit sca
  • 后台分叉无法正常工作[重复]

    这个问题在这里已经有答案了 我运行这个程序 在前景和背景中 int main int pid printf App Start pid d n getpid while 1 pid fork if pid 0 printf Child n

随机推荐

  • 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步后开始进行 这里强调一个问题 今天我们来学习将