-
Notifications
You must be signed in to change notification settings - Fork 500
/
main.rs
106 lines (94 loc) · 3.96 KB
/
main.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
use rayon::prelude::*;
use std::io::prelude::*;
/// Namespaces to exclude from code generation for the `windows` crate.
const EXCLUDE_NAMESPACES: [&str; 14] = ["Windows.AI.MachineLearning.Preview", "Windows.ApplicationModel.SocialInfo", "Windows.Devices.AllJoyn", "Windows.Devices.Perception", "Windows.Security.Authentication.Identity.Provider", "Windows.Services.Cortana", "Windows.System.Power.Diagnostics", "Windows.System.Preview", "Windows.UI.Xaml", "Windows.Win32.Interop", "Windows.Win32.System.Diagnostics.Debug.WebApp", "Windows.Win32.System.WinRT.Xaml", "Windows.Win32.Web", "Windows.Win32.UI.Xaml"];
fn main() {
let mut rustfmt = true;
let mut expect_namespace = false;
let mut namespace = String::new();
for arg in std::env::args() {
match arg.as_str() {
"-p" => rustfmt = false,
"-n" => expect_namespace = true,
_ => {
if expect_namespace {
namespace = arg;
}
}
}
}
let mut output = std::path::PathBuf::from("crates/libs/windows/src/Windows");
if namespace.is_empty() {
let _ = std::fs::remove_dir_all(&output);
}
output.pop();
let files = metadata::reader::File::with_default(&[]).unwrap();
let reader = &metadata::reader::Reader::new(&files);
if !namespace.is_empty() {
let tree = reader.tree(&namespace, &[]).expect("Namespace not found");
gen_tree(reader, &output, &tree, rustfmt);
return;
}
let root = reader.tree("Windows", &EXCLUDE_NAMESPACES).expect("`Windows` namespace not found");
let trees = root.flatten();
trees.par_iter().for_each(|tree| gen_tree(reader, &output, tree, rustfmt));
output.pop();
output.push("Cargo.toml");
let mut file = std::fs::File::create(&output).unwrap();
file.write_all(
r#"
[package]
name = "windows"
version = "0.43.0"
authors = ["Microsoft"]
edition = "2018"
license = "MIT OR Apache-2.0"
description = "Rust for Windows"
repository = "https://github.com/microsoft/windows-rs"
documentation = "https://microsoft.github.io/windows-docs-rs/"
readme = "../../../docs/readme.md"
rust-version = "1.64"
[package.metadata.docs.rs]
default-target = "x86_64-pc-windows-msvc"
targets = []
[target.'cfg(not(windows_raw_dylib))'.dependencies]
windows-targets = { path = "../targets", version = "0.42.1" }
[dependencies]
windows-implement = { path = "../implement", version = "0.43.0", optional = true }
windows-interface = { path = "../interface", version = "0.43.0", optional = true }
[features]
default = []
deprecated = []
implement = ["windows-implement", "windows-interface"]
"#
.as_bytes(),
)
.unwrap();
// Skip the root Windows tree while writing features
for tree in trees.iter().skip(1) {
let feature = tree.namespace[root.namespace.len() + 1..].replace('.', "_");
if let Some(pos) = feature.rfind('_') {
let dependency = &feature[..pos];
file.write_all(format!("{feature} = [\"{dependency}\"]\n").as_bytes()).unwrap();
} else {
file.write_all(format!("{feature} = []\n").as_bytes()).unwrap();
}
}
}
fn gen_tree(reader: &metadata::reader::Reader, output: &std::path::Path, tree: &metadata::reader::Tree, rustfmt: bool) {
println!("{}", tree.namespace);
let mut path = std::path::PathBuf::from(output);
path.push(tree.namespace.replace('.', "/"));
std::fs::create_dir_all(&path).unwrap();
let mut gen = bindgen::Gen::new(reader);
gen.namespace = tree.namespace;
gen.cfg = true;
gen.doc = true;
let mut tokens = bindgen::namespace(&gen, tree);
tokens.push_str(r#"#[cfg(feature = "implement")] ::core::include!("impl.rs");"#);
lib::format(tree.namespace, &mut tokens, rustfmt);
std::fs::write(path.join("mod.rs"), tokens).unwrap();
let mut tokens = bindgen::namespace_impl(&gen, tree);
lib::format(tree.namespace, &mut tokens, rustfmt);
std::fs::write(path.join("impl.rs"), tokens).unwrap();
}