Skip to content

Commit 13b2c8a

Browse files
authored
Merge pull request #141 from madsmtm/more-stable-sys-crates
Improve stability of `objc-sys` and `block-sys` crates
2 parents 06e538a + 5dbf3e7 commit 13b2c8a

30 files changed

+295
-124
lines changed

block-sys/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
66

77
## Unreleased - YYYY-MM-DD
88

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

1015
## 0.0.3 - 2022-01-03
1116

block-sys/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ readme = "README.md"
1919

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

2525
[features]

block-sys/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,8 @@ TODO.
9494

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

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

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

108-
for flag in std::env::var("DEP_BLOCK_CC_ARGS").unwrap().split(' ') {
108+
for flag in std::env::var("DEP_BLOCK_0_0_CC_ARGS").unwrap().split(' ') {
109109
builder.flag(flag);
110110
}
111111

block-sys/build.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,17 +47,24 @@ fn main() {
4747
// work (on newer GNUStep versions these headers are present)
4848
if env::var_os("CARGO_FEATURE_GNUSTEP_2_0").is_none() {
4949
let compat_headers =
50-
Path::new(env!("CARGO_MANIFEST_DIR")).join("gnustep-compat-headers");
50+
Path::new(env!("CARGO_MANIFEST_DIR")).join("compat-headers/gnustep");
5151
cc_args.push_str(" -I");
5252
cc_args.push_str(compat_headers.to_str().unwrap());
5353
}
5454
}
55-
(false, false, false, true) => unimplemented!(),
55+
(false, false, false, true) => {
56+
// Add compability headers to make `#include <Block.h>` work.
57+
let compat_headers = Path::new(env!("CARGO_MANIFEST_DIR")).join("compat-headers/objfw");
58+
cc_args.push_str(" -I");
59+
cc_args.push_str(compat_headers.to_str().unwrap());
60+
println!("cargo:rustc-link-lib=dylib=objfw");
61+
unimplemented!("ObjFW is not yet supported")
62+
}
5663
// Checked in if-let above
5764
(false, false, false, false) => unreachable!(),
5865
(_, _, _, _) => panic!("Invalid feature combination; only one runtime may be selected!"),
5966
}
6067

61-
// Add DEP_BLOCK_CC_ARGS
68+
// Add DEP_BLOCK_[version]_CC_ARGS
6269
println!("cargo:cc_args={}", cc_args);
6370
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#include <ObjFW/block.h>

block-sys/src/lib.rs

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@
99
//!
1010
//! [ABI]: https://clang.llvm.org/docs/Block-ABI-Apple.html
1111
12+
#![no_std]
1213
// Update in Cargo.toml as well.
1314
#![doc(html_root_url = "https://docs.rs/block-sys/0.0.3")]
1415

