这一篇继续Makefile入门。上一篇讲了Makefile的核心描述块,以及宏的使用。Makefile为了方便构建项目提供了许多预定义的特殊宏。通过对他们的操作会让build过程更简单。
特殊的宏,变量
预定义的特殊宏有四类,通过这些特殊的宏,让makefile拥有了和外部交互的能力。
文件名
当在依赖中出现文件名时文件名宏将被makefile生成。
| 当前的target的全名 |
| 当前target,只能放在依赖中 |
| 去掉后缀名 |
| 显示所有的依赖 |
| 将显示所有时间戳晚于target的依赖项 |
| 显示一个当前目标时间戳晚的依赖。只有在推断中有效.(推断 inference rule之后会提到) |
$@和$$@可以方便的根据target的名称动态选择依赖项,不同之处在于$$@只能放在依赖中看这个例子,输出的就会先输出test再输出file.exe。
# makefile 内容
file.exe: o$$@ test.obj
echo $@
echo $*
echo $**
echo $?
ofile.exe:
echo test
test.obj:
echo do nothing
# 输出
test
do nothing
file.exe
file
ofile.exe test.obj
ofile.exe test.obj
以上所列出来的关于文件名的宏也能搭配一些后缀修饰符出现,可以组合出不同的效果
| 驱动器加上目录 |
| 没有后缀的文件名 |
| 文件名加上后缀 |
| 驱动其加上文件名,不加后缀 |
为了便于理解可以看下面的例子
# makefile 内容
C:\file.exe:
echo $@
echo $(@D)
echo $(@B)
echo $(@F)
echo $(@R)
# 输出
C:\file.exe
C:\
file
file.exe
C:\file
递归
这里的递归是指在makefile里面又去调用make命令来执行另一个makefile。和include不一样,该命令相当于重新启动了一个make。和创建子进程一样,他会继承当前的环境变量,同时也有命令行宏,也有定义在tools.ini里面定义的宏。
这里简单介绍一下tools.ini,该文件将会在make执行makefile之前先去执行tools.ini里面设置的定义的宏和配置。利用该文件就可以修改一次tools.ini文件,然后是的每次执行makefile都能拥有一样用户定义的配置了。
| 这个宏就是make命令的全路径。在命令块中使用$(make) 就等于调用了一个make |
| 当前makefile所在的目录 |
| 显示当前生效的选项。 |
编译命令
编译相关命令是最重要的命令,因为makefile主要就是编译项目。而通过重定义这些宏可以增加编译选项或者是编译器。下面是nmake里面所使用的宏:
Macro Assembler |
|
|
|
C Compiler |
|
|
|
C++ Compiler |
|
|
|
C++ Compiler |
|
|
|
Resource Compiler |
|
|
|
环境变量
被预定义的环境变量最好理解,也就是当前make程序中所有的环境变量的内容都可以作为预定义宏来使用。需要注意的是,这些宏都是可以被修改的。而且让make进程的环境变量随着改变。但是如果使用SET命令来修改进程的环境变量,则环境变量的宏不会随着改变。下面用JAVA_HOME来举例
# makefile内容
all:
echo $(JAVA_HOME)
# 输出
C:\jdk-11