Raku in a mobile app
Raku++ compiled into an iOS or Android app. The app runs Raku programs on the phone itself, as native code: no server, no web view, nothing sent anywhere.
The engine becomes a library inside the app — a framework on iOS, a
.so on Android — and the app calls it through the same C API every
other host uses (rakupp.h).
Swift, Kotlin and Flutter's dart:ffi all reach it the same way.
Native, not WebAssembly #
On a web page the engine is WebAssembly. In an app it can be native code, which gives Raku programs more:
| Threads | start, await and hyper run on real threads; the WebAssembly build is single-threaded. |
| Recursion | as deep as the stack the app gives it — 5,000 nested calls on a 512 MB stack — where the WebAssembly build stops at about 200. |
| No bridge | the UI calls the engine directly, with no web view and no JavaScript in between. |
| Size | about 16 MB per architecture on iOS and 17–20 MB per ABI on Android; the stores send each device only its own. |
Neither form has a JIT: a phone app may not map executable memory, so Raku++
interprets, as rakupp does by default.
Build the engine #
There is no CMake preset for phones: the runtime's sources are compiled with
Xcode's clang or the Android NDK's, into an .xcframework for iOS
and a librakuengine.so per Android ABI.
| iOS | arm64 for devices; arm64 and x86_64 for the simulator; iOS 13+. A dynamic framework per slice, combined with xcodebuild -create-xcframework. |
| Android | arm64-v8a, armeabi-v7a and x86_64; Android 7 (API 24) and later. Static libc++, aligned to the 16 KB pages Google Play requires. |
The source list, the compiler and linker flags for both platforms, and the four small source changes that version 5.4.1 needs on them are in EMBEDDING.md.
Call it from the app #
rk_run runs a whole program and returns when it ends, so it goes
on a thread of the app's own, with a big stack, and never on the UI thread:
#include <rakupp/rakupp.h>
static void on_output(void* ud, const char* text, size_t len, int is_err) {
keep(text, len, is_err); /* copy: the bytes live only for this call */
}
static void* run_program(void* source) {
RkInterp rk = rk_new(NULL); /* a fresh interpreter per run */
int exit_code = 0;
rk_set_output(rk, on_output, NULL);
rk_set_input(rk, "", 0); /* or what the user typed */
rk_run(rk, (const char*)source, "main.raku", &exit_code);
rk_free(rk);
return NULL;
}
/* elsewhere, when the user taps Run */
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, 512u << 20);
pthread_create(&thread, &attr, run_program, (void*)source);
- Collect output on a timer. Keep what
on_outputcopies in a buffer guarded by a mutex, and let the UI take it every 40 ms or so: the output appears live, and a loop ofsays arrives as a few updates. Cap the buffer, so a runaway program cannot fill memory. - Input.
rk_set_inputfeeds a preset. For apromptthat waits for the user, as a terminal does, givestd::cina buffer that blocks until the app sends a line. - Stop. The 5.4.1 API has no interrupt yet. The Learn Raku app adds one — a flag the engine checks at every statement and loop iteration — and EMBEDDING.md describes it.
What a program can do on a phone #
- Most of the language, unchanged. Nearly every example in the Course of Raku runs as it does under
rakuppon a desktop. - Files are the app's own: its sandbox, and the working directory the app chooses for the run.
- Processes:
run,shellandProc::Asynccannot start anything on iOS. - Network: sockets work; HTTPS does not, because it goes through the system's OpenSSL, which neither platform offers an app.
The App Store and Google Play #
Apple's App Review guideline 2.5.2 allows an educational app to run code that the user writes, provided the app does not download code to run. Google Play restricts downloading native code, which an interpreter running programs typed into the app is not. In both cases the engine is inside the app as submitted.
See it running #
Learn Raku, the Course of Raku for iOS and Android, is built this way: every runnable example in the course has a Run button, a program that asks for input waits for the reader's answer, and there is a playground with the example programs from the Raku++ repository. Nothing in it needs a network connection.
Next #
- EMBEDDING.md — the C API, and the full recipe for both platforms.
- FAQ: Raku++ in an iOS or Android app — the questions that come first.
- Bindings — the same engine inside Python, the Wolfram Language, Go, Rust and C++.
- Raku on a web page — the WebAssembly form, with one script tag.