#[cfg(not(windows))] #[macro_use] extern crate serde_derive; #[cfg(not(windows))] use cc; #[cfg(not(windows))] use handlebars as hbs; #[cfg(not(windows))] use std::{ convert::From, fs::File, io::{self, Read}, path::{Path, PathBuf}, process::exit, env, }; #[cfg(not(windows))] fn main() { let target_os = env::var("CARGO_CFG_TARGET_OS"); match target_os.as_ref().map(|x| &**x) { Ok("windows") => return, _ => {}, } let in_path = Path::new("src/unix/c").join("constants.c.in"); let out_path = PathBuf::from(env::var_os("OUT_DIR").unwrap()).join("constants.c"); // Template the file. if let Err(e) = template_file(&in_path, &out_path) { println!("Error creating `constants.c` from template"); println!("-> {:?}", e); exit(1); } // Build the final library let mut cfg = cc::Build::new(); let helpers_path = Path::new("src/unix/c").join("helpers.c"); let ifaddrs_path = Path::new("src/unix/c").join("ifaddrs.c"); let cfg = cfg.file(&out_path).file(&helpers_path); if env::var_os("CARGO_CFG_TARGET_OS") .unwrap() .to_str() .unwrap() == "android" { cfg.file(ifaddrs_path); } cfg.compile("libinterfaces.a"); } #[cfg(not(windows))] fn template_file(in_path: &PathBuf, out_path: &PathBuf) -> Result<(), Error> { // Open and read the file. let mut f = File::open(in_path)?; let mut s = String::new(); f.read_to_string(&mut s)?; let mut handlebars = hbs::Handlebars::new(); handlebars.register_template_string("template", s)?; let mut f = File::create(out_path)?; let data = make_data(); handlebars.renderw("template", &data, &mut f)?; Ok(()) } #[cfg(not(windows))] fn make_data() -> Context { // These constants are "dynamically" generated by compiling a C file that includes their value // and then including that in the final build. See `constants.rs` for a function that can be // used to retrieve them. let names: &[&str] = &[ // IOCTLs "SIOCGIFCONF", "SIOCGIFHWADDR", "SIOCGIFFLAGS", "SIOCSIFFLAGS", "SIOCGIFMTU", "SIOCSIFMTU", // Address families "AF_LINK", "AF_PACKET", // Only on Linux ]; // These constants are the same as above, but we don't test them for existence with #ifdef. let anames: &[&str] = &["sizeof(struct ifreq)"]; let names = names .into_iter() .map(|x| String::from(*x)) .collect::>(); let anames = anames .into_iter() .map(|x| String::from(*x)) .collect::>(); Context { test_constants: names, always_constants: anames, } } #[cfg(not(windows))] #[derive(Serialize, Deserialize)] struct Context { test_constants: Vec, always_constants: Vec, } #[cfg(not(windows))] #[derive(Debug)] enum Error { IoError(io::Error), TemplateError(hbs::TemplateError), RenderError(hbs::RenderError), } #[cfg(not(windows))] impl From for Error { fn from(e: io::Error) -> Error { Error::IoError(e) } } #[cfg(not(windows))] impl From for Error { fn from(e: hbs::TemplateError) -> Error { Error::TemplateError(e) } } #[cfg(not(windows))] impl From for Error { fn from(e: hbs::RenderError) -> Error { Error::RenderError(e) } } #[cfg(windows)] fn main() { // No build script required }