← All questions

Turning a program into a binary

Raku++ can hand you a standalone executable. There are three ways, and they trade compile time against speed.

rakupp --exe    prog.raku -o prog     # native C++ — fastest, may fall back
rakupp --aot    prog.raku -o prog     # parse ahead of time, embed the AST
rakupp --bundle prog.raku -o prog     # embed source + interpreter — always works

Which one do I want?

--exe compiles your program to C++ and links it against the runtime. It is the fast one — 4× to 50× over the interpreter on arithmetic-heavy code with -O. Constructs the code generator does not handle yet make it fall back to bundling for that program, so it always produces a working binary; it just may not be the fast kind.

--aot skips parsing at startup by embedding the parsed AST. Same runtime speed as the interpreter, quicker to start, and it never falls back.

--bundle embeds your source and the whole interpreter. The most compatible: whatever runs under rakupp runs in the bundle, because it is the interpreter.

Add -O to --exe for the optimising code generator:

rakupp --exe -O prog.raku -o prog

-O is what turns integer loops into native arithmetic. On a tight numeric loop it is worth an order of magnitude; on IO-bound or string-shuffling code it buys close to nothing.

--exe says it cannot find a compiler

--exe and --bundle generate C++ and invoke a C++ compiler at run time — the one on your machine, when you build, not when Raku++ was built. If there isn't one, they fail.

This catches people who install a packaged rakupp (a release tarball, a distro package) onto a machine with no toolchain: the interpreter works fine and --exe does not. -e '…' and running a script never need a compiler.

Which compiler, and why it matters for speed, is in COMPILERS.md.

The binary is large

The linked runtime dominates. Stripping is the lever that works:

strip prog        # ~15% smaller

-Os does not help — the size is the runtime, not your code — and it costs speed. Use -O for speed and strip for size.

Does the binary need Raku++ installed?

No. --exe, --aot and --bundle all produce a self-contained executable. Copy it to a machine with no Raku++ and no Raku and it runs.

It is not cross-platform, though: a macOS build runs on macOS. Build on the target, or in CI for each target.

Will my program behave the same compiled?

That is the intent, and it is tested — tools/run-optbench.raku checks that the interpreter, --exe, --exe -O and Rakudo all produce identical output, and fails if any row diverges.

It is not a guarantee. The code generator is a second implementation of the language, and a divergence there is a bug we want reported: run your program both ways and compare.

rakupp prog.raku > a.txt
rakupp --exe prog.raku -o prog && ./prog > b.txt
diff a.txt b.txt

Startup time

A compiled binary starts in about 2ms. The interpreter is about the same, since it does not have a runtime to boot. If you are comparing against another Raku implementation, startup is one of the larger differences.

---

See also NATIVE.md for what compiles natively and OPTIMIZATION.md for what -O actually does.

Back to the FAQ index.