pxx
One from-scratch compiler for Pascal, C and Python: native static binaries for Linux (x86-64, i386, aarch64, arm32, riscv32), wasm32, and ESP32-S3/C3 firmware. Own RTL, ELF writer and linker; self-hosting. Beta 0.1 'Blaise'.
- Active · last change 11-1-2026
- ★ 4 on GitHub
README
PXX
One compiler, written from scratch, for Pascal, C and Python, producing native programs for Linux and the ESP32.
It has its own runtime, ELF writer and linker, so the output is a finished
static executable with no assembler, no ld, no libc and no interpreter. It
compiles itself to a byte-identical binary.
Save this as primes.py. It's plain Python, nothing PXX-specific:
def primes(n):
sieve = [True] * (n + 1)
out = []
for i in range(2, n + 1):
if sieve[i]:
out.append(i)
for j in range(i * i, n + 1, i):
sieve[j] = False
return out
ps = primes(100)
print(len(ps), "primes below 100, the last is", ps[-1])Then, on x86-64 Linux, with the beta 0.1 release:
sha256sum -c SHA256SUMS && tar xzf pxx-v0.1.0-beta.1.tar.gz
cd pxx-v0.1.0-beta.1 && ./install.sh --yes
./pxx ../primes.py ../primes && ../primes25 primes below 100, the last is 97That primes is a 515 KB static ELF executable with the same output as
CPython. Download: v0.1.0-beta.1 "Blaise".
- Three languages, one backend: Pascal (the Free Pascal dialect, solid), C (solid: SQLite, Lua, QuickJS, zlib, the Tiny C Compiler and BusyBox compile unmodified and match GCC's build), and Nil Python (ordinary Python compiled ahead of time; best effort).
- Targets: x86-64, i386, aarch64, arm32, riscv32 and wasm32, plus native firmware for the ESP32-S3 and ESP32-C3. On real C3 and S3 boards every example passed, Python calling Pascal ran on the C3, and 300 HTTP fetches over real Wi-Fi on the S3 ran with 0 errors.
- How it was made: one person's architecture, decisions and hardware testing; the code was written by AI coding agents under that direction, and every commit says so.
The Pascal side covers a tested Object Pascal subset: classes, generics, overloads, operators, exceptions, RTTI and C interop, with experimental BASIC, Rust and Zig frontends beside the main three. The long-term direction is a multi-language native compiler sharing one IR and backend.
Home: https://pxxc.org, the documentation site, published from this
repository. Source: https://github.com/yoctobyte/pxx. Those two are the
only official sources; nothing else distributes PXX. (PXX is a provisional
name; the compiler binary is still compiler/pascal26. Naming things is the
one compiler problem not solved by recursion.)
Looking for sponsors
Development is ongoing. The first beta, 0.1 "Blaise", is
published; work continues on master. We are looking for sponsors to
help sustain it. What exists
today: a self-hosting Pascal compiler, mostly on par with Free Pascal's
dialect, for the common Linux CPU targets and the ESP32, with C and Nil Python
frontends alongside. What continued development would bring: memory-leak
hardening across every target, Nil Python maturity, and more platforms. If you
or your organisation would fund that, open an issue at
https://github.com/yoctobyte/pxx/issues titled "Sponsorship".
⚠️ Security warning — do not expose to a network
PXX is early, unaudited, experimental software. The compiler, its runtime, and its networking code almost certainly contain bugs — including ones that could be exploited over a network connection, whether the program acts as a server or a client, and whether the input comes from a remote peer or a file it fetches.
Do not build or run any publicly reachable network service with software compiled by PXX, and do not point a PXX-built client at untrusted remote hosts. Treat anything it produces as suitable only for local experimentation on inputs you fully control.
This restriction stands until the compiler, runtime, and networking stack have been independently tested, hardened, and reach a mature, reviewed state — and even then the software is provided without any warranty and with no liability on the authors (see License and LICENSE.md). If you choose to ignore this, you do so entirely at your own risk.
Highlights
- Self-hosting:
makerebuilds the compiler through the checked-in PXX seed and requires a byte-identical fixedpoint — at the default optimisation level — before replacing it. - Small direct ELF output: benchmarks report Pascal Hello World in both the
managed-default string mode and the frozen
-uPXX_MANAGED_STRINGcompatibility mode; see the newest run in the benchmarks directory. - Fast pipeline: one in-memory frontend-to-ELF path, no assembler or linker subprocess. See the newest run in the benchmarks directory.
- Pascal + C interop: local C files can be compiled into the same output, and supported C headers can be imported directly.
- Wrapper-free Nil Python C calls:
.npycan importsqlite3directly and run SQLite CRUD without a Pascal wrapper. - ESP32, in Pascal and in Python: PXX compiles Pascal, and Nil Python
(Python written the MicroPython way, compiled ahead of time with no
interpreter on the chip), to native code for the ESP32. The output is an
ESP-IDF component, so it builds against Espressif's own SDK. On silicon, the
examples have run on an ESP32-S3, an ESP32-C3 and a classic ESP32. Nil Python
gets MicroPython's module names (
machine,time.sleep_ms,network,urequests,ssl), and micropython-lib's ownumqttcompiles unchanged; the C3 has joined Wi-Fi and made HTTPS requests with a checked certificate. Memory stays level over long network soaks, each checked against a deliberate leak../espide.shis a small IDE that detects the chip, builds, flashes and monitors. Start at ESP32 and MicroPython code on PXX.
Quick Start
Prerequisites: Linux x86-64 and GNU make. FPC is needed only for bootstrap or
recovery builds.
From a release tarball (pxx-<version>.tar.gz), unpack it and set up in
place. There is no stable_linux_amd64/ in a tarball; its compilers are
compiler/pxx-<arch>, one per host, and compiler/pascal26 is the x86-64 one:
tar xzf pxx-<version>.tar.gz && cd pxx-<version>
./install.sh --yes # writes ./pxx: the compiler plus the library roots
./pxx test/hello.pas /tmp/hello && /tmp/hello
./selfcheck.sh # rebuilds every shipped binary; must match MANIFEST.sha256make and make test work in the tarball as they do in a checkout. The rest
of this section is for a git checkout.
A fresh checkout already ships a working compiler at
stable_linux_amd64/default/pinned, so you can compile something before you
build anything. ./install.sh is the friendly setup path — it checks that a
compiler runs on this host and writes a ready-to-use ./pxx wrapper in the
project root (--yes to skip the prompts, --no-path to skip the PATH
offer); the documentation's Install page leads with
it. The recipes below are the from-source path, and ./pxx in the
documentation's examples is the wrapper that script writes — this README uses
./compiler/pascal26, which is the same compiler after make.
During the
0.xbeta there is no stable tag yet. Use the Current recipe below; the stable-tag one is what to use once tags exist. The command is written to be a no-op rather than an error in the meantime, because a baregit checkout ""fails with "empty string is not a valid pathspec" — which reads as a typo and sends a first-time reader hunting for one.
Latest stable (recommended, once a stable tag exists) — clone, then check out the newest stable release tag:
git clone https://github.com/yoctobyte/pxx
cd pxx
TAG="$(git tag -l 'v*.*.*' | awk '!/-/' | sort -V | tail -n1)" # newest stable tag
if [ -n "$TAG" ]; then git checkout "$TAG"; else echo 'no stable tag yet — staying on master'; fi
cp stable_linux_amd64/default/pinned compiler/pascal26 # seed: make refuses without it
make
make testCurrent — the tip of master is the live tree (passes its gates; ahead of
the last stable tag, and during the beta it is the only tree there is). Skip
the checkout to track it:
git clone https://github.com/yoctobyte/pxx && cd pxx
cp stable_linux_amd64/default/pinned compiler/pascal26 # seed: make refuses without it
make && make testA fresh clone has no compiler/pascal26; make stops with "self-hosted
compiler seed missing" until it is copied from the pin as above (or built by
FPC with make bootstrap). Accept the build once make prints
converged after N round(s).
Bootstrap from FPC (first build on a fresh machine, or recovery):
sudo apt install fpc
git clone https://github.com/yoctobyte/pxx
cd pxx
make bootstrap
make test
make test-nilpy
make fpc-checkThe bootstrap path reseats compiler/pascal26 only after the self-built
compiler reaches byte-identical fixedpoint. That build passes no -O flag, so
the property proved is "it reproduces itself at the default optimisation level"
— a narrower and more accurate claim than "it reproduces itself".
A release is a git tag plus a prebuilt tarball (full source + RTL/PCL + host binaries + docs in one archive). Tags mark the stable points; the tarballs exist mainly for offline use, packaging, and distro repackaging — cloning is the primary path.
Using The Compiler
Compile and run a Pascal source file:
./compiler/pascal26 test/hello.pas /tmp/hello
/tmp/helloEnable compiler tracing:
./compiler/pascal26 --debug source.pas /tmp/outOptional PATH symlink for active development:
mkdir -p "$HOME/.local/bin"
ln -sfn "$PWD/compiler/pascal26" "$HOME/.local/bin/pxx"Optional PATH symlink for the latest recorded stable compiler (git checkout
only; from a tarball, run ./install.sh and answer yes to the PATH offer):
mkdir -p "$HOME/.local/bin"
ln -sfn "$PWD/stable_linux_amd64/default/latest" "$HOME/.local/bin/pxx"Demo: build busybox with pxx
pxx builds busybox as one translation unit and links it
itself: a static binary, no libc. busybox is GPL-2.0 and is not in this
repository or the tarball. Fetch it yourself; the version this is tested
against is 1.36.1 (git commit 1a64f6a20aaf6ea4dbba68bbfa8cc1ab7e5c57c4):
curl -LO https://busybox.net/downloads/busybox-1.36.1.tar.bz2 # sha256 b8cc24c9...de314
tar xjf busybox-1.36.1.tar.bz2
# or: git clone https://git.busybox.net/busybox && git -C busybox checkout 1a64f6a20aaf
PXX_BUSYBOX_DIR=$PWD/busybox-1.36.1 tools/busybox_diff.sh --build-only \
--applets "cat echo ls wc" --out ./busybox-pxx
./busybox-pxx/busybox_x86_64 echo hello--build-only prints the applet list, runs one smoke applet, and leaves the
binary in --out. Configuring the tree needs gcc on the host. That step is
busybox's own make, which builds kconfig and the link map the unity's file
list is read from, and busybox's Makefile calls gcc. It runs once per applet list; after
that, --build-only needs no gcc at all. Without --build-only the script is
the full differential test against a gcc build of the same source. In a git
checkout, tools/install_lib_candidates.sh busybox fetches the pinned commit to
the default location.
Documentation
- Public documentation — install, getting started, language, features, targets, library, and reference pages. Published at https://pxxc.org/docs/; the Markdown here is the source it renders.
- Internal documentation — plans, progress tickets, legacy command-line and
dialect notes, developer docs — is in the repository's
devdocs/. It is not part of a release bundle. - Agent instructions — guidelines and workflow for AI agents working on this repo (repository only).
Repository Layout
agents/- shared AI-agent instructions (agents/AGENTS.md) and generated code map.benchmarks/- dated benchmark snapshots.compiler/- compiler source, the checked-in seed, andbuiltin/(the compiler-specific runtime unit auto-included into compiled programs: heap allocator,Str/Val, variant helpers).docs/- public website documentation.devdocs/- project state, plans, progress tickets, and historic handovers (repository only; not in a release bundle).lib/- Pascal library units used by tests and demos (rtl/,pcl/).stable_linux_amd64/- stable/recovery compiler binaries. The default channel uses managedAnsiString; historical managed/frozen channels may remain for compatibility.test/- regression tests, fixtures, and manual harnesses.tools/- repository maintenance helpers.
License
- Compiler and tools: Mozilla Public License 2.0.
- Runtime and libraries (
lib/rtl,lib/pcl,lib/crtl,lib/asmcore,compiler/builtin): zlib — the code embedded in binaries the compiler produces places no obligations on your programs. - Examples: 0BSD. Docs: CC BY 4.0.
See LICENSE.md for the per-directory map and CONTRIBUTING.md for the DCO sign-off required on contributions.
The compiler remains experimental: do not use it for security-sensitive, safety-sensitive, financial, legal, medical, or infrastructure work, and do not expose software built with it to a network (see the Security warning near the top of this README).
Acknowledgements
PXX depends on Free Pascal for bootstrap and on the Lazarus/FPC ecosystem as a compatibility reference.

