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

Linux---项目自动化构建工具-make/Makefile

一、背景

  • 会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力
  • 一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的 规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂 的功能操作
  • makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编 译,极大的提高了软件开发的效率。
  • make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命 令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一 种在工程方面的编译方法。
  • make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建

二、make/Makefile的初步认识

首先我们要知道make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建

1、举例

我们先创建一个源文件,源文件中写上我们需要编译运行的代码

再创建一个makefile文件,可以写成makefile或者Makefile都可以,创建后打开

我们在makefile文件中写一些程序,具体作用后文会慢慢解释

我们将一个可执行程序命名为mytest,生成源文件code.c的可执行程序名为mytest

clean部分 我在后面再做解释,现在你知道他是一个清理功能,命令为make clean 删除可执行程序mytest

我们直接使用make命令,创建可执行程序mytest并执行。

我们发现make命令后生成了可执行程序mytest,再使用命令make clean后将可执行程序mytest删除

这个举例就是对make/makefile的简单认识,了解它的作用,接下来我们深入讲解。

2、认清原理

一、依赖关系

我们先把在例子中,对makefile文件中的代码给大家做一下解释

mytest与code.c的依赖关系就是:源文件通过依赖方法生成可执行程序mytest。

make命令会根据makefile的内容,完成编译/清理工作

clean和他的依赖方法是一种特殊情况,因为它不需要依赖文件列表,rm表示清理

二、PHONY的了解

首先我们要弄清楚为什么我们使用make命令就会直接生成可执行文件mytest,而想清理的时候,就必须在make命令后加上clean呢?

因为make命令的执行推导规则是从上到下依次扫描,默认形成第一个目标文件。

那么第三行的.PHONY是什么呢?

当我们make生成可执行程序时,将同一个程序生成两次可以吗?

它会提醒我们目前存在的可执行程序是最新的,不可以再生成,会自动给你拦截

除非我们对源文件进行修改或者删除才可以继续make

那我们不想让他拦截,想一直生成的话怎么办呢?这就是.PHONY的作用

我们用.PHONY来修饰mytest,表示mytest要总是被执行

再重新make多次,这里make了三次也没有被拦截

具体使用方法如下: 

.PHONY:xxx
xxx对应的方法,要总是被执行

  我们之所以不在生成可执行程序这里使用,是因为没有这个必要,在大项目里,编译时间会很长,重复编译会浪费时间,不重复生成也提高了编译效率,在clean部分用是因为,我们可能会用到多次清理。

这里有两个问题需要理解:

1、为什么makefile对最新的可执行程序。默认不想重新生成呢?

我们之所以不在生成可执行程序这里使用,是因为没有这个必要,在大项目里,编译时间会很长,重复编译会浪费时间,不重复生成也提高了编译效率,在clean部分用是因为,我们可能会用到多次清理。

2、makefile是怎么做到的呢?

通过对时间的比较,只要源文件的修改时间比可执行程序文件的修改时间的话,就不会继续生成,而源文件的修改时间比可执行程序文件的修改时间的话,就可以再生成。

我们可以使用命令stat查看文件的修改时间

stat <文件名>

通过Modify的时间比较就可以确定是否要重新编译

我们也可以使用touch命令更新文件Modify的时间,touch命令本来是创建新文件,但是在这里用来更新Modify时间。

3、依赖关系的深入理解

  在我们makefile文件中我们是直接从code.c生成可执行程序mytest,但是我们在上文讲过程序的编译过程,整个流程应该是code.c→code.i→code.s→code.o→mytest,那我们在makefile文件中应该怎么写呢?

  我们已经知道,make的工作推导规则是从上到下,生成第一个目标文件,所以mytest还是应该在第一行,mytest的依赖文件列表是code.o,那么依赖方法就是gcc code.o -o code.exe。

  剩下的以此类推得:

  他们之间的依赖关系就是 mytest依赖code.o、code.o依赖code.s、code.s依赖code.i、code.i依赖code.c.

  这里大家可能会有疑问:我想生成目标文件mytest时,我并没有code.o文件啊

  我用一张图给大家作答:

  make/makefile会根据文件中的依赖关系,进行自动推导,帮助我们执行所有相关得依赖方法

  这个其实就是我们所知道得递归算法。

