use std::env; use std::path::PathBuf; use std::process::Command; fn tell_cargo(name: &str, val: &str) { println!("cargo:{}={}", name, val); } fn main() { let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); let librist_path = out_path.join("librist/build").to_string_lossy().to_string(); if let Err(e) = run_meson("librist", librist_path.as_ref()) { tell_cargo("warning", &format!("meson build of librist failed: {:?}", e)); // fall-through, since maybe we are just running cargo doc, and if not then linking will // fail later anyway } tell_cargo("rustc-link-lib", "static=rist"); tell_cargo("rustc-link-search", &format!("native={}", librist_path)); // Tell cargo to invalidate the built crate whenever the wrapper changes tell_cargo("rerun-if-changed", "wrapper.h"); // The bindgen::Builder is the main entry point // to bindgen, and lets you build up options for // the resulting bindings. let bindings = bindgen::Builder::default() // The input header we would like to generate // bindings for. .header("wrapper.h") .clang_arg("-Ilibrist/include") .clang_arg("-I/usr/include/x86_64-linux-musl") .clang_arg(format!("-I{}/include/librist", librist_path)) .whitelist_type("^rist_.*") .whitelist_function("^rist_.*") .whitelist_var("^RIST_.*") .blacklist_type("FILE") .blacklist_type("size_t") .blacklist_type("__uint\\d+_t") .blacklist_type("__off_t") .blacklist_type("__off64_t") .blacklist_item("_IO_.*") // Tell cargo to invalidate the built crate whenever any of the // included header files changed. .parse_callbacks(Box::new(bindgen::CargoCallbacks)) // Finish the builder and generate the bindings. .generate() // Unwrap the Result and panic on failure. .expect("Unable to generate bindings"); // Write the bindings to the $OUT_DIR/bindings.rs file. bindings .write_to_file(out_path.join("bindings.rs")) .expect("Couldn't write bindings!"); } fn run_meson(lib: &str, dir: &str) -> Result<(), String>{ if !is_configured(dir) { let cross_file = env::var("MESON_CROSS_FILE"); let mut args = vec!["--default-library=static", ".", dir]; if let Ok(ref cross) = cross_file { args.push("--cross-file"); args.push(cross); } args.push("-Dbuiltin_cjson=true"); args.push("-Duse_mbedtls=false"); args.push("-Dbuilt_tools=false"); if Ok("true".to_string()) == env::var("DEBUG") { println!("!DEBUG!"); env::set_var("ARGS", "-g"); } run_command(lib, "meson", &args[..])? } run_command(dir, "ninja", &[]) } fn is_target_musl_libc() -> bool { "musl" == env::var("CARGO_CFG_TARGET_ENV").unwrap() } fn run_command(dir: &str, name: &str, args: &[&str]) -> Result<(), String> { let mut cmd = Command::new(name); cmd.current_dir(dir); if args.len() > 0 { cmd.args(args); } let status = cmd.status().map_err(|e| format!("{} failed: {:?}", name, e))?; if status.success() { Ok(()) } else { Err(format!("{} failed: {}", name, status)) } } fn is_configured(dir: &str) -> bool { let mut path = PathBuf::from(dir); path.push("build.ninja"); return path.as_path().exists(); }