Skip to content
Latchkey

How to Build a Universal Binary in GitHub Actions

Build for both arm64 and x86_64, then combine the slices into one universal binary with lipo -create, or let xcodebuild emit both arches at once.

With xcodebuild, set ARCHS="arm64 x86_64" and ONLY_ACTIVE_ARCH=NO. For raw tools, build each arch separately and merge them with lipo -create -output.

Steps

  • For Xcode: build with ARCHS="arm64 x86_64" ONLY_ACTIVE_ARCH=NO.
  • For swiftc/clang: build each slice, then lipo -create them.
  • Verify the result with lipo -info <binary>.

Workflow

.github/workflows/ci.yml
jobs:
  build:
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@v4
      - name: Build both slices
        run: |
          swiftc -O -target arm64-apple-macos11 main.swift -o app-arm64
          swiftc -O -target x86_64-apple-macos11 main.swift -o app-x86_64
      - name: Make universal
        run: |
          lipo -create -output app app-arm64 app-x86_64
          lipo -info app

Gotchas

  • lipo -info should report both arm64 and x86_64; if not, one slice failed to build.
  • Every dependency you link must also be universal, or the merge fails on the missing arch.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →