Skip to content

Commit 6d4d2d5

Browse files
committed
Automatically generate framework imports
1 parent 7681f6c commit 6d4d2d5

File tree

123 files changed

+325
-590
lines changed

Some content is hidden

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

123 files changed

+325
-590
lines changed

crates/header-translator/src/config.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,15 @@ pub struct LibraryData {
6969
#[serde(rename = "gnustep-library")]
7070
#[serde(default)]
7171
pub gnustep_library: Option<String>,
72+
#[serde(default)]
73+
#[serde(rename = "extra-docs")]
74+
pub extra_docs: String,
75+
#[serde(default)]
76+
#[serde(rename = "additions")]
77+
pub has_additions: bool,
78+
#[serde(default)]
79+
#[serde(rename = "fixes")]
80+
pub has_fixes: bool,
7281
#[serde(rename = "extra-features")]
7382
#[serde(default)]
7483
pub extra_features: Vec<String>,
@@ -82,6 +91,16 @@ pub struct LibraryData {
8291
pub tvos: Option<semver::VersionReq>,
8392
#[serde(default)]
8493
pub watchos: Option<semver::VersionReq>,
94+
#[serde(default)]
95+
pub examples: Vec<Example>,
96+
}
97+
98+
#[derive(Deserialize, Debug, Default, Clone, PartialEq, Eq)]
99+
#[serde(deny_unknown_fields)]
100+
pub struct Example {
101+
pub name: String,
102+
#[serde(default)]
103+
pub description: String,
85104
}
86105

87106
#[derive(Deserialize, Debug, Default, Clone, PartialEq, Eq)]

crates/header-translator/src/file.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@ use std::fmt;
33
use crate::context::Context;
44
use crate::stmt::Stmt;
55

6-
pub(crate) const FILE_PRELUDE: &str = r#"//! This file has been automatically generated by `objc2`'s `header-translator`.
7-
//! DO NOT EDIT"#;
8-
96
#[derive(Debug, PartialEq)]
107
pub struct File {
118
library_name: String,
@@ -41,7 +38,11 @@ impl File {
4138

4239
impl fmt::Display for File {
4340
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44-
writeln!(f, "{FILE_PRELUDE}")?;
41+
writeln!(
42+
f,
43+
"//! This file has been automatically generated by `objc2`'s `header-translator`."
44+
)?;
45+
writeln!(f, "//! DO NOT EDIT")?;
4546

4647
writeln!(f, "use crate::common::*;")?;
4748
writeln!(f, "use crate::{}::*;", self.library_name)?;

crates/header-translator/src/library.rs

Lines changed: 60 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,21 @@ use std::io;
55
use std::path::Path;
66

77
use crate::config::LibraryData;
8-
use crate::file::{File, FILE_PRELUDE};
8+
use crate::file::File;
99

1010
#[derive(Debug, PartialEq, Default)]
1111
pub struct Library {
1212
pub files: BTreeMap<String, File>,
1313
link_name: String,
14-
gnustep_library: Option<String>,
14+
data: LibraryData,
1515
}
1616

1717
impl Library {
1818
pub fn new(name: &str, data: &LibraryData) -> Self {
1919
Self {
2020
files: BTreeMap::new(),
2121
link_name: name.to_string(),
22-
gnustep_library: data.gnustep_library.clone(),
22+
data: data.clone(),
2323
}
2424
}
2525

@@ -46,11 +46,63 @@ impl Library {
4646
}
4747
}
4848

49+
fn prepare_for_docs(s: &str) -> String {
50+
s.trim().replace('\n', "\n//! ")
51+
}
52+
4953
impl fmt::Display for Library {
5054
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51-
writeln!(f, "{FILE_PRELUDE}")?;
52-
writeln!(f, "#![allow(unused_imports)]")?;
53-
writeln!(f, "#![allow(deprecated)]")?;
55+
let name = self.data.name.as_deref().unwrap_or(&self.link_name);
56+
writeln!(
57+
f,
58+
"// This file has been automatically generated by `objc2`'s `header-translator`."
59+
)?;
60+
writeln!(f, "// DO NOT EDIT")?;
61+
writeln!(f)?;
62+
writeln!(f, "//! # Bindings to the `{name}` framework")?;
63+
if !self.data.extra_docs.is_empty() {
64+
writeln!(f, "//!")?;
65+
writeln!(f, "//! {}.", prepare_for_docs(&self.data.extra_docs))?;
66+
}
67+
if !self.data.examples.is_empty() {
68+
writeln!(f, "//!")?;
69+
writeln!(f, "//!")?;
70+
let examples_plural = if self.data.examples.len() > 1 {
71+
"s"
72+
} else {
73+
""
74+
};
75+
writeln!(f, "//! ## Example{examples_plural}")?;
76+
for example in &self.data.examples {
77+
writeln!(f, "//!")?;
78+
writeln!(f, "//! {}.", prepare_for_docs(&example.description))?;
79+
writeln!(f, "//!")?;
80+
writeln!(f, "//! ```ignore")?;
81+
writeln!(
82+
f,
83+
"#![doc = include_str!(\"../../../examples/{}.rs\")]",
84+
example.name
85+
)?;
86+
writeln!(f, "//! ```")?;
87+
}
88+
}
89+
if self.data.name.is_some() {
90+
writeln!(f, "#![doc(alias = \"{}\")]", self.link_name)?;
91+
}
92+
writeln!(f)?;
93+
94+
if self.data.has_additions {
95+
writeln!(f, "#[path = \"../../additions/{name}/mod.rs\"]")?;
96+
writeln!(f, "mod additions;")?;
97+
writeln!(f, "pub use self::additions::*;")?;
98+
}
99+
writeln!(f)?;
100+
if self.data.has_fixes {
101+
writeln!(f, "#[path = \"../../fixes/{name}/mod.rs\"]")?;
102+
writeln!(f, "mod fixes;")?;
103+
writeln!(f, "pub use self::fixes::*;")?;
104+
}
105+
writeln!(f)?;
54106

55107
// Link to the correct framework
56108
//
@@ -60,14 +112,15 @@ impl fmt::Display for Library {
60112
"#[cfg_attr(feature = \"apple\", link(name = \"{}\", kind = \"framework\"))]",
61113
self.link_name
62114
)?;
63-
if let Some(gnustep_library) = &self.gnustep_library {
115+
if let Some(gnustep_library) = &self.data.gnustep_library {
64116
writeln!(
65117
f,
66118
"#[cfg_attr(feature = \"gnustep-1-7\", link(name = \"{}\", kind = \"dylib\"))]",
67119
gnustep_library
68120
)?;
69121
}
70122
writeln!(f, "extern \"C\" {{}}")?;
123+
writeln!(f)?;
71124

72125
for name in self.files.keys() {
73126
// NOTE: some SDK files have '+' in the file name

crates/header-translator/src/main.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::fs;
12
use std::io::{Read, Write};
23
use std::path::{Path, PathBuf};
34

@@ -138,19 +139,26 @@ fn main() -> Result<(), BoxError> {
138139
cache.update(&mut final_result);
139140
drop(span);
140141

142+
let generated_dir = crate_src.join("generated");
143+
fs::create_dir_all(&generated_dir)?;
144+
141145
for (library_name, files) in &final_result.libraries {
142146
let _span = info_span!("writing", library_name).entered();
143-
let output_path = crate_src.join("generated").join(library_name);
144-
std::fs::create_dir_all(&output_path)?;
147+
let output_path = generated_dir.join(library_name);
148+
fs::create_dir_all(&output_path)?;
145149
files.output(&output_path).unwrap();
146150
}
147151

152+
final_result
153+
.output_module(&generated_dir.join("mod.rs"))
154+
.unwrap();
155+
148156
let span = info_span!("writing features").entered();
149157
const FEATURE_SECTION_PATTERN:
150158
&str = "# This section has been automatically generated by `objc2`'s `header-translator`.\n# DO NOT EDIT\n";
151159
let mut cargo_toml = {
152160
let path = crate_src.parent().unwrap().join("Cargo.toml");
153-
std::fs::OpenOptions::new()
161+
fs::OpenOptions::new()
154162
.read(true)
155163
.write(true)
156164
.append(true)

crates/header-translator/src/output.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
use std::collections::{BTreeMap, BTreeSet, HashMap};
2+
use std::fmt::{self, Write};
3+
use std::fs;
4+
use std::path::Path;
25
use std::str::FromStr;
36

47
use crate::config::{Config, LibraryData};
@@ -30,6 +33,19 @@ impl Output {
3033
);
3134
}
3235

36+
pub fn output_module(&self, path: &Path) -> fmt::Result {
37+
let mut f = String::new();
38+
39+
for library_name in self.libraries.keys() {
40+
writeln!(&mut f, "#[cfg(feature = \"{library_name}\")]")?;
41+
writeln!(&mut f, "pub mod {library_name};")?;
42+
}
43+
44+
fs::write(path, f).unwrap();
45+
46+
Ok(())
47+
}
48+
3349
pub fn cargo_features(&self, config: &Config) -> BTreeMap<String, Vec<String>> {
3450
let mut features = BTreeMap::new();
3551

crates/header-translator/translation-config.toml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ tvos = "9.0"
2828
[library.AppKit]
2929
imports = ["CoreData", "Foundation"]
3030
gnustep-library = "gnustep-gui"
31+
fixes = true
3132
extra-features = [
3233
# Temporary, since some structs and statics use these
3334
"AppKit_NSApplication",
@@ -45,8 +46,17 @@ extra-features = [
4546
macos = "10.0"
4647
maccatalyst = "13.0"
4748

49+
[[library.AppKit.examples]]
50+
name = "delegate"
51+
description = "Implementing `NSApplicationDelegate` for a custom class"
52+
53+
[[library.AppKit.examples]]
54+
name = "nspasteboard"
55+
description = "An example showing basic and a bit more advanced usage of `NSPasteboard`"
56+
4857
[library.AuthenticationServices]
4958
imports = ["AppKit", "Foundation"]
59+
fixes = true
5060
# Temporary, since some structs and statics use these
5161
extra-features = ["Foundation_NSURL"]
5262
macos = "10.15"
@@ -191,6 +201,14 @@ ios = "11.0"
191201
[library.Foundation]
192202
imports = []
193203
gnustep-library = "gnustep-base"
204+
extra-docs = """
205+
This is the [`std`] equivalent for Objective-C, containing essential data
206+
types, collections, and operating-system services.
207+
208+
See [Apple's documentation](https://developer.apple.com/documentation/foundation?language=objc)
209+
"""
210+
additions = true
211+
fixes = true
194212
extra-features = [
195213
"objective-c",
196214
"block",
@@ -211,8 +229,17 @@ ios = "2.0"
211229
tvos = "9.0"
212230
watchos = "2.0"
213231

232+
[[library.Foundation.examples]]
233+
name = "basic_usage"
234+
description = "Basic usage of a few Foundation types"
235+
236+
[[library.Foundation.examples]]
237+
name = "speech_synthesis"
238+
description = "An example showing how to define your own interfaces to parts that may be missing in `icrate`"
239+
214240
[library.GameController]
215241
imports = ["AppKit", "Foundation"]
242+
fixes = true
216243
extra-features = [
217244
"GameController_GCControllerAxisInput",
218245
"GameController_GCControllerButtonInput",
@@ -255,11 +282,13 @@ ios = "11.0"
255282

256283
[library.InputMethodKit]
257284
imports = ["AppKit", "Foundation"]
285+
fixes = true
258286
macos = "10.5"
259287
maccatalyst = "13.0"
260288

261289
[library.LocalAuthentication]
262290
imports = ["Foundation"]
291+
fixes = true
263292
macos = "10.10"
264293
maccatalyst = "13.0"
265294
ios = "8.0"
@@ -285,6 +314,7 @@ macos = "12.0"
285314

286315
[library.MapKit]
287316
imports = ["AppKit", "Contacts", "CoreLocation", "Foundation"]
317+
fixes = true
288318
extra-features = [
289319
"MapKit_MKDirectionsResponse",
290320
"MapKit_MKETAResponse",
@@ -307,11 +337,17 @@ watchos = "5.0"
307337

308338
[library.Metal]
309339
imports = ["Foundation"]
340+
additions = true
341+
fixes = true
310342
macos = "10.11"
311343
maccatalyst = "13.0"
312344
ios = "8.0"
313345
tvos = "9.0"
314346

347+
[[library.Metal.examples]]
348+
name = "metal"
349+
description = "Drawing a rotating triangle"
350+
315351
[library.MetalFX]
316352
imports = ["Metal"]
317353
macos = "13.0"
@@ -332,6 +368,7 @@ tvos = "9.0"
332368

333369
[library.MetricKit]
334370
imports = ["Foundation"]
371+
fixes = true
335372
macos = "12.0"
336373
maccatalyst = "13.0"
337374
ios = "13.0"
@@ -351,6 +388,11 @@ macos = "10.4"
351388

352389
[library.QuartzCore]
353390
name = "CoreAnimation"
391+
fixes = true
392+
extra-docs = """
393+
This actually lives in the `QuartzCore` framework, but `CoreAnimation` is
394+
the name that people use to refer to it.
395+
"""
354396
imports = ["Foundation"]
355397
macos = "10.3"
356398
maccatalyst = "13.0"
@@ -398,11 +440,15 @@ watchos = "3.0"
398440

399441
[library.WebKit]
400442
imports = ["AppKit", "Foundation"]
443+
fixes = true
401444
extra-features = ["Foundation_NSAttributedString"]
402445
macos = "10.2"
403446
maccatalyst = "13.0"
404447
ios = "16.0"
405448

449+
[[library.WebKit.examples]]
450+
name = "browser"
451+
406452
###
407453
### Attributes that change a function/method's calling convention.
408454
###

crates/icrate/src/Accessibility/mod.rs

Lines changed: 0 additions & 4 deletions
This file was deleted.

crates/icrate/src/AdServices/mod.rs

Lines changed: 0 additions & 4 deletions
This file was deleted.

crates/icrate/src/AdSupport/mod.rs

Lines changed: 0 additions & 4 deletions
This file was deleted.

0 commit comments

Comments
 (0)