一個程序從無到有的過程是這樣的: 編輯代碼 -> 預(yù)處理 -> 編譯(成dcu等) -> 鏈接(為exe等).
什么是預(yù)處理?
譬如 VCL 中有很多代碼是兼容 Linux 的, 在 Windows 下就需要在編譯之前預(yù)處理掉那些 for Linux 的代碼.
1、判斷操作系統(tǒng):
其中的 "MSWINDOWS" 和 "LINUX" 就是 Delphi 預(yù)定義的 "條件標(biāo)識符".
begin {$IFDEF MSWINDOWS} ShowMessage('Windows'); {$ENDIF} {$IFDEF LINUX} ShowMessage('Linux'); {$ENDIF}end;
2、自定義條件標(biāo)識符(DEFINE):
下面例子中自定義了條件標(biāo)識符: WanYi; 標(biāo)識符和定義它的指令都不區(qū)分大小寫, 但大家一般慣用大寫.
begin {$DEFINE WANYI} {$IFDEF WanYi} ShowMessage('標(biāo)識符 WanYi 已定義'); {$ELSE} ShowMessage('標(biāo)識符 WanYi 未定義'); {$ENDIF}end;
3、取消條件標(biāo)識符的定義(UNDEF):
begin {$DEFINE WANYI} {$IFDEF WANYI} ShowMessage('確認(rèn)標(biāo)識符 WanYi 是否定義'); {$ENDIF} {$UNDEF WANYI} {$IFDEF WANYI} ShowMessage('再次確認(rèn)標(biāo)識符 WanYi 是否定義'); {$ENDIF}end;
4、取消定義的簡單辦法:
在 {$...} 的 $ 前面隨便加點(diǎn)什么, 讓它變成 "注釋", 譬如: {.$}
begin {.$DEFINE WANYI} {$IFDEF WANYI} ShowMessage('確認(rèn)標(biāo)識符 WanYi 是否定義'); {$ENDIF} {.$UNDEF WANYI} {$IFDEF WANYI} ShowMessage('再次確認(rèn)標(biāo)識符 WanYi 是否定義'); {$ENDIF}end;
5、調(diào)試編譯指令時特別要注意的:
Delphi 有個常識: 如果單元代碼沒有改變, 相應(yīng)的 dcu 不會重新生成!
因此, 為了有準(zhǔn)確的調(diào)試結(jié)果, 執(zhí)行前先用 Shift+F9 強(qiáng)制編譯當(dāng)前工程, 然后再 Run;
強(qiáng)制編譯所有相關(guān)單元也可以, 方法: Project -> Build all project.
當(dāng)然修改下代碼也很方便, 譬如在代碼中打個空格再退回來.
6、測試預(yù)定義的 Debug 和 Release:
當(dāng)我們當(dāng)新建一個工程, Delphi 默認(rèn)的是調(diào)試(Debug)狀態(tài), 當(dāng)我們發(fā)布軟件時應(yīng)該切換到發(fā)布(Release)狀態(tài).
兩種狀態(tài)下編譯指令是有區(qū)別的, 在 Release 狀態(tài)下發(fā)布的 dcu 或 exe 會更小、更優(yōu)化.
Debug 和 Release 的切換方法:
進(jìn)入 Project Manager -> Build Configurations, 在 Debug 或 Release 上雙擊, 或從右鍵 Activate.
下面的代碼可以檢測到這種改變, 不過要注意上面提到的 Shift+F9 或 Project -> Build all project.
begin {$IFDEF DEBUG} ShowMessage('調(diào)試模式'); {$ENDIF} {$IFDEF RELEASE} ShowMessage('發(fā)布模式'); {$ENDIF}end;
7、編譯指令寫在哪?:
編譯指令可以寫在代碼頁的任何地方, 不過在代碼的不同區(qū)域有時也會不同;
譬如: {$APPTYPE GUI} 和 {$APPTYPE CONSOLE} 就只能寫在工程文件里才有效.
{$APPTYPE GUI} 和 {$APPTYPE CONSOLE} 分別表示窗口工程和控制臺工程.
其中 {$APPTYPE GUI} 是默認(rèn)的, 所以很少見到它.
它甚至可以嵌入到代碼行當(dāng)中, 譬如 ActnColorMaps 單元就有這么一句:
begin SystemParametersInfo(SPI_GETFLATMENU, 0, {$IFNDEF CLR}@{$ENDIF}FlatMenus, 0);end;
8、條件標(biāo)識符的有效范圍:
Delphi 預(yù)定義的條件標(biāo)識符都是全局的, 我們用 {$DEFINE ...} 自定義的標(biāo)識符都是局部的.
如何自定義全局的標(biāo)識符呢?
Project -> Options... -> 選定 Delphi Compiler -> 點(diǎn)擊 Conditional defines 右邊小按鈕 -> 添加.
不過這和系統(tǒng)預(yù)定義的還是有區(qū)別, 咱們自定義的只能用于當(dāng)前文件.
如何定義每個文件都可以使用的標(biāo)識符呢?
從 Project -> Options... 定義后, 馬上選擇左下角的 Default.
這和系統(tǒng)預(yù)定義的還是有區(qū)別, 因?yàn)檫@只能左右以后的文件, 管不著以前存在的文件.
如何...沒辦法了.
其他編譯指令, 譬如在 Debug 或 Release 中的設(shè)置也都是這樣; 也就是說: 每個文件都有相對獨(dú)立的編譯設(shè)置.
看到 Project -> Options... 馬上明白了編譯指令的設(shè)置方法有兩種:
1、使用 {$...} 在代碼中嵌入;
2、從 Project -> Options... 設(shè)置.
但在代碼中嵌入有時是不可替代的, 譬如現(xiàn)在討論的條件編譯.
9、編譯指令有多少?:
現(xiàn)在談到的還只是條件編譯, 實(shí)際應(yīng)用最多的是開關(guān)編譯; 在任一代碼頁執(zhí)行快捷鍵
Ctrl+O+O , 然后看看最上面...
下面列出了這些默認(rèn)設(shè)置:
{$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}