【Day9】make/makeFile如何让项目构建自动化起飞
【Day9】make/makeFile如何让项目构建自动化起飞
- 使用make命令
- 编写makefile文件
- 依赖管理
- 增量构建
- makefile注释:#
- makefile其他语法
- make/makefile递归式工作过程
在Linux中,项目自动化构建是指使用一系列工具和脚本来自动执行软件项目的编译、测试、打包和部署等过程。
make和makefile是linux中常用的项目自动化构建工具。make是一条命令,makefile/Makefile是一个文件。两个搭配使⽤,完成项目自动化构建。
一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中。makefile定义了一系列的规则来指定,哪些源文件需要先翻译,哪些源文件需要后翻译,哪些源文件需要重新翻译,甚至于进行更复杂的功能操作。make是一个命令工具,是一个解释makefile中指令的命令工具。
在makefile中写好构建步骤,再用make命令启动makefile,整个工程完全“自动化编译”,能极大提高软件开发的效率。
使用make命令
makefile文件的位置:和源文件在同一目录下。
总结make的用法:
make 目标文件:在当前目录下找makefile文件,扫描makefile,并执行目标文件。
make:make命令中如果没有指定目标文件,make命令默认从上往下依次扫描makefile中的内容,默认扫描到的第一个目标文件作为本次要执行的目标文件。
编写makefile文件
依赖管理
一个项目中的源文件之间可能存在各种依赖关系,例如一个源文件可能依赖于其他源文件或头文件,Makefile 明确地定义这些依赖关系(目标(target)、依赖(prerequisites)和规则(rules)),确保在编译时按照正确的顺序进行处理,避免因依赖关系错误导致的编译错误。
例如:
在下面这个makefile文件中,
第一行是依赖关系,第二行是依赖方法。根据依赖关系执行依赖方法。
在依赖关系中,目标文件依赖的源文件可以不写明。
用.PHONY修饰的目标文件,表示这个目标文件是一个伪目标。伪目标的特点是伪目标对应的依赖关系和依赖方法总是被执行。也就是,只要makefile中有下面3、4、5行内容,只要make,目标文件对应的依赖方法被执行的同时,3、4、5行内容是一定会执行的。
3、4、5行的意思是清除所有生成的目标文件。

增量构建
全量构建:在目标文件和对应的所有依赖文件中,哪怕只有一个文件被修改过,再次make目标文件的时候,对应的所有依赖文件都要重新编译然后链接。
增量构建:再次make目标文件的时候,Makefile 会检查文件的修改时间,如果依赖文件比目标文件更新,就重新编译这个依赖文件。

伪目标对应的依赖关系和依赖方法总是被执行,总是被执行即忽略对比modify时间。
例如:


自己的程序不建议使用.PHONY修饰。
什么叫做不被执行?
场景:假设一个可执行程序依赖了100个源文件,但如果此时我们对其中一个源文件做出了修改,我们并不需要重新编译所有源文件。
只有make伪目标文件的时候,伪目标对应的依赖关系和依赖方法才总是被执行。
该可执行程序不是伪目标文件,所以gcc在重新编译时,老代码没被修改过且是不被执行的,不会被重新编译,gcc只会把修改过的代码重新编译下。
make命令怎么知道:二进制文件(依赖文件被编译成.o文件)和源文件(目标文件的依赖文件)哪个修改时间更新呢?
通过文件的Modify属性判断。Modify属性是文件/目录的内容最后一次被修改的时间。可以使用stat命令查看文件/目录的详细信息。
makefile注释:#

