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

【Linux】Linux编译器-g++、gcc、动静态库

 只要积极创造,机遇无时不有;只要善于探索,真理无处不在。💓💓💓

目录

  ✨说在前面

🍋知识点一:Linux编译器-g++、gcc

•🌰1. 背景知识

•🌰2. gcc如何完成

•🌰3. 条件编译的作用

•🌰4. 函数库

 🍇库的定义

 🍇动态库与静态库

 🍇动静态库对比

 🍇验证工作

 🍇技术上理解库

 • ✨SumUp结语


  ✨说在前面

亲爱的读者们大家好!💖💖💖,我们又见面了,上篇文章我们讲解了linux中的重要工具-yum和vim,大家可以回顾一下,加深印象~

我们今天给大家讲解一下Linux中的另外一个重要工具-编译器g++、gcc以及他们在Linux命令中的使用。更重要的是,由编译和链接这部分知识所牵涉出来的动态库、静态库的链接问题。动静态库是很重要的,在后面我们还会进行二次学习,希望大家可以好好学习本篇博客,为以后的学习打下坚实的基础。

   👇👇👇
💘💘💘相关链接如下(直接点击即可)

【Linux】Linux重要工具

 🎉🎉🎉xshell + 云服务器🎉🎉🎉

 博主主页传送门:愿天垂怜的博客

 

 

🍋知识点一:Linux编译器-g++、gcc

•🌰1. 背景知识

对于这一部分内容,需要一些前置的编译链接的相关知识。如果大家忘记了或者对这部分内容还有欠缺,可以看看我的这两篇文章:

【C语言】编译与链接过程详解:从源码到可执行程序,-CSDN博客

【C语言】详解预处理-CSDN博客

•🌰2. gcc如何完成

🍇预处理

预处理功能主要包括宏定义、文件包含、条件编译、去注释等。 预处理指令是以#号开头的代码行。 gcc –E hello.c –o hello.i 选项“-E”,该选项的作用是让 gcc 在预处理结束后停止编译过程。 选项“-o”是指目标文件,“.i”文件为已经过预处理的C原始程序。

我们可以看到.i为后缀的文件处理了宏、条件编译,并且展开了头文件,所以main函数所在的位置是841行,而上面都是头文件的内容。 

 🍇编译

在这个阶段中,gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc 把代码翻译成汇编语言。 用户可以使用“-S”选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码。 

  🍇汇编

汇编阶段是把编译阶段生成的“.s”文件转成目标文件,读者在此可使用选项“-c”就可看到汇编代码已转化为“.o”的二进制目标代码了。

注意:以.o为后缀的文件称为二进制可重定位目标文件

🍇链接

在编译代码的过程中,我们通常将多个.c文件编译形成.o文件,然后结合链接库一起打包形成可执行文件,而对于.i、.s为后缀的文件在编译过程中不会正在形成。

 举例如下:

•🌰3. 条件编译的作用

从大家从学习面向过程语言开始,就学习了条件编译。那么大家当时是否疑惑,为什么要有条件编译,条件编译究竟有什么作用呢?

我们利用上节课学习的vim写出下面代码:

 这份代码相信大家都能看懂,由于定义M被注释了,所以应该会输出 professional version(专业版)。但是注意,在编译的过程中,我们可以加上宏定义的指令,如下

 因此,条件编译有什么意义呢?我们举出下面三个场景:

scene1:如上,软件对专业度、收费情况进行区分(业务),使用条件编译,可以进行代码动态裁剪。

scene2:内核源代码也是采用条件编译进行动态裁剪。

scene3:开发工具,应用软件。

 

•🌰4. 函数库

 🍇库的定义

我们的C程序中,并没有定义“printf”的函数实现,且在预编译中包含的“stdio.h”中也只有该函数的声明,而没有定义函数的实现,那么,是在哪里实“printf”函数的呢?

答案是:系统把这些函数实现都被做到名为 libc.so.6 的库文件中去了,在没有特别指定,gcc 会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到 libc.so.6 库函数中去,这样就能实现函数“printf”了,而这也就是链接的作用。

定义库是一套方法或数据集,为我们的开发提供最基本的保证(基本接口、功能,加速我们二次开发)

 🍇动态库与静态库

1. 动态库(.so / .ddl):动态链接既涉及编译时的准备工作(如记录外部符号引用、生成占位符地址等),也涉及运行时的实际链接过程(如加载动态库、解析符号地址等)。程序的编译链接阶段会进行一些相关的设置,以确保程序具备在运行时到动态库中寻找所需方法的能力。

 我们可以用一个例子来理解动态库链接的过程。