三、make/makefile的符号替换和变量

1、符号替换

$@代表的是依赖文件列表,$@代表的是目标文件,make之后会自动替换

2、变量

我们在c语言中定义变量是需要变量类型、初始化的。比如:int a=0;

我们在Liunx中的makefile中不是,我们直接:

变量=xxx

再与符号替换结合: 

之后我们修改目标文件或者依赖文件列表,直接修改变量就可以了,会方便很多。 

四、总结

1、make工作原理

  • 1. make会在当前目录下找名字叫“Makefile”或“makefile”的文件。
  • 2. 如果找到,它会找文件中的第一个目标文件(target)
  • 3. 如果mytest所依赖的code.o文件不存在,那么make会在当前文件中找目标为code.o文件的依赖性,如果找到则再根据那一个规则生成code.o文件。(这有点像一个堆栈的过程)
  • 4. 这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。
  • 5. 在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错, 而对于所定义的命令的错误,或是编译不成功,make根本不理。
  • 6. make只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起, 我就不工作啦。

2、项目清理

  • 工程是需要被清理的
  • 像clean这种,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行, 不过,我们可以显示要make执行。即命令——“make clean”,以此来清除所有的目标文件,以便重新编译。
  • 但是一般我们这种clean的目标文件,我们将它设置为伪目标,用 .PHONY 修饰,伪目标的特性是,总是被执行的。

相关文章:

Linux---项目自动化构建工具-make/Makefile

一、背景 会不会写makefile&#xff0c;从一个侧面说明了一个人是否具备完成大型工程的能力一个工程中的源文件不计数&#xff0c;其按类型、功能、模块分别放在若干个目录中&#xff0c;makefile定义了一系列的 规则来指定&#xff0c;哪些文件需要先编译&#xff0c;哪些文件…...

嘉立创EDA个人学习笔记1(PCB板介绍)

前言 本篇文章属于嘉立创EDA的学习笔记&#xff0c;来源于B站教学视频。下面是这位up主的视频链接。本文为个人学习笔记&#xff0c;只能做参考&#xff0c;细节方面建议观看视频&#xff0c;肯定受益匪浅。 嘉立创EDA-PCB设计零基础入门课程&#xff08;54集全&#xff09;_…...

(转)Restful接口设计(1)

.representational&#xff1a;代表性的 URI&#xff08;Universal Resouce Identifier&#xff09;&#xff1a;Universal &#xff1a;普遍的;共同的。Identifier&#xff1a;标识符。统一资源标识符。 31-RESTful接口介绍-02_哔哩哔哩_bilibili 31-RESTful接口介绍-03_哔哩…...

Python进阶之3D图形

Python进阶之3D图形 在数据可视化中&#xff0c;2D图形通常可以满足大多数需求。然而&#xff0c;对于一些复杂的数据或分析&#xff0c;3D图形可以提供更多的视角和洞察。在Python中&#xff0c;使用 Matplotlib 和 Plotly 等库可以轻松创建各种3D图形。本文将介绍如何使用这…...

机器学习深度学习中的搜索算法浅谈

机器学习&深度学习中的搜索算法浅谈 搜索算法是计算机科学中的核心算法&#xff0c;用于在各种数据结构&#xff08;如数组、列表、树、图等&#xff09;中查找特定元素或信息。这些算法不仅在理论上具有重要意义&#xff0c;还在实际应用中扮演着关键角色。本文将详细探讨…...

基于IMX8M_plus+FPGA+AI监护仪解决方案

监护仪是一种以测量和控制病人生理参数&#xff0c;并可与已知设定值进行比较&#xff0c;如果出现超标可发出警报的装置或系统。 &#xff08;1&#xff09;监护仪主要采集测量人体生理参数&#xff0c;心电、血压、血氧、体温等需要采集处理大量的数据&#xff0c;系统需要多…...

