Skip to content

Commit afc2f4f

Browse files
committed
Add malloc feature to allow cutting down on dependencies
1 parent 3bb9688 commit afc2f4f

File tree

7 files changed

+93
-31
lines changed

7 files changed

+93
-31
lines changed

.github/workflows/apple.yml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ jobs:
7777
with:
7878
command: test
7979
# Not using --all-features because some features are nightly-only
80-
args: --no-fail-fast --features block,exception,catch_all,verify_message
80+
args: --no-fail-fast --features malloc,block,exception,catch_all,verify_message
8181

8282
build_32_bit:
8383
name: Build 32-bit
@@ -105,8 +105,14 @@ jobs:
105105
tar -xyf MacOSX10.13.tar.bz2
106106
echo "SDKROOT=$(pwd)/MacOSX10.13.sdk" >> $GITHUB_ENV
107107
108+
- name: Build without features
109+
uses: actions-rs/cargo@v1
110+
with:
111+
command: build
112+
args: -Zbuild-std --tests --no-default-features
113+
108114
- name: Build with features
109115
uses: actions-rs/cargo@v1
110116
with:
111117
command: build
112-
args: -Zbuild-std --tests --features exception,catch_all,verify_message
118+
args: -Zbuild-std --tests --features malloc,exception,catch_all,verify_message

.github/workflows/gnustep.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,4 +148,4 @@ jobs:
148148
with:
149149
command: test
150150
# Not using --all-features because some features are nightly-only
151-
args: --no-fail-fast --features gnustep-1-9,block,exception,catch_all,verify_message
151+
args: --no-fail-fast --features gnustep-1-9,malloc,block,exception,catch_all,verify_message

objc2/CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,23 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
1919
// `init` takes ownership and possibly returns a new object.
2020
let obj = Id::new(msg_send![obj, init]);
2121
```
22+
* New cargo feature `"malloc"`, which allows cutting down on dependencies,
23+
most crates don't need the introspection features that this provides.
2224

2325
### Changed
2426
* Deprecated `runtime::BOOL`, `runtime::YES` and `runtime::NO`. Use the
2527
newtype `Bool` instead, or low-level `ffi::BOOL`, `ffi::YES` and `ffi::NO`.
28+
* **BREAKING**: The following methods now require the new `"malloc"` feature
29+
flag to be enabled:
30+
- `MessageReceiver::verify_message` (temporarily)
31+
- `Method::return_type`
32+
- `Method::argument_type`
33+
- `Class::classes`
34+
- `Class::instance_methods`
35+
- `Class::adopted_protocols`
36+
- `Class::instance_variables`
37+
- `Protocol::protocols`
38+
- `Protocol::adopted_protocols`
2639

2740
### Removed
2841
* **BREAKING**: Removed the raw FFI functions from the `runtime` module. These

objc2/Cargo.toml

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,22 @@ exception = ["cc"]
2424

2525
# Wrap every `objc2::msg_send` call in a `@try/@catch` block
2626
catch_all = ["exception"]
27-
verify_message = []
27+
28+
# Verify type encodings on every message send
29+
# Only intended to be used while debugging!
30+
verify_message = ["malloc"] # TODO: Remove malloc feature here
31+
32+
# Expose features that require linking to `libc::free`.
33+
#
34+
# This is not enabled by default because most users won't need it, and it
35+
# increases compilation time.
36+
malloc = ["malloc_buf"]
37+
38+
# Uses nightly features to make AutoreleasePool zero-cost even in debug mode
2839
unstable_autoreleasesafe = []
2940

3041
[dependencies]
31-
malloc_buf = "1.0"
42+
malloc_buf = { version = "1.0", optional = true }
3243
objc-sys = { path = "../objc-sys", version = "0.1.0" }
3344
# Loose dependency, because objc2-encode is not expected to change much more
3445
objc2-encode = { path = "../objc2-encode", version = "^2.0.0-beta.0" }
@@ -39,7 +50,7 @@ cc = { version = "1", optional = true }
3950
[package.metadata.docs.rs]
4051
default-target = "x86_64-apple-darwin"
4152

42-
features = ["exception"]
53+
features = ["exception", "malloc"]
4354

4455
targets = [
4556
# MacOS

objc2/examples/introspection.rs

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,22 @@ use core::ptr::NonNull;
22

33
use objc2::rc::{Id, Owned};
44
use objc2::runtime::{Class, Object};
5-
use objc2::{class, msg_send, sel, Encode};
5+
use objc2::{class, msg_send};
6+
#[cfg(feature = "malloc")]
7+
use objc2::{sel, Encode};
68

79
fn main() {
810
// Get a class
911
let cls = class!(NSObject);
1012
println!("NSObject size: {}", cls.instance_size());
1113

12-
// Inspect its ivars
13-
println!("NSObject ivars:");
14-
for ivar in cls.instance_variables().iter() {
15-
println!("{}", ivar.name());
14+
#[cfg(feature = "malloc")]
15+
{
16+
// Inspect its ivars
17+
println!("NSObject ivars:");
18+
for ivar in cls.instance_variables().iter() {
19+
println!("{}", ivar.name());
20+
}
1621
}
1722

1823
// Allocate an instance
@@ -27,12 +32,15 @@ fn main() {
2732
let isa: *const Class = unsafe { *obj.get_ivar("isa") };
2833
println!("NSObject isa: {:?}", isa);
2934

30-
// Inspect a method of the class
31-
let hash_sel = sel!(hash);
32-
let hash_method = cls.instance_method(hash_sel).unwrap();
33-
let hash_return = hash_method.return_type();
34-
println!("-[NSObject hash] return type: {:?}", hash_return);
35-
assert!(usize::ENCODING.equivalent_to_str(&hash_return));
35+
#[cfg(feature = "malloc")]
36+
{
37+
// Inspect a method of the class
38+
let hash_sel = sel!(hash);
39+
let hash_method = cls.instance_method(hash_sel).unwrap();
40+
let hash_return = hash_method.return_type();
41+
println!("-[NSObject hash] return type: {:?}", hash_return);
42+
assert!(usize::ENCODING.equivalent_to_str(&hash_return));
43+
}
3644

3745
// Invoke a method on the object
3846
let hash: usize = unsafe { msg_send![obj, hash] };

objc2/src/message/mod.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use alloc::string::{String, ToString};
1+
use alloc::string::String;
22
use core::fmt;
33
use core::mem;
44
use core::mem::ManuallyDrop;
@@ -27,6 +27,7 @@ unsafe fn conditional_try<R: Encode>(f: impl FnOnce() -> R) -> Result<R, Message
2727
Ok(f())
2828
}
2929

30+
#[cfg(feature = "malloc")]
3031
mod verify;
3132

3233
#[cfg(apple)]
@@ -37,6 +38,7 @@ mod platform;
3738
mod platform;
3839

3940
use self::platform::{send_super_unverified, send_unverified};
41+
#[cfg(feature = "malloc")]
4042
use self::verify::{verify_message_signature, VerificationError};
4143

4244
/// Types that can be sent Objective-C messages.
@@ -197,6 +199,7 @@ pub unsafe trait MessageReceiver: private::Sealed {
197199
/// let result = obj.verify_message::<(&Class,), Bool>(sel);
198200
/// assert!(result.is_ok());
199201
/// ```
202+
#[cfg(feature = "malloc")]
200203
fn verify_message<A, R>(&self, sel: Sel) -> Result<(), MessageError>
201204
where
202205
A: EncodeArguments,
@@ -357,8 +360,10 @@ impl Error for MessageError {
357360
}
358361
}
359362

