1 extern crate bindgen; 2 extern crate pkg_config; 3 4 use std::path::{Path, PathBuf}; 5 use std::process::Command; 6 7 fn main() { 8 let out_dir = PathBuf::from(env("OUT_DIR").unwrap()); 9 let statik = env("CARGO_FEATURE_STATIC").is_some(); 10 let system = env("CARGO_FEATURE_SYSTEM").is_some(); 11 12 let ceed_pc = if system { 13 "ceed".to_string() 14 } else { 15 // Install libceed.a or libceed.so to $OUT_DIR/lib 16 let makeflags = env("CARGO_MAKEFLAGS").unwrap(); 17 let mut make = Command::new("make"); 18 make.arg("install") 19 .arg(format!("prefix={}", out_dir.to_string_lossy())) 20 .arg(format!( 21 "OBJDIR={}", 22 out_dir.join("build").to_string_lossy() 23 )) 24 .arg(format!( 25 "LIBDIR={}", 26 out_dir.join("build").join("lib").to_string_lossy() 27 )) 28 .arg("FC=") // Don't try to find Fortran (unused library build/install) 29 .env("MAKEFLAGS", makeflags) 30 .current_dir("c-src"); 31 if statik { 32 make.arg("STATIC=1"); 33 } 34 run(&mut make); 35 out_dir 36 .join("lib") 37 .join("pkgconfig") 38 .join("ceed.pc") 39 .to_string_lossy() 40 .into_owned() 41 }; 42 pkg_config::Config::new() 43 .statik(statik) 44 .atleast_version("0.12.0") 45 .probe(&ceed_pc) 46 .unwrap(); 47 48 // Tell cargo to invalidate the built crate whenever the wrapper changes 49 println!("cargo:rerun-if-changed=c-src/include/ceed.h"); 50 println!("cargo:rerun-if-changed=c-src/include/ceed/types.h"); 51 println!("cargo:rerun-if-changed=c-src/Makefile"); 52 if Path::new("c-src/config.mk").is_file() { 53 println!("cargo:rerun-if-changed=c-src/config.mk"); 54 } 55 56 // The bindgen::Builder is the main entry point 57 // to bindgen, and lets you build up options for 58 // the resulting bindings. 59 let bindings = bindgen::Builder::default() 60 // The input header we would like to generate 61 // bindings for. 62 .header("c-src/include/ceed.h") 63 .allowlist_function("Ceed.*") 64 .allowlist_type("Ceed.*") 65 .allowlist_var("Ceed.*") 66 .allowlist_var("CEED_.*") 67 // Don't chase recursive definitions of these system types 68 .opaque_type("FILE") 69 .opaque_type("va_list") 70 // Accessing directly here, but perhaps should use libc crate 71 .allowlist_function("fclose") 72 .allowlist_function("open_memstream") 73 // Tell cargo to not mangle the function names 74 .trust_clang_mangling(false) 75 // Tell cargo to invalidate the built crate whenever any of the 76 // included header files changed. 77 .parse_callbacks(Box::new(bindgen::CargoCallbacks)) 78 // Finish the builder and generate the bindings. 79 .generate() 80 // Unwrap the Result and panic on failure. 81 .expect("Unable to generate bindings"); 82 83 // Write the bindings to the $OUT_DIR/bindings.rs file. 84 bindings 85 .write_to_file(out_dir.join("bindings.rs")) 86 .expect("Couldn't write bindings!"); 87 } 88 89 fn env(k: &str) -> Option<String> { 90 std::env::var(k).ok() 91 } 92 93 fn run(command: &mut Command) { 94 println!("Running: `{:?}`", command); 95 assert!(command.status().unwrap().success()); 96 } 97