Linux——编译器gcc/g++、调试器gdb以及自动化构建工具makefilemake详解
编译器—gcc/g++、调试器—gdb以及自动化构建工具—makefile&&make
文章目录
- 编译器—gcc/g++、调试器—gdb以及自动化构建工具—makefile&&make
- 1. 编译器——gcc/g++
- 1.1 生成可执行文件与修改默认可执行文件
- 1.2 程序的翻译过程以及对应的gcc选项
- 1.2.1 预处理 gcc -E
- 1.2.2 编译 gcc -S
- 1.2.3 汇编 gcc -c
- 1.2.4 链接 gcc
- 2. 调试器——gdb
- 2.1 debug版本和release版本
- 2.2 gdb常用功能及其选项
- 2.2.1 查看代码
- 2.2.2 开始/退出调试
- 2.2.3 断点设置
- 2.2.4 逐语句/逐过程
- 2.2.5 断点跳跃
- 2.2.6 查看变量
- 2.2.7 查看函数调用堆栈
- 3. 自动划构建工具——makekfile&&make
- 3.1 makefile
- 3.2 make
- 3.2.1 工作原理
- 3.2.2 文件的acm时间
本章思维导图:

.xmind
和
.png
文件都已同步导入至
资源
1. 编译器——gcc/g++
安装命令:
- gcc:
sudo yum install -y gcc
- g++:
sudo yum install -y gcc-c++
- gcc只能编译C语言代码,g++既可以编译C语言代码也可以编译C++代码
- 推荐用gcc编译C语言代码
注:gcc和g++的选项一致,下面的讲解都以gcc为例
1.1 生成可执行文件与修改默认可执行文件
我们可以直接用gcc编译器将一个.c
文件直接编译成可执行文件
命令:
gcc filename
在这种情况下,会默认生成一个a.out
可执行文件
如果我们想要指定生成的可执行文件的名字,可以加入-o
选项
gcc -o newName filename
当然,如果想要对gcc编译器做更多的了解,上面的操作显然是不够的,我们需要结合程序的翻译过程来进行学习。
1.2 程序的翻译过程以及对应的gcc选项
众所周知,程序的翻译分为了四个步骤:预处理、编译、汇编、链接。要学会只用Linux的编译器:gcc/g++,固然也需要理解这四个步骤
关于这四个步骤,博主已经在程序的翻译环境和运行环境做了较为详细的阐述,故下面只对这四个步骤做简单的讲解:
1.2.1 预处理 gcc -E
在这一过程,编译器会进行头文件展开、宏替换、条件编译等过程
对应的gcc命令为:
gcc -E -o file.i file
-E
:即为预处理的gcc选项。表示预处理完后就停止- 预处理完后生成的文件后缀一般为
.i
演示:
可以看到,所谓的头文件展开实际上就是将头文件的内容拷贝至源文件中,预处理后得到的文件仍是C语言
1.2.2 编译 gcc -S
在这一过程,会对与处理过后的文件进行语法分析和词义分析,如果没有错误,就会生成以一个由汇编代码所写的文件
对应的gcc命令为:
gcc -S -o file.s file
-
-S
:即为编译的gcc选项。表示编译完后就停止 -
编译生成的文件的后缀名一般为
.s
演示:
1.2.3 汇编 gcc -c
在这一过程中,会将汇编代码转换为二进制代码,形成一个二进制文件
对应的gcc命令为:
gcc -c -o file.o file
-c
:即为汇编的gcc选项。表示汇编完后就停止- 汇编生成的二进制文件我们称其为目标文件
.obj
,文件后缀可以为.o
演示:
1.2.4 链接 gcc
会对目标文件进行动静态库链接,形成最终的可执行程序
.exe
对应的gcc命令为:
gcc -o newName filename
- 可以看到,用这条命令就可以直接生成一个可执行程序
演示:
以前写代码时大家可能会有一个疑惑:我明明没有声明和定义
printf()、scanf()
等库函数,为什么我可以正常使用呢?而之所以我们可以使用这些库函数,正是因为编译器有链接这一过程,这一过程将目标文件和库文件进行链接,从而让我们可以使用库中声明和定义好的函数
我们可以用命令:
ldd file
,查看一个文件依赖的库文件函数库分为动态库和静态库两种:
动态库:
- 动态库不包含在可执行程序中,而是在程序运行时由操作系统或者程序自行加载
- 多个程序可以共享一个动态库,因此如果采用动态链接可以**减少程序所占用的
- 使用动态链接的程序对库的依赖性较强,因此一旦库丢失,会使依赖这个库的程序都无法运行
- gcc/g++编译默认进行的是动态链接
静态库:
一般来说,需要自己对C语言和C++的静态库进行安装,执行下面两个命令即可:
sudo yum install -y glibc -static
sudo yum install -y libstdc++ -static
- 静态库是指编译链接时,把库文件的代码全部加入到可执行文件中的库
- 静态库包含在可执行程序中,因此使用静态链接的程序对库的依赖性较弱,同类型平台都可以使用
- 由于可执行程序包含了库文件的拷贝,因此使用静态链接的程序会占用较多的资源空间(内存、磁盘)
- 如果要使gcc/g++进行静态链接,就要加入
-static
选项
2. 调试器——gdb
安装命令:
sudo yum install -y gdb
为了能够更好的理解,我们先来谈谈程序发布的两个版本——debug版本
和release版本
2.1 debug版本和release版本
首先我们要清楚:
- Linux上的gcc和g++编译出来的可执行程序默认都是
release
版本的release
版本是不支持调试的,只有在debug
版本下才能调试
为了在Linux上能够生成debug
版本的可执行程序,我们需要在编译时加上选项-g
gcc -o newFile file -g
下面,我们再来谈谈为什么一个程序要有debug
和release
两个版:
- 在程序的开发阶段,程序难免会出现各种问题,而为了能够方便程序员对这些错误进行排查,就必须要支持调试这一功能,因此程序员开发中的程序一般都是debug版本,里面包含了各种调试信息,方便进行错误排查
- 当程序员认为开发中的程序已经基本完成,就会将其交给测试组的人员进行测试。而这个程序最终肯定是要交给大众去使用的,使用这个程序的普通人显然不需要
debug
版本的调试信息,他们只需要更小的体积和更快的下载速度,因此这就要求程序需要一个**release
发行版本,这个版本就是给测试组的人员进行测试和给用户进行使用的版本**
2.2 gdb常用功能及其选项
进入调试模式的命令为:
gdb file
file
必须是一个debug
版本的可执行程序
2.2.1 查看代码
命令:
l n
- 查看第n行附近的10行代码
- 按
Enter
可以继续查看
2.2.2 开始/退出调试
命令:
r
:如果没有打断点,那么会正常运行代码;否则会运行到第一个断点处quit
:推出调试
2.2.3 断点设置
添加断点:
b n
:在第n
行添加断点b 函数名
:在指定函数的入口处添加断点b file:n
:在指定文件的第n
行添加断点。注意:这个file
不是可执行程序,而是被编译的.c/.cpp
文件
查看断点:
info b
例如:
- 第一列的数字
Num
表示断点的编号 - 第四列的字符
Enb
表示断点的使能状态,y
表示该断点处于开启状态,可被使用;n
表示处于关闭状态,不可被使用
删除断点:
d n
:表示删除**编号为n
**的断点。
- 特别注意,删除断点是按编号删除,而不是按行号
使能断点:
disable n
:关闭编号为n的断点enbale n
:开启编号为n的断点
2.2.4 逐语句/逐过程
逐语句:
-
在C语言/C++中,被一个分号
;
分割的语句都被称为一条语句。逐语句调试就是一个个分号地,不做任何跳过的调试。 -
因此逐语句调试可以进入函数体内调试。
命令:
s
逐过程:
- 一个函数成为一个过程
- 因此逐过程调试不能进入函数体内进行调试
命令:
n
2.2.5 断点跳跃
如果打了多个断点,那我们可以通过命令直接运行到下一个断点处:
c
2.2.6 查看变量
p name
:查看指定变量的内容
如果想要使变量一直显示,可以用命令:
display name
例如:
- 变量前的数字即为该变量的编号
如果想删除常显示的变量,可以使用命令:
undisplay n
:即删除编号为n的变量常显示
2.2.7 查看函数调用堆栈
命令:
bt
3. 自动划构建工具——makekfile&&make
Makefile和make
是与Linux系统中软件编译和构建相关的工具。它们通常用于自动化构建过程,确保在源代码发生变化时只重新编译必要的部分,从而提高开发效率。
3.1 makefile
- 也可以写为
Makefile
makefile
是一个文本文件- makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂
的功能操作
我们来通过一个具体的例子来学习一个makefile
文件要包括哪些内容:
mybin:code.c
- 这叫一组依赖关系。
mybin
目标文件,code.c
为依赖文件列表。 - 表示
mybin
这个目标文件依赖于code.c
这个文件列表而构建
gcc -o mybin code.c
- 注意:前面必须有
Tab
缩进,这是语法要求 - 这一行叫做依赖方法。
- 表示目标文件是通过gcc编译来完成对
code.c
这一依赖文件列表的依赖的
.PHONY:clean
- 将
clean
设置成一个伪目标 - 伪目标在任何时候都会执行,不会受时间戳限制
clean:
clean
也是一个目标文件,但是没有对应的依赖文件列标- 其被修饰为了一个伪目标,表示一个命令操作——清除
rm -f mybin
- 这就是
clean
的依赖方法,即clean
对应的操作
makefile文件的其他写法:
在一组依赖关系和依赖方法中,目标文件可以被
$@
替换,依赖关系列表可以被$^
替换,例如:
makefile文件也允许我们定义变量和选项,例如:
3.2 make
make是一个命令
3.2.1 工作原理
如果我们只输入一个make
命令:
-
会找到
makefile
中的第一个目标文件,然后根据依赖文件列表和依赖方法构建出目标文件 -
如果依赖文件列表有文件不存在,那么会继续向下找这个不存在文件的依赖关系和依赖方法,知道构建出这个文件
-
如果最终这个文件不能被构建,那么此次
make
命令就会报错 -
例如:
make后面也可以跟一个目标文件来执行指定的操作。例如:make clean
特别注意:
如果一个目标文件没有被
.PYTHON
修饰为伪目标,那么它的make
构建就会收到时间戳的影响
即,如果该文件的
修改时间
没有改变,那么就不会进行make构建例如,重复构建目标文件
mybin
,会报错:
而提到修改时间,我们就有必要了解一个文件的acm
时间
3.2.2 文件的acm时间
我们可以用命令查看一个文件的acm
时间:
stat filename
Access
:访问时间。即最后一次读写文件的时间Modify
:修改时间。即最后一次修改文件内容的时间。这个时间就是影响make
构建的时间Change
:改变时间。文件 = 内容 + 属性,即最后一次改变文件内容或属性的时间。
我们也可以用命令来刷新一个文件的acm时间:
touch filename
本章完。
下一章,我们将进入Linux系统编程部分,各位如果感兴趣不妨点个关注。
相关文章:

