xref: /libCEED/rust/libceed-sys/build.rs (revision 9bc2a9358358ee74d2946142a545c20eb5a5e454)
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.11")
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/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/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