Delphi 的编译指令(1): $DEFINE、$UNDEF、$IFDEF、$ELSE、$ENDIF
<p>Delphi 的编译指令(1): $DEFINE、$UNDEF、$IFDEF、$ELSE、$ENDIF<br>本文转自:http://www.cnblogs.com/awei0611/archive/2009/02/26/1398459.html</p><p> </p>
<p>一个程序从无到有的过程是这样的: 编辑代码 -> 预处理 -> 编译(成dcu等) -> 链接(为exe等).</p>
<p>什么是预处理? <br>譬如 VCL 中有很多代码是兼容 Linux 的, 在 Windows 下就需要在编译之前预处理掉那些 for Linux 的代码.</p>
<p><br>1、判断操作系统:</p>
<p>其中的 "MSWINDOWS" 和 "LINUX" 就是 Delphi 预定义的 "条件标识符".</p>
<p>begin<br>{$IFDEF MSWINDOWS}<br>ShowMessage('Windows');<br>{$ENDIF}<br>{$IFDEF LINUX}<br>ShowMessage('Linux');<br>{$ENDIF}<br>end;</p>
<p> </p>
<p> </p>
<p>2、自定义条件标识符(DEFINE):</p>
<p>下面例子中自定义了条件标识符: WanYi; 标识符和定义它的指令都不区分大小写, 但大家一般惯用大写.</p>
<p>begin<br>{$DEFINE WANYI}<br>{$IFDEF WanYi}<br>ShowMessage('标识符 WanYi 已定义');<br>{$ELSE}<br>ShowMessage('标识符 WanYi 未定义');<br>{$ENDIF}<br>end;</p>
<p> </p>
<p> </p>
<p>3、取消条件标识符的定义(UNDEF):</p>
<p>begin<br>{$DEFINE WANYI}<br>{$IFDEF WANYI}<br>ShowMessage('确认标识符 WanYi 是否定义');<br>{$ENDIF}<br>{$UNDEF WANYI}<br>{$IFDEF WANYI}<br>ShowMessage('再次确认标识符 WanYi 是否定义');<br>{$ENDIF}<br>end;</p>
<p> </p>
<p> </p>
<p>4、取消定义的简单办法:</p>
<p>在 {$...} 的 $ 前面随便加点什么, 让它变成 "注释", 譬如: {.$}</p>
<p>begin<br>{.$DEFINE WANYI}<br>{$IFDEF WANYI}<br>ShowMessage('确认标识符 WanYi 是否定义');<br>{$ENDIF}<br>{.$UNDEF WANYI}<br>{$IFDEF WANYI}<br>ShowMessage('再次确认标识符 WanYi 是否定义');<br>{$ENDIF}<br>end;</p>
<p> </p>
<p> </p>
<p>5、调试编译指令时特别要注意的:</p>
<p>Delphi 有个常识: 如果单元代码没有改变, 相应的 dcu 不会重新生成!</p>
<p>因此, 为了有准确的调试结果, 执行前先用 Shift+F9 强制编译当前工程, 然后再 Run;<br>强制编译所有相关单元也可以, 方法: Project -> Build all project.</p>
<p>当然修改下代码也很方便, 譬如在代码中打个空格再退回来.</p>
<p><br>6、测试预定义的 Debug 和 Release:</p>
<p>当我们当新建一个工程, Delphi 默认的是调试(Debug)状态, 当我们发布软件时应该切换到发布(Release)状态.<br>两种状态下编译指令是有区别的, 在 Release 状态下发布的 dcu 或 exe 会更小、更优化.</p>
<p>Debug 和 Release 的切换方法:<br>进入 Project Manager -> Build Configurations, 在 Debug 或 Release 上双击, 或从右键 Activate.</p>
<p>下面的代码可以检测到这种改变, 不过要注意上面提到的 Shift+F9 或 Project -> Build all project.</p>
<p>begin<br>{$IFDEF DEBUG}<br>ShowMessage('调试模式');<br>{$ENDIF}<br>{$IFDEF RELEASE}<br>ShowMessage('发布模式');<br>{$ENDIF}<br>end;</p>
<p> </p>
<p> </p>
<p>7、编译指令写在哪?:</p>
<p>编译指令可以写在代码页的任何地方, 不过在代码的不同区域有时也会不同;</p>
<p>譬如: {$APPTYPE GUI} 和 {$APPTYPE CONSOLE} 就只能写在工程文件里才有效.</p>
<p>{$APPTYPE GUI} 和 {$APPTYPE CONSOLE} 分别表示窗口工程和控制台工程.<br>其中 {$APPTYPE GUI} 是默认的, 所以很少见到它.</p>
<p>它甚至可以嵌入到代码行当中, 譬如 ActnColorMaps 单元就有这么一句:</p>
<p>begin<br>SystemParametersInfo(SPI_GETFLATMENU, 0, {$IFNDEF CLR}@{$ENDIF}FlatMenus, 0);<br>end;</p>
<p> </p>
<p> </p>
<p>8、条件标识符的有效范围:</p>
<p>Delphi 预定义的条件标识符都是全局的, 我们用 {$DEFINE ...} 自定义的标识符都是局部的.</p>
<p>如何自定义全局的标识符呢?<br>Project -> Options... -> 选定 Delphi Compiler -> 点击 Conditional defines 右边小按钮 -> 添加.</p>
<p>不过这和系统预定义的还是有区别, 咱们自定义的只能用于当前文件.</p>
<p>如何定义每个文件都可以使用的标识符呢?<br>从 Project -> Options... 定义后, 马上选择左下角的 Default.</p>
<p>这和系统预定义的还是有区别, 因为这只能左右以后的文件, 管不着以前存在的文件.<br>如何...没办法了.</p>
<p>其他编译指令, 譬如在 Debug 或 Release 中的设置也都是这样; 也就是说: 每个文件都有相对独立的编译设置.</p>
<p>看到 Project -> Options... 马上明白了编译指令的设置方法有两种:<br>1、使用 {$...} 在代码中嵌入;<br>2、从 Project -> Options... 设置.</p>
<p>但在代码中嵌入有时是不可替代的, 譬如现在讨论的条件编译.</p>
<p><br>9、编译指令有多少?:</p>
<p>现在谈到的还只是条件编译, 实际应用最多的是开关编译; 在任一代码页执行快捷键 Ctrl+O+O , 然后看看最上面...</p>
<p>下面列出了这些默认设置:</p>
<p>{$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}<br>{$MINSTACKSIZE $00004000}<br>{$MAXSTACKSIZE $00100000}<br>{$IMAGEBASE $00400000}<br>{$APPTYPE GUI}<br>{$WARN SYMBOL_DEPRECATED ON}<br>{$WARN SYMBOL_LIBRARY ON}<br>{$WARN SYMBOL_PLATFORM ON}<br>{$WARN SYMBOL_EXPERIMENTAL ON}<br>{$WARN UNIT_LIBRARY ON}<br>{$WARN UNIT_PLATFORM ON}<br>{$WARN UNIT_DEPRECATED ON}<br>{$WARN UNIT_EXPERIMENTAL ON}<br>{$WARN HRESULT_COMPAT ON}<br>{$WARN HIDING_MEMBER ON}<br>{$WARN HIDDEN_VIRTUAL ON}<br>{$WARN GARBAGE ON}<br>{$WARN BOUNDS_ERROR ON}<br>{$WARN ZERO_NIL_COMPAT ON}<br>{$WARN STRING_CONST_TRUNCED ON}<br>{$WARN FOR_LOOP_VAR_VARPAR ON}<br>{$WARN TYPED_CONST_VARPAR ON}<br>{$WARN ASG_TO_TYPED_CONST ON}<br>{$WARN CASE_LABEL_RANGE ON}<br>{$WARN FOR_VARIABLE ON}<br>{$WARN CONSTRUCTING_ABSTRACT ON}<br>{$WARN COMPARISON_FALSE ON}<br>{$WARN COMPARISON_TRUE ON}<br>{$WARN COMPARING_SIGNED_UNSIGNED ON}<br>{$WARN COMBINING_SIGNED_UNSIGNED ON}<br>{$WARN UNSUPPORTED_CONSTRUCT ON}<br>{$WARN FILE_OPEN ON}<br>{$WARN FILE_OPEN_UNITSRC ON}<br>{$WARN BAD_GLOBAL_SYMBOL ON}<br>{$WARN DUPLICATE_CTOR_DTOR ON}<br>{$WARN INVALID_DIRECTIVE ON}<br>{$WARN PACKAGE_NO_LINK ON}<br>{$WARN PACKAGED_THREADVAR ON}<br>{$WARN IMPLICIT_IMPORT ON}<br>{$WARN HPPEMIT_IGNORED ON}<br>{$WARN NO_RETVAL ON}<br>{$WARN USE_BEFORE_DEF ON}<br>{$WARN FOR_LOOP_VAR_UNDEF ON}<br>{$WARN UNIT_NAME_MISMATCH ON}<br>{$WARN NO_CFG_FILE_FOUND ON}<br>{$WARN IMPLICIT_VARIANTS ON}<br>{$WARN UNICODE_TO_LOCALE ON}<br>{$WARN LOCALE_TO_UNICODE ON}<br>{$WARN IMAGEBASE_MULTIPLE ON}<br>{$WARN SUSPICIOUS_TYPECAST ON}<br>{$WARN PRIVATE_PROPACCESSOR ON}<br>{$WARN UNSAFE_TYPE OFF}<br>{$WARN UNSAFE_CODE OFF}<br>{$WARN UNSAFE_CAST OFF}<br>{$WARN OPTION_TRUNCATED ON}<br>{$WARN WIDECHAR_REDUCED ON}<br>{$WARN DUPLICATES_IGNORED ON}<br>{$WARN UNIT_INIT_SEQ ON}<br>{$WARN LOCAL_PINVOKE ON}<br>{$WARN MESSAGE_DIRECTIVE ON}<br>{$WARN TYPEINFO_IMPLICITLY_ADDED ON}<br>{$WARN RLINK_WARNING ON}<br>{$WARN IMPLICIT_STRING_CAST ON}<br>{$WARN IMPLICIT_STRING_CAST_LOSS ON}<br>{$WARN EXPLICIT_STRING_CAST OFF}<br>{$WARN EXPLICIT_STRING_CAST_LOSS OFF}<br>{$WARN CVT_WCHAR_TO_ACHAR OFF}<br>{$WARN CVT_NARROWING_STRING_LOST OFF}<br>{$WARN CVT_ACHAR_TO_WCHAR OFF}<br>{$WARN CVT_WIDENING_STRING_LOST OFF}<br>{$WARN XML_WHITESPACE_NOT_ALLOWED ON}<br>{$WARN XML_UNKNOWN_ENTITY ON}<br>{$WARN XML_INVALID_NAME_START ON}<br>{$WARN XML_INVALID_NAME ON}<br>{$WARN XML_EXPECTED_CHARACTER ON}<br>{$WARN XML_CREF_NO_RESOLVE ON}<br>{$WARN XML_NO_PARM ON}<br>{$WARN XML_NO_MATCHING_PARM ON}<br>————————————————</p>
</div>
<div id="MySignature" role="contentinfo">
好的代码像粥一样,都是用时间熬出来的<br><br>
来源:https://www.cnblogs.com/jijm123/p/14681706.html 感谢楼主的分享!
这篇关于Delphi编译指令的教程真是非常详细和实用啊!对于我们这些Delphi开发者来说,条件编译确实是日常开发中经常要用到的功能。
补充一点点小经验:
除了帖子中提到的内容,其实在实际项目中,条件编译还有很多妙用:
1. 版本控制:可以用条件编译来区分试用版、正式版等不同版本
2. 功能开关:快速开启/关闭某些新功能
3. 多语言支持:配合资源文件实现国际化
另外提醒一下,现在新版Delphi(XE系列以上)还支持{$IF}、{$IFEND}这种更现代的条件编译语法,功能更强大,和帖子中介绍的经典语法可以配合使用。
再次感谢楼主的整理! 期待看到后续的编译指令系列文章~
頁:
[1]