Makefile 中一些需要注意的知识点

1.Makefile中把那些没有任何依赖只有执行动作的目标称为 “伪目标”( phony targets)。

2. 在命令行之前使用“ -”,意思是忽略命令 “ rm”的执行错误(参考 5.4 命令的错误 一节)。
"@" 符号放到最前是去回显的意思(不打印命令)。

.PHONY : clean
clean :
@-rm edit $(objects)

3.注释:
Makefile 中“ #”字符后的内容被作为是注释内容(和 shell 脚本一样)处理。
如果此行的第一个非空字符为“ #”,那么此行为注释行。注释行的结尾如果存在反斜线( \),那么下一行也被作为注释行
一般在书写 Makefile时推荐将注释作为一个独立的行,而不要和 Makefile 的有效行放在一行中书写。
当在 Makefile 中需要使用字符“ #”时,可以使用反斜线加“ #”( \#)来实现(对特殊字符“ #”的转义),其表示将“ #”作为一字符而不是注释的开始标志。

4.需要注意的地方:
Makefile 中第一个规则之后的所有以[Tab]字符开始的的行, make 程序都会将其交给系统 shell 程序去解释执行。
因此,以[Tab]字符开始的注释行也会被交给 shell 来处理,此命令行是否需要被执行( shell 执行或者忽略)是由系统 shell 程序来判决的。
另外,在使用指示符“ define”定义一个多行的变量或者命令包时,其定义体(“ define”和“ endef”之间的内容)会被完整的展开到 Makefile 中引用此变量的地方
(包含定义体中的注释行); make 在引用此变量的地方对所有的定义体进行处理,决定是注释还是有效内容。 Makefile 中变量的引用和 C 语言中的宏类似
(但是其实质并不相同,后续将会详细讨论)。对一个变量引用的地方 make 所做的就是将这个变量根据定义进行基于文本的展开,展开变量的过程不涉及到任何变量的具体含义和功能分
析。

5.关于include的使用:
指示符“ include”和文件名之间、多个文件之间使用空格或者[Tab]键隔开。行尾的空白字符在处理时被忽略。使用指示符包含进来的Makefile中,如果存在变量或者函数的引用。
它们将会在包含它们的Makefile中被展开(详细可参考第六章 Makefile中的变量)。
来看一个例子,存在三个.mk 文件 a.mk、 b.mk、 c.mk,“ $(bar)”被扩展为“ bish bash”。则

include foo *.mk $(bar)
等价于
include foo a.mk b.mk c.mk bish bash

使用“ include FILENAMES...”, make 程序处理时,如果“ FILENAMES”列表中的任何一个文件不能正常读取而且不存在一个创建此文件的规则时 make 程序将会提示错误并退出。
使用“ -include FILENAMES...”的情况是,当所包含的文件不存在或者不存在一个规则去创建它, make 程序会继续执行,只有真正由于不能正确完成终极目标的重建
时(某些必需的目标无法在当前已读取的 makefile 文件内容中找到正确的重建规则),才会提示致命错误并退出。

 

6.VARIABLES
GNU make支持一个特殊的变量,此变量不能通过任何途经给它赋值。它被展开为
一个特定的值。一个重要的特殊的变量是“ .VARIABLES”。它被展开以后是此引用点
之前、 makefile文件中所定义的所有全局变量列表。
包括:空变量(未赋值的变量)和
make的内嵌变量(参考10.3 隐含变量 一节),但不包含目标指定的变量,目标指定变
量值在特定目标的上下文有效。关于目标变量可参考 6.10 目标指定变量 一节

7.3.7 makefile文件的重建
Makefile 可由其它文件生成,例如 RCS 或 SCCS 文件。如果 Makefile 由其它文
件重建,那么在 make 在开始解析这个 Makefile 时需要重新读取更新后的 Makefile、
而不是之前的 Makefile。 make 的处理过程是这样的:
make 在读入所有 makefile 文件之后,首先将所读取的每个 makefile 作为一个目
标,寻找更新它们的规则。如果存在一个更新某一个 makefile 文件明确规则或者隐含
规则,就去更新对应的 makefile 文件。完成对所有的 makefile 文件的更新之后,如果
之前所读取任何一个 makefile 文件被更新,那么 make 就清除本次执行的状态重新读
取一遍所有的 makefile 文件(此过程中,同样在读取完成以后也会去试图更新所有的
已经读取的 makefile 文件,但是一般这些文件不会再次被重建,因为它们在时间戳上
已经是最新的)。读取完成以后再开始解析已经读取的 makefile 文件并开始执行必要
的动作。
实际应用中,我们会明确给出makefile文件,而并不需要来由make自动重建它们。
但是make在每一次执行时总会自动地试图重建那些已经存在的makefile文件,如果需
要处于效率考虑,可以采用一些办法来避免make在执行过程时查找重建makefile的隐
含规则。例如我们可以书写一个明确的规则,以makefile文件作为目标,规则的命令定
义为空。(参考 5.8 空命令 一节)
Makefile规则中,如果使用一个没有依赖只有命令行的双冒号规则去更新一个文
件,那么每次执行make时,此规则的目标文件将会被无条件的更新(此规则定义的命
令会被无条件执行)。如果这样一个规则的目标是makefile文件,那么执行make时,
这个makefile文件(双冒号规则的目标)就会被无条件更新,而使得make的执行陷入
到一个死循环(此makefile文件被不断的更新、重新读取、更新再重新读取的过程)。
为了防止这种情况的发生, make在遇到一个目标是makefile文件的双冒号规则时,将
忽略对这个规则的执行(其中包括了使用“ MAKEFILES”指定、命令行选项指定、指
示符“ include”指定的需要make读取的所有makefile文件中定义的这一类双冒号规则)

 

