Linux相关概念和重要知识点(6)(make、makefile、gdb)

news2024/9/24 0:15:20

1.make、makefile

(1)什么是make、makefile?

在我们写完代码后,要编译运行,如果有多个.c文件就需要每次都自己用gcc -o来处理,这十分麻烦。当我们想要自定义多个文件的处理时,我们会浪费很多时间在重复的事情上,我们需要一种自动化的、可自定义文件处理方式的程序,make和makefile就是为此而生的。大型项目一定离不开make和makefile。

make和makefile联系紧密,make是一个命令,makefile是一个文件,这个文件以某种格式来自定义可执行程序的方式,当使用make时就调用这个makefile文件来处理。

(2)makefile结构

makefile本质是依赖关系和依赖方法的集合。举个例子,完成老师向学生下达任务这件事需要两个条件:首先就是这两个人得是师生关系,即依赖关系;其次就是下达任务这个动作,这叫依赖方法。要办成一件事,依赖方法和依赖关系缺一不可,首先建立依赖关系,其次传递依赖方法。

格式:(目标文件):(依赖文件)   -> 依赖关系

(tab) (依赖方法)

类似于函数的传参和返回值,依赖文件类似传递的参数,而目标文件则是返回值,或者说是计划生成的文件。隔行后就可以开始写我们的依赖方法了,类似函数体。但是要注意每行依赖方法指令必须要顶格使用tab,就像python的函数一样,对缩进的要求很高。

下面是一个简单的示例。

当我们执行make时,就会根据makefile在当前目录下找test.c文件,类似函数的参数,目标生成的文件就是test。在依赖方法中我们显式写了目标文件和依赖文件,名字也符合规范。按照我们的指令一行行执行,最终生成指定文件。

我们发现,我们不仅将指令的结果打印出来了,还将指令的内容打印出来了。当我们在依赖方法每行前面加上@时,就能只打印结果而没有指令本身,这叫关闭回显。

(3)依赖关系

我们需要进一步理解依赖文件和目标文件的作用,根据上面的例子,有人肯定会觉得目标文件和依赖文件就等同于函数的参数和返回值,但事实并不是,它们和函数有很大区别

看一下下面的依赖关系和结果

我们发现,目标文件是a,没有依赖文件,但是实际执行指令时用到了test.c,生成的文件又是test,和目标文件a完全不沾边,这应当如何解释?

目标文件理解成一种建议生成的文件或是一种规范,规范更好,不规范也不会强制终止。因为在有的时候不需要生成文件,而目标文件一定要写,所以这是一种妥协。但是我们必须保证依赖文件必须能够找到,因为不需要依赖文件时我们可以不写,不会存在目标文件的那种情况。当执行依赖方法时,每一行指令其实都被展开到当前工作目录下执行,上面的gcc -o test test.c是一句完整的指令,它不需要依赖任何的依赖文件,也能合理地生成自己的文件,和目标文件也没有任何关系。

那么依赖文件和目标文件存在有何意义?

①声明依赖关系,实现不同功能的区分

在makefile我们可以写很多指令,实现不同功能,不同功能的指令都需要先声明依赖关系,再执行依赖方法。依赖文件和目标文件存在就是为了声明依赖关系。在目标文件和依赖文件没有实际意义时它更像一种标识,标志这个功能将要开始实现,也可以和其它功能的指令作出区分。

当我们使用make时默认执行第一个依赖关系下的依赖方法。要执行其它的需要make (目标文件)

在makefile里,目标文件名不能重复,否则会导致歧义。

②自动推导

在很多情况下依赖文件和目标文件是一种建议,是一种规范,规范必定带来好处,其中有一个就是自动推导。

当我们想要通过.c先生成一个.o,再生成一个可执行文件,那就可以利用自动推导来处理。

当make之后会自动执行第一个依赖关系,按照我们写的依赖文件在目录中查找,如果找不到,会将这个依赖关系先放入栈,再找目标文件是刚刚依赖文件的依赖关系,找到了如果发现依赖文件还是找不到,那就继续入栈,以此类推。如果一个依赖关系的目标文件和依赖文件都能在当前目录找到,那就依次出栈,执行指令。

注意推导到最后的依赖关系时依赖文件一定找得到,否则就报错,和前面的规则一样。

