use gdnative_bindings_generator::*;
use std::env;
use std::fs::File;
use std::io::{BufWriter, Write as _};
use std::path::PathBuf;
use std::process::Command;
fn main() {
let api_data = std::fs::read_to_string("api.json").expect("Unable to read api.json");
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
let generated_rs = out_path.join("generated.rs");
let icalls_rs = out_path.join("icalls.rs");
let api = Api::new(&api_data);
let docs = GodotXMLDocs::new("docs");
let binding_res = generate_bindings(&api, Some(&docs));
{
let mut output = BufWriter::new(File::create(&generated_rs).unwrap());
generate(&out_path, &mut output, &binding_res);
}
{
let mut output = BufWriter::new(File::create(&icalls_rs).unwrap());
write!(&mut output, "{}", binding_res.icalls).unwrap();
}
if cfg!(feature = "formatted") {
format_file(&generated_rs);
format_file(&icalls_rs);
}
println!("cargo:rerun-if-changed=docs/");
println!("cargo:rerun-if-changed=api.json");
println!("cargo:rerun-if-changed=build.rs");
}
#[cfg(not(feature = "one_class_one_file"))]
fn generate(
_out_path: &std::path::Path,
generated_file: &mut BufWriter<File>,
binding_res: &BindingResult,
) {
for (class_name, code) in &binding_res.class_bindings {
write!(
generated_file,
r#"
pub mod {mod_name} {{
use super::*;
{content}
}}
pub use crate::generated::{mod_name}::{class_name};
"#,
mod_name = module_name_from_class_name(&class_name),
class_name = class_name,
content = code,
)
.unwrap();
}
}
#[cfg(feature = "one_class_one_file")]
fn generate(
out_path: &std::path::Path,
generated_file: &mut BufWriter<File>,
binding_res: &BindingResult,
) {
for (class_name, code) in &binding_res.class_bindings {
let mod_name = module_name_from_class_name(&class_name);
let mod_path = out_path.join(format!("{}.rs", mod_name));
let mut mod_output = BufWriter::new(File::create(&mod_path).unwrap());
write!(
&mut mod_output,
r#"use super::*;
{content}"#,
content = code,
)
.unwrap();
drop(mod_output);
if cfg!(feature = "formatted") {
format_file(&mod_path);
}
writeln!(
generated_file,
r#"
#[path = {:?}]
pub mod {mod_name};
pub use crate::generated::{mod_name}::{class_name};
"#,
mod_path.display(),
mod_name = mod_name,
class_name = class_name,
)
.unwrap();
}
}
fn format_file(output_rs: &PathBuf) {
print!(
"Formatting generated file: {}... ",
output_rs.file_name().and_then(|s| s.to_str()).unwrap()
);
match Command::new("rustup")
.arg("run")
.arg("stable")
.arg("rustfmt")
.arg("--edition=2018")
.arg(output_rs)
.output()
{
Ok(_) => println!("Done"),
Err(err) => {
println!("Failed");
println!("Error: {}", err);
}
}
}