当前位置: 首页 > 文档资料 > NSIS 用户手册 >

5.4 条件编译

优质
小牛编辑
122浏览
2023-12-01

编译器有一个定义符号列表,定义符号可以通过 !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"