Skip to content
cross-compilers

Docker image · no Mac required

Build macOS and iOS apps on Linux.

macos-cross-compiler compiles, links, and signs macOS, iOS, and Mac Catalyst software in a Linux container: Swift and SwiftUI apps, SwiftPM packages, C, C++, Objective-C, and Rust. The output matches Xcode's.

hello.c → Mach-O arm64
docker run --rm -v "$PWD:/workspace" \
  docker.io/shepherdjerred/macos-cross-compiler:27 \
  arm64-apple-macos-clang hello.c -o hello

The :27 examples require a local build. Publishing is paused; public :latest and :15.0 tags contain an older toolchain.

Runs on linux/amd64 and linux/arm64.

Built on Linux, runs on your Mac.

  • Compiles

    Swift, C, C++, Obj-C, Rust

  • Links

    Apple's ld64 and libtapi

  • Bundles

    Xcode-layout .app output

  • Signs

    ad-hoc or real identity

What it builds

The Apple toolchain, in a container

Everything you would otherwise need a Mac runner for, from a single docker run.

Quick start

Mount your project and build

Each image carries one macOS SDK. Default deployment targets are macOS 15.0 and iOS 18.0; override them with MACOSX_DEPLOYMENT_TARGET and IPHONEOS_DEPLOYMENT_TARGET.

A C program

C
docker run --rm -v "$PWD:/workspace" \
  docker.io/shepherdjerred/macos-cross-compiler:27 \
  arm64-apple-macos-clang hello.c -o hello

A Swift package

SwiftPM
docker run --rm -v "$PWD:/workspace" \
  docker.io/shepherdjerred/macos-cross-compiler:27 \
  swift build --triple arm64-apple-macosx15.0 --sdk /opt/apple/sdks/MacOSX.sdk -c release

A SwiftUI app from an XcodeGen project.yml, as a signed .app

applebuild
docker run --rm -v "$PWD:/workspace" \
  docker.io/shepherdjerred/macos-cross-compiler:27 \
  applebuild project.yml --target MyApp --output out

A Rust crate

Rust
docker run --rm -v "$PWD:/workspace" \
  docker.io/shepherdjerred/macos-cross-compiler:27 \
  cargo build --release --target aarch64-apple-darwin

Compiler wrappers

  • <arch>-apple-macos-clang | clang++ | swiftc
  • arm64-apple-ios-clang | clang++ | swiftc
  • <arch>-apple-ios-macabi-*
  • clang --target=arm64-apple-macos15

<arch> is arm64 or x86_64.

How it works

Apple's own tools, wherever they are open

Instead of reimplementing Xcode, the image assembles the pieces Apple and the Swift project publish, and fills the gaps where Xcode ships closed binaries.

  1. The real Swift toolchain

    The swift.org Linux build of Swift, compiling against Apple's macOS and iOS SDKs.

  2. Apple's linker

    Apple's open-source ld64 linker from cctools-port, with Apple's libtapi to read the SDK's .tbd stubs.

  3. Swift Build

    The build engine inside Xcode, now open source, builds SwiftPM packages exactly as Xcode would.

  4. SwiftUI macros on Linux

    Linux implementations of the macros Xcode ships only as closed macOS binaries (@State, @Entry, #Preview), checked expansion-for-expansion against Xcode's own.

  5. applebuild

    An xcodebuild stand-in that builds XcodeGen project.yml app targets into .app bundles, signed with rcodesign ad-hoc or with a real identity.

Images

One image per macOS SDK

Pull docker.io/shepherdjerred/macos-cross-compiler with the tag for the SDK you target.

Tag SDK Swift Status
:27 publishing paused Xcode 27 Swift 6.4 Coming soon
:26 Xcode 26 Swift 6.2 Coming soon
:15 Xcode 16.4 SDK Swift 6.2 Coming soon

The configured builds target linux/amd64 and linux/arm64.

Known differences

What it does not do (yet)