Delphi 的编译指令: $DEFINE、$UNDEF、$IFDEF、$ELSE、$ENDIF
来源:http://tech.ddvip.com/2009-04/1239360770114444.html 原排版更易阅读
一个程序从无到有的过程是这样的: 编辑代码 -> 预处理 -> 编译(成dcu等) -> 链接(为exe等).
什么是预处理?
譬如 VCL 中有很多代码是兼容 Linux 的, 在 Windows 下就需要在编译之前预处理掉那些 for Linux 的代码.
1、判断操作系统:
其中的 "MSWINDOWS" 和 "LINUX" 就是 Delphi 预定义的 "条件标识符".
1
2
3
4
5
6
7
8
|
begin
{
$IFDEF
MSWINDOWS}
ShowMessage(
'Windows'
);
{
$ENDIF
}
{
$IFDEF
LINUX}
ShowMessage(
'Linux'
);
{
$ENDIF
}
end
;
|
2、自定义条件标识符(DEFINE):
下面例子中自定义了条件标识符: WanYi; 标识符和定义它的指令都不区分大小写, 但大家一般惯用大写.
1
2
3
4
5
6
7
8
|
begin
{
$DEFINE
WANYI}
{
$IFDEF
WanYi}
ShowMessage(
'标识符 WanYi 已定义'
);
{
$ELSE
}
ShowMessage(
'标识符 WanYi 未定义'
);
{
$ENDIF
}
end
;
|
3、取消条件标识符的定义(UNDEF):
1
2
3
4
5
6
7
8
9
10
|
begin
{
$DEFINE
WANYI}
{
$IFDEF
WANYI}
ShowMessage(
'确认标识符 WanYi 是否定义'
);
{
$ENDIF
}
{
$UNDEF
WANYI}
{
$IFDEF
WANYI}
ShowMessage(
'再次确认标识符 WanYi 是否定义'
);
{
$ENDIF
}
end
;
|
4、取消定义的简单办法:
在 {$...} 的 $ 前面随便加点什么, 让它变成 "注释", 譬如: {.$}
1
2
3
4
5
6
7
8
9
10
|
begin
{.$DEFINE WANYI}
{
$IFDEF
WANYI}
ShowMessage(
'确认标识符 WanYi 是否定义'
);
{
$ENDIF
}
{.$UNDEF WANYI}
{
$IFDEF
WANYI}
ShowMessage(
'再次确认标识符 WanYi 是否定义'
);
{
$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.
1
2
3
4
5
6
7
8
|
begin
{
$IFDEF
DEBUG}
ShowMessage(
'调试模式'
);
{
$ENDIF
}
{
$IFDEF
RELEASE}
ShowMessage(
'发布模式'
);
{
$ENDIF
}
end
;
|
7、编译指令写在哪?:
编译指令可以写在代码页的任何地方, 不过在代码的不同区域有时也会不同;
譬如: {$APPTYPE GUI} 和 {$APPTYPE CONSOLE} 就只能写在工程文件里才有效.
{$APPTYPE GUI} 和 {$APPTYPE CONSOLE} 分别表示窗口工程和控制台工程.
其中 {$APPTYPE GUI} 是默认的, 所以很少见到它.
它甚至可以嵌入到代码行当中, 譬如 ActnColorMaps 单元就有这么一句:
1
2
3
|
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 , 然后看看最上面...
下面列出了这些默认设置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
{
$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
}
|