仿RabbitMq实现简易消息队列正式篇(路由匹配篇)

TOC 目录 路由匹配模块 代码展示 路由匹配模块 决定了一条消息是否能够发布到指定的队列 在每个队列根交换机的绑定信息中&#xff0c;都有一个binding_key&#xff08;在虚拟机篇有说到&#xff09;这是队列发布的匹配规则 在每条要发布的消息中&#xff0c;都有一个rout…...

一套完整的NVR网络硬盘录像机解决方案和NVR程序源码介绍

随着网络技术的发展&#xff0c;视频数据存储的需求激增&#xff0c;促使硬盘录像机&#xff08;DVR&#xff09;逐渐演变为具备网络功能的网络视频录像机&#xff08;NVR&#xff09;。NVR&#xff0c;即网络视频录像机&#xff0c;负责网络视音频信号的接入、存储、转发、解码…...

2024年人工智能固态硬盘采购容量预计超过45 EB

根据TrendForce发布的最新市场报告&#xff0c;人工智能&#xff08;AI&#xff09;服务器客户在过去两个季度显著增加了对企业级固态硬盘&#xff08;SSD&#xff09;的订单。为了满足AI应用中不断增长的SSD需求&#xff0c;上游供应商正在加速工艺升级&#xff0c;并计划在20…...

Java的反射原理

反射允许程序在运行时检查或修改其类、接口、字段和方法的行为。反射主要通过java.lang.reflect包中的类和接口实现&#xff0c;它主要用于以下目的&#xff1a; 在运行时分析类的能力&#xff1a;通过反射&#xff0c;可以在运行时检查类的结构&#xff0c;比如它的方法、构造…...

vue.config.js 配置

vue.config.js 文件是 Vue CLI 项目中的全局配置文件&#xff0c;它允许你以 JavaScript 的形式来配置构建选项&#xff0c;而不是通过命令行参数或者 .vue-clirc 的 JSON 格式。 官方文档: https://cli.vuejs.org/zh/config/#全局-cli-配置 基础配置 publicPath 设置构建好的…...

C ++ 也可以搭建Web?高性能的 C++ Web 开发框架 CPPCMS + MySQL 实现快速入门案例

什么是CPPCMS&#xff1f; CppCMS 是一个高性能的 C Web 开发框架&#xff0c;专为构建快速、动态的网页应用而设计&#xff0c;特别适合高并发和低延迟的场景。其设计理念类似于 Python 的 Django 或 Ruby on Rails&#xff0c;但针对 C 提供了更细粒度的控制和更高效的性能。…...

Taos 常用命令工作笔记(二)

最近测试创建一个涛思的数据库和一堆表进行测试&#xff0c;通过json配置文件配置字段的类型、名称等&#xff0c;程序通过解析json文件的配置&#xff0c;动态创建数据库的表。 其中表字段为驼峰结构的规则命名&#xff0c;创建表也是成功的&#xff0c;插入的测试数据也是成功…...

idea安装二进制文本阅读插件

引言 在软件开发过程中&#xff0c;有时需要查看二进制文件的内容以调试或分析问题。虽然有许多专用工具可以处理这类任务&#xff0c;但直接在 IDE 内集成这些功能无疑更加方便高效。本文将介绍如何在 IntelliJ IDEA 2023中安装和配置一个名为 BinEd的插件&#xff0c;以及如…...

MySQL 常用 SQL 语句大全

1. 基本查询 查询所有记录和字段 SELECT * FROM table_name; 查询特定字段 SELECT column1, column2 FROM table_name; 查询并限制结果 SELECT column1, column2 FROM table_name LIMIT 10; 条件查询 SELECT column1, column2 FROM table_name WHERE condition; 模糊匹…...

[Spring] Spring事务与事务的传播

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏: &#x1f9ca; Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 &#x1f355; Collection与…...

Java 网络编程练习

