×××××××××××××××××××××××××××××××××××××
××× 呕心整理,转载请注明出处 GuoSenZQ ×××
×××××××××××××××××××××××××××××××××××××
一. 命令
- 规则的命令
(1). 规则的命令是由shell命令组成,每一行必须以【Tab】字符开始(与目标在同一行的除外)
(2). 规则的多行命令,每一行命令将在一个独立的子shell进程中被执行,而在同一行中的多个命令是一个独立的shell命令,对于多行命令可以使用“\”来连接成一个;
(3). 命令包,使用"define"、“endef"来定义一组命令,在需要的地方通过它的名字进行引用即可,即$(name)。在定义命令包时可以使用前缀字符,如”@,-,+“等来单独控制一个命令;当命令包被引用时,命令报中的命令体会被原封不动的展开在引用它的地方,这些命令就成为了规则的命令,而且如果在引用命令包时使用了前缀字符,该前缀字符会被传递给命令包中的每一个命令;
(4). 空命令规则,格式:“target:;”,只有目标,可以存在依赖,但没有命令;目的是定一个什么也不做的规则,可以用来避免make执行时试图为重建这个目标而去查找隐含规则,它与伪目标在实际使用中是有差别的,另外最好不要给空命令规则指定依赖文件;
(5). 以“@”字符开始的命令,表示make在执行这个命令时不会回显;
(6). 以“-”字符开头的命令,告诉make忽略命令的执行失败继续往下执行,但仍会提示错误信息;
(7). 以”+"字符开头的命令,与“-”相反,表示不忽略。此外make的命令行选项如“-n”,“-t”将不会影响命令行前有“+”的命令的执行,如即使使用了“-n”选项,该选项的本意是解析命令而并不执行他们,但是Makefile中以“+”开头的规则的命令仍然会被正常执行(其效果与命令行中使用了变量“MAKE”效果相同);
二. make的执行
-
make 命令行参数
. -C 在读取Makefile之前,先进入目录,再执行make;
. -d 或 --debug[=OPTION] 在make执行过程中打印出所有的调试信息
. -e 或 --environment-overrides 使用系统环境变量覆盖Makefile中定义的同名环境变量
. -i 或 --ignore-errors,告诉make忽略所有规则中命令执行的错误,但仍会提示错误信息;
. -I 或–include-dir 指定被包含Makefile文件的搜索目录
. -j make的并发执行,告诉make同一时刻可以由多条命令被同时执行;
. -k 或 --keep-going,make出现错误时,不立即退出,继续后续命令的执行。该命令的主要用途是,在同时修改了工程中的多个文件后,用于帮助确认哪些文件的修改是正确的,哪些是错误的;
. -n 或 --just-print 只打印显示要执行的命令,并不真正执行;
. -o FILE 指定FILE不需要重建,即使相对于它的依赖已经过期,同时也不重建依赖于此文件的任何文件。该命令通常被用在防止特定文件的重建上,与"-t"配合使用,如修改了头文件,而这些修改不会对已经完成编译的程序产生影响,该参数只用来指定头文件,不能用来指定源文件;
i). 在Makefile中,若明确指定某个头文件作为某个目标文件的依赖,则该头文件更新后,再次进行make时该目标文件会被更新
. -p 或 --print-data-base 命令执行之前,打印make读取的Makefile的所有数据
. -q 或 --question 询问模式,不执行任何命令且不打印任何输出信息,只检查指定的目标是否已经是最新的,是返回0,否返回1;
. -r 或 --no-builtin-rules 取消所有的内嵌隐含规则;
. -R 或 --no-builtin-variables 取消make的内嵌隐含变量,该参数同时打开"-r"参数,没有了隐含变量,隐含规则无意义;
. -s 或 --slient 禁止所有执行命令的显示;
. -S 或 --no-keep-going 取消"-k"选项
. -t 或 --touch 对过时的目标文件不进行内容更新,只更新时间戳,由make更新数据库来完成,不需要shell来完成;
. -v 或 --version 查看make的版本信息
. -W FILE 需要指定一个文件名,通常是存在的源文件,make将当前系统时间作为这个文件的时间戳,但并不真正修改文件的时间戳;
其中:
i). -W 与 -n 配合,可用来查看修改了"-w"指定的文件后,会造成那些目标被更新;
ii). -W 与 -t 配合,只对依赖于"-W"指定的文件的目标执行"touch"命令;
. -w 或 --print-directory,可以让make在开始编译一个目录和完成此目录的编译之后给出相应的提示信息,通常在使用-C参数或是命令行中使用"cd"时,该选项会被自动打开,当然可以通过"-s"或者"–no-print-directory"来禁止该选项; -
make的执行
(1). make的终极目标,就是出现在Makefile中,除以".“开始的第一个规则中的第一个目标,make在执行时,设置了一个特殊变量"MAKECMDGOALS”,此变量记录了命令行参数指定的终极目标列表,没有通过参数指定终极目标时此变量为空,在Makefile中不要对它重新定义;
(2). 通常 make 执行失败的命令,可能改变了的目标不是一个被正确重建的文件,但文件的时间戳已经被更改因此下一次make时,它可能不会被重建,导致终极目标错误,建议在一次make失败后执行make clean,当然也可以让make自动完成这个动作,只需要在Makefile中顶一个特殊的目标“.DELETE_ON_ERROR” -
make的条件执行
(1). 根据一个变量的值来控制make执行或忽略Makefile的特定部分
(2). 格式:CONDITION-DIRECTIVE TEXT-IF-TRUE else TEXT-IF-FALSE endif
其中 CONDITION-DIRECTIVE 部分,包括关键字"ifeq"、“ifneq”、“ifdef”、“ifndef”;
(3). 对于 “ifdef” 它只是测试一个变量是否有值,若变量未定义(为空),或者定义时指定为空"VAR=",此时该判断返回false,若是变量通过引用一个定义为空的变量,该判断也将返回 true,因此若想判断变量是否为空,建议使用"ifeq";
(4). 条件表达式中不能使用自动化变量,自动化变量自由在规则的命令执行时才有效,而条件判断是在make读取Makefile时就需要确定; -
make的递归
(1). 在make的递归执行过程中,在规则的命令行中建议使用 “MAKE” 代替 “make”,因为在命令行中make的"选项参数"会被赋值给内嵌变量"MAKEFLAGS",且被传递给下一级的make程序中,能保证所有的make过程都是用命令行中make的参数;此外,make的参数 “-t,-n,-q"等参数是告诉make不执行任何规则的命令,但是对包含"MAKE"变量的命令行除外(即$(MAKE)),意思就是即使make的一些特殊功能的参数控制规则的命令行的执行,但是若命令行中包含"MAKE"变量,则该命令不会受参数控制的影响,仍然能够正常执行,如此便确保了子make过程也能按照预期执行。同理的还有命令行中包含”+“前缀的命令【有几个特殊的命令行选项例外,它们不会被赋值给"MAKEFLAGS”,分别是"-C,-f,-o,-W"】。而如果不希望传递"MAKEFLAGS"给子make时,需要在调用子make时将这个变量赋值为空;
(2). 默认情况下只有系统环境变量和通过命令行方式定义的变量才会被传递给子make进程,在Makefile中定义的普通变量需要传递给子make时,使用"export"指示符来完成,相反可以通过unexport来禁止一个变量的向下传递【老版本make中:不带参数的"export"表示将当前Makefile中定义的所有变量都传递给子make,新版本中使用特殊目标".EXPORT_ALL_VARIABLES"】。但由于变量的优先级如下:
命令行变量【MAKEFLAGS中的变量】 > Makefile定义的变量 > 系统环境变量
所以上层make通过export传递给子make的变量(即系统环境变量)不会覆盖子make的Makefile中定义的变量,除非命令行中使用"-e"参数,但在命令行中定义的参数则可以覆盖子make的Makefile中的同名变量,且"export"和"unexport"不能用来对命令行中定义的变量的控制;