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

【Linux】自动化构建-Make/Makefile

前言

        上文我们讲到了Linux中的编译器gcc/g++        【Linux】编译器gcc/g++及其库的详细介绍-CSDN博客

        本来我们将一个对于编译来说很重要的工具:make/makfile

1.背景

        在一个工程中源文件不计其数,其按类型、功能、模块分别放在若干个目录中,makefile可以来定义那些文件先编译,那些文件后编译,那些文件需要重新编译。甚至是一些更为复制的功能

        makefile带来是好处就是"一键化编译",只需要一个make命令就可以实现。这极大的提高了开发的效率

会不会写makefile从侧面很大程度的反应了一个人是否具有完成大型工程项目的能力 

2.简单认识什么是make/makefile

make是一个命令工具,用于解释makefile中指令的工具

make是一个指令,makefile是一个文件,需要我们自己建立。两个搭配使用就可以实现我们的自动化编译

3.make/makefile的基本使用

3.1简单一键化编译

创建makefile,并使用vim写入内容(m大小写都可以)

hyc@hcss-ecs-4ce7:~$ touch makefile
hyc@hcss-ecs-4ce7:~$ vim makefile

makefile的基本结构为:依赖关系+依赖方法 

注:写入依赖方法前,要先点击TAB键。一定要TAB键不要4个空格,这是写书格式!!) 

退出并保存,执行make指令,自动化执行编译

hyc@hcss-ecs-4ce7:~$ make
gcc test.c -o testhyc@hcss-ecs-4ce7:~$ ./test
hi,Yuzurihahyc@hcss-ecs-4ce7:~$ ls
makefile  test  test.c

3.2简单一键化清理

再次打开makefile,写入清除命令

注:

        先忽略.PHONY:clear不看,clear的格式其实和上面的格式都是:依赖关系+依赖方法。只不过clear并没有依赖什么文件,就不写依赖文件

退出并保存,执行make clear,完成一键清除

hyc@hcss-ecs-4ce7:~$ ls
makefile  test  test.chyc@hcss-ecs-4ce7:~$ make clear
rm testhyc@hcss-ecs-4ce7:~$ ls
makefile  test.c

大家看到这里可能一头雾水,但是没关系我们来一个一个看

3.2.1为什么这个我们要使用make clear才能达到效果,而前面只需要执行make就可以了呢?

我们可以把这个两个指令交换一下位置,看看效果

我们可以看到此时我们执行make指令时,实现的效果就是清除效果 

hyc@hcss-ecs-4ce7:~$ ls
makefile  test  test.c
hyc@hcss-ecs-4ce7:~$ make
rm test
hyc@hcss-ecs-4ce7:~$ ls
makefile  test.c
总结: 

        执行make指令时,会从上到下扫描makefile文件,并且默认执行第一个扫描到的方法。如果想要执行其他方法,可以make + 目标名,显示的调用

3.2.2  .PHONY是什么东西?

.PHONY + 目标名用于声明伪目标

伪目标不是实际存在的目标,而是用于执行特定的命令(如清理)

.PHONT的主要功能是保证对应的依赖关系和依赖方法总是被执行 

要理解什么叫总是被执行?我们可以先理解什么叫不总是被执行。我们可以看到当我们多次执行make指令时,第一次正常执行,而后面的都不再执行了。这就叫不总是被执行。

而换做clear,则可以正常执行多次

同样的,当我们使用 .PHNOY修饰test时,也可以反复的执行编译语句 

 总结:

        .PHONY是定义伪目标,其功能是让其对应的依赖关系和依赖方法总是被执行但一般情况下编译都是不要.PHNOY修饰的,因为代码没有经过修改是不需要反复编译的。反复编译会极大的浪费资源。

补充:make是如何判断源文件是否被修改? 

1.文件的acm时间

make正是通过两个文件的Modify时间来判断出源文件是否被修改的。

如果可执行文件的时间晚于源文件时间,这代表没有被修改。反之,这代表源文件被修改了想要重新编译。

