Linux下Makefile的简单编写与使用

2023-05-16

Makefile

一个工程文件中的源文件可能有很多,并且不同的功能、模块等都放在不同的目录中,常规的编译已经不能高效化的处理这样的问题,而Makefile就是为解决这一问题而来。

Makefile一旦写好,只需一个make指令,即可完成Makefile文件中所编写的所有指令,从而编译整个工程文件,极大的提高了效率

make是一个命令工具,用来解释Makefile中的命令。

Makefile文件命名和规则

  • 文件命名
    采用makefile或Makefile都可。
  • Makefile规则

Makefile中的命令规则如下:

xxx(目标文件):xxx(依赖文件)

制表符)命令(shell命令)

其中,目标文件即最终要生成的文件(伪目标除外),依赖文件即生成目标文件所需的文件,命令即shell命令。

注意,命令前必须有一个tab缩进。

例如:

#Makefile
app: a.c b.c #目标:依赖
	gcc a.c b.c -o app #注意这行最开始的缩进

make以上这个Makefile后就会将目录下的a.cb.c编译为目标文件app

Makefile的工作原理

  • Makefile中的命令在执行前,会检查是否存在所需的依赖文件

如果存在:执行命令
如果不存在:向下检查其他规则,是否存在其他规则生成当前规则所需要的依赖,如果有,则执行该规则中的命 令。
例如:

#Makefile
app: a.o b.o
	gcc a.o b.o -o app
a.o: a.c
	gcc -c a.c -o a.o
b.o: b.c
	gcc -c b.c -o b.o

在上方这个Makefile中,当执行到app规则时,会发现所需的依赖文件a.o与b.o都不存在于当前目录,所以会向下寻找是否有其他规则生成此文件,当寻找到a.o规则时,发现其是所需的文件,就执行gcc -c a.c -o a.o,b.o同理。

  • Makefile在执行规则中的命令时,会比较目标文件和依赖文件的修改时间

如果依赖文件晚于目标文件修改时间,即依赖文件在上一次生成目标后进行过修改,则会重新生成目标文件。

如果依赖文件早于目标文件修改时间,即依赖文件在上一次生成目标后没进行修改,则不会执行相应的命令。

例如,你对一个Makefile使用两次make,第二次会提示make:"app"已是最新

利用这个特性,在加上我们将依赖与目标分级生成,即上方第二个Makefile,这样当我们仅修改其中的a.c文件,再一次make只会执行a.o规则与app规则,b.o规则因为b.c未修改而不执行,这样可以大大减少资源浪费。

Makefile变量

以上虽然可以减少编译代码的重复量,但是如果一个工程中有1000个.c .h文件,我们编写一个Makefile就会浪费大量时 间。因此,我们要采用一些变量来提高效率。

  • 变量的获取
    我们使用 $(变量名) 来使用变量。
  • 自定义变量

我们使用变量名 = 变量值var = hello来自定义我们所需的变量。

例如上方第一个Makefile就可改写为:

#Makefile
rsc = a.c b.c
app: $(rsc) #目标:依赖
	gcc $(rsc) -o app #注意这行最开始的缩进
  • 预定义的变量

有部分变量是系统预定义的,我们可以直接使用。

AR:归档维护程序的名称,默认值为ar

CC:C编译器的名称,默认值为cc

CXX:C++编译器的名称,默认值为g++

$@:目标的完整名称

$<:第一个依赖文件的名称

$^:所有依赖文件的名称

为了方便理解接下来的例子,我们简单讲解一下Makefile中的模式匹配。

%.o:%.c中,%是通配符,匹配一个字符串,而两个%则匹配同一个字符串。

例如上方第二个Makefile可改写为:

#Makefile
rcs = a.o b.o
app: $(rcs)
	$(CC) $(rcs) -o $@
%.o: %.c #上方规则会执行两次此规则
	$(CC) -c $< -o $@

Makefile函数

