FPC compatibility
PXX targets full FPC-language compatibility — the Object Pascal language as Free Pascal accepts it. It does not aim at parity with the rest of FPC's world: the FPC RTL and package ecosystem, the object-file format, and the command-line interface are out of scope by design.
What usually ports well
Small Pascal programs using ordinary declarations, routines, records, arrays, classes, basic generics, exceptions, and simple units are the best fit.
{$mode objfpc} and -Mobjfpc are accepted as compatibility markers, as are
fpc, tp, delphiunicode and pxx — PXX has one dialect and they all map
onto it. {$mode delphi} is the one marker that changes behavior (two deltas,
listed under modes).
Pascal dialects outside the FPC/Delphi family are not compiled as if they were
inside it: {$mode iso} and {$mode extendedpascal} warn, {$mode macpas} is
an error, and an unrecognised mode name is an error. Support for those is
deferred rather than refused — see modes
for why MacPas is the one that errors.
Porting checklist
Start with a small, direct compile:
./pxx program.pas program
If the program uses local units, add their directories explicitly:
./pxx -Fusrc -Fusrc/common program.pas program
For code that probes FPC identity symbols or expects FPC-style conditional branches, try the curated compatibility define set:
./pxx --mimic-fpc -Fuvendor/lib program.pas program
--mimic-fpc is opt-in. It is meant for FPC-oriented library code that chooses
implementation branches by compiler identity. Do not use it as a blanket default
for every PXX project, and do not use it to decide whether code is running under
real Free Pascal.
Identity symbols
| Symbol | Meaning |
|---|---|
PXX |
Defined by PXX. |
FPC |
Not defined by PXX. Reserved for actual Free Pascal builds. |
Use this pattern for compiler-specific code:
{$ifdef PXX}
{ PXX-specific path }
{$endif}
{$ifdef FPC}
{ Free Pascal-specific path }
{$endif}
Important differences
- The FPC RTL and package ecosystem are not bundled as compatible units.
- The CLI is PXX-specific; it does not emulate the full FPC command line.
- Unit/object/package binary compatibility with FPC is not provided.
- Some FPC directives are accepted only as comments or compatibility markers.
- Overflow (
{$Q+}), range ({$R+}), and IO ({$I+}) checking are implemented but opt-in per region and off in the lax default; several other compile-switch states are still inert markers. - On the ESP targets (xtensa, riscv32)
RealmeansSingle, notDouble— it is the target's native float depth, deliberately. FPC makesRealaDoubleeverywhere. See Types. - Only tested project units and examples should be treated as supported.
Hint directives
FPC hint modifiers on const, type, and routine declarations are accepted, and
deprecated may carry a message string:
const OldLimit = 100 deprecated;
type TLegacy = Integer platform;
procedure OldWay; deprecated 'use NewWay';
procedure Probe; experimental;
deprecated, platform, experimental, unimplemented, and library parse on
those declarations. They are accepted for source compatibility; PXX does not yet
emit a usage warning for them, and they are not accepted on var declarations.
These are one group among several. Which routine directives are inert, which
change what is compiled, and which are rejected outright is tabulated under
routine directives — varargs in particular
does not parse at all and needs removing when porting. Every calling-convention
spelling now parses in every position, stdcall included, and so do the inert
FPC directives noreturn, nostackframe, noinline, far, near and
local.
Common fixes
Prefer these changes when moving small FPC examples to PXX:
- Replace implicit package assumptions with explicit
usesclauses and-Fusearch roots. - Keep compiler-specific branches under
{$ifdef PXX}or{$ifdef FPC}. - Avoid depending on FPC's full RTL surface unless the needed unit exists in
lib/rtl. - Build C-header or imported-library experiments separately from the first Pascal port; get the Pascal-only slice compiling first.