Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions block-sys/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## Unreleased - YYYY-MM-DD

### Changed
* **BREAKING**: Changed `links` key from `block` to `block_0_0` for better
future compatibility, until we reach 1.0 (so `DEP_BLOCK_X` in build scripts
becomes `DEP_BLOCK_0_0_X`).


## 0.0.3 - 2022-01-03

Expand Down
2 changes: 1 addition & 1 deletion block-sys/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ readme = "README.md"

# Downstream users can customize the linking!
# See https://doc.rust-lang.org/cargo/reference/build-scripts.html#overriding-build-scripts
links = "block"
links = "block_0_0"
build = "build.rs"

[features]
Expand Down
6 changes: 3 additions & 3 deletions block-sys/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ TODO.

To our knowledge, currently only `clang` supports the [Language Specification
for Blocks][block-lang]. To assist in compiling C (or Objective-C) sources
using these features, this crate's build script expose the `DEP_BLOCK_CC_ARGS`
environment variable to downstream build scripts.
using these features, this crate's build script expose the
`DEP_BLOCK_0_0_CC_ARGS` environment variable to downstream build scripts.

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

Expand All @@ -105,7 +105,7 @@ fn main() {
builder.compiler("clang");
builder.file("my_script_using_blocks.c");

for flag in std::env::var("DEP_BLOCK_CC_ARGS").unwrap().split(' ') {
for flag in std::env::var("DEP_BLOCK_0_0_CC_ARGS").unwrap().split(' ') {
builder.flag(flag);
}

Expand Down
13 changes: 10 additions & 3 deletions block-sys/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,24 @@ fn main() {
// work (on newer GNUStep versions these headers are present)
if env::var_os("CARGO_FEATURE_GNUSTEP_2_0").is_none() {
let compat_headers =
Path::new(env!("CARGO_MANIFEST_DIR")).join("gnustep-compat-headers");
Path::new(env!("CARGO_MANIFEST_DIR")).join("compat-headers/gnustep");
cc_args.push_str(" -I");
cc_args.push_str(compat_headers.to_str().unwrap());
}
}
(false, false, false, true) => unimplemented!(),
(false, false, false, true) => {
// Add compability headers to make `#include <Block.h>` work.
let compat_headers = Path::new(env!("CARGO_MANIFEST_DIR")).join("compat-headers/objfw");
cc_args.push_str(" -I");
cc_args.push_str(compat_headers.to_str().unwrap());
println!("cargo:rustc-link-lib=dylib=objfw");
unimplemented!("ObjFW is not yet supported")
}
// Checked in if-let above
(false, false, false, false) => unreachable!(),
(_, _, _, _) => panic!("Invalid feature combination; only one runtime may be selected!"),
}

// Add DEP_BLOCK_CC_ARGS
// Add DEP_BLOCK_[version]_CC_ARGS
println!("cargo:cc_args={}", cc_args);
}
1 change: 1 addition & 0 deletions block-sys/compat-headers/objfw/Block.h
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#include <ObjFW/block.h>
51 changes: 50 additions & 1 deletion block-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@
//!
//! [ABI]: https://clang.llvm.org/docs/Block-ABI-Apple.html

#![no_std]
// Update in Cargo.toml as well.
#![doc(html_root_url = "https://docs.rs/block-sys/0.0.3")]

extern crate std;

