Platform Targets
Perry compiles TypeScript to native binaries for multiple platforms. Each target uses platform-specific UI libraries and rendering backends.
Supported Platforms
| Platform | Target Flag | UI Library | Rendering Backend |
|---|---|---|---|
| macOS | (default, no flag) | perry-ui-macos | Metal, CoreGraphics, CoreText |
| iOS | --target ios-simulator | perry-ui-ios | UIKit, CoreGraphics, CoreText |
| Windows | --target windows | perry-ui-windows | Direct2D, DirectWrite, DirectComposition |
| Linux | --target linux | perry-ui-linux | Cairo, Pango |
| Android | --target android | perry-ui-android | Android NDK |
| Web | --target web | (WASM) | WebAssembly, Canvas/WebGL |
Compile-Time Platform Detection
Perry provides the __platform__ compile-time constant. Code guarded by platform checks is dead-code-eliminated for non-matching platforms.
| Value | Platform |
|---|---|
| 0 | macOS |
| 1 | iOS |
| 2 | Android |
declare const __platform__: number;
function getDefaultFontSize(): number {
if (__platform__ === 0) {
return 13; // macOS — standard desktop size
} else if (__platform__ === 1) {
return 16; // iOS — larger for touch
} else if (__platform__ === 2) {
return 16; // Android — larger for touch
}
return 13;
}
Because __platform__ is resolved at compile time, the non-matching branches are stripped entirely from the binary. This means platform-specific imports and FFI calls in dead branches do not need to link.
Per-Platform FFI Crates
Each platform has dedicated Rust crates that implement the FFI functions using native APIs. These crates all export the same __wrapper_* symbols, so TypeScript code remains platform-agnostic.
Editor FFI crates:
| Platform | Crate | Key APIs |
|---|---|---|
| macOS | hone-editor/native/macos/ | CoreText for text shaping, Metal for GPU rendering |
| iOS | hone-editor/native/ios/ | CoreText for text, UIKit for input |
| Windows | hone-editor/native/windows/ | DirectWrite for text, Direct2D for rendering |
| Linux | hone-editor/native/linux/ | Pango for text, Cairo for rendering |
| Android | hone-editor/native/android/ | Android NDK Canvas, Skia |
Terminal FFI crates follow the same pattern in hone-terminal/native/.
Compilation Examples
# macOS (default target)
perry compile src/app.ts --output hone-ide
# iOS Simulator
perry compile src/app.ts --target ios-simulator --output Hone
# Web
perry compile src/app.ts --target web --output hone-ide.html
UI Testing by Platform
macOS — geisterhand
geisterhand is the UI automation tool for macOS Perry binaries.
# Capture screenshot
geisterhand screenshot --output /tmp/shot.png
# Click at pixel coordinates
geisterhand click 200 350
# Type text
geisterhand type "hello world"
iOS Simulator — AppleScript
For iOS Simulator targets, use osascript (AppleScript) to drive the Simulator app:
# Tap at coordinates in Simulator
osascript -e 'tell application "Simulator" to activate'
# Use Accessibility APIs or xcrun simctl for interaction
geisterhand does not work with the iOS Simulator — it only targets native macOS windows.
Output Artifacts
| Target | Output | Size (typical) |
|---|---|---|
| macOS | Static binary | 5-15 MB |
| iOS | .app bundle | 8-20 MB |
| Web | .html + .wasm | 2-5 MB |
| Auth server (macOS) | Static binary | ~2.8 MB |
All native binaries are statically linked — no runtime dependencies, no Node.js, no V8. The binary includes the Perry stdlib, platform UI library, and all FFI crates.