Skip to content
Moku
@moku-labs/native pages

iOS simulator

An unsigned .app for the simulator, the tools it needs, and why rebuilds work.

On this page

How it fits together

simulator: true builds the host's simulator slice. It never exports an archive, and it collects the .app folder instead of an .ipa. No Apple account is needed.

Example

scripts/native-sim.ts
import { native } from "../src/native";

await native.start();

const ok = await native.cli.doctor({ target: "ios" });
if (ok) await native.cli.build({ target: "ios", simulator: true });

await native.stop();
  1. An unsigned .app in dist-native/ios/.

What it needs

doctor checks each of these.

NeedInstallCheck
Rust targetsrustup target add aarch64-apple-ios aarch64-apple-ios-simios-tools (fail)
xcodegenbrew install xcodegenios-tools (fail)
CocoaPodsbrew install cocoapodsios-tools (fail)
An iOS platform and simulatorxcodebuild -downloadPlatform iOSios-platform (warn)

What the first build does

It runs tauri ios init once. Then it rewrites the build phase Tauri put in the Xcode project: that phase calls whichever runner Tauri detected, and none resolve inside Xcode. patchMobile puts in the absolute node and tauri.js pair instead.

Rebuilds

Building a kept tree again would fail twice over. The packager handles both.

FailureHandled by
Entitlements file … was modified during the buildpatchMobile writes CODE_SIGN_ALLOW_ENTITLEMENTS_MODIFICATION into the Xcode project and project.yml.
failed to rename app … Directory not emptyThe compile phase removes gen/apple/build first. A build symlink out of projectDir is refused.

A kept tree also follows the config. tauri ios build never runs xcodegen on it, so each patchMobile writes iosMinimumSystemVersion and ios.privacyManifest into both project files.

  • On an Intel Mac the slice is x86_64. Tauri's Intel simulator slice carries no -sim suffix.
  • exportMethod is ignored here. It only applies to device archives.
  • clean({ target: "ios" }) removes gen/apple. The next build runs init again.