我们可以看到,上面这个Makefile已经相对简单了,但是,还是没有解决工程中文件很多的情况,rcs的获取还是要我们输入每个需要编译的文件,那么,就要采用函数来替我们去写入这些依赖文件。

  • $(wildcard PATTERN. . .)

这个函数的功能是获取指定目录下指定类型的文件。

其中参数PATTERN是某个目录下某种类型的文件,多个目录多个类型可用空格分隔。

返回值是一个若干个文件的文件列表,文件名用空格隔开。

例如:

$(wildcard ./*.c) 返回当前目录下的所有以c为后缀的文件。
  • $(patsubst pattern, replacement, text)

这个函数的功能是查找text中的单词是否符合模式pattern,如果符合,则用replacement替换。

pattern可以包括通配符 % 。如果replacement中也包含 % ,那么replacement中的 % 将和 pattern中的 % 保 持一致。

返回值为替换后的字符串。

例如:

$(patsubst %.c, %.o, a.c, b.c) 返回a.o, b.o。

这样,我们上面那个例子就可以改写为:

#Makefile
rcs = $(wildcard ./*.c)
objs = (patsubst %.c, %.o, $(src))
app: $(objs)
	$(CC) $(objs) -o $@
%.o: %.c #上方规则会执行两次此规则
	$(CC) -c $< -o $@

Makefile clean规则

在我们执行完make指令后,会发现当前目录下多出了很多以o为后缀的文件,但是我们仅需要最终的目标文件app,其他的都是多余的,我们该如何处理。clean规则就会帮助我们处理他们。

clean
我们只用将clean规则添加到Makefile的最后,即可在每次编译完成后执行clean规则中的命令。如:

#Makefile
rcs = $(wildcard ./*.c)
objs = (patsubst %.c, %.o, $(src))
app: $(objs)
	$(CC) $(objs) -o $@
%.o: %.c #上方规则会执行两次此规则
	$(CC) -c $< -o $@
clean:
	rm $(objs) -f #rm指令删除 -f迭代删除

但是你会发现当前目录下多出了一个clean目标文件,依旧会采用Makefile的策略,对比修改时间,导致我们时常及时执行了clean,还是无法清除文件,那么,我们就需要接下来这个操作。

我们将clean定义为伪目标,即 .PHONY:clean 那么它就不会生成目标文件,少了对比,那么每次都会执行。

例如:

#Makefile
rcs = $(wildcard ./*.c)
objs = (patsubst %.c, %.o, $(src))
app: $(objs)
	$(CC) $(objs) -o $@
%.o: %.c #上方规则会执行两次此规则
	$(CC) -c $< -o $@
.PHONY: clean #伪目标
clean:
	rm $(objs) -f #rm指令删除 -f迭代删除
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux下Makefile的简单编写与使用 的相关文章

  • JavaWeb(分页)

    1 分页显示的步骤 xff1a xff08 1 xff09 确定每页显示的数据量 xff08 2 xff09 计算显示的页码 xff08 3 xff09 编写SQL语句 当数据多起来的时候 xff0c 记得需要一个容器将它包装起来 xff0
  • HTTP代理

    HTTP代理 xff08 HTTP Proxy xff09 是一种在网络中经常使用的技术 xff0c 允许客户端计算机通过指定的代理服务器来进行HTTP请求 在本文中 xff0c 我将介绍HTTP代理的基本原理 实现方法以及相关的应用和安全
  • LayUI项目之我的会议(送审以及排座)

    目录 一 xff0c 会议排座 1 前台编码 调试后的jsp代码 2 后台编码 1 图片工具类 2 js代码 3 SQL语句编写 4 子控制器 5 dao方法 三 图片处理 图片处理类 前台代码 后台接收 三 xff0c 会议送审 1 前台
  • Docker-宿主机与容器之间的文件拷贝

    目录 一 xff0c Docker运行MySQL容器 二 xff0c 数据卷 三 xff0c 数据卷容器 四 xff0c Dockerfile制作增强版 五 xff0c Docker制作自定义Tomcat 一 xff0c Docker运行M
  • 小程序框架

    目录 一 xff0c 框架 二 xff0c 响应的数据绑定 三 xff0c 页面管理 四 xff0c 基础组件 逻辑层 App Service 五 xff0c 小程序的生命周期 六 xff0c 注册页面 1 使用 Page 构造器注册页面
  • 小程序后台数据交互-个人中心

    目录 一 xff0c 获取用户昵称和头像 登录过程 二 xff0c 登录 小程序 三 xff0c 后台 小程序服器配置 一 xff0c 获取用户昵称和头像 登录过程 小程序登录 小程序可以通过微信官方提供的登录能力方便地获取微信提供的用户身
  • 微服务框架及多模块开发

    目录 一 xff0c 项目模式 二 xff0c 项目架构图 三 xff0c 案例演示 主模块 公共子模块 子模块 添加页面公共资源 一 xff0c 项目模式 电商模式 xff1a 市面上有5种常见的电商模式 xff0c B2B B2C C2
  • Mybatis与微服务注册

    目录 一 xff0c Springboot整合MybatisPlus 创建商品微服务子模块 二 xff0c SpringBoot整合Freeamarker 三 SpringBoot整合微服务 amp gateway amp nginx 整合
  • 服务调用&分布式session

    目录 一 xff0c Nginx动静分离 二 xff0c 服务调用 创建配置zmall cart购物车模块 创建配置zmall order订单模块 服务调用 四 xff0c spring session实战 什么是Spring Sessio
  • C语言调试技巧(以vs编译器为例)

    实用调试技巧 什么是bug调试是什么 xff0c 调试有何重要调试是什么 xff1f 调试的基本步骤Debug和Release的介绍 Windows环境调试介绍调试快捷键调试的时候查看程序当前信息查看临时变量的值查看内存信息查看调用堆栈查看
  • (十三)STM32——串口通信(UART)

    目录 学习目标 内容 通信方法 并行通信 串行通信 通信方向 通信方式 UART 特点 串口参数 通信流程 寄存器 USART SR USART DR USART BRR 过程 代码 运行结果 运行结果 遇到的问题 总结 学习目标 本节我们
  • 关于VINS-MONO与VIO轨迹漂移问题定位的一些方向

    整个VINS MONO系统 xff0c 较容易在系统静止或外力给予较大冲击时产生轨迹漂移 xff0c 原因是imu的bias在预积分中持续发散 xff0c 视觉重投影误差产生的约束失效 如静止 xff0c 先验约束可能会在LM的线性求解器中
  • 爬虫的基本原理

    爬虫是一种自动化程序 xff0c 可以模拟人类在互联网上的行为 xff0c 从而获取网页上的信息 爬虫技术在互联网上的应用非常广泛 xff0c 例如搜索引擎 数据挖掘 网络爬虫等等 本文将从爬虫的基本原理 爬虫的分类 爬虫的应用 爬虫的优化
  • 通信接口五种主要的类型是什么?RS-232、485、CAN、USB

    笔者电子信息专业硕士毕业 xff0c 获得过多次电子设计大赛 大学生智能车 数学建模国奖 xff0c 现就职于南京某半导体芯片公司 xff0c 从事硬件研发 xff0c 电路设计研究 对于学电子的小伙伴 xff0c 深知入门的不易 xff0
  • 关于机器人状态估计/VIO/VSLAM中能观性/可观性/FEJ的一些直接解释

    知识来源是高翔博士与贺一家老师的VIO课程 xff0c 以及Barfoot教授的机器人学中的状态估计 可观性问题会直接带来多传感器融合融态中的关键手段 xff1a FEJ First Estimated Jacobian 即不同残差对同一状
  • 关于电子与电气自动化芯片侧的一些基础理解

    EEE Electrical and Electronics Engineering 电子与电气自动化工程 人类科技母行业 涉及的主要领域 xff1a 半导体元器件 芯片 xff0c 模组 PCBA xff0c 嵌入式系统 xff08 驱动
  • BA(后端)优化与卡尔曼滤波的一些区别

    今天这篇文章会写得深入一些 xff0c 主要知识来自于业内多位大佬的实际落地与自身的思考 主要涉及机器人状态估计与机器视觉 xff0c 多传感器结合时 xff0c BA优化与卡尔曼滤波的差异及如何选择 机器人状态估计中 xff0c 大家应该
  • 关于VIO零速更新(ZUPT)与控制三种约束的工程实践

    今天这篇是深度稍微高一些的 xff0c 尽量写细 xff0c 但是具体实践各家都有不同的方式与工程习惯 xff0c 就不多赘述了 小组工作比较忙 xff0c 代码还没来得及整理 xff0c 总体更新一下基础知识 VIO系统后端核心的三种约束
  • 关于DSO直接法与IMU预积分联合VIO/SLAM一些思路

    本文不适合初学者 xff1b 干货多没写具体方法 xff0c 目前还在数论分解和思考中 xff0c 估计得2个月后完成 必要性 xff1a 1 常规VIO系统如VINS MONO建立的地图质量太差 xff0c 稀疏且不便认知 2 假设并入D
  • 主流VIO/VSLAM系统改造与工程化落地

    今天主要写针对主流VIO和VSLAM如VINS MONO和DSO的工程改造思路 肯定是有相当价值的 xff0c 总体写得比较简单 xff0c 需要具备软件 硬件 算法等各方面综合能力才能掌握主要路径 xff0c 具体实现方面以后由其他同事来

随机推荐

  • VIO与全局快门及轮速计的一些应用小技巧

    封面就用一个可爱的小车车 之前各种针对VIO xff0c VSLAM和VINS的工程注意事项都讲过了 今天的内容主要是针对VSLAM xff0c VIO的实用性 比如Td xff0c 同步对时 xff0c 内参 xff0c 外参这一串 最近
  • 关于机器人状态估计(12)-VIO/VSLAM的稀疏与稠密

    VIO三相性与世界观室内ALL IN ONE 首先以此链接先对近期工作的视频做个正经的引流 xff0c 完成得这么好的效果 xff0c 仅仅是因为知乎限流1分钟以内的视频 xff0c 导致整个浏览量不到300 xff0c 让人非常不爽 这套
  • 关于机器人状态估计(13)-线性代数有多重要?18.06总结

    太久没更新主要是在忙开发和测试 xff0c 这几个月被很多同学提问 xff0c 同时接触了一些实习生 普遍发现动手能力不错 xff0c 数学基础却差异很大 从我身边电子 xff0c CV或者SLAM做得比较杰出的朋友来看 xff0c 大家普
  • postman的安装与使用

    目录 第一部分 xff1a 基础篇postman1 安装postman进入postman官网 如果是mac系统可以直接点击mac app安装 第二部分 xff1a 进阶篇1 使用自带的脚本对接口进行测试 第一部分 xff1a 基础篇 pos
  • DMA案例 外设到内存搬运

    DMA案例 外设到内存搬运 需求 使用DMA的方式将串口接收缓存寄存器的值搬运到内存中 xff0c 同时闪烁LED1 CubeMX配置 串口配置 DMA配置 串口中断配置 用到的库函数 HAL UART ENABLE span class
  • 用rs_lidar雷达跑lio_sam

    1 准备工作 imu绑定串口有线连接雷达并能用rviz显示雷达点云用两个imu标定包标定imu在完成第二步必要的工作后 xff0c 配置LIO SAM config 下的params yaml参数 xff0c 更改之前建议备份在旁边复制粘贴
  • ubuntu18.04安装ros及解决rosdep update失败问题

    1 安装ros 转自 https blog csdn net qq 44830040 article details 106049992 ops request misc 61 257B 2522request 255Fid 2522 25
  • 球机是枪机和云台机的结合体

    1 枪机是监控类CCD摄像机中一种 枪机外观长方体 xff0c 前面是C CS镜头接口 xff0c 枪机不包含镜头 所谓的枪机主要从外型 镜头安装接口上区分 2 监控类摄像机主要有 xff1a 枪机 小半球 大半球 一体机 球机几个类别 枪
  • ROS学习笔记-1

    一 ROS简介 ROS全称Robot Operating System 机器人操作系统 ROS是适用于机器人的开源元操作系统 ROS集成了大量的工具 xff0c 库 xff0c 协议 xff0c 提供类似OS所提供的功能 xff0c 简化对
  • C语言指针详解(1)

    指针详解 之前我说过一篇关于指针在C语言中的基本使用 xff0c 这次我再来细讲一下指针的其他内容 目录 一 指针详解 1 指针定义 2 指针类型 3 野指针 4 如何规避野指针 xff1f 1 指针定义 指针理解的2个要点 xff1a 1
  • C语言结构体详解 (2) 结构体内存对齐,默认对齐数

    前言 上次 xff0c 我讲到了关于结构体的基本使用 xff0c 大家若感兴趣的话看一看我之前写的一篇结构体博客 xff0c 里面记载了我对于结构体的创建 初始化 嵌套结构体 结构体的访问访问方式和结构体传参方式等知识的见解 xff0c C
  • C语言——十进制转换十六进制

    请编写程序 xff0c 输入十进制数 xff0c 输出对应的十六进制数 输入格式 十进制非负整数 输出格式 对应的十六进制非负整数 要求 xff1a 十六进制数中的字母均为大写形式 输入样哩 5050 输出样例 13BA 代码输入 xff1
  • 如何编写头文件及使用Makefile

    头文件中应该写什么 xff1a 头文件可能会被任意源文件包含 xff0c 意味着头文件中的内容可能会在多个目标文件中存在 xff0c 要保证合并时不要冲突 重点 xff1a 头文件只编写声明语句 xff0c 不能有定义语句 全局变量声明 函
  • 剖析Linux内存中的/proc/meminfo参数

    PROC MEMINFO之谜 proc meminfo是了解Linux系统内存使用状况的主要接口 xff0c 我们最常用的 free vmstat 等命令就是通过它获取数据的 xff0c proc meminfo所包含的信息比 free 等
  • 看完秒懂:Linux DMA mapping机制分析

    说明 xff1a Kernel版本 xff1a 4 14ARM64处理器 xff0c Contex A53 xff0c 双核使用工具 xff1a Source Insight 3 5 xff0c Visio 1 概述 DMA xff08 D
  • linux网络编程-多进程实现TCP并发服务器

    服务端流程步骤 socket函数创建监听套接字lfd bind函数将监听套接字绑定ip和端口 listen函数设置服务器为被动监听状态 xff0c 同时创建一条未完成连接队列 xff08 没走完tcp三次握手流程的连接 xff09 xff0
  • Linux内核中断下半部工作队列(work queue)

    工作队列work queue 工作队列 xff08 work queue xff09 是中断下半部的一种实现机制 xff0c 主要用于耗时任务处理 xff0c 由内核线程代表进程执行 工作队列运行于进程上下文 xff0c 因此允许阻塞 运行
  • 手把手带你部署Ceph集群

    前言 xff1a Ceph作为开源的分布式文件系统 xff0c 可以轻松地将存储容量扩展到PB以上并拥有不错的性能 Ceph提供对象存储 块存储和文件系统三种存储方式 xff0c 如果不想花时间安装ceph xff0c 可以通过ceph d
  • Linux 内核安全增强—— stack canary

    一 背景知识 aarch64的函数栈 1 栈生长方向与push pop操作 栈是一种运算受限的线性表 入栈的一端为栈顶 xff0c 另一端则为栈底 其生长方向和操作顺序理论上没有限定 而在aarch64平台上 栈是向低地址方向增长的 STA
  • Linux下Makefile的简单编写与使用

    Makefile 一个工程文件中的源文件可能有很多 xff0c 并且不同的功能 模块等都放在不同的目录中 xff0c 常规的编译已经不能高效化的处理这样的问题 xff0c 而Makefile就是为解决这一问题而来 Makefile一旦写好