Linux环境基础开发工具->make/Makefile

article/2025/8/13 12:22:57

引入:make/Makefile是什么?

前面我们知道了vim负责编辑代码,gcc负责编译代码,而make/Makefile则负责的是自动化编译!

Makefile是一个文件,make是一条指令

我们在Makefile文件中进行编辑,让哪些文件需要先编译,哪些文件需要后编译

然后简单的make指令即可让整个工程完全自动编译,极大的提高了软件开发的效率

总结:make是一条命令,Makefile是一个文件,两个搭配使用,完成项目自动化构建。

一:需要makefile的场景

现在我想自己实现一个打印功能的函数,所以我有以下三个文件

1:print.h 

#pragma once
#include<stdio.h>void print(const char* str);

2:print.c

#include"print.h"
void print(const char* s)
{printf("%s", s);}

3:main.c

#include"print.h"
int main()
{print("hello!");return 0;
}

三个文件: 

 

此时我想形成一个可执行文件,每次执行该文件的时候,就显示出"hello!"

所以现在我们让print.c和main.c通过gcc形成了.o文件

然后再gcc main.o print.o 生成可执行程序a.out

 

但是太麻烦了,我们这还仅仅只有两个.c文件的合并,以后一个项目都是几十个,难道我们要进行几十次的gcc -c吗??所以我们只需将这些写进makefile这个文件即可

 

二:makefile的使用演示

1: 在源文件所在目录下创建一个名为Makefile/makefile的文件

 

2:编写Makefile文件

3:运行make指令

此时发现其自动创建了我们想要的两个.o文件,并且对两个进行链接生成了a.out:

运行a/out 

 

makefile的出现,让我们不在需要手动的每次都gcc ,我们写在makefile中,想用直接make即可!

三:makefile的格式

Makefile文件最简单的编写格式是:

先写出文件的依赖关系,然后写出这些文件之间的依赖方法,依次写下去:

目标: 依赖文件1 依赖文件2 ...Tab键开头的依赖方法

 

注意:依赖方法最前面必须是tab键,不能连续的空格!

Q:为什么写了makefile,我们进行make就能执行这一系列的指令?

A:make的原理如下:

①:make会在当前目录下找名字为“Makefile”或“makefile”的文件。

②:如果找到,它会找文件当中的第一个目标文件,在上面的例子中,它会找到mytest这个文件,并把这个文件作为最终的目标文件。

③:如果mytest文件不存在,或是mytest所依赖的后面的test.o文件和main.o文件的文件修改时间比mytest文件新,那么它就会执行后面的依赖方法来生成mytest文件。

④:如果mytest所依赖的test.o文件不存在,那么make会在Makefile文件中寻找目标为test.o文件的依赖关系,如果找到则再根据其依赖方法生成test.o文件(类似于堆栈的过程)。

⑤:当然,你的test.c文件和main.c文件是存在的,于是make会生成test.o文件和main.o文件,然后再用test.o文件和main.o文件生成最终的mytest文件。

⑥:make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。

⑦:在寻找的过程中,如果出现错误,例如最后被依赖的文件找不到,那么make就会直接退出,并报错。

四:项目清理->clean

在我们每次重新生成可执行程序前,都应该将上一次生成可执行程序时生成的一系列文件进行清理,但是如果我们每次都手动执行一系列指令进行清理工作的话,未免有些麻烦,因为每次清理时执行的都是相同的清理指令,所以makefile也提供了clean板块来进行文件的清理

写法如下:

make clean指令即可清理指定文件:

解释:执行make clean指令之后,按照makefile文件中的指令把两个.o和a.out都删除了!

注意:clean: 是一个依赖关系,只不过clean:不依赖于任何的文件,所以:后面什么都没有

五:ACM

Q1:我重复的进行make会怎么样?

A1:

