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

Make学习二:makefile组成要素

系列文章目录

Make学习一:make初探

文章目录

  • 系列文章目录
  • 前言
  • makefile 组成
    • makefile中的长行拆分
  • 给 Makefile 取什么名字
  • 包含其他 Makefile
  • Makefile 如何被解析
  • 总结


前言

make初探 中初步使用了 Makefile 这个工具并知道 makefile 告诉 make 如何重新编译系统的信息。本篇文章负责理解 Makefile 的组成要素。

makefile 组成

Makefile 主要包含以下五种内容:

  • 显示规则:明确告诉 make 什么时候、如何去重新生成(更新)一个或多个文件。规则中的 目标(targets) 是要生成的文件,依赖(prerequisites) 是生成这些目标所依赖的文件,配方(recipe) 是具体的命令。
  • 隐式规则:隐式规则:通过文件名的模式匹配,告诉 make 如何去更新一类文件。(例如 .c 文件如何生成 .o 文件,不需要每次都手写规则。)
  • 变量定义:用来保存一些字符串,可以在 Makefile 里多次使用。
  • 指令:是对 make 本身行为的控制。例如:include(包含其他 Makefile),if / else / endif(条件判断),define / endef(多行变量定义)
  • 注释:用 # 开头,后面的内容都不被 make 解析。如果想写出 # 字符本身,可以用 #。

makefile中的长行拆分

Makefile 使用 基于行的语法,每一行(换行符 \n)是一个语句的结束标志。语句太长是可以换行写的,不受长度限制(只受内存限制)。

用反斜杠 \ 在行末续行,可以把一条逻辑语句分成多行。

反斜杠 \ + 换行 的处理方式,在 配方行(recipe line) 和 非配方行(non-recipe line) 中略有不同。(这里讲的是非配方行,配方行会在后面文章中再讲。)

在非配方行(recipe line) (比如变量定义):

  • \ + 换行 会被转换成 一个空格;
  • \ 前后的所有空白字符(比如空格或 Tab)也会合并为 一个空格;
  • 如果连续有多个 \ 换行,也都合并为一个空格。
FOO = one       \two       \three

如果你拆分一行但又不想在拆分点多出一个空格,可以用这个技巧:

var := one$\ word

这会被解释为:var := oneword,原因在于展开反斜杠加换行之后,$ 后跟一个空格是在引用空格变量的内容(" "),但这个变量并不存在没有定义,所以展开为空字符串。

给 Makefile 取什么名字

默认情况下,make 查找 Makefile 文件时,会按照这个顺序去找:GNUmakefile、makefile、Makefile
推荐用 Makefile,因为:

  • 在 ls 目录列表时,Makefile 会出现在靠前的位置(大写字母排在小写之前)
  • 和 README 等重要文件放在一起,容易一眼看到。

如果你不用默认名字(比如 Makefile),而是用其他名字,比如 build.mk,你需要在命令行用 -f 或 --file 指定,例如:make -f build.mk

包含其他 Makefile

include 指令的作用是:暂停当前 makefile 的读取,去读取一个或多个其他的 makefile 文件,读完再继续当前的。例如:include vars.mk

如果文件名不是绝对路径、也不在当前目录,make 会搜索其他目录,比如:用 -I 指定的路径:make -I path/to/includes。或者一些系统默认路径(如 /usr/include)。当前有效的搜索路径可以通过 .INCLUDE_DIRS 变量查看。

Makefile 如何被解析

GNU make 读取 Makefile 是 一行一行读取的。每读一行,就根据这一行的内容去解析它。碰到 \ 换行时续行;

make 是通过 每一行的第一个字符 来判断这一行是属于哪种类型:

  • Tab 配方(recipe)
  • # 注释(comment)
  • 其他 规则(rule)、变量定义(variable)、指令(directive)

变量会在不同的时机被展开,这取决于具体的上下文。这个具体展开时机,会在后面详细讲,我们这里先知道有“递归展开”和“立即展开”两种方式。

总结

完结撒花!!

http://www.xdnf.cn/news/185419.html

相关文章:

  • 基于STM32、HAL库的ADS1115模数转换器ADC驱动程序设计
  • 驱动开发硬核特训 · Day 22(上篇): 电源管理体系完整梳理:I2C、Regulator、PMIC与Power-Domain框架
  • ByeCode,AI无代码开发平台,拖拽式操作构建应用
  • OpenFeign 自定义拦截器
  • 基于javaweb的SpringBoot在线电子书小说阅读系统设计与实现(源码+文档+部署讲解)
  • Java详解LeetCode 热题 100(02):LeetCode 49. 字母异位词分组(Group Anagrams)详解
  • 一、接口测试01
  • 基于Python Flask的深度学习电影评论情感分析可视化系统(2.0升级版,附源码)
  • 简单的 shell 程序
  • 德州仪器(TI)—TDA4VM芯片详解—目录
  • 十七、系统可靠性分析与设计
  • Vue3 + OpenLayers 开发教程 (六)WebGL渲染优化
  • 【Nova UI】十二、打造组件库之按钮组件(上):迈向功能构建的关键一步
  • Linux系统类型及常用操作命令总结
  • Linux一个系统程序——进度条
  • QT中的事件及其属性
  • 大学之大:伦敦政治经济学院2025.4.27
  • onnexruntime u2net sharp 实现开源图片处理软件
  • vue 打包设置
  • DFPatternFunctor遍历计算图
  • 【博客系统】博客系统第一弹:博客系统项目配置、MyBatis-Plus 实现 Mapper 接口、处理项目公共模块:统一返回结果、统一异常处理
  • 关于华为高斯数据库出现Invalid or unsupported by client SCRAM mechanisms定位解决的过程
  • -信息革命-
  • OpenManus云端部署及经典案例应用
  • 心磁图技术突破传统局限!心血管疾病早筛迈入“三零“新时代
  • TV launcher官方下载-tv launcher汉化版-tv桌面启动器极简下载
  • c++17 对于临时对象作为右值的优化
  • MRI学习笔记-conjunction analysis
  • Linux——线程(2)线程互斥(锁)
  • 机器学习 | 基于回归模型的交通需求预测案例分析及代码示例