5.4 条件编译
编译器有一个定义符号列表,定义符号可以通过 !define 定义或使用 /D 命令行开关。这些定义符号可以用于条件编译 (通过 !ifdef 定义) 或用于符号替换 (一种格式简单的宏)。若要用它的值替换一个符号,请使用 ${符号} (如果没有定义符号,那么不会产生转换)。这个转换为“先到先得”,这意味着如果你做了:
!define 符号1 ${符号2}
当出现该行时,如果定义了“符号2”它将被替换。否则,当“${符号1}”被引用时,任何替换都会出现。
与定义、条件编译相关的命令:
5.4.1 !define
[/ifndef | /redef] ([/date|/utcdate] 符号 [值]) | (/math 符号 值1 OP 值2) | (/file 符号 文件.txt)
这个命令将会向全局定义列表中添加“符号”。这个效果与对编译器使用 /D 命令行开关效果相似 (定义仅在 !define 命令之后有效)。
如果使用了 /date 或 /utcdate,值将被传递到 strftime 并使用结果作为“符号”的值。strftime 将特殊符号转换为当前日期或时间的实际值部分。例如:%H 将被转换为当前小时的 24 小时格式。可用符号完整列表可在 MSDN 上搜索 strftime。在 POSIX 平台可使用 man strtime 获取列表。
如果使用了 /math,则“值1 OP 值2”的结果 (其中 OP 可以是 +、-、*、&、|、^、/ 或 %) 将作为“符号”的值。注意:值1和值2必须为整数值!
如果使用了 /file,指定的整个文本文件 (含空格和换行) 将被读取并填充到“符号”。
!define USE_SOMETHING !define VERSION 1.2 !define /date NOW "%H:%M:%S %d %b, %Y" !define /math RESULT 3 + 10 !define /math REST 15 % ${RESULT} !define /file BUNCHASTUFF 某源文件.cpp !define /redef USE_SOMETHING ${RESULT} ;重新定义 USE_SOMETHING
5.4.2 !undef
符号
从全局定义列表中移除一个符号。注意:取消定义“符号”的地方 ${符号} 将被转变为 "${符号}"。
!define SOMETHING !undef SOMETHING
5.4.3 !ifdef
符号 [布尔逻辑符号 [符号 [...]]]
当这个命令与 !endif 命令组成一对时,将会告诉编译器是否编译在其两者之间的代码。如果“符号”被全局定义了 (通过 !define 或 /D 开关),那么所含的代码将会被编译。否则,那些代码将会被跳过。“布尔逻辑符号”可以在更多的“符号”之间被指定为 & (布尔与) 或 | (布尔或)——优先度很简单,从左到右。
!define SOMETHING !ifdef SOMETHING !echo "SOMETHING 已定义!" !endif !undef SOMETHING !ifdef SOMETHING !echo "SOMETHING 已定义!" # 将不会输出 !endif
5.4.4 !ifndef
符号 [布尔逻辑符号 [符号 [...]]]
它与 !ifdef 正好相反。当“符号”没有被定义时,代码将会被编译。
5.4.5 !if
[!] 值1 [操作 值2]
当这个命令与 !endif 命令组成一对时,将会告诉编译器。如果值为非零,或者根据值 1 与值 2 比较操作的结果为真,那么所含的代码将会被编译。否则,那些代码将会被跳过。“操作”可以是 == 或 != (字符串比较),<=、<> 或 >= (浮点数比较),&& 或 || (布尔值比较)。如果设置了 [!],返回值将会从真切换为假,反之亦然。
!if 1 < 2 !echo "1 比 2 小!" !else if ! 3.1 > 1.99 !error "这一行将始终不会显示。" !else !error "这一行也不应该显示!" !endif
5.4.6 !ifmacrodef
宏名称 [布尔逻辑符号 [宏名称 [...]]]
当这个命令与 !endif 命令组成一对时,将会告诉编译器是否编译在其两者之间的代码。如果宏“宏名称”存在,那么所含的代码将会被编译。否则,那些代码将会被跳过。布尔逻辑符号可以在更多的“宏名称”之间被指定为 & (布尔与) 或 | (布尔或)——优先度很简单,从左到右。
!macro SomeMacro !macroend !ifmacrodef SomeMacro !echo "SomeMacro 已定义!" !endif
5.4.7 !ifmacrondef
宏名称 [布尔逻辑符号 [宏名称 [...]]]
它与 !ifmacrodef 正好相反。当宏“宏名称”不存在时,代码块将会被编译。
5.4.8 !else
[ifdef|ifndef|ifmacrodef|ifmacrondef [...]]
这个命令允许方便地插入不同的代码块,当有不同的定义或设置了不同的宏时。你可以创建类似 !ifdef/!else/!endif、!ifdef/!else ifdef/!else/!endif 等代码块。
!ifdef VERSION OutFile installer-${VERSION}.exe !else OutFile installer.exe !endif
5.4.9 !endif
这个命令用于关闭以 !ifdef、!ifndef、!ifmacrodef 或 !ifmacrondef 起始的代码块。
5.4.10 !insertmacro
宏名称 [参数] [...]
插入一个由 !macro 创建的宏的内容。如果创建的宏带有参数,那么你必须按宏的需求向它传送足够的参数。
!macro Print text DetailPrint "${text}" !macroend !insertmacro Print "某些文字" !insertmacro Print "更多文字"
5.4.11 !macro
宏名称 [参数][...]
创建一个名为宏。所有在 !macro 与 !macroend 之间的代码行都会被保存。若要稍后插入宏,请使用 !insertmacro。!macro 定义可以有一个或多个定义的参数。这些参数可能会按相同的方式被访问,宏参数会被依次定义 (例如:${PARMNAME}) 且在宏结束的时候依次取消定义。
!macro SomeMacro 参数1 参数2 参数3 DetailPrint "${参数1}" MessageBox MB_OK "${参数2}" File "${参数3}" !macroend
5.4.12 !macroend
结束一个以 !macro 为起始的宏。
5.4.13 !searchparse
[/ignorecase] [/noerrors] [/file] 源字符串或文件 子字符串开始 输出符号1 [子字符串 [输出符号2 [子字符串 ...]]]
解析“源字符串或文件”(视为字符串,或者,如果设置了“/file”则视为文件名) 查找“子字符串开始”。如果发现“子字符串开始”,那么“输出符号1”被定义为字符串其余部分 (减去任何其他可以找到的“子字符串”)。可以指定任意数量的“输出符号x”,并且最后的“子字符串”是可选的。
如果指定了“/noerrors”,则将允许匹配小于全部数量的字符串 (所有“输出符号x”在没有发现子字符串之后会被忽略)。
如果指定了“/file”文件会被视为一连串的行。该文件被搜索直到所有子字符串都匹配过。如果指定了“/noerrors”并且不是所有字符串都匹配,那么匹配最多的符号会被作为第一行使用。
# 查找 filename.cpp 中的一行 '#define APP_VERSION "2.5"' 并且设置 ${VER_MAJOR} 为 2,${VER_MINOR} 为 5。 !searchparse /file filename.cpp `#define APP_VERSION "` VER_MAJOR `.` VER_MINOR `"`
5.4.14 !searchreplace
[/ignorecase] 符号输出 源字符串 搜索字符串 替换字符串
查找“源字符串”。在“源字符串”中搜索“搜索字符串”并使用“替换字符串”替换所有实例。不像 !define,!searchreplace 允许你重新定义没有警告或错误的“符号输出”。
# ${blah} 被定义为 "i like ponies" !searchreplace blah "i love ponies" "love" "like"