Skip to content

Commit

Permalink
sys: Add README
Browse files Browse the repository at this point in the history
  • Loading branch information
madsmtm committed Sep 8, 2021
1 parent e63fc13 commit a97a2ea
Show file tree
Hide file tree
Showing 12 changed files with 157 additions and 27 deletions.
5 changes: 4 additions & 1 deletion objc_sys/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ version = "0.0.0" # Remember to update html_root_url in lib.rs
authors = ["Mads Marquart <mads@marquart.dk>"]
edition = "2018"

description = "Bindings to the Objective-C core runtime"
description = "Raw bindings to Objective-C runtimes"
keywords = ["objective-c", "macos", "ios", "objc_msgSend", "sys"]
categories = [
"external-ffi-bindings",
# "no_std" # TODO
"os::macos-apis",
]
repository = "https://github.com/madsmtm/objc"
Expand All @@ -20,6 +21,8 @@ exclude = [
"helper-scripts/*",
]

readme = "README.md"

# Downstream users can customize the linking to libobjc!
# See https://doc.rust-lang.org/cargo/reference/build-scripts.html#overriding-build-scripts
links = "objc"
Expand Down
100 changes: 100 additions & 0 deletions objc_sys/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# `objc_sys`

[![Latest version](https://badgen.net/crates/v/objc_sys)](https://crates.io/crates/objc_sys)
[![License](https://badgen.net/badge/license/MIT/blue)](../LICENSE.txt)
[![Documentation](https://docs.rs/objc_sys/badge.svg)](https://docs.rs/objc_sys/)
[![CI Status](https://github.com/madsmtm/objc/workflows/CI/badge.svg)](https://github.com/madsmtm/objc/actions)

Raw Rust bindings to core Objective-C runtimes and ABIs.

## Runtime Support

`objc_sys` currently supports two runtimes (support for [`ObjFW`] and
[`WinObjC`] may be added):
- Apple's [`objc4`] on `cfg(target_vendor = "apple")` targets.
- GNUStep's [`libobjc2`] on all other targets. See their [Objective-C Compiler
and Runtime FAQ][gnustep-faq].

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

Just so we're being clear, this rules out the GCC [`libobjc`][gcc-libobjc]
runtime (see [this][gcc-objc-support]), and the [`mulle-objc`] runtime.

[`ObjFW`]: https://github.com/ObjFW/ObjFW
[`WinObjC`]: https://github.com/microsoft/WinObjC
[`objc4`]: https://opensource.apple.com/source/objc4/
[`libobjc2`]: https://github.com/gnustep/libobjc2
[gnustep-faq]: http://wiki.gnustep.org/index.php/Objective-C_Compiler_and_Runtime_FAQ
[modern]: https://en.wikipedia.org/wiki/Objective-C#Modern_Objective-C
[gcc-libobjc]: https://github.com/gcc-mirror/gcc/tree/master/libobjc
[gcc-objc-support]: https://gcc.gnu.org/onlinedocs/gcc/Standards.html#Objective-C-and-Objective-C_002b_002b-Languages
[`mulle-objc`]: https://github.com/mulle-objc/mulle-objc-runtime


## Required Versions

At least `libobjc2` [version 1.7][libobjc2-1.7] or `objc4`
[version 493.9][objc4-493.9] is required.

`objc4` version 493.9 is available with:
- **macOS 10.7**
- **iOS 5.0**
- **tvOS 9.0**
- **watchOS 1.0**
- **bridgeOS 2.0**

So those are the **minimum supported Apple versions**. Functionality that was
added after these versions are not (yet?) available in `objc_sys`.

[libobjc2-1.7]: https://github.com/gnustep/libobjc2/tree/1.7
[objc4-493.9]: https://opensource.apple.com/source/objc4/


## Configuring linking

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

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.

[overriding]: https://doc.rust-lang.org/cargo/reference/build-scripts.html#overriding-build-scripts


## Objective-C compiler ABI configuration

Objective-C compilers like `clang` and `gcc` requires configuring the calling
ABI to the runtime you're using:
- `clang` uses the [`-fobjc-runtime`] flag, of which there are a few different
[options][clang-objc-kinds].
- `gcc` uses the [`-fgnu-runtime` or `-fnext-runtime`][gcc-flags] options.
Note that Modern Objective-C features are ill supported.

This is relevant if you're building and linking to custom Objective-C sources
in a build script. In the future, this crate may expose build script metadata
to help with selecting these (and other required) flags.

[`-fobjc-runtime`]: https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fobjc-runtime
[clang-objc-kinds]: https://clang.llvm.org/doxygen/classclang_1_1ObjCRuntime.html#af19fe070a7073df4ecc666b44137c4e5
[gcc-flags]: https://gcc.gnu.org/onlinedocs/gcc/Objective-C-and-Objective-C_002b_002b-Dialect-Options.html


## 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.<sup>1</sup>

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 `cfg`s that prevent
their usage on different platforms; these are **semver-stable** in the sense
that they will only get less restrictive, never more.

<sup>1</sup> That said, most of this is created with the help of `bindgen`'s
commandline interface, so huge thanks to them!
2 changes: 1 addition & 1 deletion objc_sys/helper-scripts/gen-git.fish
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# Yup, this is terrible, but was a great help in creating the correct implementations

# Source repo should be a path to https://github.com/madsmtm/objc4.git
# Source repo should be a path to https://github.com/madsmtm/objc4-mirror.git
set source_repo $argv[1]
set to_repo $argv[2]

Expand Down
6 changes: 4 additions & 2 deletions objc_sys/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,18 @@ use std::os::raw::c_int;

use crate::{id, Class, BOOL};

/// The equivalent of true for Objective-C's [`BOOL`][`super::BOOL`] type.
#[cfg(not(target_arch = "aarch64"))]
/// The equivalent of `true` for Objective-C's [`BOOL`][`super::BOOL`] type.
pub const YES: BOOL = 1;
#[cfg(target_arch = "aarch64")]
/// The equivalent of `true` for Objective-C's [`BOOL`][`super::BOOL`] type.
pub const YES: BOOL = true;

/// The equivalent of false for Objective-C's [`BOOL`][`super::BOOL`] type.
#[cfg(not(target_arch = "aarch64"))]
/// The equivalent of `false` for Objective-C's [`BOOL`][`super::BOOL`] type.
pub const NO: BOOL = 0;
#[cfg(target_arch = "aarch64")]
/// The equivalent of `false` for Objective-C's [`BOOL`][`super::BOOL`] type.
pub const NO: BOOL = false;

/// A quick alias for a [`null_mut`][`core::ptr::null_mut`] object / instance.
Expand Down
26 changes: 16 additions & 10 deletions objc_sys/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,28 @@
//! # Bindings to the objc_objective-C core runtime
//! # Raw bindings to Objective-C runtimes
//!
//! # Notable differences
//! These bindings contain almost no documentation, so it is highly
//! recommended to read the documentation of the original libraries:
//! - Apple's [official documentation][apple].
//! - Apple's `objc4` [source code][objc4] ([`git` mirror][objc4-mirror]), in
//! particular `runtime.h`.
//! - GNUStep's `libobjc2` [source code][libobjc2], in particular `runtime.h`.
//!
//! Protocol / objc_protocol is no longer a type alias of objc_object, for
//! better type safety. Their internal representation is the same, so the
//! functionality is just a cast away.
//!
//! Deprecated functions are not included for future compability, since they
//! could be removed at any macOS release, and then our code would break.

// TODO: Replace `extern "C"` with `extern "C-unwind"`.
//! [apple]: https://developer.apple.com/documentation/objectivec/objective-c_runtime?language=objc
//! [libobjc2]: https://github.com/gnustep/libobjc2/tree/v2.1/objc
//! [objc4]: https://opensource.apple.com/source/objc4/objc4-818.2/runtime/
//! [objc4-mirror]: https://github.com/madsmtm/objc4-mirror.git

#![no_std]
#![allow(non_camel_case_types)]
#![allow(non_upper_case_globals)]
#![doc(html_root_url = "https://docs.rs/objc_sys/0.0.0")]

// TODO: Replace `extern "C"` with `extern "C-unwind"` where applicable.
// See https://rust-lang.github.io/rfcs/2945-c-unwind-abi.html.

// TODO: Remove this and add "no-std" category to Cargo.toml
// Requires a better solution for C-types in `no_std` crates.
// See https://github.com/japaric/cty/issues/14.
extern crate std;

use core::cell::UnsafeCell;
Expand Down
2 changes: 1 addition & 1 deletion objc_sys/src/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub struct objc_super {
pub receiver: *mut objc_object,
/// The particular superclass of the instance to message.
///
/// Named `class` in GNUStep and in older Objective-C versions.
/// Named `class` in older Objective-C versions.
pub super_class: *const objc_class,
}

Expand Down
3 changes: 3 additions & 0 deletions objc_sys/src/method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@ pub struct objc_method {
_p: OpaqueData,
}

/// Describes an Objective-C method.
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct objc_method_description {
/// The name of the method.
pub name: *const objc_selector,
/// The types of the method arguments.
pub types: *const c_char,
}

Expand Down
2 changes: 1 addition & 1 deletion objc_sys/src/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::os::raw::c_char;

use crate::{objc_class, objc_ivar, OpaqueData};

/// An opaque type that represents an instance of a class.
/// An opaque type that represents an object / an instance of a class.
#[repr(C)]
pub struct objc_object {
// `isa` field is deprecated, so we don't expose it here.
Expand Down
6 changes: 6 additions & 0 deletions objc_sys/src/property.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,22 @@ use std::os::raw::{c_char, c_uint};

use crate::OpaqueData;

/// An opaque type that describes a property in a class.
#[repr(C)]
pub struct objc_property {
_priv: [u8; 0],
_p: OpaqueData,
}

/// Describes an Objective-C property attribute.
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct objc_property_attribute_t {
/// The name of the attribute.
pub name: *const c_char,
/// The value of the attribute
///
/// Usually NULL.
pub value: *const c_char,
}

Expand Down
4 changes: 3 additions & 1 deletion objc_sys/src/selector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ use std::os::raw::c_char;

use crate::{OpaqueData, BOOL};

/// A type that represents a method selector.
/// An opaque type that represents a method selector.
///
/// Selectors are immutable.
#[repr(C)]
pub struct objc_selector {
_priv: [u8; 0],
Expand Down
26 changes: 17 additions & 9 deletions objc_sys/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,22 @@ use crate::{
objc_class, objc_ivar, objc_method, objc_object, objc_property, objc_protocol, objc_selector,
};

/// The Objective-C `BOOL` type.
///
/// To convert an Objective-C `BOOL` into a Rust [`bool`], compare it with
/// [`NO`][`super::NO`].
#[cfg(all(apple, not(target_arch = "aarch64")))]
pub type BOOL = i8;
/// TODO: Only if STRICT_APPLE_COMPATIBILITY is NOT defined.
/// TODO: (__vxworks || _WIN32) becomes BOOL = c_int.
type BOOL_INNER = i8;

#[cfg(all(gnustep, not(target_arch = "aarch64")))]
pub type BOOL = u8;
// TODO: Only if STRICT_APPLE_COMPATIBILITY is NOT defined.
// TODO: (__vxworks || _WIN32) becomes BOOL = c_int.
type BOOL_INNER = u8;

#[cfg(target_arch = "aarch64")]
pub type BOOL = bool;
type BOOL_INNER = bool;

/// The Objective-C `BOOL` type.
///
/// The type of this varies across platforms, so to convert an it into a Rust
/// [`bool`], always compare it with [`YES`][`crate::YES`] or [`NO`][`crate::NO`].
pub type BOOL = BOOL_INNER;

/// An immutable pointer to a selector.
///
Expand Down Expand Up @@ -44,6 +48,10 @@ pub type Method = *mut objc_method;

/// An opaque type that represents a protocol.
///
/// This is not just a type alias of [`objc_object`], but of [`objc_protocol`]
/// instead, for better type safety. Their internal representation is the same,
/// so the functionality is just a cast away.
///
/// Type alias provided for convenience.
pub type Protocol = objc_protocol;

Expand Down
2 changes: 1 addition & 1 deletion objc_sys/src/various.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::os::raw::{c_char, c_int};
use crate::objc_class;
use crate::{objc_AssociationPolicy, objc_object, OpaqueData, BOOL};

/// A type that represents an instance variable.
/// An opaque type that represents an instance variable.
#[repr(C)]
pub struct objc_ivar {
_priv: [u8; 0],
Expand Down

0 comments on commit a97a2ea

Please sign in to comment.