根据上面的规则,看一下下面的makefile,在make和make clean时结果是什么

结果

当make时,会根据目标文件和依赖文件入栈出栈,当我们递归生成文件时,就需要好好规范一下目标文件和依赖文件的写法,保证能够推导到其它依赖关系上。

③通配符

当我们不写依赖文件时,依赖方法里依然可以用到目录里面的文件,因为依赖方法的指令会被展开执行,既然显式写出了调用的文件(即构成了一句完整的指令),就能正常执行。

当我们有多个.c时,我们需要逐个对所有.c进行编译,当要处理的文件都有一个相同特征时,通配符就派上用场了,在makefile里,百分号%就是通配符的意思,和指令里的*一样

注意通配符对应的依赖关系很特殊,要么整个依赖关系都用通配符,要么都不用。并且make时是无法定位由通配符组成的通配符的依赖关系的,就算名义上它是第一个依赖关系。需要我们写一个自动推导的依赖关系。

④变量和自动变量

如果我们想要依赖关系列出来的文件和实际依赖方法使用的文件有较强相关性,可以使用自动变量。

$@代表目标文件,$^代表全部依赖文件,$<代表逐个依赖文件

定义的变量可以以$(变量)形式使用,变量和自动变量的使用可以帮助我们更统一的管理文件调用,生成的文件,极大降低了重复的工作

(4).PHONY伪目标

常规的依赖关系都会根据依赖文件和目标文件的Modify来决定是否需要执行。如果依赖关系里面的文件都有且目标文件的Modify时间更晚,那就不会执行。

.PHONY:(伪目标)声明伪目标,会自动忽视伪目标的时间比对。后续直接使用(伪目标):(依赖文件)来定义依赖关系即可。我们也可以用touch显式修改时间来绕过检查。

一个.PHONY声明一个伪目标

伪目标的作用就是为了执行一些指令,不要求生成文件生成

2.gdb

gdb是调试代码的工具,我们利用gdb调试的本质是帮助我们快速找出问题,然后自己解决。这里分享一些指令和注意事项

cgdb:我们可用cgdb来替代gdb,操作一致但代码有展示,更方便。

检查是否安装:gdb --version

调试前提:编译选项加上-g(debug,添加调试信息)。默认情况都是release,无调试信息

重复操作:gdb中直接回车默认执行上一条指令

显示代码:l (num)将第num行居中显示,l (函数名)居中显示当前函数名所在行,l (源文件):(函数名/行号)查看指定文件中的代码,注意每次回车都会执行l(翻页,每次10行)

打断点:b (行数/函数名)给指定位置打断点,info b可以查看自己打的断点,每个断点都有一个编号Num

打条件断点:b (行数) if (变量) == (值)打一个条件断点,只在if成立时截停。condition (断点编号) (条件) 可以给已有的断点添加条件

暂时禁用断点:enable (断点编号)打开断点,disable (断点编号)关闭断点

删除断点:d (断点编号)删除断点,要通过info b查看自己打的断点的编号Num。注意每个断点编号对应一次断点操作,不会复用已删除的断点编号

执行代码:r在没有断点时直接将代码运行完,有断点时执行至第一个断点。调试过程中再按r意味着重新启动调试

逐语句和逐过程:n逐过程(不会进入函数),s逐语句(会进入函数)

执行至下一次断点:c直接执行到当前断点的下一个断点

执行至指定行数:until (行数)跳过中间的代码,直接执行到指定行

按函数运行:finish能把当前函数跑完,如果期间有断点会被截停,main函数不行(最外围函数不支持)。断点 + finish + until + c这几个指令组合起来很有用,能帮助我们查找bug发生点,进而实现对大的代码块进行区间debug

调试中修改:set bar (变量)=(新值),直接修改代码中的变量的值,帮助我们在调试时能根据猜想及时检验问题,如果错了也可以继续修改,而不必退出gdb检验

监视:display (变量)每次执行都会监视变量,display (监视编号)关闭显示,p (表达式)临时显示当前变量或表达式的值。监视编号也是不可复用的,每次打印监视变量就会打印其监视编号

检测变量:watch (变量)检测变量的值是否变化,它是watchpoint,能用info b查看,也能d删除。如果变量数值变了,就会显示出来,而不像display那样每次都显示