ACM时间小知识:

        Access时间并不是我们想象的我们访问一次就更新一次时间,因为整个系统最频繁的操作就是访问文件,如果每访问一次文件就统计一次时间这会带来巨大的开销。因此,Access时间是会等用户访问到一定次数才会更新

        Modify时间修改,Change时间往往也会一起修改。因为Modify是记录文件内容修改的时间,但是文件内容有修改其体积大小往往会修改,而体积是属于文件属性这一块的,所以Change时间也会修改。

4.make/makefile深入理解

4.1make的推导规则

现在makefile中为一下内容:

执行make指令我们可以看见,执行的指令顺序和我们写入makefile中的顺序是不一样的

因为makefile的推导规则是满足类似栈结构的:myproc由myproc.o文件推导,而myproc.o当先并不存在,要由myproc.s文件推导。那就先把推导myproc的指令入栈,先推导myproc.o文件。以此类推,直到前置条件完成后,通过出栈依次执行后面的指令

4.2makefile的升级之路

4.2.1makefile可以使用变量

makefile可以像我们的编程语言一样使用自定义变量,来指代文件、指令、选项等等

$:表示这个变量所指代的内容,比如:$(BIN)就表示myproc这个文件

4.2.2makefile中的特殊变量

$@:表示目标文件,既$(BIN)

$^:表示依赖文件,既$(SRC)

特殊符号可以帮助我们简化makefile的书写

4.2.3makefile中一段依赖关系中可以存在多个依赖方法

一段依赖关系中可以存在多个依赖方法,比如这里我们想直观的看到我们做了什么操作,就可以利用echo来输出信息

效果如下: 

我们这里看到了我们自己写是echo指令回显了,我们如果想要指令不回显只看效果,可以使用@符号

这样指令就不会回显了

4.2.4makefile处理多文件编译

对于多文件的编译,我们上一篇文章讲到过,我们一般都是先将所有文件编译为.o文件,最后在将所有的.o文件连接

%是makefile下的通配符%.c:%.o表示将当前路径下的所有.o/.c文件全部展开,比如有100个.c文件,这里就会展开一百个依赖关系,并执行一百个依赖方法。 

效果如下:

4.2.5makefile最终版本        

        上面我们说到,如果有多文件的编译makefile的处理方式。确实在依赖方法的书写上,这个便捷多了。但是我们没有考虑到这一切都是建立在使用变量上的,而我们的变量则需要将多个文件表示出来。

如果我们想要编译多个文件,就需要在变量里写多个文件 

 

 3个文件还能接受,可对于项目工程来说有上百个文件怎么办?我们不可能一个一个写上去

解决这一问题有两个方法

方法一:

  OBJ=$(SRC:.c=.o) :语法格式,将.c文件替换为同名.o文件
  SRC=$(shell ls *.c):使用命令行指令,一键获取.c文件

方法二:

 SRC=$(wildcard *.c) :wildcard为makefile的函数,其作用就是获取所有.c文件

至此这就是makefile的最终形态

相关文章:

【Linux】自动化构建-Make/Makefile

前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具:make/makfile 1.背景 在一个工程中源文件不计其数,其按类型、功能、模块分别放在若干个目录中,mak…...

如何应对敏捷转型中的团队阻力

应对敏捷转型中的团队阻力需要明确沟通敏捷转型目的、提升团队参与感、提供充分的培训与支持、逐步推进敏捷实践、建立清晰的奖励和反馈机制。其中,明确沟通敏捷转型目的尤为关键,团队成员只有清晰理解转型背后的原因和利益,才能降低对变化的…...

安卓基础(Java 和 Gradle 版本)

1. 设置项目的 JDK 版本 方法1:通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分,设置 Gradle JDK 方法2:通过 Settings File → Settings... (或 CtrlAltS)…...

华为OD机试-最短木板长度-二分法(A卷,100分)

此题是一个最大化最小值的典型例题, 因为搜索范围是有界的,上界最大木板长度补充的全部木料长度,下界最小木板长度; 即left0,right10^6; 我们可以设置一个候选值x(mid),将木板的长度全部都补充到x,如果成功…...

【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error

