Skip to content

Commit 210befc

Browse files
committed
Make objc2 optional when translating frameworks
1 parent 8ba2a96 commit 210befc

File tree

67 files changed

+248
-157
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+248
-157
lines changed

crates/header-translator/src/context.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,18 @@ impl MacroLocation {
3333

3434
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3535
pub struct MacroEntity {
36+
/// The name and location of the macro definition.
3637
pub(crate) id: ItemIdentifier,
3738
pub(crate) is_function_like: bool,
3839
}
3940

4041
impl MacroEntity {
4142
pub fn from_entity(entity: &Entity<'_>, context: &Context<'_>) -> Self {
43+
let definition = entity.get_definition();
4244
Self {
43-
id: ItemIdentifier::new(entity, context),
45+
// Try to get location from the definition itself, but if that
46+
// doesn't exist, let's just get it from the entity.
47+
id: ItemIdentifier::new(definition.as_ref().unwrap_or(entity), context),
4448
is_function_like: entity.is_function_like_macro(),
4549
}
4650
}

crates/header-translator/src/id.rs

Lines changed: 50 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,18 @@ impl Location {
6060
// These types are redefined in the framework crate itself.
6161
"Darwin.MacTypes" => "__builtin__".into(),
6262

63+
// int8_t, int16_t etc., translated to i8, i16 etc.
64+
"_stdint" => "__builtin__".into(),
65+
// Implementation of the above
66+
"DarwinFoundation.types.machine_types" => "__builtin__".into(),
67+
6368
// `core::ffi` types
64-
"DarwinFoundation.types.machine_types" => "__core__.ffi".into(),
6569
"_Builtin_stdarg.va_list" => {
66-
error!("va_list is not yet supported");
70+
warn!("va_list is not yet supported");
6771
"__core__.ffi".into()
6872
}
73+
// c_float and c_double
74+
"_float" | "_Builtin_float" => "__core__.ffi".into(),
6975

7076
// `libc`
7177
name if name.starts_with("sys_types") => "__libc__".into(),
@@ -169,26 +175,6 @@ impl Location {
169175
}
170176
}
171177

172-
/// The place from where a given item exists.
173-
pub fn import(&self, config: &Config, emission_library: &str) -> Option<Cow<'static, str>> {
174-
match self.library_name() {
175-
"__builtin__" => None,
176-
// TODO: Use `core::xyz` here.
177-
"__core__" => None,
178-
// Rare enough that it's written directly instead of
179-
// glob-imported, see `ItemIdentifier::path`.
180-
"__bitflags__" | "__libc__" | "block" => None,
181-
"ObjectiveC" => Some("objc2::__framework_prelude".into()),
182-
// Not currently needed, but might be useful to emit
183-
// `Some("crate")` here in the future.
184-
library if library == emission_library => None,
185-
library => {
186-
let krate = &config.library(library).krate;
187-
Some(krate.replace('-', "_").into())
188-
}
189-
}
190-
}
191-
192178
// Feature names are based on the file name, not the whole path to the feature.
193179
pub fn cargo_toml_feature(&self, config: &Config, emission_library: &str) -> Option<String> {
194180
match self.library_name() {
@@ -240,7 +226,11 @@ impl Location {
240226

241227
// FIXME: This is currently wrong for nested umbrella frameworks
242228
// (specifically MetalPerformanceShaders).
243-
fn cfg_feature<'a>(&self, config: &'a Config, emission_library: &str) -> Option<Cow<'a, str>> {
229+
pub fn cfg_feature<'a>(
230+
&self,
231+
config: &'a Config,
232+
emission_library: &str,
233+
) -> Option<Cow<'a, str>> {
244234
match self.library_name() {
245235
"__builtin__" | "__core__" => None,
246236
library if library == emission_library => {
@@ -317,10 +307,14 @@ impl<N: ToOptionString> ItemIdentifier<N> {
317307
.get_location()
318308
.unwrap_or_else(|| panic!("no entity location: {entity:?}"))
319309
.get_expansion_location()
320-
.file
321-
.expect("expanded location file");
310+
.file;
322311

323-
let mut location = Location::from_file(file);
312+
let mut location = if let Some(file) = file {
313+
Location::from_file(file)
314+
} else {
315+
// Assume item to be a built-in macro like __nonnull if no file.
316+
Location::new("__builtin__")
317+
};
324318

325319
// Defined in multiple places for some reason.
326320
if let Some("IOSurfaceRef" | "__IOSurface") = name.to_option() {
@@ -399,14 +393,14 @@ impl ItemIdentifier {
399393
pub fn core_ffi(name: &str) -> Self {
400394
Self {
401395
name: name.into(),
402-
location: Location::new("ObjectiveC"), // Temporary
396+
location: Location::new("__core__.ffi"),
403397
}
404398
}
405399

406-
pub fn core_ptr(name: &str) -> Self {
400+
pub fn core_ptr_nonnull() -> Self {
407401
Self {
408-
name: name.into(),
409-
location: Location::new("ObjectiveC"), // Temporary
402+
name: "NonNull".into(),
403+
location: Location::new("__core__.ptr"),
410404
}
411405
}
412406

@@ -433,6 +427,32 @@ impl ItemIdentifier {
433427
self.location.library_name() == "Foundation" && self.name == "NSComparator"
434428
}
435429

430+
/// The import needed for a given item to exist.
431+
pub fn import(&self, config: &Config, emission_library: &str) -> Option<Cow<'static, str>> {
432+
match self.library_name() {
433+
"__builtin__" => None,
434+
"__core__" => match &*self.location().module_path {
435+
"__core__.ffi" => Some("core::ffi::*".into()),
436+
"__core__.ptr" if self.name == "NonNull" => Some("core::ptr::NonNull".into()),
437+
_ => {
438+
error!("unknown __core__: {self:?}");
439+
None
440+
}
441+
},
442+
// Rare enough that it's written directly instead of
443+
// glob-imported, see `ItemIdentifier::path` below.
444+
"__bitflags__" | "__libc__" | "block" => None,
445+
"ObjectiveC" => Some("objc2::__framework_prelude::*".into()),
446+
// Not currently needed, but might be useful to emit
447+
// `Some("crate")` here in the future.
448+
library if library == emission_library => None,
449+
library => {
450+
let krate = &config.library(library).krate;
451+
Some(format!("{}::*", krate.replace('-', "_")).into())
452+
}
453+
}
454+
}
455+
436456
pub fn path(&self) -> impl fmt::Display + '_ {
437457
struct ItemIdentifierPath<'a>(&'a ItemIdentifier);
438458

crates/header-translator/src/library.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,16 @@ impl Library {
106106
}
107107
}
108108

109+
// Encode need the inner encode impl to be available.
110+
if self.data.required_crates.contains("objc2") {
111+
for (krate, (_, _, krate_features)) in &mut dependencies {
112+
let data = config.library_from_crate(krate);
113+
if !data.required_crates.contains("objc2") && !data.skipped {
114+
krate_features.insert("objc2".into());
115+
}
116+
}
117+
}
118+
109119
dependencies
110120
}
111121

crates/header-translator/src/module.rs

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -80,25 +80,29 @@ impl Module {
8080
.iter()
8181
.flat_map(|stmt| stmt.required_items_inner())
8282
.filter_map(|item| {
83-
item.location()
84-
.import(config, emission_library)
85-
.map(|import_data| (item.library_name().to_string(), import_data))
83+
item.import(config, emission_library).map(|import| {
84+
(
85+
import,
86+
(
87+
item.location().cfg_feature(config, emission_library),
88+
item.library_name().to_string(),
89+
),
90+
)
91+
})
8692
})
8793
.collect();
8894

8995
let emission_config = &config.library(emission_library);
90-
for (library_name, import) in imports {
91-
let krate = &config.library(&library_name).krate;
92-
let required = emission_config.required_crates.contains(krate);
93-
if !required {
94-
writeln!(f, "#[cfg(feature = {krate:?})]")?;
96+
for (import, (cfg_feature, library_name)) in imports {
97+
if let Some(cfg_feature) = cfg_feature {
98+
writeln!(f, "#[cfg(feature = {cfg_feature:?})]")?;
9599
}
96100
let mut platform_cfg = PlatformCfg::from_config(emission_config);
97101
platform_cfg.dependency(config.library(&library_name));
98102
if let Some(cfg) = platform_cfg.cfgs() {
99103
writeln!(f, "#[cfg({cfg})]")?;
100104
}
101-
writeln!(f, "use {import}::*;")?;
105+
writeln!(f, "use {import};")?;
102106
}
103107
writeln!(f)?;
104108
writeln!(f, "use crate::*;")?;

crates/header-translator/src/rust_type.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1159,7 +1159,7 @@ impl Ty {
11591159
} => {
11601160
let mut items = pointee.required_items();
11611161
if *nullability == Nullability::NonNull {
1162-
items.push(ItemIdentifier::core_ptr("NonNull"));
1162+
items.push(ItemIdentifier::core_ptr_nonnull());
11631163
}
11641164
items
11651165
}
@@ -1172,7 +1172,7 @@ impl Ty {
11721172
let mut items = to.required_items();
11731173
items.push(id.clone());
11741174
if *nullability == Nullability::NonNull {
1175-
items.push(ItemIdentifier::core_ptr("NonNull"));
1175+
items.push(ItemIdentifier::core_ptr_nonnull());
11761176
}
11771177
items
11781178
}

crates/header-translator/src/stmt.rs

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1544,15 +1544,10 @@ impl Stmt {
15441544
for (_, field_ty) in fields {
15451545
items.extend(field_ty.required_items());
15461546
}
1547-
items.push(ItemIdentifier::objc("Encoding"));
15481547
items
15491548
}
15501549
// Variants manage required items themselves
1551-
Self::EnumDecl { ty, .. } => {
1552-
let mut items = ty.required_items();
1553-
items.push(ItemIdentifier::objc("Encoding"));
1554-
items
1555-
}
1550+
Self::EnumDecl { ty, .. } => ty.required_items(),
15561551
Self::ConstDecl { ty, value, .. } => {
15571552
let mut items = ty.required_items();
15581553
items.extend(value.required_items());
@@ -1600,6 +1595,7 @@ impl Stmt {
16001595
.iter()
16011596
.flat_map(|method| method.required_items())
16021597
.collect(),
1598+
Self::StructDecl { .. } => vec![ItemIdentifier::objc("Encoding")],
16031599
Self::EnumDecl { kind, variants, .. } => {
16041600
let mut items: Vec<_> = variants
16051601
.iter()
@@ -1608,6 +1604,7 @@ impl Stmt {
16081604
if let Some(UnexposedAttr::Options) = kind {
16091605
items.push(ItemIdentifier::bitflags());
16101606
}
1607+
items.push(ItemIdentifier::objc("Encoding"));
16111608
items
16121609
}
16131610
_ => vec![],
@@ -1720,6 +1717,13 @@ impl Stmt {
17201717
return Ok(());
17211718
}
17221719

1720+
let cfg = cfg_gate_ln(
1721+
[ItemIdentifier::objc("extern_class")],
1722+
[self.location()],
1723+
config,
1724+
self.location(),
1725+
);
1726+
write!(f, "{cfg}")?;
17231727
writeln!(f, "extern_class!(")?;
17241728
writeln!(f, " /// {}", id.doc_link())?;
17251729
write!(f, " #[unsafe(super(")?;
@@ -1772,6 +1776,13 @@ impl Stmt {
17721776
category_name,
17731777
methods,
17741778
} => {
1779+
let cfg = cfg_gate_ln(
1780+
[ItemIdentifier::objc("extern_methods")],
1781+
[self.location()],
1782+
config,
1783+
self.location(),
1784+
);
1785+
write!(f, "{cfg}")?;
17751786
writeln!(f, "extern_methods!(")?;
17761787
if let Some(source_superclass) = source_superclass {
17771788
writeln!(
@@ -1845,6 +1856,13 @@ impl Stmt {
18451856
cls_required_items,
18461857
methods,
18471858
} => {
1859+
let cfg = cfg_gate_ln(
1860+
[ItemIdentifier::objc("extern_category")],
1861+
[self.location()],
1862+
config,
1863+
self.location(),
1864+
);
1865+
write!(f, "{cfg}")?;
18481866
writeln!(f, "extern_category!(")?;
18491867

18501868
if let Some(actual_name) = actual_name {
@@ -2038,6 +2056,13 @@ impl Stmt {
20382056
required_sendable: _,
20392057
required_mainthreadonly,
20402058
} => {
2059+
let cfg = cfg_gate_ln(
2060+
[ItemIdentifier::objc("extern_protocol")],
2061+
[self.location()],
2062+
config,
2063+
self.location(),
2064+
);
2065+
write!(f, "{cfg}")?;
20412066
writeln!(f, "extern_protocol!(")?;
20422067

20432068
writeln!(f, " /// {}", id.doc_link())?;
@@ -2141,6 +2166,11 @@ impl Stmt {
21412166
writeln!(f, "}}")?;
21422167
writeln!(f)?;
21432168

2169+
let mut required_items = self.required_items();
2170+
required_items.push(ItemIdentifier::objc("Encoding"));
2171+
let cfg_encoding =
2172+
cfg_gate_ln(required_items, [self.location()], config, self.location());
2173+
21442174
let encoding = FormatterFn(|f| {
21452175
write!(
21462176
f,
@@ -2155,9 +2185,9 @@ impl Stmt {
21552185
});
21562186

21572187
// SAFETY: The struct is marked `#[repr(C)]`.
2158-
write!(f, "{}", self.cfg_gate_ln(config))?;
2188+
write!(f, "{cfg_encoding}")?;
21592189
writeln!(f, "{}", unsafe_impl_encode(&id.name, encoding))?;
2160-
write!(f, "{}", self.cfg_gate_ln(config))?;
2190+
write!(f, "{cfg_encoding}")?;
21612191
writeln!(f, "{}", unsafe_impl_refencode(&id.name))?;
21622192

21632193
if let Some(true) = sendable {
@@ -2316,12 +2346,17 @@ impl Stmt {
23162346
_ => panic!("invalid enum kind"),
23172347
}
23182348

2349+
let mut required_items = self.required_items();
2350+
required_items.push(ItemIdentifier::objc("Encoding"));
2351+
let cfg_encoding =
2352+
cfg_gate_ln(required_items, [self.location()], config, self.location());
2353+
23192354
// SAFETY: The enum is either a `#[repr(transparent)]` newtype
23202355
// over the type, or a `#[repr(REPR)]`, where REPR is a valid
23212356
// repr with the same size and alignment as the type.
2322-
write!(f, "{}", self.cfg_gate_ln(config))?;
2357+
write!(f, "{cfg_encoding}")?;
23232358
writeln!(f, "{}", unsafe_impl_encode(&id.name, ty.enum_encoding()))?;
2324-
write!(f, "{}", self.cfg_gate_ln(config))?;
2359+
write!(f, "{cfg_encoding}")?;
23252360
writeln!(f, "{}", unsafe_impl_refencode(&id.name))?;
23262361

23272362
if let Some(true) = sendable {

crates/objc2/src/__framework_prelude.rs

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,6 @@
33
// Note: While this is not public, it is still a breaking change to remove
44
// entries in here, since framework crates rely on it.
55

6-
pub use core::ffi::{
7-
c_char, c_double, c_float, c_int, c_long, c_longlong, c_schar, c_short, c_uchar, c_uint,
8-
c_ulong, c_ulonglong, c_ushort, c_void,
9-
};
10-
pub use core::marker::PhantomData;
11-
pub use core::ptr::NonNull;
12-
136
pub use crate::encode::{Encode, Encoding, RefEncode};
147
pub use crate::ffi::{NSInteger, NSIntegerMax, NSUInteger, NSUIntegerMax};
158
pub use crate::rc::{Allocated, DefaultRetained, Retained};

framework-crates/objc2-accessibility/Cargo.toml

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

framework-crates/objc2-app-kit/Cargo.toml

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)