extern crate bindgen; use std::env; use std::path::PathBuf; use std::process::Command; fn main() { let out_dir = PathBuf::from(env::var("OUT_DIR").expect("OUT_DIR not defined")); // Directory containing uplink-c project source let uplink_c_src = PathBuf::from("uplink-c"); // Directory containing uplink-c project for building let uplink_c_dir = out_dir.join("uplink-c"); // Copy project to OUT_DIR for building Command::new("cp") .args(&[ "-R", &uplink_c_src.to_string_lossy(), &uplink_c_dir.to_string_lossy(), ]) .status() .expect("Failed to copy uplink-c directory."); // Set Go Cache location // Default needs to change to be contained within rust build directory std::env::set_var("GOCACHE", out_dir.as_os_str()); // Build uplink-c // generates precompiled lib and header files in .build directory Command::new("make") .arg("build") .current_dir(&uplink_c_dir) .status() .expect("Failed to run make command from build.rs."); // Directory containting uplink-c build let uplink_c_build = uplink_c_dir.join(".build"); // Header file with complete API interface let uplink_c_header = uplink_c_build.join("uplink/uplink.h"); // Link (statically) to uplink-c library during build println!("cargo:rustc-link-lib=static=uplink"); // Add uplink-c build directory to library search path println!( "cargo:rustc-link-search={}", uplink_c_build.to_string_lossy() ); // Make uplink-c interface header a dependency of the build println!( "cargo:rerun-if-changed={}", uplink_c_header.to_string_lossy() ); // Manually link to core and security libs on MacOS #[cfg(target_os = "macos")] { println!("cargo:rustc-flags=-l framework=CoreFoundation -l framework=Security"); } bindgen::Builder::default() // Use 'allow lists' to avoid generating bindings for system header includes // a lot of which isn't required and can't be handled safely anyway. // uplink-c uses consistent naming so whitelisting is much easier than blacklisting. // All uplink types start with Uplink .allowlist_type("Uplink.*") // except for uplink_const_char .allowlist_type("uplink_const_char") // All uplink functions start with uplink_ .allowlist_function("uplink_.*") // Uplink error code #define's start with UPLINK_ERROR_ .allowlist_var("UPLINK_ERROR_.*") // This header file is the main API interface and includes all other header files that are required // (bindgen runs c preprocessor so we don't need to include nested headers) .header( uplink_c_dir .join(".build/uplink/uplink.h") .to_string_lossy(), ) // Also make headers included by main header dependencies of the build .parse_callbacks(Box::new(bindgen::CargoCallbacks)) // Generate bindings .generate() .expect("Error generating bindings.") // Write bindings to file to be referenced by main build .write_to_file(out_dir.join("bindings.rs")) .expect("Error writing bindings to file."); }