makefile其他语法
Makefile 支持变量、条件判断、函数和外部脚本调用,可以灵活扩展构建逻辑。
例如:
BIN=proc.exe # 定义变量
CC=g++
SRC=myproc.c
OBJ=myproc.c
LFLAGS=-o
FLAGS=-c.PHONY:test
test: @echo $(SRC) # 命令前面加@,表示make的时候只显示结果,不回显命令echo $(CC) # $(CC):最开始我们定义了变量CC,此时$(CC)等价gcc。$()的意思是把此处内容替换成括号里的$(BIN):$(SRC)@$(CC) $(LFLAGS) $@ $^ # $@:代表⽬标⽂件名,此时相当于$(BIN)。 $^: 代表依赖⽂件列表,此时相当于$(SRC)@echo "linking ... $^ to $@"# 依赖文件不止一个时可以像下面这样写:
%.o:%.c # %相当于makefile中的通配符$(CC) $(FLAGS) $< # $<的意思是对匹配到的.c文件,依次交给gcc@echo "compling ... $^ to $@"SRC1=$(shell ls *.c) # 在makefile中可以直接使用linux命令,方法是`shell 命令`。所以这句的意思是显示所有.c文件,并把它们放到SRC1中。SRC2=$(wildcard *.c) # makefile内部也有函数,其中函数wildcard的功能是获取符合特定模式的文件名列表。所以`wildcard *.c`的意思是获取当前所有后缀是.c的⽂件。SRC3=$(SRC:.c=.o) # 将SRC的所有同名.c 替换 成为.o 形成⽬标⽂件列表
make/makefile递归式工作过程
目录中存在myproc.c文件。
以下面内容为例展示makefile的工作过程:
myproc:myproc.o gcc myproc.o -o myproc
myproc.o:myproc.s gcc -c myproc.s -o myproc.o
myproc.s:myproc.i gcc -S myproc.i -o myproc.s
myproc.i:myproc.cgcc -E myproc.c -o myproc.i.PHONY:clean
clean: rm -f *.i *.s *.o myproc
通过make命令执行makefile后,(默认只输⼊make命令),则:
- make会在当前⽬录下找名字叫“Makefile”或“makefile”的⽂件。
- 如果找到,它会找⽂件中的第⼀个⽬标⽂件(target),在上⾯的例⼦中,他会找到 myproc 这个⽂件,并把这个⽂件作为最终的⽬标⽂件。
- 如果 myproc ⽂件不存在,或是 myproc 所依赖的后⾯的 myproc.o ⽂件的⽂件修改时间要⽐ myproc 这个⽂件新,那么,他就会执⾏后⾯所定义的命令来⽣成
myproc 这个⽂件。 - 如果 myproc 所依赖的 myproc.o ⽂件不存在,那么 make 会在当前⽂件中找⽬标为
myproc.o ⽂件的依赖性,如果找到则再根据那⼀个规则⽣成 myproc.o ⽂件。makefile工作时会维护一个类似于栈的东西。 - 依次类推(相当于进栈过程)。
- 当前目录下存在myproc.c文件,经过编译后make 会⽣成myproc.i ⽂件(相当于出栈过程)。最终,make 会⽣成myproc.o ⽂件,然后myproc.o ⽂件编译后,形成最终的目标文件myproc。
- 这就是整个make的依赖性,make会⼀层⼜⼀层地去找⽂件的依赖关系,直到最终编译出第⼀个⽬标⽂件。
- 在找寻的过程中,如果出现错误,⽐如最后被依赖的⽂件找不到,那么make就会直接退出,并报错。make只管⽂件的依赖性,即,如果在我找了依赖关系之后,冒号后⾯的⽂件还是不在,那么对不起,我就不⼯作啦。对于其他错误,make根本不理。

下次见~

