Makefiles中包含5种内容,分别是显式规则、隐含规则、变量定义、指令以及注释。

Makefiles中包含什么

Makefiles中包含5种内容,分别是显式规则、隐含规则、变量定义、指令以及注释。

显式规则明确了何时以及如何生成target,它会列出target的所有prerequisitesrecipes

隐含规则说明了如何根据与target名称相应的依赖文件来生成target

变量定义是指为变量指定文本字符串值得行,可以在其他地方将变量替换到文本中。

指令是make在读取Makefile时执行的某些特殊操作的指令。包括引用其他Makefile、决定是否根据变量值使用还是忽略相关部分(ifdef)等

Makefile#开头的行是注释。如果需要字符#,需要进行转义\#recipes中的注释会被传递给shell

Makefile名称

make默认查找文件名顺序为GNUmakefilemakefile以及Makefile

通常建议使用Makefile,因为首字母大写名称更加明显。如果想要使用其他名称,可以手动指定名称-f name--file=name告诉make。当通过-f--file指定文件之后,GNUmakefilemakefile以及Makefile则不会检查读取。

引用其他Makefiles

make遇到include指令会停止读取当前的makefile,先将include包含的makefile读入。

include filenames...

filenamesshell的文件名通配符。如果为空,不会被读入也不报错。

使用include指令的一种情况是,不同目录下的多个程序的makefile使用一组通用的变量定义。

如果指定的filenames没有找到,则会搜索-I--include-dir指定的目录,要是还没有找到就会搜索/usr/local/include

如果filenames指定的文件没有找到会产生一条警告,然后继续执行。

Makefiles变量

如果环境变量Makefiles变量被定义,那么make会优先读取Makefiles变量定义的文件。这个和include指令是相同的功能。但是默认target不会从这些文件中指定。当然,如果没有找到文件也不会保存。

Makefiles变量的调用通常是支持make的递归调用。

make如何读入Makefile

make读入Makefile分为两个阶段,分别如下:

第一阶段:

  1. 读入所有Makefiles
  2. 读入include指令引用的Makefile
  3. 初始化变量。
  4. 推导隐含规则。
  5. 为所有target构建依赖关系图。

第二阶段:

  1. make根据依赖关系决定哪些target需要更新。
  2. 执行recipe生成相应target

变量的扩展阶段如下

immediate = deferred
immediate ?= deferred
immediate := immediate
immediate ::= immediate
immediate += deferred or immediate
immediate != immediate

define immediate
  deferred
endef

define immediate =
  deferred
endef

define immediate ?=
  deferred
endef

define immediate :=
  immediate
endef

define immediate ::=
  immediate
endef

define immediate +=
  deferred or immediate
endef

define immediate !=
  immediate
endef

如果变量被使用,则根据上述方式决定是立即扩展还是延迟扩展。

如何解析Makefiles

  1. 读取完整的逻辑行,包含\转义的行。
  2. 移除注释。
  3. 如果改行是以recipe前缀开头并处于规则上下文中,则将其添加到当前recipe中,并读取下一行。
  4. 展开immediate元素。
  5. 查找分隔符,比如:=,确定该行是赋值还是规则。
  6. 读取下一行。