16+
extern crate std;
17+
1518
// Ensure linkage actually happens
1619
#[cfg(feature = "gnustep-1-7")]
1720
extern crate objc_sys as _;
@@ -298,7 +301,6 @@ pub struct Block_descriptor {
298301
///
299302
/// Requires BLOCK_HAS_SIGNATURE
300303
#[repr(C)]
301-
#[cfg(not(feature = "objfw"))]
302304
pub struct Block_descriptor_basic {
303305
pub header: Block_descriptor_header,
304306

@@ -388,3 +390,50 @@ pub struct Block_byref_extended {
388390
pub inner: Block_byref,
389391
pub layout: *const c_char,
390392
}
393+
394+
#[cfg(test)]
395+
mod tests {
396+
use super::*;
397+
use core::ptr;
398+
use std::println;
399+
400+
#[test]
401+
fn smoke() {
402+
assert_eq!(unsafe { _Block_copy(ptr::null()) }, ptr::null_mut());
403+
}
404+
405+
#[test]
406+
fn test_linkable() {
407+
println!("{:p}", unsafe { &_NSConcreteGlobalBlock });
408+
println!("{:p}", unsafe { &_NSConcreteStackBlock });
409+
println!("{:p}", unsafe { &_NSConcreteMallocBlock });
410+
println!(
411+
"{:p}",
412+
_Block_copy as unsafe extern "C" fn(*const c_void) -> *mut c_void
413+
);
414+
println!(
415+
"{:p}",
416+
_Block_object_assign
417+
as unsafe extern "C" fn(*mut c_void, *const c_void, block_assign_dispose_flags)
418+
);
419+
println!(
420+
"{:p}",
421+
_Block_object_dispose
422+
as unsafe extern "C" fn(*const c_void, block_assign_dispose_flags)
423+
);
424+
println!(
425+
"{:p}",
426+
_Block_release as unsafe extern "C" fn(*const c_void)
427+
);
428+
#[cfg(any(feature = "apple", feature = "compiler-rt"))]
429+
{
430+
println!("{:p}", unsafe { &_NSConcreteAutoBlock });
431+
println!("{:p}", unsafe { &_NSConcreteFinalizingBlock });
432+
println!("{:p}", unsafe { &_NSConcreteWeakBlockVariable });
433+
println!(
434+
"{:p}",
435+
Block_size as unsafe extern "C" fn(*mut c_void) -> c_ulong
436+
);
437+
}
438+
}
439+
}

objc-sys/CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,19 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
66

77
## Unreleased - YYYY-MM-DD
88

9+
### Changed
10+
* **BREAKING**: Changed `links` key from `objc` to `objc_0_2` for better
11+
future compatibility, until we reach 1.0 (so `DEP_OBJC_X` in build scripts
12+
becomes `DEP_OBJC_0_2_X`).
13+
14+
### Removed
15+
* **BREAKING**: Removed type aliases `Class`, `Ivar`, `Method` and `Protocol`
16+
since they could easily be mistaken for the `objc2::runtime` structs with
17+
the same name.
18+
* **BREAKING**: Removed `objc_property_t`.
19+
* **BREAKING**: Removed `objc_hook_getClass` and `objc_hook_lazyClassNamer`
20+
type aliases (for now).
21+
922

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

objc-sys/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ readme = "README.md"
1919

2020
# Downstream users can customize the linking to libobjc!
2121
# See https://doc.rust-lang.org/cargo/reference/build-scripts.html#overriding-build-scripts
22-
links = "objc"
22+
links = "objc_0_2"
2323
build = "build.rs"
2424

2525
# The default is `apple` on Apple platforms; all other platforms will error

objc-sys/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,8 @@ ABI to the runtime you're using:
116116

117117
This is relevant if you're building and linking to custom Objective-C sources
118118
in a build script. To assist in compiling Objective-C sources, this crate's
119-
build script expose the `DEP_OBJC_CC_ARGS` environment variable to downstream
120-
build scripts.
119+
build script expose the `DEP_OBJC_0_2_CC_ARGS` environment variable to
120+
downstream build scripts.
121121

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

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

130-
for flag in std::env::var("DEP_OBJC_CC_ARGS").unwrap().split(' ') {
130+
for flag in std::env::var("DEP_OBJC_0_2_CC_ARGS").unwrap().split(' ') {
131131
builder.flag(flag);
132132
}
133133

objc-sys/build.rs

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::env;
1+
use std::{env, path::Path};
22

33
/// TODO: Better validation of this
44
///
@@ -114,7 +114,9 @@ fn main() {
114114
}
115115
}
116116
(false, false, true) => {
117-
unimplemented!()
117+
// For now
118+
unimplemented!("ObjFW is not yet supported")
119+
// ObjFW(None)
118120
}
119121
(false, false, false) => {
120122
// Choose sensible defaults when generating docs
@@ -142,7 +144,7 @@ fn main() {
142144
};
143145
println!("cargo:rustc-cfg={}", runtime_cfg);
144146
// Allow downstream build scripts to do the same
145-
println!("cargo:runtime={}", runtime_cfg); // DEP_OBJC_RUNTIME
147+
println!("cargo:runtime={}", runtime_cfg); // DEP_OBJC_[version]_RUNTIME
146148

147149
// Tell downstream build scripts our features
148150
// match &runtime {
@@ -202,8 +204,8 @@ fn main() {
202204
WinObjC => "gnustep-1.8".into(),
203205
ObjFW(version) => {
204206
// Default in clang
205-
let _version = version.as_deref().unwrap_or("0.8");
206-
todo!()
207+
let version = version.as_deref().unwrap_or("0.8");
208+
format!("objfw-{}", version)
207209
}
208210
};
209211

@@ -221,12 +223,27 @@ fn main() {
221223
// - `-miphoneos-version-min={}`
222224
// - `-mmacosx-version-min={}`
223225
// - ...
224-
println!(
225-
"cargo:cc_args=-fobjc-arc -fobjc-arc-exceptions -fobjc-exceptions -fobjc-runtime={}",
226-
// TODO: -fobjc-weak ?
226+
//
227+
// TODO: -fobjc-weak ?
228+
let mut cc_args = format!(
229+
"-fobjc-arc -fobjc-arc-exceptions -fobjc-exceptions -fobjc-runtime={}",
227230
clang_runtime
228-
); // DEP_OBJC_CC_ARGS
231+
);
232+
233+
if let Runtime::ObjFW(_) = &runtime {
234+
// Add compability headers to make `#include <objc/objc.h>` work.
235+
let compat_headers = Path::new(env!("CARGO_MANIFEST_DIR")).join("compat-headers-objfw");
236+
cc_args.push_str(" -I");
237+
cc_args.push_str(compat_headers.to_str().unwrap());
238+
}
229239

230-
// Link to libobjc
231-
println!("cargo:rustc-link-lib=dylib=objc");
240+
println!("cargo:cc_args={}", cc_args); // DEP_OBJC_[version]_CC_ARGS
241+
242+
if let Runtime::ObjFW(_) = &runtime {
243+
// Link to libobjfw-rt
244+
println!("cargo:rustc-link-lib=dylib=objfw-rt");
245+
} else {
246+
// Link to libobjc
247+
println!("cargo:rustc-link-lib=dylib=objc");
248+
}
232249
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#import <ObjFW-RT/ObjFW-RT.h>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#import <ObjFW-RT/ObjFW-RT.h>

objc-sys/src/class.rs

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
use std::os::raw::{c_char, c_int, c_uint};
22

3-
use crate::{
4-
objc_ivar, objc_method, objc_object, objc_property, objc_property_attribute_t, objc_protocol,
5-
objc_selector, OpaqueData, BOOL, IMP,
6-
};
3+
#[cfg(not(objfw))]
4+
use crate::{objc_ivar, objc_method, objc_object, objc_property, objc_property_attribute_t};
5+
use crate::{objc_protocol, objc_selector, OpaqueData, BOOL, IMP};
76

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

16+
#[cfg(not(objfw))]
1717
/// This is `c_char` in GNUStep's libobjc2 and `uint8_t` in Apple's objc4.
1818
///
1919
/// The pointer represents opaque data, and is definitely not just an integer,
@@ -27,6 +27,7 @@ extern_c! {
2727
pub fn objc_getClass(name: *const c_char) -> *const objc_class;
2828
pub fn objc_getRequiredClass(name: *const c_char) -> *const objc_class;
2929
pub fn objc_lookUpClass(name: *const c_char) -> *const objc_class;
30+
#[cfg(not(objfw))]
3031
pub fn objc_getMetaClass(name: *const c_char) -> *const objc_class;
3132
pub fn objc_copyClassList(out_len: *mut c_uint) -> *mut *const objc_class;
3233
pub fn objc_getClassList(buffer: *mut *const objc_class, buffer_len: c_int) -> c_int;
@@ -42,9 +43,11 @@ extern_c! {
4243
name: *const c_char,
4344
extra_bytes: usize,
4445
) -> *mut objc_class;
46+
#[cfg(not(objfw))]
4547
pub fn objc_disposeClassPair(cls: *mut objc_class);
4648
pub fn objc_registerClassPair(cls: *mut objc_class);
4749

50+
#[cfg(not(objfw))]
4851
pub fn class_addIvar(
4952
cls: *mut objc_class,
5053
name: *const c_char,
@@ -58,53 +61,68 @@ extern_c! {
5861
imp: IMP,
5962
types: *const c_char,
6063
) -> BOOL;
64+
#[cfg(not(objfw))]
6165
pub fn class_addProperty(
6266
cls: *mut objc_class,
6367
name: *const c_char,
6468
attributes: *const objc_property_attribute_t,
6569
attributes_count: c_uint,
6670
) -> BOOL;
71+
#[cfg(not(objfw))]
6772
pub fn class_addProtocol(cls: *mut objc_class, protocol: *const objc_protocol) -> BOOL;
6873
pub fn class_conformsToProtocol(cls: *const objc_class, protocol: *const objc_protocol)
6974
-> BOOL;
75+
76+
#[cfg(not(objfw))] // Available in newer versions
7077
pub fn class_copyIvarList(
7178
cls: *const objc_class,
7279
out_len: *mut c_uint,
7380
) -> *mut *const objc_ivar;
81+
#[cfg(not(objfw))] // Available in newer versions
7482
pub fn class_copyMethodList(
7583
cls: *const objc_class,
7684
out_len: *mut c_uint,
7785
) -> *mut *const objc_method;
86+
#[cfg(not(objfw))] // Available in newer versions
7887
pub fn class_copyPropertyList(
7988
cls: *const objc_class,
8089
out_len: *mut c_uint,
8190
) -> *mut *const objc_property;
91+
#[cfg(not(objfw))]
8292
pub fn class_copyProtocolList(
8393
cls: *const objc_class,
8494
out_len: *mut c_uint,
8595
) -> *mut *const objc_protocol;
8696

97+
#[cfg(not(objfw))]
8798
pub fn class_createInstance(cls: *const objc_class, extra_bytes: usize) -> *mut objc_object;
99+
#[cfg(not(objfw))]
88100
pub fn class_getClassMethod(
89101
cls: *const objc_class,
90102
name: *const objc_selector,
91103
) -> *const objc_method;
104+
#[cfg(not(objfw))]
92105
pub fn class_getClassVariable(cls: *const objc_class, name: *const c_char) -> *const objc_ivar;
93106
#[cfg(apple)]
94107
pub fn class_getImageName(cls: *const objc_class) -> *const c_char;
108+
#[cfg(not(objfw))] // Available in newer versions
95109
pub fn class_getInstanceMethod(
96110
cls: *const objc_class,
97111
name: *const objc_selector,
98112
) -> *const objc_method;
99113
pub fn class_getInstanceSize(cls: *const objc_class) -> usize;
114+
#[cfg(not(objfw))]
100115
pub fn class_getInstanceVariable(
101116
cls: *const objc_class,
102117
name: *const c_char,
103118
) -> *const objc_ivar;
119+
#[cfg(not(objfw))]
104120
pub fn class_getIvarLayout(cls: *const objc_class) -> *const ivar_layout_type;
105121
pub fn class_getName(cls: *const objc_class) -> *const c_char;
122+
#[cfg(not(objfw))]
106123
pub fn class_getProperty(cls: *const objc_class, name: *const c_char) -> *const objc_property;
107124
pub fn class_getSuperclass(cls: *const objc_class) -> *const objc_class;
125+
#[cfg(not(objfw))]
108126
pub fn class_getVersion(cls: *const objc_class) -> c_int;
109127
#[cfg(apple)]
110128
pub fn class_getWeakIvarLayout(cls: *const objc_class) -> *const ivar_layout_type;
@@ -115,14 +133,17 @@ extern_c! {
115133
imp: IMP,
116134
types: *const c_char,
117135
) -> IMP;
136+
#[cfg(not(objfw))]
118137
pub fn class_replaceProperty(
119138
cls: *mut objc_class,
120139
name: *const c_char,
121140
attributes: *const objc_property_attribute_t,
122141
attributes_len: c_uint,
123142
);
124143
pub fn class_respondsToSelector(cls: *const objc_class, sel: *const objc_selector) -> BOOL;
144+
#[cfg(not(objfw))]
125145
pub fn class_setIvarLayout(cls: *mut objc_class, layout: *const ivar_layout_type);
146+
#[cfg(not(objfw))]
126147
pub fn class_setVersion(cls: *mut objc_class, version: c_int);
127148
#[cfg(apple)]
128149
pub fn class_setWeakIvarLayout(cls: *mut objc_class, layout: *const ivar_layout_type);

0 commit comments

Comments
 (0)