use std::collections::HashSet; use std::env; use std::fs; use std::io::Read; use std::io::Write; use std::path::Path; use dbus_codegen::ConnectionType; use dbus_codegen::GenOpts; fn main() { println!("cargo:rerun-if-env-changed=DBUS_XML_PATH"); println!("cargo:rerun-if-changed=build.rs"); let required_files = HashSet::from([ "org.freedesktop.NetworkManager.AccessPoint.xml", "org.freedesktop.NetworkManager.Connection.Active.xml", "org.freedesktop.NetworkManager.xml", "org.freedesktop.hostname1.xml", ]); let required_interfaces = required_files .iter() .map(|name| name.strip_suffix(".xml").unwrap().to_string()) .collect(); let opts = GenOpts { connectiontype: ConnectionType::Nonblock, methodtype: None, interfaces: Some(required_interfaces), ..Default::default() }; let out_dir_str = env::var("OUT_DIR").unwrap(); let out_dir = Path::new(&out_dir_str); let mut generated_file = fs::File::create(out_dir.join("generated.rs")).unwrap(); let dbus_paths_raw = env::var("DBUS_XML_PATH").unwrap_or("/usr/share/dbus-1/interfaces".to_string()); dbus_paths_raw .split(':') .map(fs::read_dir) .flat_map(Result::unwrap) .map(Result::unwrap) .filter(|file| required_files.contains(file.file_name().to_str().unwrap())) .for_each(|in_file| { println!( "cargo:rerun-if-changed={}", in_file.path().to_str().unwrap() ); let mut xml = String::new(); fs::File::open(in_file.path()) .unwrap() .read_to_string(&mut xml) .unwrap(); let code = dbus_codegen::generate(&xml, &opts).unwrap(); let module_name = in_file .file_name() .into_string() .unwrap() .strip_suffix(".xml") .unwrap() .replace('.', "_"); let out_path = out_dir.join(module_name.clone() + ".rs"); fs::File::create(out_path) .unwrap() .write_all(code.as_bytes()) .unwrap(); generated_file .write_all( format!( r#"mod {module_name} {{ include!(concat!(env!("OUT_DIR"), "/{module_name}.rs")); }} pub use {module_name}::*; "# ) .as_bytes(), ) .unwrap(); }) }