相关文章:
【Day9】make/makeFile如何让项目构建自动化起飞
【Day9】make/makeFile如何让项目构建自动化起飞 使用make命令编写makefile文件依赖管理增量构建makefile注释:#makefile其他语法 make/makefile递归式工作过程 在Linux中,项目自动化构建是指使用一系列工具和脚本来自动执行软件项目的编译、测试、打包和…...
【单片机】嵌入式系统的硬件与软件特性
嵌入式系统的软件结构 嵌入式系统的软件结构一般分为 不带操作系统(Bare Metal) 和 带操作系统(RTOS / Linux) 两种。不同的软件架构适用于不同的应用场景,如 简单控制系统、实时控制系统、物联网、工业自动化等。 嵌…...
C语言学习笔记-初阶(30)深入理解指针2
1. 数组名的理解 在上一个章节我们在使用指针访问数组的内容时,有这样的代码: int arr[10] {1,2,3,4,5,6,7,8,9,10}; int *p &arr[0]; 这里我们使用 &arr[0] 的方式拿到了数组第⼀个元素的地址,但是其实数组名本来就是地址&…...
ROM修改进阶教程------修改安卓机型SELinux宽容的几种方式方法 以及第三方系统中如何关闭SELinux宽容
SELinux是一种强制访问控制安全机制,用于增强Linux系统的安全性。在某些情况下,可能需要对 SELinux 进行宽容设置,以满足特定的应用需求。当SELinux处于宽容模式时,系统允许违反安全策略的行为发生,但不会阻止这些行为,通常会在日志中记录这些违规事件。这与强制模式不同…...
亚马逊云科技Marketplace(中国区)上架专业服务产品, “云生态连接器”价值凸显
近日,由西云数据运营的亚马逊云科技Marketplace(中国区)正式支持专业服务产品。此次发布将大幅简化企业对云专业服务的采购流程,实现云软件从规划、部署到支持的全生命周期管理,同时也为合作伙伴提供了更多的销售机会。…...
【音视频】音频基础
一、音频基础 1.1 声音的物理性质 ——振动 声音是一种由物体振动引发的物理现象,如小提琴的弦声等。物体的振动使其四周空气的压强产生变化,这种忽强忽弱变化以波的形式向四周传播,当被人耳所接收时,我们就听见了声音。 1.2 声…...
策略模式的C++实现示例
核心思想 策略模式是一种行为型设计模式,它定义了一系列算法,并将每个算法封装在独立的类中,使得它们可以互相替换。策略模式让算法的变化独立于使用它的客户端,从而使得客户端可以根据需要动态切换算法,而不需要修改…...
本地部署pangolin获取谱系,从而达到预测新冠的流行趋势
步骤 1:安装Docker 注:此步骤忽略,可通过Docker官网对于文档进行安装,地址如下 Docker: Accelerated Container Application Developmenthttps://www.docker.com/ 步骤 2:拉取Pangolin镜像 docker pull staphb/pangolin:latest 步…...
【我的 PWN 学习手札】House of Emma
House of Emma 参考文献 第七届“湖湘杯” House _OF _Emma | 设计思路与解析-安全KER - 安全资讯平台 文章 - house of emma 心得体会 - 先知社区 前一篇博客【我的 PWN 学习手札】House of Kiwi-CSDN博客的利用手法有两个关键点,其一是利用__malloc_assert进入…...
4 Redis4 List命令类型讲解
Redis 列表(List)命令详解 1. Redis 列表(List)简介 Redis 列表(List)是一个简单的字符串列表,按照插入顺序排序。它可以用作 栈(Stack) 和 队列(Queue&…...
CentOS 7 安装 Redis6.2.6
获取资源、下载安装 Redis6.2.6 安装Redis6.2.6 上传到服务器或直接下载(wget http://download.redis.io/releases/redis-6.2.6.tar.gz)、再解压安装 tar -zxvf redis-6.2.6.tar.gz 进入redis解压目录 cd redis-6.2.6先编译 make再执行安装 make PREFI…...
数据库原理4
1.数据库中的数据通常可分为用户数据和系统数据两部分。用户数据是用户使用的数据;系统数据称为数据字典。 2.SQL语言的功能:数据查询;数据操纵;数据定义;数据操作;数据控制 3.对未提交更新的依赖&#x…...
doris: MySQL
Doris JDBC Catalog 支持通过标准 JDBC 接口连接 MySQL 数据库。本文档介绍如何配置 MySQL 数据库连接。 使用须知 要连接到 MySQL 数据库,您需要 MySQL 5.7, 8.0 或更高版本 MySQL 数据库的 JDBC 驱动程序,您可以从 Maven 仓库下载最新或指定版本的…...
Django模型数据删除:详解两种方式
Django模型数据删除:详解两种方式 在Django框架中,数据模型(Model)不仅定义了应用的数据结构,还提供了与数据库交互的接口,包括数据的删除操作。本文将详细介绍两种在Django中删除数据的方式:通…...
C++并发以及多线程的秘密
1.基础概念 并发(Concurrency) 并发是指在同一时间段内,多个任务看起来像是同时执行的。并发并不一定意味着真正的同时执行,它可以是通过时间片轮转等方式在多个任务之间快速切换,让用户感觉多个任务在同时进行。并发…...
自学微信小程序的第十二天
DAY12 1、腾讯地图SDK是一套为开发者提供多种地理位置服务的工具,可以使开发者在自己的应用中加入地图相关功能,轻松访问腾讯地图服务和数据,更好地实现微信小程序的地图功能。 表49:search()方法的常用选项 选项 类型 说明 keyword string POI搜索关键词,默认周边搜索 l…...
⭐算法OJ⭐跳跃游戏【贪心算法】(C++实现)Jump Game 系列 I,II
既股票买卖系列之后的第二组贪心算法题目:跳跃游戏系列。这一篇介绍的两个问题,其输入均为一个数组,每个元素表示在该位置可以跳跃的最大长度。 55. Jump Game You are given an integer array nums. You are initially positioned at the …...
带你从入门到精通——自然语言处理(五. Transformer中的自注意力机制和输入部分)
建议先阅读我之前的博客,掌握一定的自然语言处理前置知识后再阅读本文,链接如下: 带你从入门到精通——自然语言处理(一. 文本的基本预处理方法和张量表示)-CSDN博客 带你从入门到精通——自然语言处理(二…...
ubuntu挂载固态硬盘
Ubuntu 中挂载位于 /dev/sdc1 的固态硬盘,可以按照以下步骤操作: 步骤 1:确认分区信息 首先,确保设备 /dev/sdc1 存在且已正确分区: sudo fdisk -l /dev/sdc # 查看分区表 lsblk # 确认分区路…...
WPF+WebView 基础
1、基于.NET8,通过NuGet添加Microsoft.Web.WebView2。 2、MainWindow.xaml代码如下。 <Window x:Class"Demo.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/win…...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...
Vue记事本应用实现教程
文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展:显示创建时间8. 功能扩展:记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...
使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...
[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
tomcat入门
1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效,稳定,易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...
Kubernetes 节点自动伸缩(Cluster Autoscaler)原理与实践
在 Kubernetes 集群中,如何在保障应用高可用的同时有效地管理资源,一直是运维人员和开发者关注的重点。随着微服务架构的普及,集群内各个服务的负载波动日趋明显,传统的手动扩缩容方式已无法满足实时性和弹性需求。 Cluster Auto…...
