Build iOS Applications on Linux
Once can cross-compile native Apple targets on Linux using Swift and the Darwin
Swift SDK installed by xtool. Once still owns compilation,
linking, resource packaging, caching, and action scheduling. It does not run
xtool dev build behind the scenes.
The omarchy-apple-dev project provides an installer and Linux replacements for Apple resource tools. Its installer supports Omarchy's Arch-based environment on ARM64 and x86_64. Once's integration uses the installed tools and SDK rather than depending on that distribution's package manager.
Install the Toolchain#
Follow omarchy-apple-dev's installation guide. You need:
- A Linux Swift toolchain matching the Swift version in the selected Xcode.
- An xtool Darwin SDK built from your own Apple-provided
Xcode.xipdownload. rcodesignfor ad-hoc bundle signing.- The Linux
actool,momc, andibtoolcompatibility tools when your targets use asset catalogs, Core Data models, storyboards, or xibs. Their supported resource formats are determined by omarchy-apple-dev, not by Once. llvm-lipoonPATHif you build multi-architecture libraries. The xtool toolset supplies its linker and archiver but does not always include lipo.
Apple's SDK is not downloaded or redistributed by Once. Obtain Xcode from Apple with an Apple ID and install the SDK with xtool:
xtool sdk install /path/to/Xcode.xip
swift sdk listThe SDK list must include darwin. Run the installer with your downloaded
Xcode archive to also install the compatibility tools:
XCODE_XIP=/path/to/Xcode.xip ./install-toolchain.shUse the Swift toolchain's own Clang when installing the SDK. Host Clang headers
from a different compiler version can make SwiftUI fail to compile. Once
resolves both Swift and Clang from the active Swift toolchain for its actions.
If your toolchain requires a compatibility LD_LIBRARY_PATH, Once passes it
through to compiler and resource actions and includes it in their cache identity.
Build a Starter#
Materialize the Linux starter in an empty directory:
once edit materialize-example apple_application apple-application-linux
once build HelloThe starter links a Swift library into an iOS application. Both targets use:
[target.attrs]
platform = "ios"
sdk_variant = "device"
minimum_os = "17.0"Set sdk_variant = "device" on dependencies as well as the application.
The default remains "simulator"; Once does not silently change it on Linux.
An iOS device target defaults to ARM64 even on an x86_64 Linux host. Library
archs overrides still apply.
Once discovers SDK and Swift resource paths through
swift sdk configure darwin <target-triple> --show-configuration. It uses the
SDK's Mach-O linker and archiver, rather than the host's ELF tools. SDK contents,
tool binaries, and the compiler environment contribute to Linux action cache
identity. Changes to an SDK therefore invalidate affected actions.
To pin an installed SDK, set the existing xcode_developer_dir attribute to the
SDK bundle's Developer directory on every relevant target:
xcode_developer_dir = "/home/me/.swiftpm/swift-sdks/darwin.artifactbundle/Developer"This selects SDK metadata and tools, not macOS executables extracted from Xcode.
After switching Swift installations, re-register the matching SDK using
omarchy-apple-dev's install-toolchain.sh --repair.
Deploying and Shipping#
Once produces an ad-hoc signed application bundle. It does not provision an
Apple identity, install a provisioning profile, or upload a build. The bundle
must be provisioned and re-signed before a physical iPhone will accept it.
Use xtool or omarchy-apple-dev's documented signing and USB deployment workflow
for those steps. Its ship.sh workflow separately handles distribution signing,
validation, and App Store Connect uploads; a Once build is not automatically
an App Store-ready archive.
Boundaries#
- Native
apple_library,apple_framework,apple_application, andapple_executablebuilds use the Linux toolchain. Available destinations are limited to those present in your Darwin SDK. - Apple binaries cannot execute on Linux. Simulator runs, XCTest and Swift Testing bundles, Xcode app thinning, and Intent definition code generation still require macOS.
swift_macrobuilds still require macOS. Prebuilt compiler plugins supplied throughbinary_swift_pluginsmust be Linux executables. SDK-provided macros use the SDK's OpenAppleMacros server when installed.- Native Xcode and Swift package workspace resolution is not enabled by this
integration. Declare native Apple targets in
once.tomlfor Linux builds. - Mac Catalyst and platforms absent from the SDK are not supported by this Linux integration.