ios-cmake

August 6, 2026 · View on GitHub

A CMake toolchain file for iOS (+ Catalyst), watchOS, tvOS, visionOS and macOS development with full simulator support and toggleable options!

catalyst-jobs   combined-jobs   ios-jobs

macos-jobs   tvos-jobs   watchos-jobs

visionos-jobs

Quick start

Grab ios.toolchain.cmake from the latest release (or add this repository as a submodule), then:

cmake -B build -G Xcode -DCMAKE_TOOLCHAIN_FILE=path/to/ios.toolchain.cmake -DPLATFORM=OS64
cmake --build build --config Release

That is all it takes to build your CMake project for iOS devices (arm64). Pick another PLATFORM value from the table below to target something else. The -G Xcode generator is recommended, but Ninja and Unix Makefiles work too.

Working examples are available in the example folder.

Choosing a platform

Pass exactly one of these as -DPLATFORM=<value>:

iOS

PLATFORMBuilds forArchitectures
OS64iOS devicesarm64
SIMULATOR64iOS Simulator on Intel Macsx86_64
SIMULATORARM64iOS Simulator on Apple Siliconarm64
SIMULATOR64COMBINEDiOS Simulator, fat libraryarm64, x86_64
OS64COMBINEDiOS devices + Simulator, fat library (see note below)arm64, x86_64

tvOS

PLATFORMBuilds forArchitectures
TVOSApple TV devicesarm64
SIMULATOR_TVOStvOS Simulator on Intel Macsx86_64
SIMULATORARM64_TVOStvOS Simulator on Apple Siliconarm64
TVOSCOMBINEDApple TV devices + Simulator, fat library (see note below)arm64, x86_64

watchOS

PLATFORMBuilds forArchitectures
WATCHOSApple Watch devicesarm64, armv7k, arm64_32
SIMULATOR_WATCHOSwatchOS Simulator on Intel Macsx86_64
SIMULATORARM64_WATCHOSwatchOS Simulator on Apple Siliconarm64
SIMULATOR_WATCHOSCOMBINEDwatchOS Simulator, fat libraryarm64, x86_64
WATCHOSCOMBINEDApple Watch devices + Simulator, fat library (see note below)arm64, armv7k, arm64_32, x86_64

The arm64 slice for watchOS devices is included when building with Xcode 15 or later. Apple requires arm64 support in watchOS apps submitted from April 2026.

visionOS (Apple Silicon host required)

PLATFORMBuilds forArchitectures
VISIONOSApple Vision Proarm64
SIMULATOR_VISIONOSvisionOS Simulatorarm64
VISIONOSCOMBINEDVision Pro + Simulator, fat library (see note below)arm64

macOS and Mac Catalyst

PLATFORMBuilds forArchitectures
MACmacOS on Intelx86_64
MAC_ARM64macOS on Apple Siliconarm64
MAC_UNIVERSALmacOS universal binaryx86_64, arm64
MAC_CATALYSTMac Catalyst on Intelx86_64
MAC_CATALYST_ARM64Mac Catalyst on Apple Siliconarm64
MAC_CATALYST_UNIVERSALMac Catalyst universal binaryx86_64, arm64

Options

All options are passed on the CMake command line, e.g. -DDEPLOYMENT_TARGET=15.0:

OptionDefaultDescription
DEPLOYMENT_TARGET13.0 iOS/tvOS, 6.0 watchOS, 1.0 visionOS, 11.0 macOS, 13.1 CatalystMinimum OS version to target
ARCHSper PLATFORM, see aboveSemicolon separated architecture override, e.g. -DARCHS="arm64;x86_64"
ENABLE_ARCONObjective-C automatic reference counting
ENABLE_VISIBILITYOFFOFF hides symbols (-fvisibility=hidden), ON keeps them visible
ENABLE_STRICT_TRY_COMPILEOFFON makes try_compile() link for real, so link dependent checks (e.g. HAVE_LIBATOMIC) give correct answers
ENABLE_BITCODEOFFBitcode; dead since Xcode 14, leave it off
NAMED_LANGUAGE_SUPPORTONUse enable_language(OBJC)/enable_language(OBJCXX) for Objective-C sources