6.1 变量的引用
变量的引用方式是:“ $( VARIABLE_NAME)”或者“ ${ VARIABLE_NAME }”来引用一个
变量的定义。例如:“ $(foo) ”或者“ ${foo}”就是取变量“ foo”的值。美元符号“ $”
在 Makefile 中有特殊的含义,所有在命令或者文件名中使用“ $”时需要用两个美元符
号“ $$”来表示。

注意: Makefile 中在对一些简单变量的引用,我们也可以不使用“()”和“ {}”来
标记变量名,而直接使用“ $x”的格式来实现,此种用法仅限于变量名为单字符的情
况。
另外自动化变量也使用这种格式。对于一般多字符变量的引用必须使用括号了标记,
否则 make 将把变量名的首字母作为作为变量而不是整个字符串(“ $PATH”在 Makefile
中实际上是“ $(P)ATH”)。这一点和 shell 中变量的引用方式不同。 shell 中变量的引
用可以是“ ${xx}”或者“ $xx”格式。但在 Makefile 中多字符变量名的引用只能是“ $(xx)”
或者“ ${xx}”格式

一般在我们书写 Makefile 时,各部分变量引用的格式我们建议如下:
1. make 变量( Makefile 中定义的或者是 make 的环境变量)的引用使用“ $(VAR)”格式,无论“ VAR”是单字符变量名还是多字符变量名。
2. 出现在规则命令行中 shell 变量(一般为执行命令过程中的临时变量,它不属于Makefile 变量,而是一个 shell 变量)引用使用 shell 的“ $tmp”格式。
3. 对出现在命令行中的 make 变量我们同样使用“ $(CMDVAR)” 格式来引用。
例如:

# sample Makefile
……
SUBDIRS := src foo
.PHONY : subdir

#注意下方的$$dir,是出现在规则命令行中 shell 变量(一般为执行命令过程中的临时变量,它不属于#Makefile 变量,而是一个 shell 变量)引用使用 shell 的“ $tmp”格式。
Subdir :
    @for dir in $(SUBDIRS); do \
    $(MAKE) –C $$dir || exit 1; \
    done
……


-------------------20210114-----------------------------------------------------------------------------------------------------------------

Make -e
--environment-overrides
使用系统环境变量的定义覆盖Makefile中的同名变量定义(参考 6.9 系统环境
变量 一节)
 

  1. 在 Makefile 中对一个变量的定义或者以 make 命令行形式对一个变量的定义,
    都将覆盖同名的环境变量
    (注意:它并不改变系统环境变量定义,被修改的环
    境变量只在 make 执行过程有效)。而 make 使用“ -e”参数时, Makefile 和命
    令行定义的变量不会覆盖同名的环境变量, make 将使用系统环境变量中这些变
    量的定义值。

我们来看一个例子,结束本节。假如我们的机器名为“ server-cc”;我们的 Makefile
内容如下:

# test makefile
HOSTNAME = server-http  ##这里覆盖了我们的环境变量HOSTNAME 
…………
…………
.PHONY : debug
debug :
@echo “hostname is : $( HOSTNAME)”
@echo “shell is $(SHELL)”

1. 执行“ make debug”将显示:
hostname is : server-http
shell is /bin/sh
2. 执行“ make –e debug”;(-e表示在Makefile中不覆盖系统环境变量,使用系统默认的)将显示:
hostname is : server-cc
shell is /bin/sh
3. 执行“ make –e HOSTNAEM=server-ftp”(这里使用命令行指定了环境变量HOSTNAME将覆盖同名的环境变量 ???和-e不矛盾??);将显示:
hostname is : server-ftp
shell is /bin/sh

-------------------20210415-----------------------------------------------------------------------------------------------------------------

在 Linux( unix)中,以波浪线“ ~”开始的文件名有特殊含义。单独使用它或者其后跟一个斜线( ~/),代表了当前用户的宿主目录(在 shell 下可以通过
命令“ echo ~(~\)”来查看,(echo ~/ 就能打印出当前用户的宿主目录))。例如“ ~/bin”代表“ /home/username/bin/”(当前用户宿主目录下的 bin 目录)。
波浪线之后跟一个单词( ~word),代表由这个“ word”所指定的用户的宿主目录。例如“ ~john/bin”就是代表用户 john 的宿主目录下的 bin 目录。
在一些系统中(像 MS-DOS 和 MS-Windows),用户没有各自的宿主目录,此情况下可通过设置环境变量“ HOME”来模拟

 

参考:《Makefile编程.pdf》

 


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值