TypePHP: Swoole's AOT compiler turns PHP source into native binaries
Compile PHP to Native Binaries
At a glance
- What is it?
- TypePHP lowers PHP to C++17 and then to machine code, producing executables, PHP extensions or shared libraries. It supports a deliberate subset of PHP, ships under GPL-3.0, and is written in PHP itself.
- Who is it for?
- TypePHP fits teams that can keep a codebase inside its documented PHP subset and want native executables, extensions or libraries without an interpreter process. It is the wrong tool for an existing application that relies on features on the incompatible-feature list, and for anyone who needs drop-in compatibility with arbitrary dynamic PHP.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly PHP, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 17, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem TypePHP addresses: PHP that still pays interpreter costs
OPcache and the PHP 8 JIT both keep a bytecode layer. The README's comparison table puts TypePHP AOT against an opcode cache and against a trace-based JIT: TypePHP compiles to native machine code, has no per-process warm-up, and applies type-driven optimization across the whole program at compile time. The opcode cache column lists no type-driven optimization and a per-process warm-up; the JIT column describes limited, trace-based optimization and JIT warm-up.
The audience is narrow and specific. It is for engineers who already write PHP and want the same syntax to produce a native executable, a loadable PHP extension, or a shared library, and who are willing to trade PHP's dynamic corners for compile-time type information. The README states plainly that TypePHP "intentionally supports a defined, testable subset of PHP rather than claiming drop-in compatibility with every dynamic PHP program." That sentence should decide most adoption questions before any benchmark does.
A second motivation appears in the table: source protection. Compiled artifacts are native binaries rather than readable PHP files, while bytecode is described as reversible. If you distribute PHP code to customers you do not fully trust, that difference matters more than throughput.
How the compiler works: two phases, C++17, and reusable caches
The pipeline in the README is short enough to memorize. PHP source, .stub.php declarations and optional C or C++ sources go through parse, validate and declaration collection. Function bodies and constants are then lowered to C++17. A native compiler runs with reusable object and PCH caches, and the output is one of four things: an executable, a PHP extension, a shared library, or a WASI component.
The design detail worth understanding is the split between a prepare phase and a convert phase. Prepare builds the complete symbol model without allocating runtime cache IDs. Constants and declaration defaults keep their AST until convert, where they are lowered after every project symbol is known. The README says this two-phase arrangement keeps multi-file and self-hosted builds deterministic. Determinism is the payoff; the cost is that the compiler must hold the whole symbol model before it can emit anything.
At runtime the boundary is explicit. Dynamic values, internal functions, reflection and object metadata interoperate with the Zend runtime through PHPX, but user functions are not executed as Zend opcodes once compiled. So a TypePHP binary is not a stripped-down runtime: it links PHPX and libphp, and the README notes those must be present in the deployment package. The compiler itself is written entirely in PHP and is self-hosting: tpc is built by compiling the compiler's own PHP source with TypePHP, and the README describes the bootstrap chain as pure PHP with no C or C++ glue in the compiler.
Installing TypePHP and compiling a first file
The README does not print a package-manager install line, so treat the repository as the source of truth and check the Homepage at swoole.com/aot/ and the docs/ directory for the current bootstrap instructions. What the README does establish is the compiler's name, tpc, and that it is built by compiling the compiler's own source with TypePHP. The repository layout supports that reading: cli.php, package.php, bin/, src/, tests/, phpunit/, and a composer.json at the top level.
The README gives no end-to-end command transcript, so the only honest first exercise is to read the shipped examples before compiling anything of your own. They are ordinary PHP files, which is the point: examples/array.php, examples/closure.php, examples/binary-tree.php, examples/concat.php, examples/const.php, examples/const_expr.php, plus directories for attributes, C interop, bigint, cases and benchmarks.
A TypePHP source file is still PHP. The features the README highlights are additions on top of PHP 8.4 and 8.5 syntax, not a new language. Universal methods let you call methods on primitives, and the README gives these calls as the example:
$s->upper()
$arr->contains()
$big->mul(2)The README states that statically-known calls are resolved directly at compile time. Numeric locals are the other thing to look for when reading examples. Inferred int, float and bool locals use native C++ storage, and the README names std::any() as the escape hatch for an individual dynamic value. It also lists std::object(), std::ref(), std::expected() and std::unexpected() among the compile-time functions and keywords, alongside toObject(), toInt(), toString() and toArray(). When a file needs PHP's integer widening behaviour instead of native scalar storage, the README points to `use varint_types`. Expect strict calls everywhere: the README says TypePHP never enables weak scalar coercion, so `declare(strict_types=1)` is unnecessary.
Where TypePHP is the wrong tool
The compatibility model is the limitation, and the project is unusually direct about it. TypePHP supports a defined subset, and the README tells you to read docs/en/INCOMPATIBLE_PHP_FEATURES.md before adopting it for an existing application. That is a pre-adoption gate, not a footnote. If your codebase depends on anything on that list, the compiler will not be a drop-in replacement no matter how good the generated machine code is.
Deployment is the second constraint. Binary mode removes the need for the PHP CLI or a separate interpreter process, but the README states that the executable still embeds or links PHPX, libphp, and any configured native libraries, and those must be available in the deployment package. A single static binary is not what is being promised. Plan for a package, not a file.
There is also a typing cost. Always-strict calls and native scalar storage are the mechanism behind the numeric speedups, and they change how code behaves at the boundaries. Code that quietly relied on string-to-number coercion has to be rewritten or routed through std::any() or `use varint_types`. That is real work, and it is the kind of work that is easy to underestimate when the source file already looks like valid PHP.
Finally, the README describes TypePHP as under active development, and the repository's last push was on 2026-09-17, the day before this writing, with v0.9.0 released the same day. A 0.9 series compiler with a documented incompatible-feature list is a tool you evaluate against a subset you control, not one you point at a decade-old application.
TypePHP against OPcache and the JIT
The obvious alternative is not another language, it is staying on the standard PHP runtime with OPcache, or with the PHP 8 JIT enabled. The README's own table frames the difference: OPcache compiles to bytecode with a per-process warm-up and no type-driven optimization; the JIT produces machine code but only along traces, with a warm-up period and limited optimization; TypePHP produces native machine code with no warm-up and full-program, compile-time type information.
The practical divergence is what each one can emit. OPcache and the JIT run inside a PHP process. TypePHP emits a native executable, a loadable PHP extension, or a shared library from the same codebase, and it can also target WASI 0.2 and browser output through Jco according to the README. Neither OPcache nor the JIT produces a shared library you can link into something else.
The trade is compatibility for control. OPcache and the JIT accept essentially any PHP program you already run. TypePHP accepts a subset, documented in the incompatible-feature list, and asks you to keep types visible enough for the compiler to lower them. If your workload is I/O-bound and your profiles show little time in numeric or container-heavy code, the AOT path buys you source protection and a native entry point more than it buys you throughput. The README's own benchmark section is the place to check the numbers it claims, including the up-to-10x figure for strongly-typed containers against PHP arrays.
Licence and the cost of keeping up with a 0.9 compiler
TypePHP is GPL-3.0. That is a copyleft licence, and it governs the compiler. Whether your compiled artifact inherits obligations is a question for your own counsel, not for this article, but the licence identifier is public and unambiguous in the README badge and the LICENSE file. If you ship closed-source binaries, read the licence before you build a release process around tpc.
Upgrade cost is shaped by the release cadence visible in the repository. v0.8.1 landed on 2026-09-10, v0.8.2 on 2026-09-15, and v0.9.0 on 2026-09-17. Three releases in eight days is a fast-moving pre-1.0 series. The CHANGELOG.md at the repository root is where the differences between those versions are recorded, and it is the file to read before moving a build. The compiler is self-hosting, which cuts both ways: the bootstrap chain is pure PHP with no C or C++ glue, so the compiler is auditable in the language you already know, but any regression in the compiler also affects the build of the compiler itself.
Two more files matter for maintenance. phpstan.neon and phpunit.xml sit at the top level alongside a phpunit/ directory and run-tests.php, so the project carries static analysis and its own test harness. The tests/ directory is the reference for what the compiler is expected to accept. When you upgrade, that is the surface to compare against your own code.
Editorial conclusion
TypePHP fits teams that can keep a codebase inside its documented PHP subset and want native executables, extensions or libraries without an interpreter process. It is the wrong tool for an existing application that relies on features on the incompatible-feature list, and for anyone who needs drop-in compatibility with arbitrary dynamic PHP. Before adopting it, read docs/en/INCOMPATIBLE_PHP_FEATURES.md, confirm the deployment package carries PHPX and libphp, and check whether GPL-3.0 fits how you ship the compiled artifact.
Frequently asked questions
What is TypePHP?
TypePHP is an ahead-of-time compiler that translates PHP source into C++17 and then into native machine code, producing native executables, PHP extensions, or shared libraries. It keeps PHP syntax and adds compile-time type information so hot paths can be emitted as statically-typed C++.
Is TypePHP a loosely typed language?
No. TypePHP never enables PHP's weak scalar coercion, so declare(strict_types=1) is unnecessary, and inferred int, float and bool locals use native C++ storage. You can opt into a dynamic value with std::any() or into PHP integer widening with use varint_types.
Is TypePHP like C++?
The generated code is C++17, and the type system maps int, float and bool to int64_t, double and bool, but you still write PHP. The README also allows calling C++ functions from PHP and the reverse for performance-critical kernels.
Is TypePHP easier than Python?
The README does not compare TypePHP with Python in terms of learning difficulty. It does describe a Python bridge that generates IDE helpers for Python modules and converts Python scripts to TypePHP.
Is PHP still relevant in 2026?
The README does not discuss PHP's overall relevance. It positions TypePHP as an AOT compiler for a defined subset of PHP 8.4 and 8.5, aimed at native executables, extensions and shared libraries.
Community notes