在Lazarus交流群中看见有人提出有关判断CPU架构问题,我把官方文档的链接发了过去。为了方便在未来更多使用Free Pascal的中文开发者使用,故撰写这篇文章用于整理资料。
官方文档请参见:Compiler defines during compilation
Free Pascal中提供了很多编译期间的符号,可以在编译时进行判断,来让程序在不同平台上表现出不同的行为。
系统环境 链接到标题
架构 链接到标题
Free Pascal还定义了一些符号来判断处理器的架构。例如,如果目标处理器是x86_64,那么会定义CPUX86_64。
{$IFDEF CPUX86_64}
// 这里的代码只在x86_64架构上执行
{$ENDIF}
表格 G.2: 使用 FPC 编译时可能的 CPU 定义
| 定义 | 定义时机 |
|---|---|
| CPU86 | Free Pascal 目标是 Intel 80x86 或兼容的 (16 和 32 位) |
| CPU87 | Free Pascal 目标是 Intel 80x86 或兼容的 (16 和 32 位) |
| CPU386 | Free Pascal 目标是 Intel 80386 或更高版本 |
| CPUI386 | Free Pascal 目标是 Intel 80386 或更高版本 |
| CPU68K | Free Pascal 目标是 Motorola 680x0 或兼容的 |
| CPUM68K | Free Pascal 目标是 Motorola 680x0 或兼容的 |
| CPUM68020 | Free Pascal 目标是 Motorola 68020 或更高版本 |
| CPU68 | Free Pascal 目标是 Motorola 680x0 或兼容的 |
| CPUSPARC32 | Free Pascal 目标是 SPARC v7 或兼容的 |
| CPUSPARC | Free Pascal 目标是 SPARC v7 或兼容的 |
| CPUALPHA | Free Pascal 目标是 Alpha AXP 或兼容的 |
| CPUPOWERPC | Free Pascal 目标是 32 位或 64 位的 PowerPC 或兼容的 |
| CPUPOWERPC32 | Free Pascal 目标是 32 位的 PowerPC 或兼容的 |
| CPUPOWERPC64 | Free Pascal 目标是 64 位的 PowerPC 或兼容的 |
| CPUX86_64 | Free Pascal 目标是 AMD64 或 Intel 64 位处理器 |
| CPUAMD64 | Free Pascal 目标是 AMD64 或 Intel 64 位处理器 |
| CPUX64 | Free Pascal 目标是 AMD64 或 Intel 64 位处理器 |
| CPUIA64 | Free Pascal 目标是 Intel Itanium 64 位处理器 |
| CPUARM | Free Pascal 目标是 ARM 32 位处理器 |
| CPUAVR | Free Pascal 目标是 AVR 16 位处理器 |
| CPU16 | Free Pascal 目标是 16 位 CPU |
| CPU32 | Free Pascal 目标是 32 位 CPU |
| CPU64 | Free Pascal 目标是 64 位 CPU |
| CPUI8086 | 表示 16 位 x86 目标 (i8086) |
操作系统 链接到标题
Free Pascal也定义了一些符号来判断目标操作系统。例如,如果目标操作系统是Windows,那么会定义MSWINDOWS。
{$IFDEF MSWINDOWS}
// 这里的代码只在Windows操作系统上执行
{$ENDIF}
表格 G.4: 使用目标操作系统编译时可能的定义
| 目标操作系统 | 定义 |
|---|---|
| AIX | AIX, UNIX |
| Amiga | AMIGA |
| Android | ANDROID |
| linux | LINUX, UNIX |
| freebsd | FREEBSD, BSD, UNIX, DRAGONFLY |
| netbsd | NETBSD, BSD, UNIX |
| openbsd | OPENBSD, BSD, UNIX |
| sunos | SUNOS, SOLARIS, UNIX |
| go32v2 | GO32V2, DPMI |
| MS-DOS 16 bit real mode | MSDOS (2.7.1 及更高版本) |
| Haiku | HAIKU |
| os2 | OS2 |
| NETWARE | NETWARE, NETWLIBC |
| Nintendo DS | NDS |
| emx | OS2, EMX |
| Solaris | SOLARIS |
| WII | WII |
| Windows (native NT) | NATIVENT |
| Windows (16-bit) | WIN16 |
| Windows (all) | WINDOWS |
| Windows 32-bit | WIN32, MSWINDOWS |
| Windows 64-bit | WIN64, MSWINDOWS |
| Windows (winCE) | WINCE, UNDER_CE, FPC_OS_UNICODE |
| Classic Amiga | AMIGA |
| Atari TOS | ATARI |
| Classic Macintosh | MACOS |
| PalmOS | PALMOS |
| BeOS | BEOS, UNIX |
| QNX RTP | QNX, UNIX |
| Mac OS X | BSD, DARWIN, UNIX, IPHONESYM |
编译器信息 链接到标题
表格 G.1: 使用 FPC 编译时可能的定义
| 定义 | 描述 |
|---|---|
| FPC_LINK_DYNAMIC | 当输出将动态链接时定义。这是在使用 -XD 编译器开关时定义的。 |
| FPC_LINK_STATIC | 当输出将静态链接时定义。这是默认模式。 |
| FPC_LINK_SMART | 当输出将进行智能链接时定义。这是在使用 -XX 编译器开关时定义的。 |
| FPC_PROFILE | 当向程序添加分析代码时定义。这是在使用 -pg 编译器开关时定义的。 |
| FPC_CROSSCOMPILING | 当目标 OS/CPU 与源 OS/CPU 不同时定义。 |
| FPC | 总是为 Free Pascal 定义。 |
| VER2 | 总是为 Free Pascal 版本 2.x.x 定义。 |
| VER2_0 | 总是为 Free Pascal 版本 2.0.x 定义。 |
| VER2_2 | 总是为 Free Pascal 版本 2.2.x 定义。 |
| VER3 | 总是为 Free Pascal 版本 3.x.x 定义。 |
| VER3_0 | 总是为 Free Pascal 版本 3.0.x 定义。 |
| VER3_2 | 总是为 Free Pascal 版本 3.2.x 定义。 |
| FPC_VERSION | 包含来自 FPC 的主版本号。 |
| FPC_RELEASE | 包含来自 FPC 的次版本号。 |
| FPC_PATCH | 包含来自 FPC 的版本号的第三部分。 |
| FPC_FULLVERSION | 包含来自 FPC 的整个版本号作为单个数字,可用于比较。对于 FPC 2.2.4,它将包含 20204。 |
| ENDIAN_LITTLE | 当 Free Pascal 目标是小端处理器(80x86、Alpha、ARM)时定义。 |
| ENDIAN_BIG | 当 Free Pascal 目标是大端处理器(680x0、PowerPC、SPARC、MIPS)时定义。 |
| FPC_DELPHI | Free Pascal 处于 Delphi 模式,要么使用编译器开关 -MDelphi,要么使用 $MODE DELPHI 指令。 |
| FPC_OBJFPC | Free Pascal 处于 OBJFPC 模式,要么使用编译器开关 -Mobjfpc,要么使用 $MODE OBJFPC 指令。 |
| FPC_TP | Free Pascal 处于 Turbo Pascal 模式,要么使用编译器开关 -Mtp,要么使用 $MODE TP 指令。 |
| FPC_MACPAS | Free Pascal 处于 Mac Pascal 模式,要么使用编译器开关 -Mmacpas,要么使用 $MODE MACPAS 指令。 |
调试模式 链接到标题
在 Free Pascal 中,{$IFOPT} 指令可以用于检查特定编译器开关的状态。如果该开关处于指定状态,则会编译其后的文本。如果该开关不处于指定状态,则编译会在对应的 {$ELSE} 或 {$ENDIF} 指令后继续。
例如,如果你想检查是否处于调试模式,可以使用以下代码:
{$IFOPT D+}
writeln('调试模式已激活');
{$ENDIF}
在上述代码中,如果编译器的调试模式开关(D+)已打开,那么 writeln('调试模式已激活'); 这行代码就会被编译。否则,这行代码会被忽略。
此外,你还可以在代码的开始部分添加以下代码,以便在 IDE 的调试模式下自动定义 DEBUG:
{$IFOPT D+}
{$DEFINE DEBUG}
{$ENDIF}
这样,当你从 IDE 中以调试模式运行应用程序时,DEBUG 就会被定义。你可以在代码的其他部分使用 {$IFDEF DEBUG} 来检查 DEBUG 是否已被定义。例如:
{$IFDEF DEBUG}
writeln('DEBUG 已定义');
{$ENDIF}
在上述代码中,如果 DEBUG 已被定义,那么 writeln('DEBUG 已定义'); 这行代码就会被编译。否则,这行代码会被忽略。这样,你就可以根据是否定义了 DEBUG 来决定是否编译某些代码,从而实现在调试模式下执行特定的代码。