Distributing for device + simulator: use an xcframework

A fat library cannot contain both a device arm64 slice and a simulator arm64 slice, which makes the old *COMBINED fat library approach a dead end on Apple Silicon. Apple's (and CMake's) supported way to ship one artifact for both device and simulator is an xcframework. Build each platform in its own build directory and combine:

cmake -S . -B build-device -G Xcode -DCMAKE_TOOLCHAIN_FILE=ios.toolchain.cmake -DPLATFORM=OS64
cmake --build build-device --config Release

cmake -S . -B build-simulator -G Xcode -DCMAKE_TOOLCHAIN_FILE=ios.toolchain.cmake -DPLATFORM=SIMULATOR64COMBINED
cmake --build build-simulator --config Release

xcodebuild -create-xcframework \
  -library build-device/Release-iphoneos/libexample.a \
  -library build-simulator/Release-iphonesimulator/libexample.a \
  -output example.xcframework

CMake 3.28+ can consume xcframeworks directly via find_library, and if you distribute CMake packages, have a look at generate_apple_platform_selection_file() in the CMakePackageConfigHelpers module (CMake 3.29+).

The *COMBINED platform options still exist and build device + simulator fat libraries through cmake --install, but due to the arm64 slice conflict above they are not recommended for distribution anymore. They only work with the Xcode generator.

Code signing

The toolchain disables code signing by default (CODE_SIGNING_ALLOWED=NO), which is what you want for building libraries. If you need signed output, provide your team:

cmake -B build -G Xcode -DCMAKE_TOOLCHAIN_FILE=ios.toolchain.cmake -DPLATFORM=OS64 \
  -DCMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED=YES \
  -DCMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM=YOUR_TEAM_ID

Exposed variables and helpers

NameDescription
XCODE_VERSIONVersion of Xcode detected
SDK_VERSIONVersion of the SDK being used
CMAKE_OSX_ARCHITECTURESArchitectures being compiled for (derived from PLATFORM)
APPLE_TARGET_TRIPLETarget triple, useful for autoconf style build systems
set_xcode_property(TARGET PROPERTY VALUE VARIANT)Macro to set any Xcode attribute on a target
find_host_package(...)Macro that runs find_package against the host system instead of the target SDK

FAQ

"Signing for X requires a development team" when building. Update the toolchain; signing is disabled by default since 4.5.0. For one off builds you can also pass CODE_SIGNING_ALLOWED=NO directly to xcodebuild.

"Bundle identifier is missing" for executable targets. iOS executables are bundles and need an identifier: set_target_properties(mytool PROPERTIES MACOSX_BUNDLE_GUI_IDENTIFIER com.example.mytool).

A binary built during the build is "Killed: 9". Everything in a cross-compile targets the device, so intermediate helper tools cannot run on your Mac. Build the helpers in a native macOS pass first and point the cross-build at them.

My installed .app crashes but the one in the build folder runs. fixup_bundle invalidates the code signature. Re-sign after it: execute_process(COMMAND codesign --force --deep --sign - <the .app>) in an install(CODE ...) block.

A configure check found a library that does not exist on iOS (e.g. HAVE_LIBATOMIC). Configure checks do not link by default. Pass -DENABLE_STRICT_TRY_COMPILE=ON.

CMake picked up a Homebrew library for my iOS build. The toolchain filters the common Homebrew paths, but you can lock it down completely with -DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY.

Different source files per architecture in a COMBINED build? Not possible, CMake configures once for all archs. Use the Xcode build settings EXCLUDED_SOURCE_FILE_NAMES/INCLUDED_SOURCE_FILE_NAMES with $(CURRENT_ARCH), or build each arch separately.

Thanks To

  • 🌟 A heartfelt thank you to everyone who contributes to keeping this repository up-to-date! Your support and collaboration are invaluable in managing and tracking all the changes. Your help is greatly appreciated! 🙏🎉