363+
#[cfg(feature = "malloc")]
360364
impl<'a> From<VerificationError<'a>> for MessageError {
361365
fn from(err: VerificationError<'_>) -> MessageError {
366+
use alloc::string::ToString;
362367
MessageError(err.to_string())
363368
}
364369
}
@@ -448,6 +453,7 @@ mod tests {
448453
}
449454

450455
#[test]
456+
#[cfg(feature = "malloc")]
451457
fn test_verify_message() {
452458
let obj = test_utils::custom_object();
453459
assert!(obj.verify_message::<(), u32>(sel!(foo)).is_ok());

objc2/src/runtime.rs

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ use core::fmt;
88
use core::panic::{RefUnwindSafe, UnwindSafe};
99
use core::ptr;
1010
use core::str;
11+
#[cfg(feature = "malloc")]
1112
use malloc_buf::Malloc;
1213
use std::ffi::{CStr, CString};
14+
#[cfg(feature = "malloc")]
1315
use std::os::raw::c_uint;
1416

1517
pub use super::bool::Bool;
@@ -177,6 +179,7 @@ impl Method {
177179
}
178180

179181
/// Returns the `Encoding` of self's return type.
182+
#[cfg(feature = "malloc")]
180183
pub fn return_type(&self) -> Malloc<str> {
181184
unsafe {
182185
let encoding = ffi::method_copyReturnType(self.as_ptr());
@@ -186,6 +189,7 @@ impl Method {
186189

187190
/// Returns the `Encoding` of a single parameter type of self, or
188191
/// [`None`] if self has no parameter at the given index.
192+
#[cfg(feature = "malloc")]
189193
pub fn argument_type(&self, index: usize) -> Option<Malloc<str>> {
190194
unsafe {
191195
let encoding = ffi::method_copyArgumentType(self.as_ptr(), index as c_uint);
@@ -243,6 +247,7 @@ impl Class {
243247
// fn lookup(name: &str) -> Option<&'static Self>;
244248

245249
/// Obtains the list of registered class definitions.
250+
#[cfg(feature = "malloc")]
246251
pub fn classes() -> Malloc<[&'static Self]> {
247252
unsafe {
248253
let mut count: c_uint = 0;
@@ -340,6 +345,7 @@ impl Class {
340345
}
341346

342347
/// Describes the instance methods implemented by self.
348+
#[cfg(feature = "malloc")]
343349
pub fn instance_methods(&self) -> Malloc<[&Method]> {
344350
unsafe {
345351
let mut count: c_uint = 0;
@@ -356,6 +362,7 @@ impl Class {
356362
}
357363

358364
/// Get a list of the protocols to which this class conforms.
365+
#[cfg(feature = "malloc")]
359366
pub fn adopted_protocols(&self) -> Malloc<[&Protocol]> {
360367
unsafe {
361368
let mut count: c_uint = 0;
@@ -365,6 +372,7 @@ impl Class {
365372
}
366373

367374
/// Describes the instance variables declared by self.
375+
#[cfg(feature = "malloc")]
368376
pub fn instance_variables(&self) -> Malloc<[&Ivar]> {
369377
unsafe {
370378
let mut count: c_uint = 0;
@@ -431,6 +439,7 @@ impl Protocol {
431439
}
432440

433441
/// Obtains the list of registered protocol definitions.
442+
#[cfg(feature = "malloc")]
434443
pub fn protocols() -> Malloc<[&'static Protocol]> {
435444
unsafe {
436445
let mut count: c_uint = 0;
@@ -440,6 +449,7 @@ impl Protocol {
440449
}
441450

442451
/// Get a list of the protocols to which this protocol conforms.
452+
#[cfg(feature = "malloc")]
443453
pub fn adopted_protocols(&self) -> Malloc<[&Protocol]> {
444454
unsafe {
445455
let mut count: c_uint = 0;
@@ -612,8 +622,8 @@ mod tests {
612622
assert!(<u32>::ENCODING.equivalent_to_str(ivar.type_encoding()));
613623
assert!(ivar.offset() > 0);
614624

615-
let ivars = cls.instance_variables();
616-
assert!(ivars.len() > 0);
625+
#[cfg(feature = "malloc")]
626+
assert!(cls.instance_variables().len() > 0);
617627
}
618628

619629
#[test]
@@ -623,11 +633,14 @@ mod tests {
623633
let method = cls.instance_method(sel).unwrap();
624634
assert_eq!(method.name().name(), "foo");
625635
assert_eq!(method.arguments_count(), 2);
626-
assert!(<u32>::ENCODING.equivalent_to_str(&method.return_type()));
627-
assert!(Sel::ENCODING.equivalent_to_str(&method.argument_type(1).unwrap()));
636+
#[cfg(feature = "malloc")]
637+
{
638+
assert!(<u32>::ENCODING.equivalent_to_str(&method.return_type()));
639+
assert!(Sel::ENCODING.equivalent_to_str(&method.argument_type(1).unwrap()));
628640

629-
let methods = cls.instance_methods();
630-
assert!(methods.len() > 0);
641+
let methods = cls.instance_methods();
642+
assert!(methods.len() > 0);
643+
}
631644
}
632645

633646
#[test]
@@ -648,8 +661,13 @@ mod tests {
648661
}
649662

650663
#[test]
651-
fn test_classes() {
664+
fn test_classes_count() {
652665
assert!(Class::classes_count() > 0);
666+
}
667+
668+
#[test]
669+
#[cfg(feature = "malloc")]
670+
fn test_classes() {
653671
let classes = Class::classes();
654672
assert!(classes.len() > 0);
655673
}
@@ -660,8 +678,8 @@ mod tests {
660678
assert_eq!(proto.name(), "CustomProtocol");
661679
let class = test_utils::custom_class();
662680
assert!(class.conforms_to(proto));
663-
let class_protocols = class.adopted_protocols();
664-
assert!(class_protocols.len() > 0);
681+
#[cfg(feature = "malloc")]
682+
assert!(class.adopted_protocols().len() > 0);
665683
}
666684

667685
#[test]
@@ -676,17 +694,17 @@ mod tests {
676694
let sub_proto = test_utils::custom_subprotocol();
677695
let super_proto = test_utils::custom_protocol();
678696
assert!(sub_proto.conforms_to(super_proto));
679-
let adopted_protocols = sub_proto.adopted_protocols();
680-
assert_eq!(adopted_protocols[0], super_proto);
697+
#[cfg(feature = "malloc")]
698+
assert_eq!(sub_proto.adopted_protocols()[0], super_proto);
681699
}
682700

683701
#[test]
684702
fn test_protocols() {
685703
// Ensure that a protocol has been registered on linux
686704
let _ = test_utils::custom_protocol();
687705

688-
let protocols = Protocol::protocols();
689-
assert!(protocols.len() > 0);
706+
#[cfg(feature = "malloc")]
707+
assert!(Protocol::protocols().len() > 0);
690708
}
691709

692710
#[test]

0 commit comments

Comments
 (0)