第五章 linux编译器——gcc/g++的使用

news2024/11/15 11:01:34

第五章 linux编译器——gcc/g++的使用

  • 一、编辑器与编译器的区别
  • 二、gcc/g++的编译过程
    • 前言
    • 1、阶段1:预处理(头文件、宏的替换)
      • (1)作用
      • (2)指令
      • (3)示例
    • 2、阶段2:编译(生成汇编代码)
      • (1)作用
      • (2)指令
      • (3)示例
    • 3、阶段3:汇编(生成二进制文件)
      • (1)作用
      • (2)指令
      • (3)示例
    • 4、阶段4:链接(生成可执行文件)
      • (1)作用
      • (2)静态链接与动态链接
      • (3)指令
      • (4)示例
    • 5、指令的简化
  • 三、Linux项目自动化构建工具——make/Makefile
    • 1、背景
    • 2、Makefile文件的编写
      • (1)项目的构建
        • 依赖关系
        • 依赖方法
        • 顺序说明
      • (2)项目的清理
    • 3、make相关的指令
      • (1)项目的自动化搭建——make
      • (2)项目的自动化清理——make clean

一、编辑器与编译器的区别

在前一个章节中提到的vim是代码编辑器,代码编辑器的功能是让我们输入代码的。所以从这个角度出发,我们常见的记事本也可以算作一个代码编辑器,只不过这个编辑器没有高亮等功能。而我们今天介绍的代码编译器的功能是把编辑器中写入的代码翻译为机器能够听懂的语言并生成可执行文件。所以这二者是有本质区别的。

二、gcc/g++的编译过程

前言

gcc是用来编译C语言代码的,g++是用来编译C++代码的。这两个编译器在指令和编译过程等方面几乎是一样的。所以作者在这里只以g++为例子介绍编译器。

1、阶段1:预处理(头文件、宏的替换)

(1)作用

预处理过程主要作用是将代码中的宏定义进行替换,同时将头文件写入到我们代码的前面,除此以外还会去掉我们写的注释。

(2)指令

g++ -E A.cpp -o A.i

g++是指我们想要用的编译器是g++,"-E"的作用是让g++在预处理结束后停止编译过程,“A.cpp”是需要被处理的c++代码。“-o”是指利用前面处理过的内容生成一个目标文件,“A.i”是我们目标文件的名字,其中“.i”是与处理文件的后缀。

(3)示例

下面是作者写的源文件:
在这里插入图片描述
接下来,我们进行文件的预处理工作,在命令行中输入刚刚讲解的指令,如下图所示:
在这里插入图片描述
根据上面这个图我们会发现,预处理过后的文件非常的大,而这背后的主要原因就是在预处理的过程中,编译器将我们头文件引入到了代码中。

然后我们打开预处理后的文件:“t1.i”,结果如下图所示。
在这里插入图片描述
通过观察上面的图,我们会发现,除了头文件被替换了以外,我们的宏定义也被替换了。注释也被删除了。

2、阶段2:编译(生成汇编代码)

(1)作用

以g++为例,在编译阶段,编译器会将预处理过后的C++文件翻译为汇编语言的文件。

(2)指令

g++ -S A.i -o A.s

(3)示例

在这里插入图片描述
如上图所示,编译工作结束后,我们的目录下多了一个.s的文件。那么我们可以预览一下这个文件里的内容。
在这里插入图片描述
我们发现,我们原本用C++写的代码已经被翻译为了汇编代码。

3、阶段3:汇编(生成二进制文件)

(1)作用

在汇编阶段,编译器会将编译后的汇编文件翻译为二进制文件。

(2)指令

g++ -c A.s -o A.o

(3)示例

在这里插入图片描述
我们可以预览一下汇编过后的代码。
在这里插入图片描述
由于我们vim无法查看用二进制写的代码,所以这里显示了乱码。

4、阶段4:链接(生成可执行文件)

(1)作用

