Linux中的`make`与`Makefile`:项目自动化构建工具
Linux中的make与Makefile:项目自动化构建工具
在Linux及类Unix系统中,make是一种广泛使用的自动化构建工具,它通过读取和执行Makefile(或makefile,文件名不区分大小写)中的指令来自动化编译和构建程序。Makefile定义了构建过程中需要执行的命令、依赖关系以及构建目标,极大地简化了复杂项目的构建过程。本文将深入探讨make命令、Makefile的编写规则、常用函数以及高级特性,帮助读者更好地理解和使用这一强大的工具。
一、make命令简介
make命令是一个根据Makefile中的指令来自动编译和链接程序的工具。它首先会检查所有需要编译的源文件以及它们所依赖的库或文件是否是最新的,如果不是,则根据Makefile中的规则重新编译这些文件。这种方式避免了不必要的编译,提高了构建效率。
二、Makefile的基本结构
Makefile由一系列规则(rules)组成,每个规则定义了如何生成一个或多个目标文件(target)。规则的基本格式如下:
target: dependenciescommand...
- target:规则的目标,通常是文件名,也可以是一个伪目标(如
clean)。 - dependencies:目标的依赖文件列表,用于判断目标是否需要重新构建。如果依赖文件比目标文件新,或者目标文件不存在,则执行命令。
- command:当目标需要被构建时执行的命令。每个命令前必须有一个制表符(Tab),而不是空格。
三、Makefile的编写规则
1. 变量
Makefile中可以使用变量来存储文件名、编译选项等,以便在多处重复使用。变量定义和引用的方式如下:
CC=gcc
CFLAGS=-Wall -ghello: hello.o$(CC) $(CFLAGS) -o hello hello.ohello.o: hello.c$(CC) $(CFLAGS) -c hello.c
2. 自动变量
make还定义了一系列自动变量,用于在规则中代表文件名、依赖列表等。常用的自动变量包括$@(代表目标文件名)、$<(代表第一个依赖文件名)、$^(代表所有依赖文件名)等。
3. 伪目标
伪目标不是文件名,而是一个标签,用于执行一些特定的操作,如清理构建文件。伪目标后面通常使用.PHONY来声明,以避免与同名文件冲突。
.PHONY: cleanclean:rm -f *.o hello
4. 模式规则
模式规则允许为符合特定模式的文件定义构建规则,而不需要为每个文件单独编写规则。模式规则使用%作为通配符。
%.o: %.c$(CC) $(CFLAGS) -c $< -o $@
四、Makefile的常用函数
Makefile支持多种内置函数,用于字符串处理、文件名操作、条件判断等。
wildcard:用于查找符合特定模式的文件名列表。patsubst:用于模式替换,将符合模式的字符串替换为另一个字符串。if、ifeq、ifneq、ifdef、ifndef:用于条件判断。
五、高级特性
1. 递归make
在大型项目中,可能会将项目拆分成多个子项目,每个子项目都有自己的Makefile。此时,可以在顶层Makefile中调用子项目的Makefile,实现递归构建。
subdir:cd subdir && $(MAKE)
2. 静态模式规则
静态模式规则是模式规则的一种扩展,它允许更精确地指定目标和依赖的模式。
objects = foo.o bar.oall: $(objects)$(objects): %.o: %.c$(CC) -c $(CFLAGS) $< -o $@
3. 变量覆盖
在命令行中可以通过-e选项或直接在命令行中指定变量值来覆盖Makefile中的变量值。
make CC=clang
4. 隐式规则
make内置了许多隐式规则,用于编译和链接C、C++等语言的源文件。当Makefile中没有为特定目标定义规则时,make会尝试使用隐式规则来构建目标。
六、实践案例
假设我们有一个简单的C语言项目,包含main.c、utils.c和utils.h三个文件,我们希望使用make和Makefile来自动化编译和构建这个项目。下面是一个可能的Makefile示例:
# 定义编译器和编译选项
CC=gcc
CFLAGS=-Wall -g# 定义项目中的源文件和目标文件
SRCS=main.c utils.c
OBJS=$(SRCS:.c=.o)
TARGET=myapp# 默认目标,即当不指定目标时执行的操作
all: $(TARGET)# 链接目标文件生成可执行文件
$(TARGET): $(OBJS)$(CC) $(CFLAGS) -o $@ $^# 编译C源文件生成目标文件
%.o: %.c$(CC) $(CFLAGS) -c $< -o $@# 伪目标,用于清理构建过程中生成的文件
.PHONY: cleanclean:rm -f $(OBJS) $(TARGET)# 依赖关系(如果项目中有头文件,则不需要显式写出,但保持其最新状态很重要)
# 注意:这里不直接写出头文件依赖,因为make会基于时间戳自动检查
# 但对于复杂的项目,可能需要使用-MM等gcc选项生成依赖关系# 如果需要自动处理头文件依赖,可以在Makefile中加入如下规则(示例)
# 注意:这里只是一个简单的示例,实际项目中可能需要更复杂的逻辑
%.d: %.c@set -e; rm -f $@; \$(CC) -MM $(CFLAGS) $< > $@.$$$$; \sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \rm -f $@.$$$$# 引入所有.d文件(如果存在),这些文件包含了文件的依赖关系
-include $(SRCS:.c=.d)
然而,上面的%.d规则及其sed命令是处理头文件依赖的一种较为复杂的方式,主要用于生成.d文件,这些文件包含了源文件和目标文件以及它们所依赖的头文件的列表。在上面的示例中,如果源文件更改或依赖的头文件更改,则.d文件也会更新,并且make会基于这些更新来重新编译相应的源文件。
但是,对于简单的项目或刚开始使用make的用户来说,可能不希望一开始就引入这么复杂的逻辑。在实际应用中,可以根据项目的复杂度和需求来选择是否自动生成依赖关系。
对于上面的简单项目,如果头文件(如utils.h)更改,用户通常需要手动触发重新编译。但在更复杂的项目中,使用自动生成依赖关系的方法可以极大地简化构建过程,并减少因忘记更新依赖关系而导致的编译错误。
七、总结
make和Makefile是Linux及类Unix系统中不可或缺的项目自动化构建工具。通过编写Makefile,开发者可以定义项目的构建规则、依赖关系以及编译选项,从而实现高效的自动化构建。本文介绍了make命令的基本用法、Makefile的编写规则、常用函数以及高级特性,并给出了一个简单项目的Makefile示例。希望这些内容能够帮助读者更好地理解和使用make和Makefile,提高项目构建的效率和质量。
相关文章:
Linux中的`make`与`Makefile`:项目自动化构建工具
Linux中的make与Makefile:项目自动化构建工具 在Linux及类Unix系统中,make是一种广泛使用的自动化构建工具,它通过读取和执行Makefile(或makefile,文件名不区分大小写)中的指令来自动化编译和构建程序。Ma…...
GitHub开源项目精选:轻量级预约/预订日历组件,用React和TypeScript构建
在日常开发中,我们经常需要在项目中添加预约或预订功能。今天给大家推荐一个超级轻量级的预约/预订日历组件,它是用React和TypeScript构建的,非常适合那些需要简单易用的日历解决方案的开发者。 安装方法: 你可以选择使用npm或者y…...
闲钱放在哪里?收益稳定且又高!
家庭理财,最大的问题就是,手里这点闲钱,说多不多,但打理起来,还真的很”挠头“。 放银行,存款利率接二连三下调,利息又又又要变少了! 投资出去,看着到处的雷声隆隆&…...
【Linux】简易线程池项目
线程池是一个可以巩固一些线程相关接口 && 加强理解的一个小项目。 注意:这里的线程池使用的线程并不是Linux原生接口,而是经过封装的,具体请看线程封装,为什么不使用原生接口? 因为原生接口一旦进行pthread…...
基于vue框架的NBA球星管理系统1878g(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。
系统程序文件列表 项目功能:用户,球员,球员数据,榜单类型,联盟榜单,重要比赛回放,精彩时刻视频,视频专栏,本赛季赛程,十佳球,投票信息,投票结果 开题报告内容 基于Vue框架的NBA球星管理系统 开题报告 一、选题背景 随着互联网的普及和体育产业的蓬勃发展&#x…...
【docker】Dockerfile练习
1、overlay文件系统原理测试 cd /mnt mkdir A B C worker merged echo "From A">./A/a.txt echo "From A">./A/b.txt echo "From A">./A/c.txt echo "From B">./B/a.txt echo "From B">./B/d.txt echo &quo…...
数据可视化的魔法:Python Matplotlib库的奇妙之旅
标题:数据可视化的魔法:Python Matplotlib库的奇妙之旅 在数据科学和分析领域,数据可视化是一种将复杂数据转换为图形表示的强有力工具,它可以帮助我们更直观地理解数据。Python中的Matplotlib库是进行数据可视化的瑞士军刀&…...
Python数据科学的秘密武器:Pandas库的深度解析
标题:Python数据科学的秘密武器:Pandas库的深度解析 Python作为数据科学领域的宠儿,其强大的数据处理能力离不开Pandas库的加持。Pandas是一个开源的数据分析和操作库,它提供了快速、灵活和表达力强的数据结构,旨在使…...
云计算实训24——python基本环境搭建、变量和数据类型、数据集合、py脚本
一、python环境搭建 确保拥有阿里云镜像 查看python环境 [rootpython ~]# yum list installed | grep python 查看epel是否安装 [rootpython ~]# yum list installed | grep epel 安装epel [rootpython ~]# yum -y install epel-release.noarch 查看是否安装python3 [rootpyt…...
深入了解网络性能监控(NPM):优化网络性能的关键
目录 网络性能监控(NPM)是什么? 关键网络性能指标 案例分享:如何利用NPM优化网络性能 实用技巧:如何高效运维你的网络 结论 随着企业依赖于互联网和内部网络进行业务运营,网络的稳定性和性能显得尤为重…...
Vue引入使用iconfont字体图标
由于element-ui或element-plus提供的图标有时候并不能满足日常需求,所以这篇介绍一下前端引入阿里巴巴矢量图标库使用,不止是vue使用,不限于vue2、vue3,html或是其他框架也是同样的道理,只要引入都是同样可以使用的。 1. 首先进入阿里巴巴矢量图标库官网 官网:https://…...
Doc2Vec
Doc2Vec 是一种扩展自 Word2Vec 的算法,它不仅可以生成词向量,还可以生成句子或文档的向量。下面是一个使用 Doc2Vec 比较两个句子的具体过程: 步骤 1: 训练 Doc2Vec 模型 首先,你需要有一个训练好的 Doc2Vec 模型。训练过程大致…...
MES生产过程透明管理,实施掌握生产每个环节
MES(制造执行系统)生产过程透明管理,旨在通过集成多种技术手段和管理模块,实现对生产过程的实时监控和精准掌握,确保每个生产环节都能被清晰地记录和追踪。以下是对MES生产过程透明管理的详细阐述: 一、MES…...
Java解析压缩包,并根据指定文件夹上传文件
方法 public Multimap<String, String> getCodeBucketMultimap(HttpServletRequest request)throws IOException {MultipartHttpServletRequest multiRequest (MultipartHttpServletRequest) request;// 基于servlet获取文件流List<MultipartFile> multipartFile…...
【HTML】纯前台字符验证码
效果图: 大致思路: 1.在<canvas>画布里写出几个字符; 2.给字符一个随机的角度和颜色; 3.给字符上画出一些干扰线和干扰点。 <canvas width"100" height"30" id"canvasRef" click"…...
如何在 Vue.js 项目中动态设置页面标题
目录 方法 1:使用 Vue Router 的元信息(meta) 步骤 1: 配置路由元信息 步骤 2: 使用路由守卫设置标题 方法 2:在组件内设置标题 在组件挂载时设置标题 使用响应式数据动态更新标题 在开发 Vue.js 应用时,设置动态页面标题是常见需求,尤其当应用包含多个页面时,为每…...
Eval绕过限制参数限制
PHP Eval函数参数限制在16个字符 PHP代码 <?php$param $_REQUEST[param]; if (strlen($param) < 17 && stripos($param, eval) false && stripos($param, assert) false){eval($param);}?># 部署环境属于ubuntu系统 通过GET传参绕过 由于是…...
计算机网络408考研 2021
2021 计算机网络408考研2021年真题解析_哔哩哔哩_bilibili 1 1 11 1 1 11...
element table表格树形数据展示
element table表格树形数据展示 1、效果 2、代码 <el-table ref"pointMultipleTable" border class"table-box" :data"[damActiveObj]"row-key"id" :tree-props"{ children: children }" :expand-row-keys"expand…...
Ubuntu 安装 Snipaste
一、下载 Snipaste 下载Snipastehttps://zh.snipaste.com/ 二、在/opt 创建 Snipaste 目录,创建 bin 和 icon 子目录,将 Snipaste.AppImage 移动到 bin 目录 三、创建快捷键图标 1. 创建桌面图标,右键→允许运行 yammiemy-pc >/home/y…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
微服务商城-商品微服务
数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...
在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案
这个问题我看其他博主也写了,要么要会员、要么写的乱七八糟。这里我整理一下,把问题说清楚并且给出代码,拿去用就行,照着葫芦画瓢。 问题 在继承QWebEngineView后,重写mousePressEvent或event函数无法捕获鼠标按下事…...
音视频——I2S 协议详解
I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...
深度学习水论文:mamba+图像增强
🧀当前视觉领域对高效长序列建模需求激增,对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模,以及动态计算优势,在图像质量提升和细节恢复方面有难以替代的作用。 🧀因此短时间内,就有不…...
Spring AI Chat Memory 实战指南:Local 与 JDBC 存储集成
一个面向 Java 开发者的 Sring-Ai 示例工程项目,该项目是一个 Spring AI 快速入门的样例工程项目,旨在通过一些小的案例展示 Spring AI 框架的核心功能和使用方法。 项目采用模块化设计,每个模块都专注于特定的功能领域,便于学习和…...
嵌入式常见 CPU 架构
架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集,单周期执行;低功耗、CIP 独立外设;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel(原始…...
【SpringBoot自动化部署】
SpringBoot自动化部署方法 使用Jenkins进行持续集成与部署 Jenkins是最常用的自动化部署工具之一,能够实现代码拉取、构建、测试和部署的全流程自动化。 配置Jenkins任务时,需要添加Git仓库地址和凭证,设置构建触发器(如GitHub…...
c# 局部函数 定义、功能与示例
C# 局部函数:定义、功能与示例 1. 定义与功能 局部函数(Local Function)是嵌套在另一个方法内部的私有方法,仅在包含它的方法内可见。 • 作用:封装仅用于当前方法的逻辑,避免污染类作用域,提升…...
