Command line
The installed wrapper is normally called as:
pxx [options] source [output]
From a checkout, use:
./pxx [options] source [output]
The wrapper created by install.sh calls the pinned compiler and adds bundled
library roots. The underlying compiler executable is still named
compiler/pascal26.
Source and output
The frontend is selected by the source file's extension: .pas/.pp for
Pascal, .c for C, .npy or .py for
Nil Python, and .asm for the assembly-source
frontend.
With an output path, PXX writes the executable there and emits a matching map file. Without an output path, it derives one from the source name and refuses to overwrite the source.
An output path ending in .o also selects object-output mode, the same as
passing --emit-obj. An output path ending in .so selects shared-library
mode, the same as passing --shared.
Options
| Option | Effect |
|---|---|
--target=ARCH |
Select x86_64, i386, aarch64, arm32, riscv32, or xtensa. |
--xtensa-abi=call0|windowed |
Select the Xtensa call ABI. |
--xtensa-cpu=lx6 |
Use the older ESP32 LX6 software divide/mod profile. |
--xtensa-fpu |
Use Xtensa hardware single-precision float operations where supported. |
--esp-profile=bare |
Select the bare-metal ESP platform profile for riscv32 or xtensa. |
--emit-obj |
Emit a relocatable object (.o) instead of a linked executable, on any target. Same as an output path ending in .o. |
--shared |
Emit an ET_DYN shared library (.so) instead of an executable. x86-64 only; introduced for and validated with the .asm assembly-source frontend. Same as an output path ending in .so. |
-S |
Also write <output>.s, a best-effort x86-64 disassembly text dump of the emitted code. Additive — the normal output (executable, --emit-obj, or --shared) still happens. x86-64 only. |
-g |
Emit DWARF debug information. |
--debug |
Print compiler tracing diagnostics. |
--dump-ir |
Print lowered IR while still emitting output. |
--dump-rtti |
Print generated RTTI tables while still emitting output. |
-dNAME |
Define a conditional compilation symbol. |
-uNAME |
Undefine a conditional compilation symbol, except PXX. |
-FuDIR |
Add a Pascal unit search root. |
-IDIR |
Add a C include directory and a Pascal unit search root. |
-Mobjfpc |
Accept the Object Pascal compatibility mode marker. |
--threadsafe |
Use atomic refcounts for managed strings and arrays. On x86-64, i386, aarch64, and arm32 only. |
--no-auto-var |
Disable auto-typed variable declarations. |
--no-lazy-var |
Disable inline/lazy variable declarations. |
--system-libs |
Disable the Magic Link auto-pull mechanism and link C dependencies dynamically. |
--system-libs=stems |
Granular opt-out: dynamically link listed comma-separated C libraries (e.g. m,pthread), keeping the rest magic-linked. |
-nostdinc / --nostdinc |
Disable adding default C header search directories. |
Strictness and dialect
PXX is lax by default and turns FPC-parity checks on individually. See the
compiler modes page for the whole lax → --strict → granular →
--mimic-fpc model; each flag below is documented there in context. The
directive column names the in-source directive with the same
effect where one exists.
| Option | Effect | Directive |
|---|---|---|
--strict |
FPC-parity strictness umbrella (currently the routine-visibility check below). | {$STRICT ON} |
--strict-fpc |
The FPC-parity umbrella: --strict-case, --strict-operator, --strict-visibility and --require-forward together — the checks that match FPC and are proven against the real FPC corpora. --strict-overload is deliberately not included; see modes. |
{$STRICT_FPC ON} |
--require-forward |
A routine must be defined above its call, forward;-declared, in an interface section, or be a class method — no whole-source pre-scan. First check under --strict. |
{$STRICT ON} |
--strict-overload |
Require explicit overload; on overloaded routines. |
{$STRICT_OVERLOAD ON} |
--permissive-overload |
Relax the overload marker requirement (the default). | {$STRICT_OVERLOAD OFF} |
--strict-operator |
FPC-parity rejection of = / <> on class operands (lax default allows them). |
{$STRICT_OPERATOR ON} |
--strict-case |
FPC-parity case-label diagnostics: inverted ranges, duplicate/overlapping labels. |
{$STRICT_CASE ON} |
--strict-visibility |
Enforce private / protected / strict member access (lax default parses the markers but grants access anywhere). |
{$STRICT_VISIBILITY ON} |
--lax-decl-order |
Opt out of declare-before-use gating for forward-visible globals (strict/FPC-parity is the default). | {$DECLORDER OFF} |
--auto-locals |
Assignment to an undeclared name declares a routine-local inferred-type var instead of erroring. Off by default (masks typos). | {$IMPLICITVARS ON} |
--mimic-fpc |
FPC-compatibility preset: the curated FPC define set plus --require-forward, {$I+}, and --strict-visibility. See FPC compatibility. |
{$MIMIC FPC} |
Runtime and codegen
| Option | Effect |
|---|---|
-O0 … -O3 |
Optimization level. -O2 is the proven default; -O3 carries newer, still-promoting passes. -g implies -O0 unless an -O level is given explicitly. |
--no-default-rtl |
Do not pull the default standard-unit surface (textfile + builtin). Used by the compiler self-build. |
--no-div-check |
Opt out of the integer div/mod pre-divide zero check (default on: divide by zero raises a clean runtime error rather than a raw SIGFPE). |
--no-signals |
Opt out of the default signal runtime (graceful SIGINT/SIGTERM dispatch + SetSignalHandler). PC targets only. |
--no-unhandled-handler |
Do not install the default unhandled-exception handler. |
--no-strict-ir |
Opt out of the self-host IR guard (the hard error on any unlowered IR node). For an in-development frontend only. |
--strict-ir |
Accepted no-op: the IR guard is the default now. Kept so existing invocations keep working. |
--map / --no-map |
Force the map file next to the output on or off. A map is written by default when an output path is given. |
--no-shims |
Refuse every mimic_<module> substitution — an import must resolve to a real unit of that name or fail. Turns "compiled without compatibility shims" from a claim into a checked property. Nil Python only; see shims. |
--max-stack-frame=N |
Set the oversized-stack-frame warning threshold in bytes (=0 disables it). |
--werror / -Werror |
Promote any warning to a fatal error. |
--xtensa-soft-divide / --xtensa-cpu=lx6 |
Route div/mod through software helpers (ESP32 classic LX6, no hardware divide). |
--experimental-ir-codegen is accepted as a deprecated no-op (IR is the only
backend).
Diagnostics and internal flags
These serve compiler development and self-inspection, not normal builds. Use them only when directed.
| Option | Effect |
|---|---|
--dump-cpp |
Dump the intermediate C++-ish form. |
--proc-map |
Dump the procedure map. |
--selftest |
Run the built-in self-test. |
--measure-inline / --measure-regcall |
Emit inline / register-call instrumentation. |
--warn-missed-fold |
Warn on constant-fold opportunities the optimizer missed. |
--warn-self-result |
Warn when a parameterless function's bare own name is read as its Result. |
--warn-uses-leak |
Warn whenever a name resolves through a unit not reachable by the non-transitive uses rule. Read-only measurement — resolution itself is unchanged. |
Search paths
The wrapper created by install.sh already passes the bundled lib/ roots.
Use -Fu for project-local units:
./pxx -Fusrc -Fulib/more app.pas app
Search roots are checked in flag order before the default library roots. That lets a project override or add units deliberately without changing the checkout.
Use -I for C headers. It also feeds the Pascal unit search path, which is
useful for generated bindings that sit next to the imported header:
./pxx -Iinclude main.pas main
Examples
./pxx hello.pas hello
./pxx -g hello.pas hello
./pxx --target=aarch64 hello.pas hello.a64
./pxx -dDEBUG hello.pas hello
./pxx -Fusrc -Iinclude app.pas app
./pxx --target=riscv32 --esp-profile=bare main.pas main.o