Delphi的编译指令

来源:互联网 发布:淘宝开店实名认证步骤 编辑:程序博客网 时间:2024/05/27 09:46
一个程序从无到有的过程是这样的: 编辑代码 -> 预处理 -> 编译(成dcu等) -> 链接(为exe等).
一、什么是预处理?
譬如 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}
0 0
原创粉丝点击