假设你初中刚毕业,看到了高中的课表,其中计划下午13:00进行上网,但是不知道在哪里上网,于是你询问学长得知在学校东门左100米处有一个XX网吧,可以在这个地方上网。

 在这个例子中,初中刚毕业,是在上高中之前通过询问学长的方式得到上网的地址,而高中就相当于程序,当上高中之后,我直接根据之前询问学长所得知的网吧地址直接去就行了,这就是动态链接在运行时的实际链接过程。

注意:动态库被多个程序共享,一旦缺失,会导致所有程序无法执行!

2. 静态库(.a / .lib):程序在编译链接的时候将库的代码连接到可执行文件中,程序运行的时候将不再需要静态库。

我们依然继续刚才的例子,学校发现了很多学生都喜欢在网吧打游戏,这对学生的成绩造成了很大的影响,所以学校取缔了这个网吧,于是你中午没上网,导致你不想听下午的课程了,这就对应了动态库的不可缺失性。

但是你就是想完成这样一个过程,于是你找到了这个网吧的老板,要求在电脑仓库中拿出进而我之前上网的机子同款的机子买下来,然后带到学校去进行操作,这就是静态链接。静态链接会将静态库中对应函数的方法直接拷贝给我自己,因此会造成静态链接的程序体积很大。

注意:静态链接只有在链接的时候有用,一旦形成可执行程序,该程序可以不再需要此静态库。

 🍇动静态库对比

1. 链接动态库形成的可执行程序一定很小。

2. 可执行程序对静态库的依赖小,而动态库不能缺失。

3. 程序运行,需要加载到内存。如果是静态链接,会导致内存中出现大量重复代码,浪费资源。

4. 动态链接比较节省内存和磁盘资源。

 🍇验证工作

1. 我们可以在 /usr/lib64 目录下查看系统的库:


 

 2. 我们可以用 ldd 命令查看该文件依赖哪些动态库:

而 libc.so 就是C语言的标准库,包含了多种C函数方法的实现。

3. 我们可以通过在选项后面增加 -static 来强制静态链接:

注意:C++和C在库的链接上是一样的,唯一的不同是C的编译器使用的是gcc,而C++使用的工具是g++,大家可以敲一敲键盘自行体验C++的工静态库链接过程。

 🍇技术上理解库

我们知道,在编译的过程中,我们会将一份或多份的.c文件转换成.o文件再和库进行链接。假设我们希望提供被人程序以及方法的声明,而不希望方法的实现被看到,我们应该怎么操作呢?

我们先写一份代码:

我们希望在 code1.h 中声明 func1 ,在 code1.c 中实现 func1,func2 同理,那么我们新创建一个 lib 目录,在该目录下进行操作:

 完成code1和code2相应内容代码:

 ​​​​​

 我们可以将 lib 保留,将备份文件拷贝出去:

接着,我们先将.c文件编译,然后我们就可以将含有 func1 和 func2 的.c文件删除了:

接下来我们直接链接.o文件,得到可执行程序:

这样,我们就像别人隐藏了主函数中特定接口的实现了。

其实,借助这个示例,我想表达的是,所谓库,本质也是许许多多个.o文件构成的。我们写的代码编译成.o后,和库链接,其实就是链接这些.o文件。

    

 • ✨SumUp结语

到这里本篇文章的内容就结束了,本节给大家讲解了Linux的又一类重要工具-编译器。大家可以将我文章中写的操作自己实操一遍。加深印象。希望大家能够认真学习,迎接接下来的挑战,期待大家继续捧场~💖💖💖


http://www.kler.cn/a/519594.html

相关文章:

  • uva 1354 Mobile Computing
  • 【Postman接口测试】Postman的全局变量和环境变量设置
  • 快门:凝固瞬间与塑造动感的魔法开关
  • AR智慧点巡检系统探究和技术方案设计
  • 计算机图形学:实验四 带纹理的OBJ文件读取和显示
  • python学opencv|读取图像(四十二)使用cv2.add()函数实现多图像叠加
  • 7、知识库内容更新与自动化
  • 系统编程(线程互斥)
  • 牛角棋项目实践1:牛角棋的定义和用python实现简单功能
  • 大模型开发 | RAG在实际开发中可能遇到的坑
  • rewrite规则
  • STL中的list容器
  • 汇编的使用总结
  • CSS:跑马灯
  • 使用MQTT.fx向阿里云物理网平台上报物理模型数据
  • mysql安装记录
  • 十、VUE中的CSS
  • 边缘存储如何高效存储和调用数据?
  • “AI教学实训系统:打造未来教育的超级引擎
  • C# OpenCV机器视觉:利用CNN实现快速模板匹配
  • 【JS|第29期】JavaScript中的事件类型
  • 【PySide6 快速入门】第一个QtWidget程序
  • 1_相向双指针_leetcode_16_4
  • AWS Outposts
  • 低代码系统-钉、微表单控件对比
  • VMware 的 AWS