swift_bridge_build/
lib.rs1#![deny(missing_docs)]
5
6mod package;
7use crate::generate_core::write_core_swift_and_c;
8pub use package::*;
9use std::path::Path;
10use swift_bridge_ir::{CodegenConfig, SwiftBridgeModule};
11use syn::__private::ToTokens;
12use syn::{File, Item};
13
14mod generate_core;
15
16pub fn parse_bridges(
19 rust_source_files: impl IntoIterator<Item = impl AsRef<Path>>,
20) -> GeneratedCode {
21 let mut generated_code = GeneratedCode::new();
22
23 for rust_file in rust_source_files.into_iter() {
24 let rust_file: &Path = rust_file.as_ref();
25
26 let file = std::fs::read_to_string(rust_file).unwrap();
27 let gen = match parse_file_contents(&file) {
28 Ok(generated) => generated,
29 Err(e) => {
30 panic!(
32 r#"
33Error while parsing {:?}
34{}
35"#,
36 rust_file, e
37 )
38 }
39 };
40
41 generated_code.generated.push(gen);
42 }
43
44 generated_code
45}
46
47pub struct GeneratedCode {
49 generated: Vec<GeneratedFromSwiftBridgeModule>,
50}
51
52impl GeneratedCode {
53 fn new() -> Self {
54 GeneratedCode { generated: vec![] }
55 }
56}
57
58impl GeneratedCode {
59 pub fn write_all_concatenated(&self, swift_bridge_out_dir: impl AsRef<Path>, crate_name: &str) {
62 let swift_bridge_out_dir = swift_bridge_out_dir.as_ref();
63
64 let mut concatenated_swift = "".to_string();
65 let mut concatenated_c = "".to_string();
66
67 for gen in &self.generated {
68 concatenated_swift += &gen.swift;
69 concatenated_c += &gen.c_header;
70 }
71
72 let out = swift_bridge_out_dir.join(&crate_name);
73 match std::fs::create_dir_all(&out) {
74 Ok(_) => {}
75 Err(_) => {}
76 };
77
78 std::fs::write(out.join(format!("{}.h", crate_name)), concatenated_c).unwrap();
79 std::fs::write(
80 out.join(format!("{}.swift", crate_name)),
81 concatenated_swift,
82 )
83 .unwrap();
84
85 write_core_swift_and_c(swift_bridge_out_dir.as_ref());
86 }
87
88 pub fn concat_swift(&self) -> String {
90 let mut swift = "".to_string();
91
92 for gen in &self.generated {
93 swift += &gen.swift;
94 }
95
96 swift
97 }
98
99 pub fn concat_c(&self) -> String {
101 let mut c_header = "".to_string();
102
103 for gen in &self.generated {
104 c_header += &gen.c_header;
105 }
106
107 c_header
108 }
109}
110
111fn parse_file_contents(file: &str) -> syn::Result<GeneratedFromSwiftBridgeModule> {
112 let file: File = syn::parse_str(file)?;
113
114 let mut generated = GeneratedFromSwiftBridgeModule {
115 c_header: "".to_string(),
116 swift: "".to_string(),
117 };
118
119 for item in file.items {
120 match item {
121 Item::Mod(module) => {
122 if module.attrs.iter().any(|a| {
125 let attrib = a.path.to_token_stream().to_string();
126 attrib == "swift_bridge :: bridge" || attrib == "swift_bridge_macro :: bridge"
127 }) {
128 let module: SwiftBridgeModule = syn::parse2(module.to_token_stream())?;
129
130 let config = CodegenConfig {
131 crate_feature_lookup: Box::new(|feature_name| {
132 let normalized_feature_name = feature_name.replace("-", "_");
133 let normalized_feature_name = normalized_feature_name.to_uppercase();
134
135 let env_var_name = format!("CARGO_FEATURE_{}", normalized_feature_name);
136 std::env::var(env_var_name).is_ok()
137 }),
138 };
139 let swift_and_c = module.generate_swift_code_and_c_header(config);
140
141 generated.c_header += &swift_and_c.c_header;
142 generated.c_header += "\n\n";
143
144 let swift = &swift_and_c.swift;
145 generated.swift += &swift;
146 generated.swift += "\n\n";
147 }
148 }
149 _ => {}
150 }
151 }
152
153 Ok(generated)
154}
155
156#[derive(Debug)]
157struct GeneratedFromSwiftBridgeModule {
158 c_header: String,
159 swift: String,
160}