Compile Perl 5 scripts and modules into standalone native binaries. No perl interpreter required at runtime.
perla parses real Perl, lowers it to Strada, and Strada compiles it to C. You get a single binary you can ship — no CPAN install, no DynaLoader, no libperl dependency.
Real Perl is wonderful for scripting and prototyping. perla is for the moments where you'd rather ship a compiled artifact than a script that depends on a runtime.
One statically-linked executable. No perl to install on the target, no version skew, no CPAN bootstrap, no cpanm on boot. Drop it on a server or into a container and run.
No perl interpreter warm-up. For short-lived scripts and CLI tools that get invoked constantly, the difference between 40ms perl startup and a sub-millisecond native exec matters.
Tight inner loops compile to real machine code. perla's backend is Strada — which consistently outruns Perl, Python, and Ruby on CPU-bound work. You choose the tradeoff: -O0 for fast compiles, -O3 for release.
__C__ { ... } drops inline C into a Perl sub. FFI to libc, libcurl, zstd, or a custom .so — without writing XS. All of Perl's value for rapid development, all of C's value for the 5% that needs it.
Runs well under Cannoli, Strada's preforking web server. perla-compiled handlers load as .so's — see the cannoli_perla bridge for how large-scale apps serve HTTP.
Sigils, regex, map/grep/sort, bless, AUTOLOAD, Moose-style has/extends/with, tie, typeglobs, format/write, try/catch — the idioms you know from Perl work here. The most-used modules (JSON, DBI, Carp, List::Util, Encode…) are native; the rest install from CPAN with perla-cpan.
perla -M lib/ builds every module in a tree to .pm.o once. Subsequent compiles of scripts that use them skip re-parsing the source — a big speedup on programs with deep use trees.
Reference counting with tagged integers — most data dies deterministically the moment its last reference drops. An automatic cycle collector reclaims indirect cycles (no Scalar::Util::weaken required), and a request arena is available for bump-allocated per-request workloads under Cannoli. Everything is debuggable with valgrind.
perla is mature, not magic. Most Perl compiles unchanged; here's where you still have to think.
local on some magical variables, or very baroque overload dispatch.eval STRING at runtime isn't a native interpreter. There's an opt-in path that shells out to a child compile, but it's not ergonomic. eval BLOCK (exception handling) works normally.use chains can take a minute or two at -O2. Warm the cache with perla -M lib/ and iterate at -O0.--keep preserves the generated .c for inspection, but there's no perl -d.perla isn't a toy subset. It tracks the parts of Perl people really use — the metaprogramming, the text-processing machinery, the modules — backed by 119 feature tests covering everything below.
bless, @ISA, SUPER::, AUTOLOAD, Perl's method resolution order, overload, DESTROY. Plus Moose-style has/extends/with and before/after/around — implemented natively, not via Class::MOP.
m//, s///, tr/// with /e /g /i /x /s, numbered and named captures, lookahead/lookbehind, backreferences, and embedded code (?{ ... }).
tie/untie/tied on scalars, hashes, arrays, and filehandles. Typeglob aliasing (*A = *B, *A = \$x), glob derefs, and stash iteration.
Perl's report templates, in full: picture fields, top-of-page headers, pagination, per-filehandle formats via select, $^A, and formline.
UTF-8 string semantics with the SVf_UTF8 flag, Unicode::Normalize (NFC/NFD/NFKC/NFKD), Encode transcoding, and UTF-8-aware substr/split/chop.
Tagged 64-bit integers, unsigned 64-bit (UV) arithmetic with overflow promotion, NVs, hex/oct, and srand/rand that's bit-for-bit compatible with perl.
try/catch (5.34) with a bound error variable, state variables, chained comparisons (5.32), goto LABEL, lvalue substr, and local on slices.
Native, no install: JSON, DBI (SQLite / MySQL / MariaDB / PostgreSQL), Carp, Data::Dumper, List::Util, Scalar::Util, Storable, Encode, File::Temp, Digest::*, MIME::Base64, Time::HiRes.
perla-cpan Module::Name fetches from MetaCPAN, resolves transitive dependencies, and compiles XS — pure-Perl and C-extension modules alike, no DynaLoader required.
Compile, run, ship. No preamble, no type annotations, no IDE setup.
# hello.pl use strict; use warnings; use JSON; sub greet { my ($name) = @_; return encode_json({ hello => $name, time => time() }); } print greet("world"), "\n";
$ perla -O2 -o hello hello.pl $ ./hello {"hello":"world","time":1755123456} $ file hello hello: ELF 64-bit LSB pie executable, x86-64, statically linked
That's the entire workflow. perla reads your .pl, resolves its use tree, lowers it to Strada, compiles to C, and links a binary. No cpanm install JSON, no Carton bundling, no fatpack. The JSON encoder is wired into perla's runtime as a native module.
Install Strada, build perla against it, then compile any Perl file.
# 1. build & install Strada $ git clone https://github.com/strada-lang/strada-lang $ cd strada-lang && ./configure && make && sudo make install # 2. build perla against the system Strada $ git clone https://github.com/strada-lang/perla $ cd perla && make && sudo make install # 3. compile any Perl file $ echo 'print "hi\n"' > hi.pl $ perla hi.pl hi