#objective-c #macos #ios #sys #objc-msg-send

sys no-std objc-sys

Raw bindings to the Objective-C runtime and ABI

11 releases

0.3.2 Dec 3, 2023
0.3.1 Jun 20, 2023
0.3.0 Feb 7, 2023
0.2.0-beta.3 Dec 24, 2022
0.1.0 Nov 22, 2021

#60 in macOS and iOS APIs

Download history 30921/week @ 2023-11-07 31489/week @ 2023-11-14 33891/week @ 2023-11-21 31706/week @ 2023-11-28 35226/week @ 2023-12-05 30268/week @ 2023-12-12 27223/week @ 2023-12-19 22166/week @ 2023-12-26 35692/week @ 2024-01-02 39400/week @ 2024-01-09 40889/week @ 2024-01-16 42182/week @ 2024-01-23 38734/week @ 2024-01-30 45160/week @ 2024-02-06 42401/week @ 2024-02-13 31862/week @ 2024-02-20

164,802 downloads per month
Used in 1,078 crates (2 directly)

MIT license

941 lines


Latest version License Documentation CI

Raw Rust bindings to the Objective-C runtime and ABI.

This crate is part of the objc2 project, see that for related crates.

Runtime Support

Objective-C has a runtime, different implementations of said runtime exist, and they act in slightly different ways. By default, Apple platforms link to Apple's runtime, but if you're using another runtime you must tell it to this library using feature flags (you might have to disable the default apple feature first).

One could ask, why even bother supporting other runtimes? For me, the primary reasoning iss robustness. By testing with these alternative runtimes in CI, we become by extension much more confident that our implementation doesn't rely on brittle unspecified behaviour, and works across different macOS and iOS versions.

Apple's objc4

  • Feature flag: apple.

This is used by default, and has the highest support priority (all of objc2/icrate will work with this runtime).

The supported runtime version (higher versions lets the compiler enable newer optimizations, at the cost of not supporting older operating systems) can be chosen using the standard X_DEPLOYMENT_TARGET environment variables:

  • macOS: MACOSX_DEPLOYMENT_TARGET, default 10.12, 11.0 on Aarch64.
  • iOS / iPadOS: IPHONEOS_DEPLOYMENT_TARGET, default 10.0.
  • tvOS: TVOS_DEPLOYMENT_TARGET, default 10.0.
  • watchOS: WATCHOS_DEPLOYMENT_TARGET, default 5.0.

The default (and minimum) versions are the same as those Rust itself has.

GNUStep's libobjc2

  • Feature flag: gnustep-1-7, gnustep-1-8, gnustep-1-9, gnustep-2-0 and gnustep-2-1 depending on the version you're using. Recommended default is gnustep-1-8.

Microsoft's WinObjC

  • Feature flag: unstable-winobjc.

Unstable: Hasn't been tested on Windows yet!

A fork based on GNUStep's libobjc2 version 1.8, with very few user-facing changes.


  • Feature flag: unstable-objfw.

Unstable: Doesn't work yet!


Other runtimes

This library will probably only ever support "Modern" Objective-C runtimes, since support for reference-counting primitives like objc_retain and objc_autoreleasePoolPop is a vital requirement for most applications.

This rules out the GCC libobjc runtime (see this), the mulle-objc runtime and cocotron. (But support for darling may be added). More information on different runtimes can be found in GNUStep's Objective-C Compiler and Runtime FAQ.

Advanced linking configuration

This crate defines the links key in Cargo.toml so it's possible to change the linking to libobjc, see the relevant cargo docs.

In the future, this crate may vendor the required source code to automatically build and link to the runtimes. Choosing static vs. dynamic linking here may also become an option.

Objective-C Compiler configuration

Objective-C compilers like clang and gcc requires configuring the calling ABI to the runtime you're using:

This is relevant if you're building and linking to custom Objective-C sources in a build script. To assist in compiling Objective-C sources, this crate's build script expose the DEP_OBJC_0_3_CC_ARGS environment variable to downstream build scripts.

Example usage in your build.rs (using the cc crate) would be as follows:

fn main() {
    let mut builder = cc::Build::new();

    for flag in std::env::var("DEP_OBJC_0_3_CC_ARGS").unwrap().split(' ') {


Design choices

It is recognized that the most primary consumer of this library will be macOS and secondly iOS applications. Therefore it was chosen not to use bindgen in our build script to not add compilation cost to those targets.1

Deprecated functions are also not included for future compability, since they could be removed in any macOS release, and then our code would break. If you have a need for these, please open an issue and we can discuss it!

Some items (in particular the objc_msgSend_X family) have cfgs that prevent their usage on different platforms; these are semver-stable in the sense that they will only get less restrictive, never more.

1: That said, most of this is created with the help of bindgen's commandline interface, so huge thanks to them!