解释:第一次make生效了,但是第二次打印:`a.out' is up to date. (译为a.out已经是最新的了!)

Q2:系统怎么知道a.out是最新的了?

A2:因为文件的最近修改时间没有变,所以系统对之后的make不作处理!

任何一个文件都有三个时间,简称ACM!

A:最近访问时间
C:最近的属性修改时间
M:最近的内容修改时间

系统在执行make指令的时候,会去比对所涉及的文件的ACM是否发生变化,变化了,此时的make指令才有意义,系统才会进行一些列的gcc指令!

在我们连续的make期间,既没有影响到任何一个文件的最近访问时间,最近属性修改时间,最近内容修改时间,所以最后发现没有任何的变化,所以对第二次及后面的make不做处理!

六:.PHONY

.PHONY 的作用

  1. 将目标(如 clean)标记为 伪目标,表明它不生成同名文件。

  2. 当调用伪目标时,Make 跳过对该目标文件存在性的检查,直接执行其命令。

所以我们的clean常常用.PHONY修饰

格式如下:

现在 我们连续的make clean,系统也不会去比对文件的ACM了!

七:makefile的简写方式

Makefile文件的简写方式:

自动变量:

        $@:目标文件(如 a.out 或 print.o)。

        $^:所有依赖文件(如 print.o main.o)。

        $<:第一个依赖文件(如 print.c)。

模式规则:

        %.o: %.c:匹配所有 .c 文件生成对应的 .o 文件,避免为每个 .o 文件写重复规则。

通配符清理:

        rm -f *.o:删除所有 .o 文件,无需手动列出。

所以可以 简写成如下:

八:一些细节

1:makefile的执行顺序

当你把clean板块放在makefile文件的上面是,此时直接运行 make 时会执行 clean!此时只能进行make a.out,才能执行 a.out 的构建规则

 

2:ACM这三个时间可以通过stat指令来查看

需要注意的是,尽管能影响的A的是访问,也就是cat或者touch,但是由于优化,只有第一次的cat能够影响A,后面连续的cat不会改变A!

但是touch指令就算什么都不做,也能够一次性影响ACM三个时间,且能够连续的影响,如图:

 

3: 为什么要给clean加上.PHONY

  • 无 .PHONY 时
    Make 会检查 clean 的依赖文件和它本身的时间戳,但这种检查对伪目标毫无意义(例如 clean 本就不该对应任何文件)。

  • 有 .PHONY 时
    Make 会跳过文件检查,直接执行命令,减少不必要的计算。

总结:提高性能

4:makefile和Makefile都一样,看个人喜好

5:makefile中也能进行宏替换

CC := gcc        # 定义编译器
CFLAGS := -Wall  # 定义编译选项
TARGET := a.out  # 定义目标文件名

好处:修改编译器或选项时只需修改变量值。


http://www.hkcw.cn/article/ajwSDwVHrE.shtml

相关文章

VMware Tools 手动编译安装版

OWASPBWA安装VMware tools 安装时&#xff0c;显示如下提示 官方安装手册参考&#xff1a;https://knowledge.broadcom.com/external/article?legacyId1014294 按照提示&#xff0c;下载linux.iso文件&#xff0c;并连接到虚拟机的CDROM里&#xff0c;状态勾选已连接&#x…

OpenFeign和Gateway集成Sentinel实现服务降级

目录 OpenFeign集成Sentinel实现fallback服务降级cloud-alibaba-payment8003(支付服务)cloud-common-api(通用模块)cloud-alibaba-order9003(订单服务)Sentinel配置流控规则测试结果 Gateway集成Sentinel实现服务降级cloud-gateway9527(网关)测试结果 总结 OpenFeign集成Sentin…

远程管理SSH服务的搭建

一、搭建SSH服务 1、关闭防火墙与SELinux # 关闭firewalld防火墙 # 临时关闭 systemctl stop firewalld # 关闭开机自启动 systemctl disable firewalld# 关闭selinux # 临时关闭 setenforce 0 # 修改配置文件 永久关闭 vim /etc/selinux/config SELINUXdisabled2、配置yum源…

Cesium快速入门到精通系列教程二

一、添加地形与添加自定义地形 在 Cesium 1.93 中添加地形可以通过配置terrainProvider实现。Cesium 支持多种地形数据源&#xff0c;包括 Cesium Ion 提供的全球地形、自定义地形服务以及开源地形数据。下面介绍几种常见的添加地形的方法&#xff1a; 使用 Cesium Ion 全球地…

基于FashionMnist数据集的自监督学习(生成式自监督学习VAE算法)

目录 一&#xff0c;VAE 1.1 VAE的简介 1.2 VAE的核心思想 1.3 VAE的结构 1.4 VAE的工作原理 1.5 VAE 与传统自动编码器&#xff08;AE&#xff09;的区别 1.6 VAE 的应用场景 二&#xff0c;代码逻辑分析 2.1 整体逻辑 2.2 VAE模型 2.3 训练策略与优化 2.4 自适应学…

ESP32基础知识1:项目工程建立和烧录

ESP32基础知识1&#xff1a;项目工程建立和烧录 一、本文内容与前置知识点1. 本文内容2. 前置知识点 二、新建工程1. 工程配置2. 依照模板建立项目 三、硬件烧录1. 硬件准备2. 烧录器和ESP32连接3. 电脑端设置4. 烧录成功演示 四、参考文献 一、本文内容与前置知识点 1. 本文内…

duilib图片属性中corner属性九宫格拉伸说明

在duilib中&#xff0c;图片设置里有corner属性&#xff0c;类似于android系统里的九宫格&#xff0c;对应的分区域拉伸被称为九宫格拉伸。设置corner属性后&#xff0c;将区域分成3x3的九个区域&#xff0c;如下所示&#xff1a; 除了4个拐角区域不拉伸&#xff0c;其余5个区域…

《操作系统真相还原》——进入内核

ELF 按书上的操作来&#xff0c;在现代操作平台编译链接默认生成elf64 格式的文件&#xff0c; 很显然程序头位置发生变化&#xff0c;因为定义elf 结构的类型中有64位&#xff0c;所以我们需要将编译链接出32位格式的 gcc -m32 -c -o main.o main.c ld -m elf_i386 main.o …

笔试笔记(运维)

&#xff08;数据库&#xff0c;SQL&#xff09; limit1 随机返回其中一个聚合函数不可以嵌套使用 【^】这个里面的数据任何形式组合都没有 sql常用语句顺序&#xff1a;from-->where-->group by-->having-->select-->order by-->limit 只要其中一个表存在匹…

医疗数理范式化:从范式迁移到认知革命的深度解析

引言 在当代医疗领域,数理思维已经从辅助工具逐渐发展成为核心决策支持系统的关键组成部分。随着数字技术的迅猛发展,医疗行业正经历着前所未有的变革,而数理思维作为这一变革的核心驱动力,正在深刻重塑医疗实践的方方面面。数理思维在医疗领域的应用,本质上是将抽象的数…

golang -- slice 底层逻辑

目录 一、前言二、结构三、创建3.1 根据 make创建3.2 通过数组创建 四、内置append追加元素4.1 追加元素4.2 是否扩容4.2.1 不扩容4.2.2 扩容 总结 一、前言 前段时间学了go语言基础&#xff0c;过了一遍之后还是差很多&#xff0c;所以又结合几篇不同资料重新学习了一下相关…

Fashion-MNIST LeNet训练

前面使用线性神经网络softmax 和 多层感知机进行图像分类&#xff0c;本次我们使用LeNet 卷积神经网络进行 训练&#xff0c;期望能捕捉到图像中的图像结构信息&#xff0c;提高识别精度&#xff1a; import torch import torchvision from torchvision import transforms f…

数据库系统概论(十)SQL 嵌套查询 超详细讲解(附带例题表格对比带你一步步掌握)

数据库系统概论&#xff08;十&#xff09;SQL 嵌套查询 超详细讲解&#xff08;附带例题表格对比带你一步步掌握&#xff09; 前言一、什么是嵌套查询&#xff1f;1. 基础组成&#xff1a;查询块2. 嵌套的两种常见位置&#xff08;1&#xff09;藏在 FROM 子句里&#xff08;当…

Azure 机器学习初学者指南

Azure 机器学习初学者指南 在我们的初学者指南中探索Azure机器学习&#xff0c;了解如何设置、部署模型以及在Azure生态系统中使用AutoML & ML Studio。Azure 机器学习 &#xff08;Azure ML&#xff09; 是一项全面的云服务&#xff0c;专为机器学习项目生命周期而设计&am…

使用win11圆角指针教程

一.准备文件 win11圆角指针下载链接&#xff1a;https://wwxh.lanzoum.com/iwsZH2xqmy0d 密码&#xff1a;em 二.开始安装 1.将下载的压缩包解压&#xff08;随便存哪&#xff0c;最后可以删掉&#xff09; 右键&#xff0c;点击“全部解压缩” 点击“提取” 2.安装 选…

day16 leetcode-hot100-30(链表9)

24. 两两交换链表中的节点 - 力扣&#xff08;LeetCode&#xff09; 1.模拟法 思路 模拟题目要求进行两两交换&#xff0c;但有一点需要注意&#xff0c;比如交换3与4后&#xff0c;1仍然指的是3&#xff0c;这是不正确的&#xff0c;所以1指针的next也需要修改&#xff0c;所…

C语言进阶--程序的编译(预处理动作)+链接

1.程序的翻译环境和执行环境 在ANSI C标准的任何一种实现中&#xff0c;存在两种不同的环境。 第一种是翻译环境&#xff1a;将源代码转换为可执行的机器指令&#xff08;0/1&#xff09;; 第二种是执行环境&#xff1a;用于实际执行代码。 2.详解编译链接 2.1翻译环境 程…

GCA解码大脑因果网络

格兰杰因果分析&#xff08;Granger Causality Analysis,GCA&#xff09; 是一种测量脑区之间有效性连接&#xff08;effective connectivity&#xff09;的成熟方法。利用多元线性回归分析一个时间序列的过去值是否能正确预测另一个时间序列的当前值&#xff0c;可以用来描述脑…

H5S 大华SDK带图报警类型及热成像报警支持

目前很多应用都希望报警带对应的图片&#xff0c;比如控制中心在弹报警框的时候需要有一张图片让人工更快的做出判断&#xff0c;下面介绍使用大华SDK 的带图报警功能。 大华SDK支持接入设备带图报警&#xff0c;并且支持热成像通道报警&#xff0c;设置订阅事件并吧协议端口设…

(javaSE)Java数组进阶:数组初始化 数组访问 数组中的jvm 空指针异常

数组的基础 什么是数组呢? 数组指的是一种容器,可以用来存储同种数据类型的多个值 数组的初始化 初始化&#xff1a;就是在内存中,为数组容器开辟空间,并将数据存入容器中的过程。 数组初始化的两种方式&#xff1a;静态初始化&#xff0c;动态初始化 数组的静态初始化 初始化…