在预处理阶段,编译器会将头文件的内容拷贝到我们写的代码文件中。这里就会有一个问题,头文件中只写了函数的声明,也就是说头文件的作用仅仅是告诉编译器这个函数的的确确存在,但是并没有告诉编译器这个函数到底是怎么实现的,函数的具体实现是写在库文件中的。我们此处介绍的链接其实就是将我们的代码和这些写有函数实现的库文件之间构建联系,从而生成一个可执行文件。

(2)静态链接与动态链接

写有函数实现的库文件分为两大类,一类是静态库,一类是动态库。

如果是静态链接的话,编译器就会将静态库中的代码实现拷贝到我们的代码中。这种静态链接的方式有好处也有坏处。好处在于,如果我们的静态库丢失了,由于我们已经对函数实现进行了拷贝,所以代码文件是独立的,依旧可以正常运行。但坏处也显而易见,由于该过程进行了大量的拷贝工作,所以会浪费很多空间。

动态链接则与之相反,动态链接并不会将代码实现进行拷贝,而是和动态库建立一种联系,从而让编译器了解到函数的具体实现。由于很多代码文件都和一个动态库建立联系,所以动态库又叫做共享库。那么这么做有什么优点呢?首先,由于动态链接并不会将代码拷贝到文件中,所以动态链接的方式能够节约大量的空间。缺点也显而易见,如果动态库发生了丢失,那么该文件将无法执行。

(3)指令

g++ A.o -o A

(4)示例

在这里插入图片描述
我们只要访问生成的文件,即可看到我们的代码运行结果。
在这里插入图片描述

5、指令的简化

如果每次运行代码都需要输入上面四个指令的话,其实是非常麻烦的。所以我们可以将上面四个编译命令合并成一个简化的命令。

g++ A.cpp -o A

在这里插入图片描述

三、Linux项目自动化构建工具——make/Makefile

1、背景

当一个工程越来越大的时候,源文件就会越来越多,我们的编译命令就会越来越麻烦。无论是源文件的数量,还是文件先后的编译顺序都会对我们的编译工作造成困扰。那么为了解决这个问题,我们就需要了解一下自动化构建的工具:make。这里先解释一下标题,make是一个命令,Makefile是一个文件,Makefile文件中要写的是编译的指令。当写好这个文件后,我们只需要用make指令调用Makefile文件即可。

2、Makefile文件的编写

(1)项目的构建

为了后续的讲解更加清楚,作者在这里直接给出项目构建的Makefile文件。
在这里插入图片描述

依赖关系

在上面的图片中,我们将每两行看成一组,在每一组的第一行就是依赖关系。冒号前面的绿色字体所描绘的文件的生成依赖于冒号后面的文件。

依赖方法

在每一组中,第二行紫色的字体所写的代码是依赖方法,即如何用被依赖的文件生成目标文件。

上图只是为了让大家更好的理解Makefile文件的书写,其实我们可以直接放一个简化后的命令在上面,不用细化这么多。即下图:
在这里插入图片描述

顺序说明

从上面的图片中我们还发现了一个规律,我们的顺序是倒着来的,从可执行文件倒推到,cpp文件。这里用到的其实是栈这种数据结构。如果无法用栈理解的话,读者可以强行记住这里是从后往前写的。我们这利用一下后面马上要介绍的make指令运行一下Makefile文件。将会发生下面的现象。
在这里插入图片描述
通过这张图片,我们会发现,虽然我们是倒着写的,但是最终是正着执行的。即我们先写的是后执行的,即后进先出,恰好是栈这种数据结构的特点。

(2)项目的清理

我们还是先给出项目清理的makefile文件写法。如下图所示:
在这里插入图片描述
我们先看最后两行,这两行很好解释。clean指的是清楚命令。第二行指的是我们清楚目标文件的删除命令。而倒数第三行则不一样。.PHONY是强制执行的命令,冒号后面的clean是指我们要强制执行哪一条命令。那么这一行的意思就是,我们要强制执行clean命令。

