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!
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
| PLATFORM | Builds for | Architectures |
|---|---|---|
OS64 | iOS devices | arm64 |
SIMULATOR64 | iOS Simulator on Intel Macs | x86_64 |
SIMULATORARM64 | iOS Simulator on Apple Silicon | arm64 |
SIMULATOR64COMBINED | iOS Simulator, fat library | arm64, x86_64 |
OS64COMBINED | iOS devices + Simulator, fat library (see note below) | arm64, x86_64 |
tvOS
| PLATFORM | Builds for | Architectures |
|---|---|---|
TVOS | Apple TV devices | arm64 |
SIMULATOR_TVOS | tvOS Simulator on Intel Macs | x86_64 |
SIMULATORARM64_TVOS | tvOS Simulator on Apple Silicon | arm64 |
TVOSCOMBINED | Apple TV devices + Simulator, fat library (see note below) | arm64, x86_64 |
watchOS
| PLATFORM | Builds for | Architectures |
|---|---|---|
WATCHOS | Apple Watch devices | arm64, armv7k, arm64_32 |
SIMULATOR_WATCHOS | watchOS Simulator on Intel Macs | x86_64 |
SIMULATORARM64_WATCHOS | watchOS Simulator on Apple Silicon | arm64 |
SIMULATOR_WATCHOSCOMBINED | watchOS Simulator, fat library | arm64, x86_64 |
WATCHOSCOMBINED | Apple 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)
| PLATFORM | Builds for | Architectures |
|---|---|---|
VISIONOS | Apple Vision Pro | arm64 |
SIMULATOR_VISIONOS | visionOS Simulator | arm64 |
VISIONOSCOMBINED | Vision Pro + Simulator, fat library (see note below) | arm64 |
macOS and Mac Catalyst
| PLATFORM | Builds for | Architectures |
|---|---|---|
MAC | macOS on Intel | x86_64 |
MAC_ARM64 | macOS on Apple Silicon | arm64 |
MAC_UNIVERSAL | macOS universal binary | x86_64, arm64 |
MAC_CATALYST | Mac Catalyst on Intel | x86_64 |
MAC_CATALYST_ARM64 | Mac Catalyst on Apple Silicon | arm64 |
MAC_CATALYST_UNIVERSAL | Mac Catalyst universal binary | x86_64, arm64 |
Options
All options are passed on the CMake command line, e.g. -DDEPLOYMENT_TARGET=15.0:
| Option | Default | Description |
|---|---|---|
DEPLOYMENT_TARGET | 13.0 iOS/tvOS, 6.0 watchOS, 1.0 visionOS, 11.0 macOS, 13.1 Catalyst | Minimum OS version to target |
ARCHS | per PLATFORM, see above | Semicolon separated architecture override, e.g. -DARCHS="arm64;x86_64" |
ENABLE_ARC | ON | Objective-C automatic reference counting |
ENABLE_VISIBILITY | OFF | OFF hides symbols (-fvisibility=hidden), ON keeps them visible |
ENABLE_STRICT_TRY_COMPILE | OFF | ON makes try_compile() link for real, so link dependent checks (e.g. HAVE_LIBATOMIC) give correct answers |
ENABLE_BITCODE | OFF | Bitcode; dead since Xcode 14, leave it off |
NAMED_LANGUAGE_SUPPORT | ON | Use 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
| Name | Description |
|---|---|
XCODE_VERSION | Version of Xcode detected |
SDK_VERSION | Version of the SDK being used |
CMAKE_OSX_ARCHITECTURES | Architectures being compiled for (derived from PLATFORM) |
APPLE_TARGET_TRIPLE | Target 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! 🙏🎉