use std::collections::HashSet; use std::env; use std::fs::File; use std::path::{Path, PathBuf}; use anyhow::anyhow; use gl_generator::{Api, Fallbacks, Profile, Registry, StructGenerator}; fn main() -> Result<(), anyhow::Error> { println!("cargo::rerun-if-changed=build.rs"); println!("cargo::rerun-if-changed=Cargo.toml"); let dest = env::var("OUT_DIR")?; let mut file = File::create(Path::new(&dest).join("bindings.rs"))?; let mut registry = Registry::new(Api::Gl, (4, 6), Profile::Core, Fallbacks::All, []); let mut build_metadata = get_build_metadata()?; filter_gl_commands(&mut registry, &mut build_metadata)?; registry.write_bindings(StructGenerator, &mut file)?; Ok(()) } fn filter_gl_commands( registry: &mut Registry, build_metadata: &mut BuildMetadata, ) -> Result<(), anyhow::Error> { registry .cmds .retain(|command| build_metadata.gl_commands.remove(&command.proto.ident)); if !build_metadata.gl_commands.is_empty() { return Err(anyhow!( "Invalid GL commands: [{}]", build_metadata .gl_commands .iter() .cloned() .collect::>() .join(", ") )); } Ok(()) } fn get_build_metadata() -> Result { let manifest_path = PathBuf::from(std::env::var("CARGO_MANIFEST_PATH")?); let manifest = std::fs::read_to_string(manifest_path)?.parse::()?; let package = match manifest .get("package") .ok_or_else(|| anyhow!("Manifest does not have a package table"))? { toml::Value::Table(package) => Ok(package), _ => Err(anyhow!("Manifest package must be a table")), }?; let metadata = match package .get("metadata") .ok_or_else(|| anyhow!("Manifest does not have a package.metadata table"))? { toml::Value::Table(metadata) => Ok(metadata), _ => Err(anyhow!("Manifest package.metadata must be a table")), }?; let build_metadata = match metadata .get("build") .ok_or_else(|| anyhow!("Manifest does not have a package.metadata.build table"))? { toml::Value::Table(build_metadata) => Ok(build_metadata), _ => Err(anyhow!("Manifest package.metadata.build must be a table")), }?; let gl_command_values = match build_metadata.get("gl_commands").ok_or_else(|| { anyhow!("Manifest does not have a package.metadata.build.gl_commands array") })? { toml::Value::Array(gl_commands) => Ok(gl_commands), _ => Err(anyhow!( "Manifest package.metadata.build.gl_commands must be a array" )), }?; let gl_commands = gl_command_values .iter() .map(|gl_command_val| match gl_command_val { toml::Value::String(gl_command) => Ok(gl_command.clone()), _ => Err(anyhow!("GL command must be a string")), }) .collect::, _>>()?; Ok(BuildMetadata { gl_commands }) } #[derive(Debug)] struct BuildMetadata { gl_commands: HashSet, }