查看当前函数栈帧:bt显示逐语句位置,显示每层函数调用位置

自动变量:info locals显示当前栈帧定义的变量信息

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

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

相关文章

MatrixOne助力一道创新打造高性能智能制造AIOT系统

客户简介 深圳一道创新&#xff08;ETAO Innovation&#xff09;成立于2012年&#xff0c;是一家创新型软件及信息技术服务商&#xff0c;致力于制造戏份行业—电子制造业的数字转型服务&#xff0c;构建万物互联的智能工程。一道创新致力于把先进的软件系统、数字平台、人工智…

拯救者Legion R9000X 2021R(82K8)原厂Win10与Windows11系统恢复镜像下载

LENOVO联想拯救者R9000X锐龙版2021款【82K8】预装OEM系统WIN11/10安装包&#xff0c;恢复原装出厂时开箱状态一模一样 链接&#xff1a;https://pan.baidu.com/s/15dGwacsEG0G8pOiZAHyXaQ?pwd0xgk 提取码&#xff1a;0xgk 联想原装出厂系统自带所有驱动、出厂主题壁纸、系统…

得物App荣获新奖项,科技创新助力高质量发展

近日&#xff0c;备受瞩目的2024中国国际服务贸易交易会&#xff08;简称“服贸会”&#xff09;在北京盛大开幕&#xff0c;这一全球唯一的国家级、国际性、综合型服务贸易盛会再次汇聚了全球服务贸易领域的精英与前沿成果。服贸会由商务部和北京市政府携手打造&#xff0c;并…

大数据系统调优:从DAG到单机

目标&#xff1a;优化T10的时效性全局DAG调度层优化&#xff1a;提前任务开始时间&#xff1a; 1. 优化慢结点&#xff1a;T10依赖了T4,T7,T8, 其中T8为瓶颈&#xff0c;如果T8能提前点完成&#xff0c;T10可以早点开始&#xff0c;就能早点完成 2. 快结点做更多预计算…

Android Studio 真机USB调试运行频繁掉线问题

一、遇到问题 Android Studio使用手机运行项目时&#xff0c;总是频繁掉线&#xff0c;连接很不稳定&#xff0c;动不动就消失&#xff0c;基本上无法使用 二、问题出现原因 1、硬件问题&#xff1a;数据线 换条数据线试试&#xff0c;如果可以&#xff0c;那就是数据线的…

如何登录通义灵码,快速开启AI编码之旅?

通义灵码个人版开发者可以使用阿里云账号登录通义灵码 IDE 端插件&#xff0c;本文介绍个人版开发者登录 IDE 端插件的操作指南。 登录通义灵码 步骤 1&#xff1a;准备工作 已成功注册阿里云账号&#xff0c;具体操作可参考&#xff1a;账号注册&#xff08;PC端&#xff09;…

通信工程学习:什么是SDN软件定义网络

SDN&#xff1a;软件定义网络 SDN&#xff08;Software Defined Network&#xff09;&#xff0c;即软件定义网络&#xff0c;是一种新兴的网络架构和技术&#xff0c;它实现了网络控制平面与数据转发平面的分离&#xff0c;并通过软件平台进行集中控制和管理。以下是SDN的详细…

02 BlockChain-- ETH

以太坊与比特币有什么不同&#xff1f; 以太坊立足比特币创新之上&#xff0c;于 2015 年启动&#xff0c;两者之间有一些显著不同。 从宏观的方面&#xff1a; 比特币就仅仅是比特币&#xff1b;以太坊&#xff08;Ethereum&#xff09;包括以太币&#xff08;Ether&#x…

ubuntu中如何查看类型(函数)定义的头文件

问题&#xff1a; 1.该如何查找函数&#xff0c;或者数据类型的头文件&#xff1f; 方法&#xff1a; 1.使用vim搭配ctags 2.使用vscode 使用vscode查看头文件位置的步骤&#xff1a; 1.例如下图&#xff0c;我想添加包含file_operations的头文件 2.双击选中数据类型&#xf…

network request to https://registry.npmjs.org/xxx failed, reason: connect ETIM

目录&#xff1a; 1、问题描述2、解决方案3、npm镜像仓库替换 1、问题描述 npm install 时&#xff0c;报错&#xff1a;npm ERR! network request to https://registry.npmjs.org/postcss-pxtorem failed, reason: connect ETIMEDOU npm ERR! code ETIMEDOUT npm ERR! errno…

