这篇将作为Makefile入门最后一篇,这个系列看完基本上可以看懂以及上手开始写项目需要的Makefile了。
预处理
前面介绍了Makefile的各种结构,语法,命令,变量,以及各种规则。 但是除了通过target这种直接手动指定来实现的编译流程方法以外也能支持预处理的方式来进行控制构建流程,这和C/C++里面的#预编译指令一样,几乎有同样的功能,有对应的#include,#if 等,都有着类似的功能。这些指令都不具有实际构建的作用,但是可以帮助组织Makefile流程。
和C/C++的预处理指令以#开头不一样,Makefile用!开头。
从最简单的IF介绍起
条件预处理
!IF,!ELSE,!ELSEIF,!ELSE IF, !ENDIF
其实用方法为类似于C/C++中的if语句非常简单,同样也是判断其后的表达式是否为非零。
这里用一个例子说明其使用方法:
OPTION=0
OPTION1=1
!IF $(OPTION)
all:
echo case 1
!ELSEIF $(OPTION1) # 等同于!ELSE IF
all:
echo case 2
!ELSE
all:
echo case 3
!ENDIF
# 输出
case 2
!IFDEF,!IFNDEF,!ELSEIFDEF, !ELSE IFDEF,!UNDEF
和!IF系列不同,这里的判断条件是是否宏被定义。使用和上面类似,唯一需要注意的是不需要加$()来强调这是一个被定义的宏。下列例子说明这个用法。
!IFDEF OPTION
all:
echo case 1
!ELSE
all:
echo case 2
!ENDIF
# 输出
case 2
上面例子中就没有预先定义OPTION,所以输出的就是case 2。
!UNDEF就是可以将已经定义的宏取消。
!IF还能结合其他预处理操作符来实现除了值之外的功能
DEFINED,EXIST,[]
这三个符号分别代表判断是否宏被定义,是否文件存在,以及程序的退出码。都会作为表达式范围相应的值配合!IF所使用,从而具有和外部环境交互的能力,从而动态控制构建流程。如下所示
!IF DEFINED (OPTION)
all:
echo case 1
!ELSE
all: CASE_EXIST
echo case 2
!ENDIF
!IF EXIST(file.cpp)
CASE_EXIST:
echo case 3
!ENDIF
# 输出
case 3
case 2
显示信息预处理
!ERROR,!MESSAGE
当项目的Makefile变得很复杂的时候,特别是加上了子Makefile,有时候免不了自己都不清楚当前的Makefile所执行的流程,导致项目编译错误。这时候使用显示信息预处理就能加快调试定位问题。先看下面例子
!ERROR this is a error!
!MESSAGE just give you a tip.
all:
echo case 1
# 输出
just give you a tip.
makefile(2) : fatal error U1050: this is a error!
Stop.
向上面的例子一样,显示信息预处理使用方法特别简单,直接将想要显示的文本加载其后。但是!MESSAGE不会打断NMAKE执行,可以等同于echo命令,只是显示一段信息。!ERROR则是会打断整个make的过程,并且其信息会被作为fatal error U1050输出。并且会指明该指令的行号。
包含指令
!INCLUDE等同于C/C++的#include,甚至语法上也能用<>来讲文件路径括起来。也是先来看例子
# 文件 makefile
all: sub
echo this is main makefile
!INCLUDE <makefile1>
# 文件 makefile1
sub:
echo sub makefile
# 输出
sub makefile
this is main makefile
如例子一样,非常类似于#include。
MAKE选项预编译 !CMDSWITCHES
在运行NMAKE的时候可以指定一些参数,例如/D参数可以在检查目标是否存在的同时将目标时间戳打出来。
!CMDSWITCHES +d
all:
echo this is main makefile
# 输出
周四, 9月 21 2022 21:05:58 all
'all' is up-to-date
因为已经有一个all文件存在了,因此并不会输出all里面的命令,同时会输出all文件的时间戳。等多的MAKE选项可以看NMAKE /?的帮助。
总结
介绍Makefile基本用法一共写了四篇,基本涵盖了普通项目所会遇到的所有方面。另外需要注意该介绍是以微软的nmake为例,其他平台的make可能写法稍有不同,但是各种概念基本一致。
如果遇到问题欢迎留言或私信交流。