Rust libaries as Xcode projects
Generates Xcode project files from Cargo.toml allowing use of Rust libraries in Mac and iOS applications without leaving Xcode.
Features
It's better than just launching cargo build from a script:
- Supports Universal Binaries (lipo) and cross-compilation (iOS/tvOS/macOS/watchOS/Simulator/Mac Catalyst, Apple Silicon/Intel).
- Configures Cargo to follow Xcode's Debug and Release configurations, and uses Xcode's standard build and temporary folders.
- Makes Xcode aware of dependencies and rebuild Rust code only when needed.
- Supports Cargo workspaces and multiple targets per crate.
- Can build dynamic libraries with properly set install name.
The generated Xcode project files are self-contained, and work without cargo-xcode dependency. You can distribute the .xcodeproj files and use them with just Rust and Xcode.
Requirements
Installation
Usage
TL;DR: Run
cargo xcodeand use the generated project files as subprojects in your other Xcode projects.
This tool will generate Rust-aware project files for all binaries and C-compatible libraries in a Cargo workspace. Instead of modifying your Mac/iOS app's project file directly, take advantage of Xcode's ability to nest and combine multiple xcodeproj files together. The generated Xcode projects are not meant for standalone use. They are supposed to be used only as subprojects of other regular app Xcode projects.
-
If you don't have an existing ObjC/Swift app project yet, create one in Xcode using any Cocoa app template you like. This will be called your "parent project" in later steps.
-
If your Rust project is a library, edit
Cargo.tomland add:[] = ["lib", "staticlib"]Only Cargo libraries of type
"staticlib"or"cdylib"are suitable, andstaticlibis much easier to work with (but keep the"lib"crate type for compatibility with other Cargo libraries and tests). -
In the same directory as
Cargo.toml(or root of a Cargo workspace) run:This will generate
<rust-project-name>.xcodeproj. Don't open it yet! -
Open your parent project (from step 1) in Xcode and add the
<rust-crate-name>.xcodeprojto the workspace (drag the file into the parent project's sidebar). You should see the dragged Rust-Xcode project embedded in your parent project. If the new Rust-Xcode project appears empty in the sidebar, close all Xcode windows and re-open only the parent project. -
In your parent project's app's Build Phases, in Link Binary With Libraries phase, you can now add the Rust libraries from the workspace.
Real-world example of such usage.
Advanced usage
You can configure some settings from within Xcode's target's Build Settings:
CARGO_XCODE_FEATURESmaps to--featuresflag.RUSTUP_TOOLCHAINselects which toolchain to use (nightly,1.99.0,stable, empty string for default toolchain). Seerustup toolchain add -h.- Change Base SDK (
SDKROOT) to iOS, DriverKit, etc. as needed.
If you're building .dylib for including in an application bundle, make sure to set DYLIB_INSTALL_NAME_BASE in Xcode's settings to @executable_path/../Frameworks/ or whatever location you're going to copy the library to.
If you're putting a Rust a binary inside an app bundle, you may need to set SKIP_INSTALL=YES or run cargo xcode --skip-install.
Limitations
Rust binaries are exported as command-line tools. This tool intentionally does not make app bundles. If you want to build a Mac GUI app, create one as ObjC or Swift project in Xcode and call Rust code via a Rust static library, or use Tauri.
DIY-Tier platforms
AppleTV, Mac Catalyst, and some other rare platforms don't have pre-built rustup targets. You will need to:
- use nightly (set
RUSTUP_TOOLCHAIN=nightly) - and build libstd: In a target › Build Phases tab › Compile Sources phase, edit the Compiler Flags column of
Cargo.toml, and append-Zbuild-stdthere.