《跟我一起写Makefile》读书笔记(3)

一个Makefile例子

《跟我一起写Makefile》读书笔记(3)


五、书写规则

一般来说,定义在 Makefile 中的目标可能会有很多,但是第一条规则中的目标将被确立为最终的目标。

1、规则的语法

《跟我一起写Makefile》读书笔记(3)

(1)如果命令太长,你可以使用反斜框(‘\’)作为换行符。make 对一行上有多少个字符没有限制。

(2)一般来说,make 会以 UNIX 的标准 Shell,也就是/bin/sh 来执行命令。


2、在规则中使用通配符

(1)make支持三各通配符: “*”,“?”,“[...]”;

(2)objects = *.o ,这里objects的值就是“*.o” ,并不会展开。

如果想让 objects 的值是所有[.o]的文件名的集合,那么需要写成objects := $(wildcard *.o) 。


3、文件搜索

(1)在哪里寻找依赖的文件?

(2)Makefile 文件中的特殊变量“VPATH”就是完成这个功能的。

  • 如果没有指明这个变量,make 只会在当前的目录中去找寻依赖文件和目标文件。
  • 如果定义了这个变量,那么make就会在当当前目录找不到的情况下,到所指定的目录中去找寻文件。
  • VPATH = src:../headers, 指定两个目录,“src”和“../headers”,make 会按照这个顺序进行搜索。目录由“冒号”分隔。(当然,当前目录永远是最高优先搜索的地方)
(3)另一个设置文件搜索路径的方法是使用 make 的“vpath”关键字
  • vpath %.h ../headers,该语句表示,要求 make 在“../headers”目录下搜索所有以“.h”结尾的文件。(如果某文件在当前目录没有找到的话)

4、多目标

我们的可以使用一个自动化变量“[email protected]”,这个变量表示着目前规则中所有的目标的集合

如下面的例子:
《跟我一起写Makefile》读书笔记(3)

5、静态模式

(1)语法
<targets ...>: <target-pattern>: <prereq-patterns ...>
<commands>
....

目标集合:目标集合的模式:依赖集合的模式

(2)如果<target-parrtern>定义成“%.o”
  • 意思是我们的<target>集合中都是以“.o”结尾的;
(3)如果<prereq-parrterns>定义成“%.c” 
  • 意思是对<target-parrtern>所形成的目标集进行二次定义;
  • 即,取<target-parrtern>模式中的“%”(也就是去掉了[.o]这个结尾),并为其加上[.c]这个结尾,形成的新集合。
(4)例子示范

例子1
《跟我一起写Makefile》读书笔记(3)

例子2
《跟我一起写Makefile》读书笔记(3)

六、书写命令

1、显示命令

(1)通常,make把它要执行的命令行,在命令执行前输出到屏幕上。但如果我们用“@”字符在命令行前,那么这个命令将不被 make 显示出来,但命令还是被运行的。(这叫静默执行)

(2)如果 make 执行时,带入 make 参数“-n”或“--just-print”,那么其只是显示命令,但不会执行命令

  • 这个功能很有利于我们调试我们的 Makefile,看看我们书写的命令执行起来是什么样子的或是什么顺序的。
(3)输入make -s或make --slient时,则是全面禁止命令的显示(但是命令仍然被执行)。

2、命令错处处理

(1)每当命令运行完后,make 会检测每个命令的返回码,如果命令返回成功,那么 make 会执行下一条命令。
  • 如果一个规则中的某个命令出错了(命令退出码非零),那么 make 就会终止执行当前规则,这将有可能终止所有规则的执行。
(2)可以在 Makefile 的命令行前加一个减号“-”(在 Tab 键之后),标记为不管命令出不出错都认为是成功的。

如:

clean:

-rm -f *.o

(3)给 make 加上“-i”或是“ --ignore-errors”参数,那么,Makefile 中所有命令都会忽略错误 。

(4)make 的参数的是“-k”或是“--keep-going”,这个参数的意思是,如果某规则中的命令出错了,那么就终止该规则的执行,但继续执行其它规则。


3、嵌套执行make

(1)总控 Makefile 的变量可以传递到下级的 Makefile 中(如果你显示的声明),但是不会覆盖下层的 Makefile 中所定义的变量,除非指定了“-e”参数

(2)一些细节

  • 如果你要传递变量到下级 Makefile 中,那么你可以使用这样的声明:export <variable ...>;
  • 如果你不想让某些变量传递到下级 Makefile 中,那么你可以这样声明:unexport <variable ...> ;
  • 如果你要传递所有的变量,那么,只要一个 export 就行了,后面什么也不用跟,表示传递所有的变量;
  • 有两个变量,一个是 SHELL,一个是 MAKEFLAGS,这两个变量不管你是否 export,其总是要传递到下层 Makefile 中,特别是 MAKEFILES 变量,其中包含了 make的参数信息,如果我们执行“总控 Makefile”时有 make 参数或是在上层 Makefile 中定义了这个变量,那么 MAKEFILES 变量将会是这些参数,并会传递到下层 Makefile 中,这是一个系统级的环境变量。


4、定义命令包

《跟我一起写Makefile》读书笔记(3)

七、使用变量

  • 变量是大小写敏感的, “foo”、 “Foo”和“FOO”是三个不同的变量名;
  • 变量的命名字可以包含字符、数字,下划线(可以是数字开头);
  • 在 Makefile 中的定义的变量,就像是 C/C++语言中的宏一样,他代表了一个文本字串,在 Makefile 中执行的时候其会自动原模原样地展开在所使用的地方。其与 C/C++所不同的是(字符串常量不能修改?),你可以在 Makefile 中改变其值。

1、变量的基础

类似shell中变量的定义和使用方法,需要用$来使用,强烈建议使用()或者{ }将变量包起来使用。

《跟我一起写Makefile》读书笔记(3)


2、变量中的变量

在 Makefile 中有两种方式来在用变量定义变量的值

(1)简单的使用“=”号

  • 在“=”左侧是变量,右侧是变量的值;
  • 右侧变量的值可以定义在文件的任何一处,也就是说,右侧中的变量不一定非要是已定义好的值,也可以使用后面定义的值。
《跟我一起写Makefile》读书笔记(3)


(2)使用“:=”操作符
  • 前面的变量不能使用后面的变量,只能使用前面已定义好了的变量。
《跟我一起写Makefile》读书笔记(3)

(3)使用“?=”操作符
  • 如果前面已经定义,则本句什么也不做,跳过

(4)使用“+=”操作符
  • 接续赋值