objc2/
lib.rs

1//! # Objective-C interface and runtime bindings
2//!
3//! Quick links:
4//! - [All Topics][crate::topics].
5//! - [About framework crates][crate::topics::about_generated].
6//! - [List of framework crates][crate::topics::about_generated::list].
7//!
8//! Objective-C was the standard programming language on Apple platforms like
9//! macOS, iOS, iPadOS, tvOS and watchOS. It is an object-oriented language
10//! centered around "sending messages" to its instances - this can for the
11//! most part be viewed as a function call.
12//!
13//! It has since been superseded by Swift, but most of the core libraries and
14//! frameworks that are in use on Apple systems are still written in
15//! Objective-C, and hence we would like the ability to interact with these
16//! using Rust. This crate enables bi-directional interop with Objective-C, in
17//! as safe a manner as possible.
18//!
19//!
20//! ## Example
21//!
22//! Most of the time, you'll want to use one of [the framework crates], which
23//! contain bindings to `CoreFoundation`, `Foundation`, `AppKit`, `Metal`,
24//! `UIKit`, `WebKit` and so on.
25//!
26//! In this example we're going to be using [`objc2-foundation`] and
27//! [`objc2-app-kit`] to create a simple GUI application that displays a
28//! "Hello World" label.
29//!
30//! ```console
31//! $ # Add the necessary crates to your project.
32//! $ cargo add objc2 objc2-foundation objc2-app-kit
33//! ```
34//!
35#![cfg_attr(target_os = "macos", doc = "```no_run")]
36#![cfg_attr(not(target_os = "macos"), doc = "```ignore")]
37#![doc = include_str!("../examples/hello_world_app.rs")]
38//! ```
39//!
40//! [the framework crates]: crate::topics::about_generated
41//! [`objc2-foundation`]: https://docs.rs/objc2-foundation
42//! [`objc2-app-kit`]: https://docs.rs/objc2-app-kit
43//!
44//!
45//! ## Crate features
46//!
47//! This crate exports several optional cargo features, see [`Cargo.toml`] for
48//! an overview and description of these.
49//!
50//! The features in the framework crates are described [here][cr-feat]. Note
51//! that if you're developing a library for others to use, you might want to
52//! reduce compile times by disabling default features and only enabling the
53//! features you need.
54//!
55#![doc = concat!(
56    "[`Cargo.toml`]: https://docs.rs/crate/objc2/",
57    env!("CARGO_PKG_VERSION"),
58    "/source/Cargo.toml.orig",
59)]
60//! [cr-feat]: crate::topics::about_generated::cargo_features
61//!
62//!
63//! ## Supported operating systems
64//!
65//! - macOS: `10.12-15.4`
66//! - iOS: `10.0-18.4` (including iPadOS and Mac Catalyst)
67//! - tvOS: `10.0-18.4`
68//! - watchOS: `5.0-11.4`
69//! - visionOS: `1.0-2.4`
70//!
71//! The minimum versions are the same as those supported by `rustc`. Higher
72//! versions will also work, but the framework crates will not have bindings
73//! available for newer APIs.
74//!
75//! The framework bindings are generated from the SDKs in Xcode 16.2. The
76//! Xcode version will be periodically updated.
77//!
78//! Note that the bindings are currently generated in a very macOS-centric, so
79//! they may try to use types from AppKit, even on iOS, see for example
80//! [#637](https://github.com/madsmtm/objc2/issues/637).
81//!
82//! The bindings _can_ also be used on Linux or *BSD utilizing the
83//! [GNUstep Objective-C runtime](https://github.com/gnustep/libobjc2), see
84//! the [`ffi`] module for how to configure this, but this is very much
85//! second-class.
86//!
87//!
88//! ## Minimum Supported Rust Version (MSRV)
89//!
90//! The _currently_ minimum supported Rust version is `1.71` (to be able to
91//! use `extern "C-unwind"` functions); this is _not_ defined by policy,
92//! though, so it may change in at any time in a patch release.
93//!
94//! Help us define a policy over in [#203].
95//!
96//! [#203]: https://github.com/madsmtm/objc2/issues/203
97
98#![no_std]
99#![cfg_attr(
100    feature = "unstable-autoreleasesafe",
101    feature(negative_impls, auto_traits)
102)]
103#![cfg_attr(
104    feature = "unstable-arbitrary-self-types",
105    feature(arbitrary_self_types)
106)]
107#![cfg_attr(
108    feature = "unstable-coerce-pointee",
109    feature(derive_coerce_pointee, trait_upcasting)
110)]
111// Note: `doc_notable_trait` doesn't really make sense for us, it's only shown
112// for functions returning a specific trait.
113#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg, doc_cfg_hide))]
114#![cfg_attr(docsrs, doc(cfg_hide(doc)))]
115#![warn(missing_docs)]
116#![warn(missing_debug_implementations)]
117#![warn(clippy::missing_errors_doc)]
118#![warn(clippy::missing_panics_doc)]
119// Update in Cargo.toml as well.
120#![doc(html_root_url = "https://docs.rs/objc2/0.6.1")]
121
122#[cfg(not(feature = "alloc"))]
123compile_error!("The `alloc` feature currently must be enabled.");
124
125#[cfg(not(feature = "std"))]
126compile_error!("The `std` feature currently must be enabled.");
127
128extern crate alloc;
129extern crate std;
130
131pub use self::downcast::DowncastTarget;
132#[doc(no_inline)]
133pub use self::encode::{Encode, Encoding, RefEncode};
134pub use self::main_thread_marker::MainThreadMarker;
135pub use self::top_level_traits::{
136    AnyThread, ClassType, DefinedClass, MainThreadOnly, Message, ProtocolType, ThreadKind,
137};
138
139#[cfg(any(feature = "unstable-static-sel", feature = "unstable-static-class"))]
140#[doc(hidden)]
141pub use objc2_proc_macros::__hash_idents;
142
143#[cfg(not(any(feature = "unstable-static-sel", feature = "unstable-static-class")))]
144#[doc(hidden)]
145#[macro_export]
146macro_rules! __hash_idents {
147    // Noop; used to make our other macros a bit easier to read
148    ($($x:tt)*) => {
149        ()
150    };
151}
152
153// Note: While this is not public, it is still a breaking change to change,
154// since framework crates rely on it.
155#[doc(hidden)]
156pub mod __framework_prelude;
157#[doc(hidden)]
158pub mod __macro_helpers;
159mod downcast;
160pub mod encode;
161pub mod exception;
162pub mod ffi;
163mod macros;
164mod main_thread_marker;
165pub mod rc;
166pub mod runtime;
167#[cfg(test)]
168mod test_utils;
169mod top_level_traits;
170#[cfg(any(docsrs, doc, doctest, test))]
171pub mod topics;
172mod verify;
173
174/// Deprecated location for a few things that are now in the [`runtime`]
175/// module.
176#[deprecated = "Moved to the `runtime` module"]
177pub mod declare {
178    use super::runtime;
179    pub use super::runtime::{ClassBuilder, ProtocolBuilder};
180
181    /// Use [`runtime::ClassBuilder`] instead.
182    #[deprecated = "Use `runtime::ClassBuilder` instead."]
183    pub type ClassDecl = runtime::ClassBuilder;
184
185    /// Use [`runtime::ProtocolBuilder`] instead.
186    #[deprecated = "Use `runtime::ProtocolBuilder` instead."]
187    pub type ProtocolDecl = runtime::ProtocolBuilder;
188}
189
190/// Deprecated alias of [`DefinedClass`].
191#[deprecated = "renamed to DefinedClass"]
192pub use DefinedClass as DeclaredClass;
193
194/// Deprecated alias of [`AnyThread`].
195#[deprecated = "renamed to AnyThread"]
196pub use AnyThread as AllocAnyThread;
197
198#[cfg(not(feature = "std"))]
199compile_error!("The `std` feature currently must be enabled.");
200
201#[cfg(all(
202    not(docsrs),
203    not(any(
204        target_vendor = "apple",
205        feature = "unstable-compiler-rt",
206        feature = "gnustep-1-7",
207        feature = "unstable-objfw",
208    ))
209))]
210compile_error!("`objc2` only works on Apple platforms. Pass `--target aarch64-apple-darwin` or similar to compile for macOS.\n(If you're absolutely certain that you're using GNUStep, you can specify that with the `gnustep-x-y` Cargo feature instead).");
211
212#[cfg(all(feature = "gnustep-1-7", feature = "unstable-objfw"))]
213compile_error!("Only one runtime may be selected");
214
215#[cfg(feature = "unstable-objfw")]
216compile_error!("ObjFW is not yet supported");
217
218// Link to libobjc
219#[cfg_attr(not(feature = "unstable-objfw"), link(name = "objc", kind = "dylib"))]
220// Link to libobjfw-rt
221#[cfg_attr(feature = "unstable-objfw", link(name = "objfw-rt", kind = "dylib"))]
222extern "C" {}
223
224// Link to Foundation to make NSObject and OS version lookup work.
225#[cfg_attr(target_vendor = "apple", link(name = "Foundation", kind = "framework"))]
226#[cfg_attr(
227    all(feature = "gnustep-1-7", not(feature = "unstable-compiler-rt")),
228    link(name = "gnustep-base", kind = "dylib")
229)]
230extern "C" {}