Skip to content

Build for Apple platforms

Checked against 0015716 on 2026-11-10. The files it covers are unchanged since.

One SwiftUI host in hosts/apple runs a niso page on every Apple platform: iOS and iPadOS, macOS, tvOS, visionOS and watchOS, with CarPlay inside the iOS app. One script, hosts/apple/build.sh, builds it for any of them: it compiles niso for the platform’s Rust target, builds the example pages, compiles the Swift host against the platform’s SDK, and leaves an ad-hoc signed Niso.app.

  • macOS with Xcode, and the simulator runtime for each platform you want to run on.
  • Rust from rustup. The script adds the aarch64-apple-* target it needs when it’s missing, so there’s no target to install by hand.
  • Node and pnpm, which build the example pages (examples/build.mjs).
  • The QuickJS-ng submodule: git submodule update --init.

--platform picks the platform; without it the script builds for the iOS Simulator. The page is an example name from examples/ (default counter). --no-launch only builds; the script promises it “touches no simulator”.

Terminal window
hosts/apple/build.sh --platform ios-sim --no-launch counter

The script prints the app’s path last: target/ios/Niso.app, with its widget extension (home screen widgets and the Live Activity) in PlugIns/NisoWidgets.appex.

The first build for a platform compiles niso for that platform’s Rust target into a build directory of its own under target/, so each platform costs a full release build of niso in time and disk. NISO_LIBDIR points the script at a prebuilt libniso_app.a and an include/ of its headers instead of running cargo.

Without --no-launch, the script also installs and launches the app:

  • Simulators (ios-sim, tvos-sim, visionos-sim, watchos-sim): on the simulator NISO_SIMULATOR names, by device name or UDID, booting it if needed. A name resolves on the newest runtime that has it. iOS defaults to the iPhone 17; the other platforms have no default, so set NISO_SIMULATOR for them (simulator.sh). xcrun simctl list devices available lists the names your Xcode has.
  • macOS: it opens the app.
  • Devices (ios, tvos, visionos, watchos): it only builds. Installing on a device needs provisioning, which the script doesn’t do.
Terminal window
hosts/apple/build.sh counter # the iOS Simulator's iPhone 17
NISO_SIMULATOR="iPad Air 13-inch (M4)" hosts/apple/build.sh counter
NISO_SIMULATOR="Apple TV 4K (4th generation)" hosts/apple/build.sh --platform tvos-sim counter
hosts/apple/build.sh --platform macos counter

Arguments the script doesn’t take, or everything after --, go to the app: -niso-tap X,Y taps at a point (in CSS pixels) after launch. A simulator app’s output goes to stdout.txt and stderr.txt beside the app.

Instead of an example, the app can carry an HTML page or an app library:

Option What the app runs
EXAMPLE examples/dist/EXAMPLE.js, built from examples/EXAMPLE/
--page DIR DIR/index.html; DIR is copied into the app and served at the app’s origin, https://<bundle id>.app.niso/
--page FILE that one HTML file, copied alone
--page FILE --root DIR FILE, with DIR as the root its scripts, stylesheets and modules load from
--app LIB a static library for the platform that exports niso_app_main (Native apps)

--name and --bundle-id set the app’s name and identifier (default Niso and dev.niso.host), and --out DIR where it goes. --debug builds a host that takes -niso-page FILE -niso-root DIR at launch, to run a page from anywhere on disk. NISO_ENGINE=porffor compiles the example’s script into the app ahead of time with Porffor instead of running it on QuickJS (see JavaScript).

CarPlay is part of the iOS app, as an audio app. It shows a list template built from the page’s carplay.list surface, and the system’s Now Playing screen for the page’s media session; examples/radio declares its stations this way. It has been verified in the app only, by tests/carplay/check.sh: with Xcode 27.2 the simulator’s CarPlay window was unavailable, so no CarPlay screen has shown these templates yet. See Surfaces and the Apple host notes.

Every platform draws buttons, switches, pickers and text fields with its own controls. tvOS has no spatial navigation or focus ring yet, watchOS has fixed colors on black and one text size, and visionOS has no ornaments. The Apple host notes have the full table of input, controls and limits per platform, and Apple platforms covers what only Apple’s platforms have.