Makefile 的高级特性 除了前面介绍的规则和注释外 ,Makefile 还支持隐式规 则、变量定义、文件包含等 高级 特性。这里将前面 Makefile 示例修改 如下,然后再结合这些内容介绍一些高级特性。 # 第1 部分 objects = main.o input.o output.o command.o files.o utils.o # 第2 部分 textedit : $(objects) cc -o edit $(objects) # 第3 部分 main.o : defs.h input.o : defs.h command.h command.o : defs.h command.h output.o : defs.h buffer.h insert.o : defs.h buffer.h tools.o : defs.h # 第4 部分 .PHONY : clean clean : rm edit $(objects) (1 )隐式规 则。 前面介绍的规则属于显式规则,需要明确定义,指明要生成的文件、文件的依赖文 件 和 生成的 命令。make 功能很强大,可以自动推导文件以及文件依赖关系后面的命令,这就是 Make?le 的隐 式规则(又称隐含规则或隐晦规则) 。 本例中第 3 部分利用隐式规则简化文件依赖关系的描述。make 每发现一 个.o 文件, 它就 会 自动地把 相应的 .c 文件添加在依 赖关系中。 例如 make 找到 main.o ,就会将 main.c 作 为 main.o 的 依赖文件,并且后续命令 cc -c main.c 也会被自 动推导出来。 make 支持的 隐式规则非常多,可以通过 -p 选项 来查看它所支持的全部隐式规则。 (2 )变量定 义。 在 Make?le 中可以定义 一系列变量 ,变量一般 都是文本字 符串,有点 儿类似于 C/C++ 语言中的宏, 当 Make?le 被解析时, 其中的变量都会自动被扩展到相应的引用位置上。 变量 可以用在目标、条件、命令等要素中,以及 Make?le 的其他 部分。 变量的名字可以包含字符、 数字, 下画线 (可以是数字开头) , 但不应 该含有 “:” “#” “=”或空字符(空格、回车等) 。变 量名区分大小写。 变量在声明时需要赋初值,而在引用时需要在变量名前加上“$” ,而且最好使用圆括 号 “( )” 或花 括号 “{}” 将变量给标注起来。 如果变量名中要使用 “$ ” 字 符, 那么需要用 “$$” 来进行转义。 本例第 1 部 分声明变量 objects : objects = main.o input.o output.o command.o ?les.o utils.o 第 2 部分引 用变量 : textedit : $(objects) cc -o edit $(objects) 变量会在使用它的地方精确地展开,就像 C/C++ 中的宏一 样,展开后如下 : textedit : main.o input.o output.o command.o ?les.o tools.o cc -o textedit main.o input.o output.o command.o ?les.o utils.o 变量用 “= ” 赋值时, 表示变量被引用时才展开。 如果改用 “:= ” 赋值, 表示变量在赋值 的时候就立刻展开。 Make?le 还提供一种特殊的自动变量,不用声明,其值根据上下文的不同自动改变 。 如 $@ 代表规则中的目标文件名,$< 代 表规则的第一个依赖文件名(条件定义) 。 (3 )伪目标 。 Ubuntu Linux 操作系统实战(微课版) 上例提到过一个名为“clean ”的目标,这是一个伪目标。伪目标并不是一个文 件,只是 一个标签, 因而 make 无法生成它 的依赖关系 和决定它是 否要执行。 只有通过指 明这个 目 标 才能让其生效。当然,伪目标不能和文件名重名。 为了避免与文件重名的这种情况出现, 可以使用一个特殊的标记 “.PHONY” 来显式地指 明一个目标是伪目标, 向 make 说明 , 不管是否有这个文件, 这个目标就是伪目标。 本例第 4 部分就是这样一个例子。 (4 )使用通 配符。 make 支持通 配符 “”、“ ?”和“[...] ” , 用于代替一系列的文件。 如 “.c ” 表示所有扩展 名为 .c 的文 件。下面的例子表明执行 clean 命 令将删除所有的目标文件。 clean: rm -f .o 如果文件名中包含有通配符, 如 “ ” , 则可以用 “/”转 义 ,如 用“/”来 表 示“”这 个 字符。 (5 )文件包 含。 在一个 Make?le 文件中可以引用另一个 Make?le 文件,就像 C 语 言中的 include 一 样。被包含的文件会放在当前文件的包含位置。具体的语法格式是 : include < 文件名 > 可以引用任意多个文件,多个文件用空格分隔,也可使用通配符和变量来表示被引 用 的 文件名。 如 果文件名没有指定绝对路径或是相对路径,make 会首先在 当前目录下寻找。 如果 当前目录下没有找到,make 还会在 make 选项 -I 或 --include-dir 指定的 目录下去寻找。 2 |
|