重新发现 make: 规则背后的力量
创始人
2024-03-02 02:12:30
0

我过去认为 makefile 只是一种将一组组的 shell 命令列出来的简便方法;过了一段时间我了解到它们是有多么的强大、灵活以及功能齐全。这篇文章带你领略其中一些有关规则的特性。

备注:这些全是针对 GNU Makefile 的,如果你希望支持 BSD Makefile ,你会发现有些新的功能缺失。感谢 zge 指出这点。

规则

规则 rule 是指示 make 应该如何并且何时构建一个被称作为 目标 target 的文件的指令。目标可以依赖于其它被称作为 前提 prerequisite 的文件。

你会指示 make 如何按 步骤 recipe 构建目标,那就是一套按照出现顺序一次执行一个的 shell 命令。语法像这样:

target_name : prerequisites
    recipe

一但你定义好了规则,你就可以通过从命令行执行以下命令构建目标:

$ make target_name

目标一经构建,除非前提改变,否则 make 会足够聪明地不再去运行该步骤。

关于前提的更多信息

前提表明了两件事情:

  • 当目标应当被构建时:如果其中一个前提比目标更新,make 假定目的应当被构建。
  • 执行的顺序:鉴于前提可以反过来在 makefile 中由另一套规则所构建,它们同样暗示了一个执行规则的顺序。

如果你想要定义一个顺序但是你不想在前提改变的时候重新构建目标,你可以使用一种特别的叫做“ 唯顺序 order only ”的前提。这种前提可以被放在普通的前提之后,用管道符(|)进行分隔。

样式

为了便利,make 接受目标和前提的样式。通过包含 % 符号可以定义一种样式。这个符号是一个可以匹配任何长度的文字符号或者空隔的通配符。以下有一些示例:

  • %:匹配任何文件
  • %.md:匹配所有 .md 结尾的文件
  • prefix%.go:匹配所有以 prefix 开头以 .go 结尾的文件

特殊目标

有一系列目标名字,它们对于 make 来说有特殊的意义,被称作 特殊目标 special target 。

你可以在这个文档发现全套特殊目标。作为一种经验法则,特殊目标以点开始后面跟着大写字母。

以下是几个有用的特殊目标:

  • .PHONY:向 make 表明此目标的前提可以被当成伪目标。这意味着 make 将总是运行,无论有那个名字的文件是否存在或者上次被修改的时间是什么。
  • .DEFAULT:被用于任何没有指定规则的目标。
  • .IGNORE:如果你指定 .IGNORE 为前提,make 将忽略执行步骤中的错误。

替代

当你需要以你指定的改动方式改变一个变量的值, 替代 substitution 就十分有用了。

替代的格式是 $(var:a=b),它的意思是获取变量 var 的值,用值里面的 b 替代词末尾的每个 a 以代替最终的字符串。例如:

foo := a.o
bar : = $(foo:.o=.c) # sets bar to a.c

注意:特别感谢 Luis Lavena 让我们知道替代的存在。

档案文件

档案文件是用来一起将多个数据文档(类似于压缩文件的概念)收集成一个文件。它们由 ar Unix 工具所构建。ar 可以用于为任何目的创建档案,但除了静态库,它已经被 tar 大量替代。

make 中,你可以使用一个档案文件中的单独一个成员作为目标或者前提,就像这样:

archive(member) : prerequisite 
    recipe

最后的想法

关于 make 还有更多可探索的,但是至少这是一个起点,我强烈鼓励你去查看文档,创建一个笨拙的 makefile 然后就可以探索它了。


via: https://monades.roperzh.com/rediscovering-make-power-behind-rules/

作者:Roberto Dip 译者:tomjlw 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

相关内容

【CMake入门教程】CM...
CMake教程专栏文章列表 【实例篇】01.第一个程序【实例篇】0...
2025-06-01 10:01:50
vs项目转cmake
解决方案一: 可以尝试开源项目proj2cmake ...
2025-06-01 08:29:28
uboot学习之Makef...
uboot-1.1.6源码分析 分析配置过程: (1)安装交叉编译...
2025-05-31 23:16:03
【UNIX 环境编程】GC...
💭 写在前面:本文将介绍如何使用 G...
2025-05-31 02:18:08
QT桌面客户端在Linux...
QT桌面客户端在Linux下的开发流程可以概括为以下几个主要步骤。...
2025-05-30 11:41:09
不知道如何在Makefil...
在Makefile中包含/编译依赖项的方法如下所示:使用inclu...
2025-01-12 07:30:52

热门资讯

Helix:高级 Linux ... 说到 基于终端的文本编辑器,通常 Vim、Emacs 和 Nano 受到了关注。这并不意味着没有其他...
《Apex 英雄》正式可在 S... 《Apex 英雄》现已通过 Steam Deck 验证,这使其成为支持 Linux 的顶级多人游戏之...
使用 KRAWL 扫描 Kub... 用 KRAWL 脚本来识别 Kubernetes Pod 和容器中的错误。当你使用 Kubernet...
JStock:Linux 上不... 如果你在股票市场做投资,那么你可能非常清楚投资组合管理计划有多重要。管理投资组合的目标是依据你能承受...
Epic 游戏商店现在可在 S... 现在可以在 Steam Deck 上运行 Epic 游戏商店了,几乎无懈可击! 但是,它是非官方的。...
从 Yum 更新中排除特定/某... 作为系统更新的一部分,你也许需要在基于 Red Hat 系统中由于应用依赖排除一些软件包。如果是,如...
通过 SaltStack 管理... 我在搜索Puppet的替代品时,偶然间碰到了Salt。我喜欢puppet,但是我又爱上Salt了:)...
如何在 Github 上创建一... 学习如何复刻一个仓库,进行更改,并要求维护人员审查并合并它。你知道如何使用 git 了,你有一个 G...
Opera 浏览器内置的 VP... 昨天我们报道过 Opera 浏览器内置了 VPN 服务,用户打开它可以防止他们的在线活动被窥视。不过...
如何检查你的 Linux 系统... 不知道在使用哪个初始化系统?以下是方法。每个主流 Linux 发行版(包括 Ubuntu、Fedor...