在前端开发中,JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作(如 Promise、async/await 等),开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝(r…...

在 Spring Boot 项目里,MYSQL中json类型字段使用

前言&#xff1a; 因为程序特殊需求导致&#xff0c;需要mysql数据库存储json类型数据&#xff0c;因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...

「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案

在移动互联网营销竞争白热化的当下&#xff0c;推客小程序系统凭借其裂变传播、精准营销等特性&#xff0c;成为企业抢占市场的利器。本文将深度解析推客小程序系统开发的核心技术与实现路径&#xff0c;助力开发者打造具有市场竞争力的营销工具。​ 一、系统核心功能架构&…...

破解路内监管盲区:免布线低位视频桩重塑停车管理新标准

城市路内停车管理常因行道树遮挡、高位设备盲区等问题&#xff0c;导致车牌识别率低、逃费率高&#xff0c;传统模式在复杂路段束手无策。免布线低位视频桩凭借超低视角部署与智能算法&#xff0c;正成为破局关键。该设备安装于车位侧方0.5-0.7米高度&#xff0c;直接规避树枝遮…...

通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器

拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件&#xff1a; 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...

libfmt: 现代C++的格式化工具库介绍与酷炫功能

libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库&#xff0c;提供了高效、安全的文本格式化功能&#xff0c;是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全&#xff1a…...

在 Spring Boot 中使用 JSP

jsp&#xff1f; 好多年没用了。重新整一下 还费了点时间&#xff0c;记录一下。 项目结构&#xff1a; pom: <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://ww…...

Chrome 浏览器前端与客户端双向通信实战

Chrome 前端&#xff08;即页面 JS / Web UI&#xff09;与客户端&#xff08;C 后端&#xff09;的交互机制&#xff0c;是 Chromium 架构中非常核心的一环。下面我将按常见场景&#xff0c;从通道、流程、技术栈几个角度做一套完整的分析&#xff0c;特别适合你这种在分析和改…...

LangFlow技术架构分析

&#x1f527; LangFlow 的可视化技术栈 前端节点编辑器 底层框架&#xff1a;基于 &#xff08;一个现代化的 React 节点绘图库&#xff09; 功能&#xff1a; 拖拽式构建 LangGraph 状态机 实时连线定义节点依赖关系 可视化调试循环和分支逻辑 与 LangGraph 的深…...

elementUI点击浏览table所选行数据查看文档

项目场景&#xff1a; table按照要求特定的数据变成按钮可以点击 解决方案&#xff1a; <el-table-columnprop"mlname"label"名称"align"center"width"180"><template slot-scope"scope"><el-buttonv-if&qu…...

嵌入式常见 CPU 架构

架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集&#xff0c;单周期执行&#xff1b;低功耗、CIP 独立外设&#xff1b;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel&#xff08;原始…...

LOOI机器人的技术实现解析:从手势识别到边缘检测

LOOI机器人作为一款创新的AI硬件产品&#xff0c;通过将智能手机转变为具有情感交互能力的桌面机器人&#xff0c;展示了前沿AI技术与传统硬件设计的完美结合。作为AI与玩具领域的专家&#xff0c;我将全面解析LOOI的技术实现架构&#xff0c;特别是其手势识别、物体识别和环境…...

Qt 事件处理中 return 的深入解析

Qt 事件处理中 return 的深入解析 在 Qt 事件处理中&#xff0c;return 语句的使用是另一个关键概念&#xff0c;它与 event->accept()/event->ignore() 密切相关但作用不同。让我们详细分析一下它们之间的关系和工作原理。 核心区别&#xff1a;不同层级的事件处理 方…...

Vue ③-生命周期 || 脚手架

生命周期 思考&#xff1a;什么时候可以发送初始化渲染请求&#xff1f;&#xff08;越早越好&#xff09; 什么时候可以开始操作dom&#xff1f;&#xff08;至少dom得渲染出来&#xff09; Vue生命周期&#xff1a; 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...

uniapp 小程序 学习(一)

利用Hbuilder 创建项目 运行到内置浏览器看效果 下载微信小程序 安装到Hbuilder 下载地址 &#xff1a;开发者工具默认安装 设置服务端口号 在Hbuilder中设置微信小程序 配置 找到运行设置&#xff0c;将微信开发者工具放入到Hbuilder中&#xff0c; 打开后出现 如下 bug 解…...

Kafka主题运维全指南:从基础配置到故障处理

#作者&#xff1a;张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1&#xff1a;主题删除失败。常见错误2&#xff1a;__consumer_offsets占用太多的磁盘。 主题日常管理 …...

AI语音助手的Python实现

引言 语音助手(如小爱同学、Siri)通过语音识别、自然语言处理(NLP)和语音合成技术,为用户提供直观、高效的交互体验。随着人工智能的普及,Python开发者可以利用开源库和AI模型,快速构建自定义语音助手。本文由浅入深,详细介绍如何使用Python开发AI语音助手,涵盖基础功…...

tomcat指定使用的jdk版本

说明 有时候需要对tomcat配置指定的jdk版本号&#xff0c;此时&#xff0c;我们可以通过以下方式进行配置 设置方式 找到tomcat的bin目录中的setclasspath.bat。如果是linux系统则是setclasspath.sh set JAVA_HOMEC:\Program Files\Java\jdk8 set JRE_HOMEC:\Program Files…...

CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!

本文介绍了一种名为AnomalyAny的创新框架&#xff0c;该方法利用Stable Diffusion的强大生成能力&#xff0c;仅需单个正常样本和文本描述&#xff0c;即可生成逼真且多样化的异常样本&#xff0c;有效解决了视觉异常检测中异常样本稀缺的难题&#xff0c;为工业质检、医疗影像…...

提升移动端网页调试效率:WebDebugX 与常见工具组合实践

在日常移动端开发中&#xff0c;网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时&#xff0c;开发者迫切需要一套高效、可靠且跨平台的调试方案。过去&#xff0c;我们或多或少使用过 Chrome DevTools、Remote Debug…...

永磁同步电机无速度算法--基于卡尔曼滤波器的滑模观测器

一、原理介绍 传统滑模观测器采用如下结构&#xff1a; 传统SMO中LPF会带来相位延迟和幅值衰减&#xff0c;并且需要额外的相位补偿。 采用扩展卡尔曼滤波器代替常用低通滤波器(LPF)&#xff0c;可以去除高次谐波&#xff0c;并且不用相位补偿就可以获得一个误差较小的转子位…...

前端中slice和splic的区别

1. slice slice 用于从数组中提取一部分元素&#xff0c;返回一个新的数组。 特点&#xff1a; 不修改原数组&#xff1a;slice 不会改变原数组&#xff0c;而是返回一个新的数组。提取数组的部分&#xff1a;slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...

什么是VR全景技术

VR全景技术&#xff0c;全称为虚拟现实全景技术&#xff0c;是通过计算机图像模拟生成三维空间中的虚拟世界&#xff0c;使用户能够在该虚拟世界中进行全方位、无死角的观察和交互的技术。VR全景技术模拟人在真实空间中的视觉体验&#xff0c;结合图文、3D、音视频等多媒体元素…...

在树莓派上添加音频输入设备的几种方法

在树莓派上添加音频输入设备可以通过以下步骤完成&#xff0c;具体方法取决于设备类型&#xff08;如USB麦克风、3.5mm接口麦克风或HDMI音频输入&#xff09;。以下是详细指南&#xff1a; 1. 连接音频输入设备 USB麦克风/声卡&#xff1a;直接插入树莓派的USB接口。3.5mm麦克…...

Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?

Pod IP 的本质与特性 Pod IP 的定位 纯端点地址&#xff1a;Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址&#xff08;如 10.244.1.2&#xff09;无特殊名称&#xff1a;在 Kubernetes 中&#xff0c;它通常被称为 “Pod IP” 或 “容器 IP”生命周期&#xff1a;与 Pod …...

零知开源——STM32F103RBT6驱动 ICM20948 九轴传感器及 vofa + 上位机可视化教程

STM32F1 本教程使用零知标准板&#xff08;STM32F103RBT6&#xff09;通过I2C驱动ICM20948九轴传感器&#xff0c;实现姿态解算&#xff0c;并通过串口将数据实时发送至VOFA上位机进行3D可视化。代码基于开源库修改优化&#xff0c;适合嵌入式及物联网开发者。在基础驱动上新增…...