3、make相关的指令

(1)项目的自动化搭建——make

当我们写好Makefile文件后,我们只需要在命令行中输入一个make即可。如下图所示:
在这里插入图片描述

这里还要介绍一下,make命令的重复使用问题。
我们的如果我们的代码源文件没有更改的话,我们的make命令只能执行一次。如果重复执行的话,会出现下面的提示:
在这里插入图片描述
那么make怎么知道我们的源代码如何更改呢?其实很简单,Linux会记录文件的修改时间,make会通过时间的比较来判断你是否修改过。但是如果我们想强制运行呢?其实也是可以的,我们刚刚介绍了一个强制执行的命令:.PHONY。这里就可以使用以下,如下图:
在这里插入图片描述
我们想要重复执行哪一个命令,就在前面加上强制执行的命令,冒号后面则是我们的目标文件。结果如下图所示:
在这里插入图片描述

(2)项目的自动化清理——make clean

如果想要清理我们的项目,我们只需要在命令行中输入make clean即可。
在这里插入图片描述

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

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

相关文章

Linux--用户身份切换: su

①普通用户切换成超级用户且更改路径:su - ②普通用户切换成超级用户且不更改路径:su root 或者 su ③(由普通用户切换来的)超级用户切换回普通用户:Ctrld ④超级用户切换成普通用户:su 普通用户名 ⑤普通用户a切换成普通用户b…

Jetson Nano Swap交换空间增加

依次输入以下命令,可以使交换空间增加3G,解决一些耗尽内存的程序出错。 sudo fallocate -l 3G /var/swapfile sudo chmod 600 /var/swapfile sudo mkswap /var/swapfile sudo swapon /var/swapfile sudo bash -c echo "/var/swapfile swap swap de…

金九银十1060+ 道 Java面试题及答案整理(2023最新版)

前言 今年的金三银四可是被裁员疫情搞得人心慌慌,由于大厂纷纷裁员,面试的竞争难度又上一层,不知道你是否在金三银四中拿到 offer?不过这些都过去了,现在马上迎来的是金九银十,按照往年来说,秋…

python | 识别项目中的接口并生成接口文档

识别项目中的接口并生成接口文档 前言起点用途使用方法控制台展示文档内容展示代码注意事项 前言 前段时间也是来了一场说走就走的旅行,去看了看祖国的大好河山,不得不说也是一场让我难忘的旅行,可惜钱包太扁了,禁不起我的的折腾…

NOSQL之redis配置和安装

关系数据库与非关系型数据库 ●关系型数据库: 关系型数据库是一个结构化的数据库,创建在关系模型(二维表格模型)基础上,一般面向于记录。 SQL 语句(标准数据查询语言)就是一种基于关系型数据库…

Andriod Studio安装使用中

暑假快乐啊,终于考完啦 Android studio安装的前提是必须保证安装了jdk1.8版本以上 如果没有安装好,那么可以参考这个:win10下载jdk18以及环境配置 一、在官网下载Android Studio 官网:https://developer.android.google.cn/stud…

jedis使用,操作Redis数据库1

使用jedis的原因; 1.提高性能,减少Socket的创建和销毁对性能的影响 2.是一个线程安全的网络连接池。可以用JedisPool创建一些可靠Jedis实例,可以从池中获取Jedis实例,使用完后再把Jedis实例归还给JedisPool连接池。合理的JedisPool资源池参数…

8 款在线 API 接口文档管理工具;好用!

1、Postman Postman是被大家所熟知的网页调试Chrome插件,我们常常用它来进行临时的http请求调试。幸运的是,Postman可以将调试过的请求保存到Collection中。形成的Collection就可以作为一份简单有效且支持在线测试的接口文档,使用同一账号登录…

Jenkins+Docker 实现一键自动化部署项目

1、环境配置 环境:centos7git(gitee) 简述实现步骤:在docker安装jenkins,配置jenkins基本信息,利用Dockerfile和shell脚本实现项目自动拉取打包并运行。 2、安装docker docker 安装社区版本CE 确保 yum 包更新到最新。 yum …

