Files
scriptc/docs/content/docs/platforms.mdx
Chris Tate 5aa450c6b2 docs: migrate to Geistdocs (#611)
* docs: migrate to Geistdocs

* Restore compiler files to main
2026-10-02 00:58:25 -05:00

123 lines
9.7 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: "Platform Support"
---
## Owned LLVM targets
The compiler runs natively and bundles its TypeScript checker and LLVM helper. Outputs selected with <code>--emit=ir|llvm|asm|obj</code> need no Node installation or external compiler, archiver, linker, or SDK. Supported assembly/object targets are macOS arm64/x64 (macOS 14.0 artifacts; helper needs macOS 15+), Linux x64/arm64 glibc, Windows x64 MSVC, Linux x64/arm64 musl, and WASI Preview 1. Executables additionally need the platform linker and SDK/sysroot; the helper emits the program object and the packaged runtime supplies objects/archives. Runtime development with <code>--sanitize</code> requires an external LLVM toolchain and a C compiler for instrumentation. Object output retains undefined runtime references and is not a library archive.
## Cross-compilation via zig
The installed compiler includes its host runtime pack. Other runtime packs are optional project dependencies, pinned to the same version as <code>scriptc --version</code>. Install the appropriate <code>@scriptc/runtime-&lt;target&gt;</code> package, such as <code>@scriptc/runtime-linux-arm64-gnu</code> or <code>@scriptc/runtime-wasm32-wasi</code>, and run the compiler from your project. You can also set <code>SCRIPTC_RUNTIME_PACK</code> to a pack directory, including with standalone compiler archives. Adding a pack does not require reinstalling the compiler. Assembly and object output do not require a runtime pack.
GNU/Linux compiler distributions and runtime packs support glibc 2.34 or newer. The LLVM helper is statically linked and does not require the build machine's libc or C++ runtime to be installed.
The installed host LLVM helper emits cross-target program objects and the matching runtime pack supplies precompiled support objects. Install [zig](https://ziglang.org) for Linux, Windows, and WASI cross-linking, then select the output target:
<dl>
<dt><code>SCRIPTC_TARGET=&lt;triple&gt;</code></dt>
<dd>The target triple; GNU/Linux targets include a glibc version.</dd>
</dl>
### Linux (arm64, x86_64)
```console
$ SCRIPTC_TARGET=aarch64-linux-gnu.2.36 scriptc build fib.ts -o fib-linux
$ file fib-linux
fib-linux: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, for GNU/Linux 2.0.0, with debug_info, not stripped
```
The runtime has native Linux backends throughout: the event loop is epoll (kqueue on macOS), the server stack and TLS (with distro CA-bundle probing) and `fs.watch` all have Linux implementations, verified against Linux Node in a container-based differential lane. `x86_64-linux-gnu.2.36` works the same way. For Alpine containers, use `<arch>-linux-musl`; Zig produces a statically linked executable for either AArch64 or x86_64, and the same static runtime surface is verified against Node on Alpine.
### Windows (x86_64)
```console
$ SCRIPTC_TARGET=x86_64-windows-gnu scriptc build fib.ts -o fib.exe
$ file fib.exe
fib.exe: PE32+ executable (console) x86-64, for MS Windows
```
The full corpus runs in a differential lane against Windows Node, including `--dynamic` programs and `child_process`. The Windows fixture lanes also exercise real loopback traffic through `net`, `http`, `https`, `tls`, `http2`, `dgram`, and `dns`, plus the native `fetch` implementation (including redirects, streaming bodies, compression, cancellation, and proxy handling).
Windows executable builds use the console subsystem by default. Set <code>--windows-subsystem=gui</code> for an application that owns its own window so Windows does not open an extra console window. This selects the PE subsystem at link time.
### iOS and Android (arm64, library mode)
Three mobile triples build **library-mode static archives** for an embedding app to link — a mobile app is the executable, so `scriptc build` without `--lib` rejects these targets with `SC3002`:
<dl>
<dt><code>SCRIPTC_TARGET=aarch64-apple-ios</code></dt>
<dd>iOS device archives (Mach-O, arm64). Requires a macOS host. The runtime pack was built with Xcode's iPhoneOS SDK. Every object carries <code>LC_BUILD_VERSION</code> with minimum OS 15.0.</dd>
<dt><code>SCRIPTC_TARGET=aarch64-apple-ios-simulator</code></dt>
<dd>iOS simulator archives (Mach-O, arm64, simulator platform). Requires a macOS host. The runtime pack was built with Xcode's iPhoneSimulator SDK. Same iOS 15.0 minimum.</dd>
<dt><code>SCRIPTC_TARGET=aarch64-linux-android</code></dt>
<dd>Android archives (ELF, arm64) compiled against the NDK's bionic headers at API level 26 — the embedder's <code>minSdkVersion</code> must be 26 or higher. Creating the archive uses the precompiled Android runtime pack; the embedding app uses the NDK for its final link.</dd>
</dl>
```console
$ SCRIPTC_TARGET=aarch64-apple-ios scriptc build --lib --profile app.profile.json
$ SCRIPTC_TARGET=aarch64-linux-android scriptc build --lib --profile app.profile.json
```
The full library-mode feature set applies: profile-declared exports and ABI entry points, host-callback channels (`callbacks` + `abi.callback_register_symbol`), contract sidecars, determinism fences, `abi.localize_runtime` (multi-instance archives — Mach-O localization runs the macOS host linker for both iOS platforms; Android rides the same in-process ELF localization as the Linux cross targets), and `abi.instance_per_thread` (thread-instanced state). The archive's external-symbol contract is unchanged: undefined references only to the target's C/math runtime and system APIs, resolved by Xcode's link against the selected SDK or the NDK clang link at API 26+. Simulator and emulator execution of the archive probes is part of the test matrix; device-architecture archives are build- and link-verified.
### WebAssembly (WASI Preview 1)
Set <code>SCRIPTC_TARGET=wasm32-wasi</code> to produce a standalone <code>.wasm</code> module. Without <code>-o</code>, <code>scriptc build hello.ts</code> writes <code>.scriptc/hello.wasm</code>. Compilation does not require Node. <code>scriptc run</code> requires Node.js 24 or newer on <code>PATH</code> to host the module with Node's WASI implementation, inherits stdio and environment, preopens the current working directory as <code>/</code>, and maps the host platform's temporary directory to the guest's <code>/tmp</code>. A built module can run in another WASI Preview 1 host instead.
WASI is a production LLVM target with the same language tiers as the native targets. Its 32-bit LLVM ABI supports collections, closures, exceptions, classes, checked dynamic values, async/await, promises, synchronous and asynchronous generators, timers, stdin/readline events, process-exit listeners, filesystem callbacks and promises, and the <code>--dynamic</code> QuickJS island.
The remaining executable boundary is host capability, not language coverage. WASI Preview 1 has no portable socket, process-spawn, OS-signal, network-interface, or filesystem-notification APIs. Networking/fetch, child processes, signal APIs, <code>os.networkInterfaces()</code>, and <code>fs.watch</code> therefore fail before linking with diagnostic <code>SC3002</code>. <code>--sanitize</code> and native FFI are unavailable too. Filesystem behavior is bounded by the host's preopens, and process/OS introspection follows WASI's reduced model.
## Cross-target limits
- `--sanitize` is a host-build lane.
- On <code>wasm32-wasi</code>, <code>scriptc build --lib --profile</code> emits a callable Wasm reactor instead of a static archive. See [WebAssembly Modules](/docs/wasm) for exports, host imports, initialization, and memory ownership.
- Mobile triples are library-mode-only: standalone executable builds reject with <code>SC3002</code>, and only the library-admissible surface (the async-free static tier a library archive links) is supported there.
- iOS targets build on macOS hosts only (Mach-O localization uses the host linker); Android archives build from any supported host with Zig.
- WASI cannot host APIs for capabilities missing from Preview 1, as described above.
## Summary
<table>
<thead>
<tr>
<th>Platform</th>
<th>How</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td>macOS arm64 / x64</td>
<td>native host helper + runtime pack</td>
<td>Full surface, <code>--dynamic</code>, sanitizer lane (external C route)</td>
</tr>
<tr>
<td>Linux arm64 / x86_64</td>
<td>native host helper + runtime pack; <code>SCRIPTC_TARGET=&lt;arch&gt;-linux-musl</code> selects musl</td>
<td>Static and dynamic surfaces incl. servers, TLS, fetch, fs.watch, and child_process; executable linking needs the matching libc/sysroot</td>
</tr>
<tr>
<td>Windows x86_64</td>
<td>native x64 MSVC helper + runtime pack</td>
<td>Static and dynamic surfaces incl. servers, TLS, fetch, and child_process; executable linking uses Zig’s Windows sysroot</td>
</tr>
<tr>
<td>iOS arm64 (device and simulator)</td>
<td><code>SCRIPTC_TARGET=aarch64-apple-ios</code> or <code>aarch64-apple-ios-simulator</code>, macOS host with Xcode</td>
<td>Library mode only (<code>--lib</code>): static archives for Xcode projects, iOS 15.0 minimum; multi-instance and thread-instanced profiles; simulator-executed test matrix</td>
</tr>
<tr>
<td>Android arm64</td>
<td><code>SCRIPTC_TARGET=aarch64-linux-android</code>, any supported host with Zig</td>
<td>Library mode only (<code>--lib</code>): static archives for Gradle/NDK projects, API level 26 minimum; multi-instance and thread-instanced profiles; emulator-executed test matrix</td>
</tr>
<tr>
<td>WebAssembly / WASI Preview 1</td>
<td>matching host helper + WASI runtime pack</td>
<td>Production LLVM target; full language and dynamic tiers, bounded by WASI P1 host capabilities</td>
</tr>
</tbody>
</table>