这一篇继续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

以上所列出来的关于文件名的宏也能搭配一些后缀修饰符出现,可以组合出不同的效果

D

驱动器加上目录

B

没有后缀的文件名

F

文件名加上后缀

R

驱动其加上文件名,不加后缀

为了便于理解可以看下面的例子

# 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) 就等于调用了一个make

MAKEDIR

当前makefile所在的目录

MAKEFLAGS

显示当前生效的选项。

编译命令

编译相关命令是最重要的命令,因为makefile主要就是编译项目。而通过重定义这些宏可以增加编译选项或者是编译器。下面是nmake里面所使用的宏:

Macro Assembler

AS

ml or ml64

AFLAGS

C Compiler

CC

cl

CFLAGS

C++ Compiler

CPP

cl

CPPFLAGS

C++ Compiler

CXX

cl

CXXFLAGS

Resource Compiler

RC

rc

RFLAGS

环境变量

被预定义的环境变量最好理解,也就是当前make程序中所有的环境变量的内容都可以作为预定义宏来使用。需要注意的是,这些宏都是可以被修改的。而且让make进程的环境变量随着改变。但是如果使用SET命令来修改进程的环境变量,则环境变量的宏不会随着改变。下面用JAVA_HOME来举例

# makefile内容
all: 
	echo $(JAVA_HOME)

# 输出
C:\jdk-11