react-redux(由浅到深)

文章目录 1. redux1.1 概述与使用原则1.2工作流程1.2.1 三个核心 1.3 store1.4 action1.5 reducer1.5.1 合并reducers 1.6 dispatch getState 及状态更新 2. react-redux2.1 基本特征2.2 connect()、mapStateToProps2.3 mapDispatchToProps2.4Provider2.5. 中间件,c…

【动手学习深度学习--逐行代码解析合集】04softmax回归的从零开始实现

【动手学习深度学习】逐行代码解析合集 04softmax回归的从零开始实现 视频链接:动手学习深度学习–softmax回归的从零开始实现 课程主页:https://courses.d2l.ai/zh-v2/ 教材:https://zh-v2.d2l.ai/ 1、 softmax网络架构 2、 softmax运算 3、…

实验三:运算类编程实验

实验目的 阐明本实验的目的。 一实验目的掌握学精变C6应) 乘汉运第《结购 3位)江程产设计方法穿握双精度[3位)加法运算乡饰程产设计方法穿握双精度园) 朱讼运算 [结果为64位)汇编往广设计方讯 实验要求 说明实现本实验需要掌握的知识及本实验需要的实验环境 、实强要求 了解简单…

20+个小而精的Python实战案例(附源码和数据)

公众号:尤而小屋作者:Peter编辑:Peter 大家好,我是Peter~ 最近小编认真整理了20个基于python的实战案例,主要包含:数据分析、可视化、机器学习/深度学习、时序预测等,案例的主要特点&#xff1…

spring boot security验证码登录示例

前言 在spring boot security自定义认证一文,基本给出了一个完整的自定义的用户登录认证的示例,但是未涉及到验证的使用,本文介绍登录的时候如何使用验证码。 本文介绍一个验证码生成工具,比较老的一个库了,仅作demo…

rust warp框架教程1-helloworld

warp框架简介 warp is a super-easy, composable, web server framework for warp speeds. warp建立在hyper之上,因此,warp天生支持异步,HTTP/2,以及“正确的HTTP实现”。 warp的强大之处在于其提供的filter系统,它…

软件设计模式与体系结构-设计模式-生成模式单例模式

目录 二、生成器模式1. 生成者模式概念实例一:房屋选购系统题目时序图类图 优缺点适用场景 2. 生成器模式与抽象工厂模式3. 课程作业*** 三、单例模式1. 单例模式要点:基本思路实例一:互联网连接问题 2. 多线程情况3. 优缺点4. 适用场景5. 课…

leetcode 88.合并两个有序数组

⭐️ 题目描述 🌟 leetcode链接:合并两个有序数组 ⭕️ 代码: /*思路:双指针问题1.从前往后拷贝依次比较两个数组元素的较小值,较小值先拷贝- 问题:从前拷贝会造成覆盖(有问题)2.从后往前拷贝依次比较两个…

SpringBoot(五)SpringBoot事务

在实际开发项目时,程序并不是总会按照正常的流程去执行,有时候线上可能出现一些无法预知的问题,任何一步操作都有可能发生异常,异常则会导致后续的操作无法完成。此时由于业务逻辑并未正确的完成,所以在之前操作过数据…

单臂路由实现不同VLAN之间数据转发

实验环境: 思科模拟器,Cisco Packet Tracer 实验拓扑: 实验配置: (1)PC配置 IP地址子网掩码网关PC1192.168.10.1255.255.255.0192.168.10.254PC2192.168.10.2255.255.255.0192.168.10.254PC3192.168.20…

串口通讯监控方法

当我们调试硬件的时候,发现串口数据异常,用示波器和逻辑分析仪的话会比较麻烦,此时可以并一个监控串口,如下图所示 232串口,我们是不能直接并一个串口上去的;但是我们的监控串口,可以只接一根R…