InternetExercise1 package InternetExercise20240815;public class InternetExercise1 {public static void main(String[] args) {// 网络编程// 在网络通信协议下&#xff0c;不同计算机上面运行的程序&#xff0c;可以实现不同计算机上的数据传输// 网络编程三要素// 1.IP…...

中国科技统计年鉴,数据覆盖1991-2022年多年份

基本信息. 数据名称: 中国科技统计年鉴 数据格式: excel 数据时间: 1991-2022年 数据几何类型: xlsx 数据坐标系: WGS84 数据来源&#xff1a;国家统计局 数据预览&#xff1a; 数据可视化....

大模型的训练过程

大模型的训练是一个复杂的过程&#xff0c;涉及多个步骤和技术。下面我将概述大模型训练的主要流程&#xff0c;包括预训练、微调等关键阶段&#xff0c;并解释一些常见的技术和策略。 1. 数据准备 数据收集&#xff1a;收集大量多样化的数据&#xff0c;包括文本、图像、音频…...

4款ai在线改写工具,帮你轻松一键智能改写文章

在当今数字化内容创作的浪潮中&#xff0c;ai技术的应用为我们带来了极大的便利&#xff0c;尤其是在文章改写方面。以下将为大家详细分享四款出色的ai在线改写工具&#xff0c;从而帮助大家提升创作效率和质量。 ai在线改写工具一&#xff1a;智媒ai伪原创工具 它是一款备受好…...

Python:操作 Excel 折叠

💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...

Go 语言接口详解

Go 语言接口详解 核心概念 接口定义 在 Go 语言中&#xff0c;接口是一种抽象类型&#xff0c;它定义了一组方法的集合&#xff1a; // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的&#xff1a; // 矩形结构体…...

《C++ 模板》

目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板&#xff0c;就像一个模具&#xff0c;里面可以将不同类型的材料做成一个形状&#xff0c;其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式&#xff1a;templa…...

【Linux】Linux 系统默认的目录及作用说明

博主介绍&#xff1a;✌全网粉丝23W&#xff0c;CSDN博客专家、Java领域优质创作者&#xff0c;掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围&#xff1a;SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...

基于PHP的连锁酒店管理系统

有需要请加文章底部Q哦 可远程调试 基于PHP的连锁酒店管理系统 一 介绍 连锁酒店管理系统基于原生PHP开发&#xff0c;数据库mysql&#xff0c;前端bootstrap。系统角色分为用户和管理员。 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销 2 个人中…...

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分&#xff1a; 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...

django blank 与 null的区别

1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是&#xff0c;要注意以下几点&#xff1a; Django的表单验证与null无关&#xff1a;null参数控制的是数据库层面字段是否可以为NULL&#xff0c;而blank参数控制的是Django表单验证时字…...

小木的算法日记-多叉树的递归/层序遍历

&#x1f332; 从二叉树到森林&#xff1a;一文彻底搞懂多叉树遍历的艺术 &#x1f680; 引言 你好&#xff0c;未来的算法大神&#xff01; 在数据结构的世界里&#xff0c;“树”无疑是最核心、最迷人的概念之一。我们中的大多数人都是从 二叉树 开始入门的&#xff0c;它…...

Kubernetes 节点自动伸缩(Cluster Autoscaler)原理与实践

在 Kubernetes 集群中&#xff0c;如何在保障应用高可用的同时有效地管理资源&#xff0c;一直是运维人员和开发者关注的重点。随着微服务架构的普及&#xff0c;集群内各个服务的负载波动日趋明显&#xff0c;传统的手动扩缩容方式已无法满足实时性和弹性需求。 Cluster Auto…...

第八部分:阶段项目 6:构建 React 前端应用

现在&#xff0c;是时候将你学到的 React 基础知识付诸实践&#xff0c;构建一个简单的前端应用来模拟与后端 API 的交互了。在这个阶段&#xff0c;你可以先使用模拟数据&#xff0c;或者如果你的后端 API&#xff08;阶段项目 5&#xff09;已经搭建好&#xff0c;可以直接连…...