use std::env;
use std::path::{Path, PathBuf};
use string_literals::{string_arr, string_vec};
static CONFIG_NAME: &str = "DEP_LV_CONFIG_PATH";
fn main() {
let project_dir = canonicalize(PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()));
let vendor = project_dir.join("vendor");
println!("cargo:rerun-if-env-changed={}", CONFIG_NAME);
let mut compiler_args = string_vec![
"-DLV_USE_PRIVATE_API=1",
"-I",
vendor.to_str().unwrap(),
];
if cfg!(feature = "use-vendored-config") {
let conf_path = vendor.join("include");
compiler_args.extend(string_arr![
"-DLV_CONF_INCLUDE_SIMPLE=1",
"-I",
conf_path.to_str().unwrap(),
]);
} else {
let config_path = env::var(CONFIG_NAME)
.expect("lv_conf.h not found. Set DEP_LV_CONFIG_PATH to its directory.");
let conf_path = PathBuf::from(config_path);
if !conf_path.exists() {
panic!(
"Directory {} referenced by {} needs to exist",
conf_path.to_string_lossy(),
CONFIG_NAME
);
}
if !conf_path.is_dir() {
panic!("{} needs to be a directory", CONFIG_NAME);
}
if !conf_path.join("lv_conf.h").exists() {
panic!(
"Directory {} referenced by {} needs to contain a file called lv_conf.h",
conf_path.to_string_lossy(),
CONFIG_NAME
);
}
println!(
"cargo:rerun-if-changed={}",
conf_path.join("lv_conf.h").to_str().unwrap()
);
compiler_args.extend(string_arr![
"-DLV_CONF_INCLUDE_SIMPLE=1",
"-I",
conf_path.to_str().unwrap(),
]);
}
let mut cross_compile_flags = Vec::new();
let target = env::var("CROSS_COMPILE").map_or_else(
|_| env::var("TARGET").expect("Cargo build scripts always have TARGET"),
|c| c.trim_end_matches('-').to_owned(),
);
let host = env::var("HOST").expect("Cargo build scripts always have HOST");
if target != host {
cross_compile_flags.extend(string_arr!["-target", target.as_str()]);
}
let bindings = bindgen::Builder::default()
.clang_args(
&compiler_args
.iter()
.chain(&cross_compile_flags)
.collect::<Vec<&String>>(),
)
.header(vendor.join("lvgl/lvgl.h").to_str().unwrap())
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
.layout_tests(false)
.wrap_unsafe_ops(true)
.use_core()
.generate()
.expect("Unable to generate bindings");
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
bindings
.write_to_file(out_path.join("bindings.rs"))
.expect("Couldn't write bindings!");
#[cfg(feature = "library")]
compile_library(compiler_args, vendor);
}
#[cfg(feature = "library")]
fn compile_library(compiler_args: Vec<String>, vendor: PathBuf) {
let target = env::var("TARGET").expect("Cargo build scripts always have TARGET");
let lvgl_src = vendor.join("lvgl").join("src");
let mut cfg = cc::Build::new();
add_c_files(&mut cfg, &lvgl_src);
if !target.starts_with("x86_64") {
cfg.flag("-mlongcalls");
}
compiler_args.iter().for_each(|arg| {
let _ = cfg.flag(arg);
});
cfg.compile("lvgl");
}
#[cfg(feature = "library")]
fn add_c_files(build: &mut cc::Build, path: impl AsRef<Path>) {
for e in path.as_ref().read_dir().unwrap() {
let e = e.unwrap();
let path = e.path();
if e.file_type().unwrap().is_dir() {
add_c_files(build, e.path());
} else if path.extension().and_then(|s| s.to_str()) == Some("c") {
build.file(&path);
}
}
}
fn canonicalize(path: impl AsRef<Path>) -> PathBuf {
let canonicalized = path.as_ref().canonicalize().unwrap();
let canonicalized = &*canonicalized.to_string_lossy();
PathBuf::from(canonicalized.strip_prefix(r"\\?\").unwrap_or(canonicalized))
}