DSP学习00-F28379D学习准备(了解一个工程的构成)

叠甲 我也算初学F28379D&#xff0c;不对之处请大家斧正。不同型号的DSP在外设配置的函数上有一些区别&#xff0c;但是掌握一种对其他型号的来说则难度不大。对于我们而言学习DSP最终还是要用于算法验证&#xff0c;而DSP资源的最大化利用、代码效率提升等则是后话。 软件准…

【ASE】第一课_双面着色器

今天我们一起来学习ASE插件&#xff0c;希望各位点个关注&#xff0c;一起跟随我的步伐 今天我们来学习双面着色器&#xff0c;对颜色和贴图进行差值&#xff0c;双面显示不同的效果 最终效果&#xff1a; 思路&#xff1a; 1.先确定前后面的贴图和颜色 贴图&#xff08;Alb…

华为高级交换技术笔记 2024-2025

2024-2025 一、9/31.通信模型和封装2.以太网3.MAC地址4.以太网帧5.MAC地址表的建立 二、9/61.交换机的数据的处理2.以太网帧的分类3.广播域4.vlan技术开发背景 一、9/3 1.通信模型和封装 2.以太网 3.MAC地址 4.以太网帧 5.MAC地址表的建立 二、9/6 1.交换机的数据的处理 2.以…

[SAP ABAP] 数据字典外键关联

SE11创建自定义数据库表 学校表(ZDBT_SCH_437) 表有3个组成字段&#xff1a; ① MANDT (参考数据元素为MANDT&#xff0c;主键) ② SCHID 学校ID (参考新建数据元素ZDE_SCHID_437&#xff0c;主键&#xff0c;NUMC4) ③ SCHNAME 学校名称 (CHAR20) 学生表(ZDBT_STU_437) 表有7个…

codeforces round974 div3 分层图 树形dp

A Robin Helps 问题&#xff1a; 思路&#xff1a;模拟 代码&#xff1a; #include <bits/stdc.h> using namespace std;const int N 2e5 10;void solve() {int n, k;cin >> n >> k;vector<int> a(n 1);for(int i 1; i < n; i ) cin >&…

着色器(Vertex Shader)基础

什么是顶点着色器 顶点着色器处理顶点并告知它们在“剪辑空间”中的坐标,该空间使计算机可以轻松了解哪些顶点对摄像机可见,哪些顶点不可见,必须剪切或“剪切”掉。 这使得 GPU 在后期阶段的速度更快,因为它们需要处理的数据较少。 它们通过接收来自顶点列表中的单个顶…

手写数字识别案例分析(torch,深度学习入门)

在人工智能和机器学习的广阔领域中&#xff0c;手写数字识别是一个经典的入门级问题&#xff0c;它不仅能够帮助我们理解深度学习的基本原理&#xff0c;还能作为实践编程和模型训练的良好起点。本文将带您踏上手写数字识别的深度学习之旅&#xff0c;从数据集介绍、模型构建到…

全栈开发(四):使用springBoot3+mybatis-plus+mysql开发restful的增删改查接口

1.创建user文件夹 作为增删改查的根包 路径 src/main/java/com.example.demo/user 2.文件夹里文件作用介绍 1.User(实体类) package com.example.demo.user; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.IdType; impo…

利用影刀实现批量发布文章的RPA流程(附视频演示)

前言 大家好&#xff0c;我是小智。在这篇文章中&#xff0c;我将分享一个实战案例&#xff0c;展示如何利用影刀实现批量发布文章的RPA流程。这里主要介绍其中一个简单步骤&#xff0c;其它步骤将通过视频演示。有使用方面的疑问可以留言。 影刀是一款强大的自动化工具&#x…

Matlab|考虑柔性负荷的综合能源系统低碳经济优化调度

目录 1 主要内容 2 部分代码 3 程序结果 4 下载链接 1 主要内容 程序主要实现的是考虑柔性负荷的综合能源系统低碳经济优化调度&#xff0c;模型参考《考虑柔性负荷的综合能源系统低碳经济优化调度》&#xff0c;求解方法采用的是混合整数规划算法&#xff0c;通过matlabc…