// Ensure linkage actually happens
#[cfg(feature = "gnustep-1-7")]
extern crate objc_sys as _;
Expand Down Expand Up @@ -298,7 +301,6 @@ pub struct Block_descriptor {
///
/// Requires BLOCK_HAS_SIGNATURE
#[repr(C)]
#[cfg(not(feature = "objfw"))]
pub struct Block_descriptor_basic {
pub header: Block_descriptor_header,

Expand Down Expand Up @@ -388,3 +390,50 @@ pub struct Block_byref_extended {
pub inner: Block_byref,
pub layout: *const c_char,
}

#[cfg(test)]
mod tests {
use super::*;
use core::ptr;
use std::println;

#[test]
fn smoke() {
assert_eq!(unsafe { _Block_copy(ptr::null()) }, ptr::null_mut());
}

#[test]
fn test_linkable() {
println!("{:p}", unsafe { &_NSConcreteGlobalBlock });
println!("{:p}", unsafe { &_NSConcreteStackBlock });
println!("{:p}", unsafe { &_NSConcreteMallocBlock });
println!(
"{:p}",
_Block_copy as unsafe extern "C" fn(*const c_void) -> *mut c_void
);
println!(
"{:p}",
_Block_object_assign
as unsafe extern "C" fn(*mut c_void, *const c_void, block_assign_dispose_flags)
);
println!(
"{:p}",
_Block_object_dispose
as unsafe extern "C" fn(*const c_void, block_assign_dispose_flags)
);
println!(
"{:p}",
_Block_release as unsafe extern "C" fn(*const c_void)
);
#[cfg(any(feature = "apple", feature = "compiler-rt"))]
{
println!("{:p}", unsafe { &_NSConcreteAutoBlock });
println!("{:p}", unsafe { &_NSConcreteFinalizingBlock });
println!("{:p}", unsafe { &_NSConcreteWeakBlockVariable });
println!(
"{:p}",
Block_size as unsafe extern "C" fn(*mut c_void) -> c_ulong
);
}
}
}
13 changes: 13 additions & 0 deletions objc-sys/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,19 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## Unreleased - YYYY-MM-DD

### Changed
* **BREAKING**: Changed `links` key from `objc` to `objc_0_2` for better
future compatibility, until we reach 1.0 (so `DEP_OBJC_X` in build scripts
becomes `DEP_OBJC_0_2_X`).

### Removed
* **BREAKING**: Removed type aliases `Class`, `Ivar`, `Method` and `Protocol`
since they could easily be mistaken for the `objc2::runtime` structs with
the same name.
* **BREAKING**: Removed `objc_property_t`.
* **BREAKING**: Removed `objc_hook_getClass` and `objc_hook_lazyClassNamer`
type aliases (for now).


## 0.2.0-alpha.1 - 2022-01-03

Expand Down
2 changes: 1 addition & 1 deletion objc-sys/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ 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"
links = "objc_0_2"
build = "build.rs"

# The default is `apple` on Apple platforms; all other platforms will error
Expand Down
6 changes: 3 additions & 3 deletions objc-sys/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@ 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_CC_ARGS` environment variable to downstream
build scripts.
build script expose the `DEP_OBJC_0_2_CC_ARGS` environment variable to
downstream build scripts.

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

Expand All @@ -127,7 +127,7 @@ fn main() {
builder.compiler("clang");
builder.file("my_objective_c_script.m");

for flag in std::env::var("DEP_OBJC_CC_ARGS").unwrap().split(' ') {
for flag in std::env::var("DEP_OBJC_0_2_CC_ARGS").unwrap().split(' ') {
builder.flag(flag);
}

Expand Down
39 changes: 28 additions & 11 deletions objc-sys/build.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::env;
use std::{env, path::Path};

/// TODO: Better validation of this
///
Expand Down Expand Up @@ -114,7 +114,9 @@ fn main() {
}
}
(false, false, true) => {
unimplemented!()
// For now
unimplemented!("ObjFW is not yet supported")
// ObjFW(None)
}
(false, false, false) => {
// Choose sensible defaults when generating docs
Expand Down Expand Up @@ -142,7 +144,7 @@ fn main() {
};
println!("cargo:rustc-cfg={}", runtime_cfg);
// Allow downstream build scripts to do the same
println!("cargo:runtime={}", runtime_cfg); // DEP_OBJC_RUNTIME
println!("cargo:runtime={}", runtime_cfg); // DEP_OBJC_[version]_RUNTIME

// Tell downstream build scripts our features
// match &runtime {
Expand Down Expand Up @@ -202,8 +204,8 @@ fn main() {
WinObjC => "gnustep-1.8".into(),
ObjFW(version) => {
// Default in clang
let _version = version.as_deref().unwrap_or("0.8");
todo!()
let version = version.as_deref().unwrap_or("0.8");
format!("objfw-{}", version)
}
};

Expand All @@ -221,12 +223,27 @@ fn main() {
// - `-miphoneos-version-min={}`
// - `-mmacosx-version-min={}`
// - ...
println!(
"cargo:cc_args=-fobjc-arc -fobjc-arc-exceptions -fobjc-exceptions -fobjc-runtime={}",
// TODO: -fobjc-weak ?
//
// TODO: -fobjc-weak ?
let mut cc_args = format!(
"-fobjc-arc -fobjc-arc-exceptions -fobjc-exceptions -fobjc-runtime={}",
clang_runtime
); // DEP_OBJC_CC_ARGS
);

if let Runtime::ObjFW(_) = &runtime {
// Add compability headers to make `#include <objc/objc.h>` work.
let compat_headers = Path::new(env!("CARGO_MANIFEST_DIR")).join("compat-headers-objfw");
cc_args.push_str(" -I");
cc_args.push_str(compat_headers.to_str().unwrap());
}

// Link to libobjc
println!("cargo:rustc-link-lib=dylib=objc");
println!("cargo:cc_args={}", cc_args); // DEP_OBJC_[version]_CC_ARGS

if let Runtime::ObjFW(_) = &runtime {
// Link to libobjfw-rt
println!("cargo:rustc-link-lib=dylib=objfw-rt");
} else {
// Link to libobjc
println!("cargo:rustc-link-lib=dylib=objc");
}
}
1 change: 1 addition & 0 deletions objc-sys/compat-headers-objfw/objc/objc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#import <ObjFW-RT/ObjFW-RT.h>
1 change: 1 addition & 0 deletions objc-sys/compat-headers-objfw/objc/runtime.h
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#import <ObjFW-RT/ObjFW-RT.h>
29 changes: 25 additions & 4 deletions objc-sys/src/class.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
use std::os::raw::{c_char, c_int, c_uint};

