blob: 39c00ba4d28e3f4934e2363ef4a6068573bb95eb [file] [log] [blame]
// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
extern crate bindgen;
use std::env;
use std::fs::{self, File};
use std::io::{self, Write};
use std::path::{Path, PathBuf};
fn main() {
let root_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
let root_dir = Path::new(&root_dir);
let meson_build_root = env::var("MESON_BUILD_ROOT").unwrap();
let meson_build_root = Path::new(&meson_build_root);
assert!(
meson_build_root.join("libmosys.a").exists(),
"libmosys.a is not present, see the README for instructions on building Mosys"
);
println!(
"cargo:rustc-link-search=native={}",
meson_build_root.display()
);
println!("cargo:rustc-link-lib=dylib=mosys");
println!("cargo:rustc-link-lib=dylib=uuid");
if !env::var("USE").is_err() && env::var("USE").unwrap().contains("unibuild") {
println!("cargo:rustc-link-lib=dylib=fdt");
}
println!("cargo:rustc-link-lib=dylib=fmap");
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
let prune = vec![
root_dir.join(".git"),
root_dir.join("src"),
root_dir.join("target"),
];
let wrapper = out_path.join("wrapper.h");
generate_wrapper(root_dir, &wrapper, &prune).expect("Failed to generate wrapper.h");
let bindings = bindgen::Builder::default()
.header(wrapper.to_str().unwrap())
.clang_arg("-Iinclude")
.whitelist_function("kv_.*")
.whitelist_function("log_.*")
.whitelist_function("lprintf")
.whitelist_function("lperror")
.whitelist_function(".*platform.*")
.whitelist_function("print_.*")
.whitelist_function("mosys_.*")
.generate()
.expect("Unable to generate bindings");
bindings
.write_to_file(out_path.join("bindings.rs"))
.expect("Couldn't write bindings!");
}
/// Generates a Bindgen wrapper at target (e.g. target/debug/wrapper.h) using root dir to search
/// for C headers to include. Takes slice of paths based at root to prune from search.
fn generate_wrapper(root: &Path, target: &Path, prune: &[PathBuf]) -> io::Result<()> {
let mut found_headers = Vec::new();
find_headers(root, prune, &mut found_headers).expect("Failed to build headers");
// fs::read_dir is non-deterministic ordering
found_headers.sort();
let mut file = File::create(target)?;
writeln!(&mut file, "// This file autogenerated from build.rs")?;
writeln!(&mut file, "#include <stdint.h>")?;
writeln!(&mut file, "#include <stddef.h>")?;
writeln!(&mut file, "#include \"mosys/platform.h\"")?;
for header in found_headers {
writeln!(&mut file, "#include \"{}\"", header.display())?;
}
Ok(())
}
fn find_headers(dir: &Path, prune: &[PathBuf], found: &mut Vec<PathBuf>) -> io::Result<()> {
if dir.is_dir() {
'outer: for entry in fs::read_dir(dir)? {
let path = entry?.path();
for prune_path in prune {
if path.starts_with(prune_path.as_path()) {
continue 'outer;
}
}
if path.is_dir() {
find_headers(&path, prune, found)?;
} else if path.to_str().unwrap().ends_with(".h") {
found.push(path);
}
}
}
Ok(())
}