Linux——编译器gcc/g++、调试器gdb以及自动化构建工具makefilemake详解
编译器—gcc/g、调试器—gdb以及自动化构建工具—makefile&&make 文章目录 编译器—gcc/g、调试器—gdb以及自动化构建工具—makefile&&make1. 编译器——gcc/g1.1 生成可执行文件与修改默认可执行文件1.2 程序的翻译过程以及对应的gcc选项1.2.1 预处理 gcc -E…...
Android registerForActivityResults使用详解以及实现原理
registerForActivityResult 使用用途是监听Activity结果。 以下是使用样例 //需要传递Request用于解析Intent和解析上个Activity返回的结果 val launchdata = registerForActivityResult<PickVisualMediaRequest, Uri?>(ActivityResultContracts.PickVisualMedia()) {…...

模拟实现一个Linux中的简单版shell
exec系列接口中的环境变量 在之前我们学习了exec系类函数的功能就是将一个程序替换成另外一个程序。 然后就会出现下面的问题: 首先父进程对应的环境变量的信息是从bash中来的,因为我们自己写的父进程在运行的时候首先就要成为bash的子进程。这里我们将…...

扩散模型实战(十):Stable Diffusion文本条件生成图像大模型
推荐阅读列表: 扩散模型实战(一):基本原理介绍 扩散模型实战(二):扩散模型的发展 扩散模型实战(三):扩散模型的应用 扩散模型实战(四ÿ…...

LaTex编写伪代码,并实现根据所在章编号(连字符),例如算法1-1
1 首先导入包: 按需要添加或者删除option,但是algochapter是必须的。 \usepackage[linesnumbered,ruled,algochapter]{algorithm2e}各个option的作用如下: 您好,这是Bing。我可以帮您解释algorithm2e包中这几个option的意思。&a…...
vue.js javascript js判断是值否为空
检查一个对象(Object)是否为空,即不包含任何元素。Javascript 中的对象就是一个字典,其中包含了一系列的键值对(Key Value Pair)。检查一个对象是否为空,等价于检查对象中有没有键值对。 1、如…...

网页开发如何实现简易页面跳动/跳转,html课堂练习/作业,页面ABC的相互跳转
先建一个文件夹,文件夹包含三个文件夹,三个文件夹分别包含各自的代码。(可以只建一个文件夹,文件夹包含各页面代码) 页面1的代码: <head> <meta http-equiv"Content-Type" content"text/html; charsetu…...
某大型房地产公司绩效面谈项目成功案例纪实
——开展有效的绩效面谈,促进和完善管理工作 【客户行业】房地产行业;国有企业 【问题类型】绩效面谈改进 【客户背景】 某大型房地产公司是某国企集团的省级分公司,集团公司现拥有北京、上海、广州、山东等8大区域公司,现有员…...

BGP联盟和团体属性实验
目录 一、实验拓扑 二、实验要求 三、实验步骤 1、IP地址配置 2、ospf配置 3、BGP建邻 4、宣告网段 5、配置团体属性 一、实验拓扑 二、实验要求 1、按照图示配 IP 地址,R2,R3,R4,R5分别配 Loopbacke 口地址作为OSPF的Ro…...

代码随想录-刷题第二天
977. 有序数组的平方 题目链接:977. 有序数组的平方 思路:双指针思想,数组是有序的且含有负数,其中元素的平方一定是两边最大。定义两个指针,从两端开始向中间靠近,每次比较两个指针的元素平方大小&#…...

DAY59 503.下一个更大元素II + 42. 接雨水
503.下一个更大元素II 题目要求: 给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素。数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数&am…...

【如何将任何直流电机变成伺服电机】
【如何将任何直流电机变成伺服电机】 1 前沿2 伺服电机工作原理3 如何制作定制伺服电机4 AS5600 编码器 – 磁性旋转位置传感器5 定制伺服电机电路图6 PCB设计7 自定义伺服3D模型8 定制伺服齿轮箱的 3D 打印零件9 对控制器进行编程9.1 引导加载程序刻录9.2 代码上传9.3 源代码9…...

单片机语音芯片在工业控制中的应用优势
单片机语音芯片,这一智能化的代表产品,不仅在家庭和消费电子领域发挥着重要的作用,更为工业控制领域注入了新的活力。将单片机语音芯片与语音交互技术相结合,为工业设备的控制和监测提供了前所未有的解决方案。 首先,…...

【开源】基于Vue.js的高校实验室管理系统的设计和实现
项目编号: S 015 ,文末获取源码。 \color{red}{项目编号:S015,文末获取源码。} 项目编号:S015,文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、研究内容2.1 实验室类型模块2.2 实验室模块2.3 实…...

Xrdp+内网穿透实现远程访问Linux Kali桌面
XrdpCpolar实现远程访问Linux Kali桌面 文章目录 XrdpCpolar实现远程访问Linux Kali桌面前言1. Kali 安装Xrdp2. 本地远程Kali桌面3. Kali 安装Cpolar 内网穿透4. 配置公网远程地址5. 公网远程Kali桌面连接6. 固定连接公网地址7. 固定地址连接测试 前言 Kali远程桌面的好处在于…...

【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】
👨💻博客主页:花无缺 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 本文由 花无缺 原创 收录于专栏 【洛谷算法题】 文章目录 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】🌏题目描述🌏输入格…...

Eclipse切换中文环境
PACK包链接 地址,进入后可以看到不同版本的包。 要选择跟自己Eclipse版本一致的包,比如我的Eclipse启动界面如下,我就要找Helios的包( Juno、Indigo、Helios、Kepler这些具体怎么划分的我也不清楚)。 在线安装 打…...
栈和队列概念
栈stack 栈只能在一端插入/删除元素先入后出只能从栈顶插入,栈顶删除栈底不允许插入和删除push:进栈pop:出栈应用场景: 队列 Queue 队列的插入操作称为 “入队”(Enqueue),是在队尾进行的&am…...

a标签下载文件与解决浏览器默认打开某些格式文件的问题
前言 在实际项目中,我们通常会遇到这么一个需求:后端给前端返回一个任意文件类型的完整的url路径,前端拿到这个路径直接通过浏览器下载文件到本地。我想大家应该都会首先想到使用HTML中的<a>标签,,因为<a>…...

EasyCVR视频监控+AI智能分析网关如何助力木材厂安全生产?
旭帆科技有很多工厂的视频监管方案,小编也经常分享出来供大家参考。近期,又有伙伴后台私信我们想要关于木材厂的方案。针对木材厂的生产过程与特性以及安全风险等,我们来分享一下相关的监管方案: 1)温湿度监测…...

深入理解JavaScript设计模式之单例模式
目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...

学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...

(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...

用docker来安装部署freeswitch记录
今天刚才测试一个callcenter的项目,所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...

Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...

均衡后的SNRSINR
本文主要摘自参考文献中的前两篇,相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程,其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt 根发送天线, n r n_r nr 根接收天线的 MIMO 系…...

九天毕昇深度学习平台 | 如何安装库?
pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子: 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...

回溯算法学习
一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...