1 Reference macOS SDK
picklemustard edited this page 2026-09-07 15:49:27 -04:00

The macOS SDK

Cross-compiling for macOS from Linux uses osxcross, which needs an Apple SDK extracted from Xcode.

Why we cannot ship it

Apple's Xcode licence does not permit us to redistribute the SDK. It therefore must not be:

  • committed to this repository,
  • baked into an image pushed to a shared registry,
  • copied to a machine outside your organisation's Apple developer agreement.

.gitignore blocks build/docker/sdk/ and MacOSX*.sdk* so an accidental git add -A cannot commit one. Do not remove those rules.

Extract the SDK on a Mac you own, from an Xcode you downloaded under your own Apple ID.

Extracting it

On macOS with Xcode installed:

git clone --depth 1 https://github.com/tpoechtrager/osxcross.git
cd osxcross
./tools/gen_sdk_package.sh

This writes something like MacOSX14.0.sdk.tar.xz.

Installing it

Copy the tarball into the build context on the build host:

mkdir -p build/docker/sdk
cp /path/to/MacOSX14.0.sdk.tar.xz build/docker/sdk/

Then build the image, passing the filename if it differs from the default:

podman build -t gbb/macos:latest \
  --build-arg SDK_TARBALL=MacOSX14.0.sdk.tar.xz \
  -f build/docker/macos.Dockerfile build/docker

scripts/build-images.sh skips the macOS image entirely when no SDK is present, so the other two images still build on a host without one.

Status

This image has still never been built, and not for want of trying: M5 rewrote it against what Godot 4.4 actually requires, and then could not run it, because no Apple SDK was available. That is a permanent property of this milestone rather than a temporary one — the SDK cannot live in CI, in a shared registry, or anywhere else this project controls, so the only place this image can ever be built is a developer's own machine with their own Xcode.

What M5 corrected by reading the engine rather than running it:

  • MoltenVK was missing. platform/macos/detect.py links -lMoltenVK and calls sys.exit(255) when it cannot find it. The build container has no network, so it is now baked into the image — Godot's own moltenvk-osxcross release, which exists precisely because the official builds link it through osxcross.
  • The compiler triple was wrong. osxcross_sdk defaults to darwin16, and a 14.x SDK produces darwin23. The entrypoint now asks osxcross-conf what the image actually has.
  • osxcross was pinned to a branch, so the toolchain depended on the day the image was built. It is pinned to a commit.
  • lzma-dev was the wrong package — that name is the ancient standalone lzma; osxcross wants liblzma-dev. It resolved, so apt succeeded and the failure would have surfaced later as a confusing configure error. cpio and bzip2 were missing outright.
  • ccache was bypassed entirely. The PATH shims every other image relies on cannot work here, because the engine sets CC to an absolute path inside osxcross. CCACHE=ccache in the environment is the hook the engine provides for exactly this.
  • codesign would have killed the build at the last step. bundle_sign_identity defaults to "-", not to "", so generate_bundle would have shelled out to a tool that does not exist on Linux, after hours of compiling. The entrypoint empties it.

Two risks remain that only a real build can settle. Bookworm ships clang 14, while Godot's own container builds Apple Clang 17.0.6 and runs build_compiler_rt.sh "to ensure compatibility"; and Metal is on by default for macOS, pulling in MetalFX and spirv-cross against the SDK. Either could fail deep in a build whose toolchain installed cleanly.

Tracked as ROADMAP M5, and docs/tickets/m5-06-macos-image.md.

Signing and notarization

Cross-compiled macOS binaries are unsigned. Gatekeeper will refuse to run them without the user clearing the quarantine attribute. Real signing and notarization need codesign and notarytool, which only run on macOS — which is the case that would justify adding a CI-dispatch Runner implementation. Tracked as ROADMAP M8.