Delphi的编译指令
2015-04-20 11:23
162 查看
一个程序从无到有的过程是这样的: 编辑代码 -> 预处理 -> 编译(成dcu等) -> 链接(为exe等).
一、什么是预处理?
譬如 VCL 中有很多代码是兼容 Linux 的, 在 Windows 下就需要在编译之前预处理掉那些 for Linux 的代码.
1、判断操作系统: 其中的 "MSWINDOWS" 和 "LINUX" 就是 Delphi 预定义的 "条件标识符".
2、自定义条件标识符(DEFINE): 下面例子中自定义了条件标识符: Nobird; 标识符和定义它的指令都不区分大小写, 但大家一般惯用大写.
3、取消条件标识符的定义(UNDEF):
4、取消定义的简单办法: 在 {$...} 的 $ 前面随便加点什么, 让它变成 "注释", 譬如: {.$}
5、调试编译指令时特别要注意的: Delphi 有个常识: 如果单元代码没有改变, 相应的 dcu 不会重新生成!
因此, 为了有准确的调试结果, 执行前先用 Shift+F9 强制编译当前工程, 然后再 Run;
强制编译所有相关单元也可以, 方法: Project -> Build all project.
当然修改下代码也很方便, 譬如在代码中打个空格再退回来.
6、测试预定义的 Debug 和 Release: 当我们当新建一个工程, Delphi 默认的是调试(Debug)状态, 当我们发布软件时应该切换到发布(Release)状态.
两种状态下编译指令是有区别的, 在 Release 状态下发布的 dcu 或 exe 会更小、更优化.
Debug 和 Release 的切换方法:
进入 Project Manager -> Build Configurations, 在 Debug 或 Release 上双击, 或从右键 Activate.
下面的代码可以检测到这种改变, 不过要注意上面提到的 Shift+F9 或 Project -> Build all project.
7、编译指令写在哪?: 编译指令可以写在代码页的任何地方, 不过在代码的不同区域有时也会不同;
譬如: {$APPTYPE GUI} 和 {$APPTYPE CONSOLE} 就只能写在工程文件里才有效.
{$APPTYPE GUI} 和 {$APPTYPE CONSOLE} 分别表示窗口工程和控制台工程.
其中 {$APPTYPE GUI} 是默认的, 所以很少见到它.
它甚至可以嵌入到代码行当中, 譬如 ActnColorMaps 单元就有这么一句:
8、条件标识符的有效范围: Delphi 预定义的条件标识符都是全局的, 我们用 {$DEFINE ...} 自定义的标识符都是局部的.
如何自定义全局的标识符呢?
Project -> Options... -> 选定 Delphi Compiler -> 点击 Conditional defines 右边小按钮 -> 添加.
不过这和系统预定义的还是有区别, 咱们自定义的只能用于当前文件.
如何定义每个文件都可以使用的标识符呢?
从 Project -> Options... 定义后, 马上选择左下角的 Default.
这和系统预定义的还是有区别, 因为这只能左右以后的文件, 管不着以前存在的文件.
如何...没办法了.
其他编译指令, 譬如在 Debug 或 Release 中的设置也都是这样; 也就是说: 每个文件都有相对独立的编译设置.
看到 Project -> Options... 马上明白了编译指令的设置方法有两种:
1、使用 {$...} 在代码中嵌入;
2、从 Project -> Options... 设置.
但在代码中嵌入有时是不可替代的, 譬如现在讨论的条件编译.
9、编译指令有多少?: 现在谈到的还只是条件编译, 实际应用最多的是开关编译; 在任一代码页执行快捷键 Ctrl+O+O , 然后看看最上面...
下面列出了这些默认设置:
二、条件语句的更多用法
1. $IFDEF 等同于 $IF DEFINED(...) : 它们的结束分别是: $ENDIF、$IFEND; 例子中的 VER200 是 Delphi 2009 的标识.
2. $IFNDEF 等同于 $IF NOT DEFINED(...) : 它们的结束分别是: $ENDIF、$IFEND; 例子中的 VER150 是 Delphi 7 的标识.
3. 可以使用 or 和 and:
4. 可以使用 System 单元里的常量: 我测试了 System 单元里的很多常量都没问题.
5. 使用 $IFOPT 判断编译开关: Delphi 挺好玩, 26个字母分别安排成不同的开关指令(用 Ctrl+o+o 查看, 当然开关指令不止这些);
$IFOPT 可以判断这些指令是否打开.
这个指令不是很常用, 我看了一下 2009 的 VCL 源码, 总共才用了 6 次.
一、什么是预处理?
譬如 VCL 中有很多代码是兼容 Linux 的, 在 Windows 下就需要在编译之前预处理掉那些 for Linux 的代码.
1、判断操作系统: 其中的 "MSWINDOWS" 和 "LINUX" 就是 Delphi 预定义的 "条件标识符".
begin {$IFDEF MSWINDOWS} ShowMessage('Windows'); {$ENDIF} {$IFDEF LINUX} ShowMessage('Linux'); {$ENDIF} end;
2、自定义条件标识符(DEFINE): 下面例子中自定义了条件标识符: Nobird; 标识符和定义它的指令都不区分大小写, 但大家一般惯用大写.
begin {$DEFINE Nobird} {$IFDEF Nobird} ShowMessage('标识符 Nobird 已定义'); {$ELSE} ShowMessage('标识符 Nobird 未定义'); {$ENDIF} end;
3、取消条件标识符的定义(UNDEF):
begin {$DEFINE Nobird} {$IFDEF Nobird} ShowMessage('确认标识符 Nobird 是否定义'); {$ENDIF} {$UNDEF Nobird} {$IFDEF Nobird} ShowMessage('再次确认标识符 Nobird 是否定义'); {$ENDIF} end;
4、取消定义的简单办法: 在 {$...} 的 $ 前面随便加点什么, 让它变成 "注释", 譬如: {.$}
begin {.$DEFINE Nobird} {$IFDEF Nobird} ShowMessage('确认标识符 Nobird 是否定义'); {$ENDIF} {.$UNDEF Nobird} {$IFDEF Nobird} ShowMessage('再次确认标识符 Nobird 是否定义'); {$ENDIF} end;
5、调试编译指令时特别要注意的: Delphi 有个常识: 如果单元代码没有改变, 相应的 dcu 不会重新生成!
因此, 为了有准确的调试结果, 执行前先用 Shift+F9 强制编译当前工程, 然后再 Run;
强制编译所有相关单元也可以, 方法: Project -> Build all project.
当然修改下代码也很方便, 譬如在代码中打个空格再退回来.
6、测试预定义的 Debug 和 Release: 当我们当新建一个工程, Delphi 默认的是调试(Debug)状态, 当我们发布软件时应该切换到发布(Release)状态.
两种状态下编译指令是有区别的, 在 Release 状态下发布的 dcu 或 exe 会更小、更优化.
Debug 和 Release 的切换方法:
进入 Project Manager -> Build Configurations, 在 Debug 或 Release 上双击, 或从右键 Activate.
下面的代码可以检测到这种改变, 不过要注意上面提到的 Shift+F9 或 Project -> Build all project.
begin {$IFDEF DEBUG} ShowMessage('调试模式'); {$ENDIF} {$IFDEF RELEASE} ShowMessage('发布模式'); {$ENDIF} end;
7、编译指令写在哪?: 编译指令可以写在代码页的任何地方, 不过在代码的不同区域有时也会不同;
譬如: {$APPTYPE GUI} 和 {$APPTYPE CONSOLE} 就只能写在工程文件里才有效.
{$APPTYPE GUI} 和 {$APPTYPE CONSOLE} 分别表示窗口工程和控制台工程.
其中 {$APPTYPE GUI} 是默认的, 所以很少见到它.
它甚至可以嵌入到代码行当中, 譬如 ActnColorMaps 单元就有这么一句:
begin SystemParametersInfo(SPI_GETFLATMENU, 0, {$IFNDEF CLR}@{$ENDIF}FlatMenus, 0); end;
8、条件标识符的有效范围: Delphi 预定义的条件标识符都是全局的, 我们用 {$DEFINE ...} 自定义的标识符都是局部的.
如何自定义全局的标识符呢?
Project -> Options... -> 选定 Delphi Compiler -> 点击 Conditional defines 右边小按钮 -> 添加.
不过这和系统预定义的还是有区别, 咱们自定义的只能用于当前文件.
如何定义每个文件都可以使用的标识符呢?
从 Project -> Options... 定义后, 马上选择左下角的 Default.
这和系统预定义的还是有区别, 因为这只能左右以后的文件, 管不着以前存在的文件.
如何...没办法了.
其他编译指令, 譬如在 Debug 或 Release 中的设置也都是这样; 也就是说: 每个文件都有相对独立的编译设置.
看到 Project -> Options... 马上明白了编译指令的设置方法有两种:
1、使用 {$...} 在代码中嵌入;
2、从 Project -> Options... 设置.
但在代码中嵌入有时是不可替代的, 譬如现在讨论的条件编译.
9、编译指令有多少?: 现在谈到的还只是条件编译, 实际应用最多的是开关编译; 在任一代码页执行快捷键 Ctrl+O+O , 然后看看最上面...
下面列出了这些默认设置:
{$A8,B-,C+,D+,E-,F-,G+,H+,I+,J-,K-,L+,M-,N-,O+,P+,Q-,R-,S-,T-,U-,V+,W-,X+,Y+,Z1} {$MINSTACKSIZE $00004000} {$MAXSTACKSIZE $00100000} {$IMAGEBASE $00400000} {$APPTYPE GUI} {$WARN SYMBOL_DEPRECATED ON} {$WARN SYMBOL_LIBRARY ON} {$WARN SYMBOL_PLATFORM ON} {$WARN SYMBOL_EXPERIMENTAL ON} {$WARN UNIT_LIBRARY ON} {$WARN UNIT_PLATFORM ON} {$WARN UNIT_DEPRECATED ON} {$WARN UNIT_EXPERIMENTAL ON} {$WARN HRESULT_COMPAT ON} {$WARN HIDING_MEMBER ON} {$WARN HIDDEN_VIRTUAL ON} {$WARN GARBAGE ON} {$WARN BOUNDS_ERROR ON} {$WARN ZERO_NIL_COMPAT ON} {$WARN STRING_CONST_TRUNCED ON} {$WARN FOR_LOOP_VAR_VARPAR ON} {$WARN TYPED_CONST_VARPAR ON} {$WARN ASG_TO_TYPED_CONST ON} {$WARN CASE_LABEL_RANGE ON} {$WARN FOR_VARIABLE ON} {$WARN CONSTRUCTING_ABSTRACT ON} {$WARN COMPARISON_FALSE ON} {$WARN COMPARISON_TRUE ON} {$WARN COMPARING_SIGNED_UNSIGNED ON} {$WARN COMBINING_SIGNED_UNSIGNED ON} {$WARN UNSUPPORTED_CONSTRUCT ON} {$WARN FILE_OPEN ON} {$WARN FILE_OPEN_UNITSRC ON} {$WARN BAD_GLOBAL_SYMBOL ON} {$WARN DUPLICATE_CTOR_DTOR ON} {$WARN INVALID_DIRECTIVE ON} {$WARN PACKAGE_NO_LINK ON} {$WARN PACKAGED_THREADVAR ON} {$WARN IMPLICIT_IMPORT ON} {$WARN HPPEMIT_IGNORED ON} {$WARN NO_RETVAL ON} {$WARN USE_BEFORE_DEF ON} {$WARN FOR_LOOP_VAR_UNDEF ON} {$WARN UNIT_NAME_MISMATCH ON} {$WARN NO_CFG_FILE_FOUND ON} {$WARN IMPLICIT_VARIANTS ON} {$WARN UNICODE_TO_LOCALE ON} {$WARN LOCALE_TO_UNICODE ON} {$WARN IMAGEBASE_MULTIPLE ON} {$WARN SUSPICIOUS_TYPECAST ON} {$WARN PRIVATE_PROPACCESSOR ON} {$WARN UNSAFE_TYPE OFF} {$WARN UNSAFE_CODE OFF} {$WARN UNSAFE_CAST OFF} {$WARN OPTION_TRUNCATED ON} {$WARN WIDECHAR_REDUCED ON} {$WARN DUPLICATES_IGNORED ON} {$WARN UNIT_INIT_SEQ ON} {$WARN LOCAL_PINVOKE ON} {$WARN MESSAGE_DIRECTIVE ON} {$WARN TYPEINFO_IMPLICITLY_ADDED ON} {$WARN RLINK_WARNING ON} {$WARN IMPLICIT_STRING_CAST ON} {$WARN IMPLICIT_STRING_CAST_LOSS ON} {$WARN EXPLICIT_STRING_CAST OFF} {$WARN EXPLICIT_STRING_CAST_LOSS OFF} {$WARN CVT_WCHAR_TO_ACHAR OFF} {$WARN CVT_NARROWING_STRING_LOST OFF} {$WARN CVT_ACHAR_TO_WCHAR OFF} {$WARN CVT_WIDENING_STRING_LOST OFF} {$WARN XML_WHITESPACE_NOT_ALLOWED ON} {$WARN XML_UNKNOWN_ENTITY ON} {$WARN XML_INVALID_NAME_START ON} {$WARN XML_INVALID_NAME ON} {$WARN XML_EXPECTED_CHARACTER ON} {$WARN XML_CREF_NO_RESOLVE ON} {$WARN XML_NO_PARM ON} {$WARN XML_NO_MATCHING_PARM ON}
二、条件语句的更多用法
1. $IFDEF 等同于 $IF DEFINED(...) : 它们的结束分别是: $ENDIF、$IFEND; 例子中的 VER200 是 Delphi 2009 的标识.
begin {$IFDEF VER200} ShowMessage('这是 Delphi 2009'); {$ENDIF} {$IF DEFINED(VER200)} ShowMessage('这是 Delphi 2009'); {$IFEND} end;
2. $IFNDEF 等同于 $IF NOT DEFINED(...) : 它们的结束分别是: $ENDIF、$IFEND; 例子中的 VER150 是 Delphi 7 的标识.
begin {$IFNDEF VER150} ShowMessage('这不是 Delphi 7'); {$ENDIF} {$IF NOT DEFINED(VER150)} ShowMessage('这不是 Delphi 7'); {$IFEND} end;
3. 可以使用 or 和 and:
begin {$DEFINE AAA} {$DEFINE BBB} {$IF DEFINED(AAA) OR DEFINED(BBB)} ShowMessage('条件标识符 AAA 和 BBB 其中一个定义了'); {$IFEND} {$IF DEFINED(AAA) AND DEFINED(BBB)} ShowMessage('条件标识符 AAA 和 BBB 都定义了'); {$IFEND} end;
4. 可以使用 System 单元里的常量: 我测试了 System 单元里的很多常量都没问题.
begin ShowMessage(FloatToStr(CompilerVersion)); {在 Delphi 2009 中, CompilerVersion = 20.0} {$IF CompilerVersion >= 17.0} ShowMessage('这是 Delphi 2005 或以上的版本'); {$IFEND} end;
5. 使用 $IFOPT 判断编译开关: Delphi 挺好玩, 26个字母分别安排成不同的开关指令(用 Ctrl+o+o 查看, 当然开关指令不止这些);
$IFOPT 可以判断这些指令是否打开.
这个指令不是很常用, 我看了一下 2009 的 VCL 源码, 总共才用了 6 次.
begin {$IFOPT B+} ShowMessage('指令 B 已打开'); {$ELSE} ShowMessage('指令 B 已关闭'); {$ENDIF} {$B+} {$IFOPT B+} ShowMessage('Ok!'); {$ENDIF} end;
指令及默认值 | 可选值 | 范围 | 注释 | 举例 |
---|---|---|---|---|
{$A8} {$ALIGN8} | {$A+},{$A-}, {$A1},{$A2},{$A4},{$A8}; {$ALIGN ON},{$ALIGN OFF}, {$ALIGN 1},{$ALIGN 2}, {$ALIGN 4},{$ALIGN 8} | Local | ||
{$APPTYPE GUI} | {$APPTYPE GUI}, {$APPTYPE CONSOLE} | Global | ||
{$B-} {$BOOLEVAL OFF} | {$B+},{$B-}; {$BOOLEVAL ON}, {$BOOLEVAL OFF} | Local | ||
{$C+} {$ASSERTIONS ON} | {$C+},{$C-}; {$ASSERTIONS ON}, {$ASSERTIONS OFF} | Local | ||
{$D+} {$DEBUGINFO ON} | {$D+},{$D-} {$DEBUGINFO ON}, {$DEBUGINFO OFF} | Global | ||
{$DENYPACKAGEUNIT OFF} | {$DENYPACKAGEUNIT ON}, | Local | ||
{$DESCRIPTION 'text'} | Global | |||
{$DESIGNONLY OFF} | {$DESIGNONLY ON}, {$DESIGNONLY OFF} | Local | ||
{$E-} | {$E+},{$E-} | |||
{$E extension} {$EXTENSION extension} | ||||
{$EXTERNALSYM identifier} | ||||
{$F-} | {$F+},{$F-} | |||
{$FINITEFLOAT ON} | {$FINITEFLOAT ON}, {$FINITEFLOAT OFF} | Global | ||
{$G+} {$IMPORTEDDATA ON} | {$G+},{$G-}; {$IMPORTEDDATA ON}, {$IMPORTEDDATA OFF} | Local | ||
{$H+} {$LONGSTRINGS ON} | {$H+},{$H-} {$LONGSTRINGS ON}, {$LONGSTRINGS OFF} | Local | ||
{$HINTS ON} | {$HINTS ON}, {$HINTS OFF} | Local | ||
{$HPPEMIT 'string'} | ||||
{$I filename} {$INCLUDE filename} | Local | |||
{$I+} {$IOCHECKS ON} | {$I+},{$I-}; {$IOCHECKS ON}, {$IOCHECKS OFF} | Local | ||
{$IMAGEBASE $00400000} | {$IMAGEBASE number} | Global | ||
{$IMPLICITBUILD ON},{$IMPLICITBUILD OFF} | {$IMPLICITBUILD ON} | Global | ||
{$J-} {$WRITEABLECONST OFF} | {$J+},{$J-} {$WRITEABLECONST ON}, {$WRITEABLECONST OFF} | Local | ||
{$K-} | {$K+},{$K-} | |||
{$L+} {$LOCALSYMBOLS ON} | {$L+},{$L-} {$LOCALSYMBOLS ON}, {$LOCALSYMBOLS OFF} | Global | ||
{$L filename} {$LINK filename} | Local | |||
$LIBPREFIX 'lib' or $SOPREFIX 'bpl' $LIBSUFFIX ' ' $LIBVERSION ' ' | $LIBPREFIX 'string' $LIBSUFFIX 'string' $LIBVERSION 'string' | Global | ||
{$M-} {$TYPEINFO OFF} | {$M+},{$M-} {$TYPEINFO ON}, {$TYPEINFO OFF} | Local | ||
{$M 16384,1048576} | {$M minstacksize,maxstacksize}; {$MINSTACKSIZE number} {$MAXSTACKSIZE number} | |||
{$M 1048576} | {$M reservedbytes} {$RESOURCERESERVE reservedbytes} | Global | Linux | |
{$MESSAGE HINT|WARN|ERROR|FATAL 'text string'} | Local | |||
{$METHODINFO OFF} | {$METHODINFO ON}, {$METHODINFO OFF} | |||
{$N+} | {$N+},{$N-} | |||
{$NODEFINE identifier} | ||||
{$NOINCLUDE filename} | ||||
{$O+} {$OPTIMIZATION ON} | {$O+},{$O-}; {$OPTIMIZATION ON}, {$OPTIMIZATION OFF} | Local | ||
{$ObjExportAll Off} | {$ObjExportAll On}, {$ObjExportAll Off} | Global | ||
{$P+} {$OPENSTRINGS ON} | {$P+},{$P-} {$OPENSTRINGS ON}, {$OPENSTRINGS OFF} | Local | ||
{$POINTERMATH OFF} | {$POINTERMATH ON}, {$POINTERMATH OFF} | Local | ||
{$Q-} {$OVERFLOWCHECKS OFF} | {$Q+},{$Q-} {$OVERFLOWCHECKS ON}, {$OVERFLOWCHECKS OFF} | Local | ||
{$R filename} {$RESOURCE filename} {$R *.xxx} {$R filename.res filename.rc} | ||||
{$R-} {$RANGECHECKS OFF} | {$R+},{$R-} {$RANGECHECKS ON}, {$RANGECHECKS OFF} | Local | ||
{$REALCOMPATIBILITY OFF} | {$REALCOMPATIBILITY ON}, {$REALCOMPATIBILITY OFF} | Local | ||
{$RUNONLY OFF} | {$RUNONLY ON}, {$RUNONLY OFF} | Local | ||
{$S-} | {$S+},{$S-} | |||
{$SetPEFlags <integer expression>} {$SetPEOptFlags <integer expression>} | Local | |||
{$T-} {$TYPEDADDRESS OFF} | {$T+},{$T-} {$TYPEDADDRESS ON}, {$TYPEDADDRESS OFF} | Global | ||
{$U-} {$SAFEDIVIDE OFF} | {$U+},{$U-} {$SAFEDIVIDE ON}, {$SAFEDIVIDE OFF} | Local | ||
{$V+} {$VARSTRINGCHECKS ON} | {$V+},{$V-} {$VARSTRINGCHECKS ON}, {$VARSTRINGCHECKS OFF} | Local | ||
{$W-} {$STACKFRAMES OFF} | {$W+},{$W-} {$STACKFRAMES ON}, {$STACKFRAMES OFF} | Local | ||
{$WARN ON} | {$WARN identifier ON}, {$WARN identifier OFF} | Local | ||
{$WARNINGS ON} | {$WARNINGS ON}, {$WARNINGS OFF} | Local | ||
{$WEAKPACKAGEUNIT OFF} | {$WEAKPACKAGEUNIT ON}, {$WEAKPACKAGEUNIT OFF} | Local | ||
{$X+} {$EXTENDEDSYNTAX ON} | {$X+},{$X-}; {$EXTENDEDSYNTAX ON}, {$EXTENDEDSYNTAX OFF} | Global | ||
{$YD} {$DEFINITIONINFO ON} | {$Y+},{$Y-},{$YD}; {$REFERENCEINFO ON}, {$REFERENCEINFO OFF}; {DEFINITIONINFO ON}, {DEFINITIONINFO OFF} | Global | ||
{$Z1} {$MINENUMSIZE 1} | {$Z1},{$Z2},{$Z4}; {$MINENUMSIZE 1}, {$MINENUMSIZE 2}, {$MINENUMSIZE 4} | Local | ||
$DEFINE $UNDEF $IFDEF $ELSE $ENDIF {$IF DEFINED(...)} {$IFEND} {$IF NOT DEFINED(...)} {$IFEND} {$IF DEFINED(...) OR DEFINED(...)} {$IFEND} {$IF DEFINED(...) AND DEFINED(...)} {$IFEND} {$IF System.Const >= Number} {$IFEND} {$IFOPT ...} {$ELSE} {$ENDIF} | ||||
{$region 'text'} ... {$endregion} |
相关文章推荐
- delphi的常用条件编译指令---{$IFDEF} {$UNDEF}{$IFDEF}{$ELSE}{$ENDIF} .
- Delphi中预编译指令如何使用
- Delphi中预编译指令如何使用
- 关于Delphi中预编译指令的使用方法
- DELPHI的编译指令
- Delphi 编译指令的使用方法
- delphi的常用条件编译指令---{$IFDEF} {$UNDEF}{$IFDEF}{$ELSE}{$ENDIF}
- Delphi 的编译指令(1): $DEFINE、$UNDEF、$IFDEF、$ELSE、$ENDIF
- Delphi编译指令说明
- Delphi7.0 预编译指令说明
- Delphi编译指令说明
- Delphi 的编译指令(4): 编译指令全表(未完)
- Delphi编译指令说明
- Delphi 编译指令的使用方法
- Delphi - PointerMath编译指令
- Delphi 的编译指令(1): $DEFINE、$UNDEF、$IFDEF、$ELSE、$ENDIF
- Delphi 的编译指令(1): $DEFINE、$UNDEF、$IFDEF、$ELSE、$ENDIF
- Delphi 的编译指令(3): 常用的预定义条件标识符
- Delphi编译指令说明
- Delphi 的编译指令(4): 编译指令全表(未完)