use crate::{
objc_ivar, objc_method, objc_object, objc_property, objc_property_attribute_t, objc_protocol,
objc_selector, OpaqueData, BOOL, IMP,
};
#[cfg(not(objfw))]
use crate::{objc_ivar, objc_method, objc_object, objc_property, objc_property_attribute_t};
use crate::{objc_protocol, objc_selector, OpaqueData, BOOL, IMP};

/// An opaque type that represents an Objective-C class.
#[repr(C)]
Expand All @@ -14,6 +13,7 @@ pub struct objc_class {
_p: OpaqueData,
}

#[cfg(not(objfw))]
/// This is `c_char` in GNUStep's libobjc2 and `uint8_t` in Apple's objc4.
///
/// The pointer represents opaque data, and is definitely not just an integer,
Expand All @@ -27,6 +27,7 @@ extern_c! {
pub fn objc_getClass(name: *const c_char) -> *const objc_class;
pub fn objc_getRequiredClass(name: *const c_char) -> *const objc_class;
pub fn objc_lookUpClass(name: *const c_char) -> *const objc_class;
#[cfg(not(objfw))]
pub fn objc_getMetaClass(name: *const c_char) -> *const objc_class;
pub fn objc_copyClassList(out_len: *mut c_uint) -> *mut *const objc_class;
pub fn objc_getClassList(buffer: *mut *const objc_class, buffer_len: c_int) -> c_int;
Expand All @@ -42,9 +43,11 @@ extern_c! {
name: *const c_char,
extra_bytes: usize,
) -> *mut objc_class;
#[cfg(not(objfw))]
pub fn objc_disposeClassPair(cls: *mut objc_class);
pub fn objc_registerClassPair(cls: *mut objc_class);

#[cfg(not(objfw))]
pub fn class_addIvar(
cls: *mut objc_class,
name: *const c_char,
Expand All @@ -58,53 +61,68 @@ extern_c! {
imp: IMP,
types: *const c_char,
) -> BOOL;
#[cfg(not(objfw))]
pub fn class_addProperty(
cls: *mut objc_class,
name: *const c_char,
attributes: *const objc_property_attribute_t,
attributes_count: c_uint,
) -> BOOL;
#[cfg(not(objfw))]
pub fn class_addProtocol(cls: *mut objc_class, protocol: *const objc_protocol) -> BOOL;
pub fn class_conformsToProtocol(cls: *const objc_class, protocol: *const objc_protocol)
-> BOOL;

#[cfg(not(objfw))] // Available in newer versions
pub fn class_copyIvarList(
cls: *const objc_class,
out_len: *mut c_uint,
) -> *mut *const objc_ivar;
#[cfg(not(objfw))] // Available in newer versions
pub fn class_copyMethodList(
cls: *const objc_class,
out_len: *mut c_uint,
) -> *mut *const objc_method;
#[cfg(not(objfw))] // Available in newer versions
pub fn class_copyPropertyList(
cls: *const objc_class,
out_len: *mut c_uint,
) -> *mut *const objc_property;
#[cfg(not(objfw))]
pub fn class_copyProtocolList(
cls: *const objc_class,
out_len: *mut c_uint,
) -> *mut *const objc_protocol;

#[cfg(not(objfw))]
pub fn class_createInstance(cls: *const objc_class, extra_bytes: usize) -> *mut objc_object;
#[cfg(not(objfw))]
pub fn class_getClassMethod(
cls: *const objc_class,
name: *const objc_selector,
) -> *const objc_method;
#[cfg(not(objfw))]
pub fn class_getClassVariable(cls: *const objc_class, name: *const c_char) -> *const objc_ivar;
#[cfg(apple)]
pub fn class_getImageName(cls: *const objc_class) -> *const c_char;
#[cfg(not(objfw))] // Available in newer versions
pub fn class_getInstanceMethod(
cls: *const objc_class,
name: *const objc_selector,
) -> *const objc_method;
pub fn class_getInstanceSize(cls: *const objc_class) -> usize;
#[cfg(not(objfw))]
pub fn class_getInstanceVariable(
cls: *const objc_class,
name: *const c_char,
) -> *const objc_ivar;
#[cfg(not(objfw))]
pub fn class_getIvarLayout(cls: *const objc_class) -> *const ivar_layout_type;
pub fn class_getName(cls: *const objc_class) -> *const c_char;
#[cfg(not(objfw))]
pub fn class_getProperty(cls: *const objc_class, name: *const c_char) -> *const objc_property;
pub fn class_getSuperclass(cls: *const objc_class) -> *const objc_class;
#[cfg(not(objfw))]
pub fn class_getVersion(cls: *const objc_class) -> c_int;
#[cfg(apple)]
pub fn class_getWeakIvarLayout(cls: *const objc_class) -> *const ivar_layout_type;
Expand All @@ -115,14 +133,17 @@ extern_c! {
imp: IMP,
types: *const c_char,
) -> IMP;
#[cfg(not(objfw))]
pub fn class_replaceProperty(
cls: *mut objc_class,
name: *const c_char,
attributes: *const objc_property_attribute_t,
attributes_len: c_uint,
);
pub fn class_respondsToSelector(cls: *const objc_class, sel: *const objc_selector) -> BOOL;
#[cfg(not(objfw))]
pub fn class_setIvarLayout(cls: *mut objc_class, layout: *const ivar_layout_type);
#[cfg(not(objfw))]
pub fn class_setVersion(cls: *mut objc_class, version: c_int);
#[cfg(apple)]
pub fn class_setWeakIvarLayout(cls: *mut objc_class, layout: *const ivar_layout_type);
Expand Down
Loading