GNU make:规则专题

Posted rosefinch

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GNU make:规则专题相关的知识,希望对你有一定的参考价值。

一、Makefile规则简介

我们来进一步地讨论Makefile脚本中的规则。在GNU make的官方文档中,对规则的定义如下:

规则描述了在何种情况下使用什么命令来重建一个特定的文件,此文件被称为规则的“目标”。规则中除目标之外的罗列的其他文件称为目标的“依赖,而规则的命令是用来更新或者创建此规则的目标。

如前所述,规则由目标依赖命令组成。

二、最终目标

最终目标就是当没有使用make命令行指定具体目标时,make默认更新的那一个目标。它一般是Makefile文件中的第一个目标;如果在makefile中第一个规则有多个目标的话,那么多个目标中的第一个将会被作为make的“最终目标”)。然而,有两种情况的例外:

  • 目标名以点号“.”开始的并且其后不存在斜线“/”(“./”是当前目录;“../”是上一级目录);
  • 模式规则的目标。

当这两种目标所在的规则是Makefile的第一个规则时,它们并不会被作为最终目标。

【注意】

除了makefile的“最终目标”所在的规则以外,其它规则的顺序在makefile文件中没有意义。因为,最终目标是执行make的唯一目的,其所在的规则作为第一个被执行的规则。而其它的规则是在完成重建“最终目标”的过程中被连带出来的。所以这些目标所在规则在Makefile中的顺序无关紧要。

因此,我们书写的makefile的第一个规则应该就是重建整个程序或者多个程序的依赖关系和执行命令的描述。

三、规则的语法详解

如前所述,规则中的目标可以是以空格分开的多个文件名,也可以是一个动作的标签。我的建议是:规则只定义一个目标文件,但是偶尔会在一个规则中需要多个目标。

在书写规则时,有以下几点需要注意:

  • 规则的命令部分有两种书写方式:

    • 命令可以和依赖放在同一行,命令在依赖文件列表后并使用分号";"和依赖文件列表分开。
    • 命令在依赖的下一行,作为单独的命令行出现。

    【注意】

    当作为独立的命令行时,命令必须要以【TAB】字符开始。在Makefile中,在第一个规则之后出现的所有以[Tab]字符开始的行都会被当作命令来处理。

  • Makefile中的字符"$"字符具有特殊的含义,为了转义这个字符,可以使用$$来代替。

  • 对于Makefile中一个较长的行,我们可以使用反斜线“”将其书写到几个独立的物理行上。虽然make对Makefile文本行的最大长度是没有限制的,但还是建议这样做。不仅书写方便而且更有利于别人的阅读。

四、Order-Only依赖

在GNU make官方文档中,对与Order-Only依赖的描述如下:

有时,需要定义一个这样的规则:在更新目标(目标文件已经存在)时只需要根据依赖文件中的部分来决定目标是否需要被重建,而不是在依赖文件的任何一个被修改后都重建目标。为了实现这一目的,相应的就需要对规则的依赖进行分类,一类是在这些依赖文件被更新后,需要更新目标的依赖;另一类是这些依赖文件更新后,不需要更新目标的依赖。而这个第二类依赖就被称为:“order-only”依赖

综上所述,Order-Only依赖的主要特点是: 只有在目标文件不存在的情况下,才会参与规则的执行。当目标文件存在时此依赖不会参与规则的执行过程

Order-Only依赖的书写规则如下:

Targets: Normal-Pre | Order-Only-Pre

【注意】

规则依赖文件中如果一个文件同时出现在常规列表和“order-only”列表中,那么此文件被作为常规依赖处理。

【示例】 使用Order-Only依赖

foo.elf: foo.c | libtest.a
    gcc -o foo.elf foo.c

这里,libtest.a是一个Order-Only依赖,当且仅当foo.elf目标文件不存在时,这个依赖才会起作用。

五、文件名使用通配符

在Makefile中表示文件名时,可以使用本地Shell所支持的通配符:

  • "*":表示零个或多个字符。
  • "?":表示单个字符。
  • "[...]":表示重复的字符范围。

然而,通配符不是哪里都可以使用。在Makefile中,只有以下位置可以使用通配符:

  • 规则的目标和依赖中。make在读取Makefile时会自动对其进行展开处理
  • 规则的命令中。在命令中的通配符将交由Shell来处理。

如果在以上位置的文本中需要通配符文本,则要进行转义。

【示例】在命令中使用通配符

clean:
    rm -rf *.o *.elf

【示例】在依赖中使用通配符

main.o: *.c
    gcc -o HelloMakefile.elf *.c

以上是关于GNU make:规则专题的主要内容,如果未能解决你的问题,请参考以下文章

GNU make规则的命令④书写命令

GNU make 可以在发生错误时执行规则吗?

GNU Make - 终端规则和关键字“null”

GNU Make 无法检测到明显的规则

《GNU_makefile》第五章——为规则书写命令

《GNU_makefile》第五章——为规则书写命令