mod build_support;
use bindgen;
use build_support::{
binaries_config,
cargo::{self, Target},
features, kwui,
};
use std::io;
use std::path::PathBuf;
use globmatch;
fn main() -> Result<(), io::Error> {
if env::is_docs_rs_build() {
println!("DETECTED DOCS_RS BUILD");
println!("cargo:root={}", std::env::var("OUT_DIR").unwrap());
return fake_bindings();
}
let skia_debug = env::is_kwui_debug();
let features = features::Features::default();
let binaries_config =
binaries_config::BinariesConfiguration::from_features(&features, skia_debug);
if let Some(source_dir) = env::source_dir() {
if let Some(search_path) = env::kwui_lib_search_path() {
println!("STARTING BIND AGAINST SYSTEM KWUI");
binaries_config.import(&search_path, false).unwrap();
generate_bindings(
&binaries_config,
&source_dir,
cargo::target(),
);
} else {
println!("STARTING OFFLINE BUILD");
let final_build_configuration = build_from_source(
features.clone(),
&binaries_config,
&source_dir,
skia_debug,
true,
);
generate_bindings(
&binaries_config,
&source_dir,
final_build_configuration.target,
);
}
} else {
let build_kwui = build_support::binary_cache::try_prepare_download(&binaries_config);
if build_kwui {
println!("STARTING A FULL BUILD");
let source_dir = std::env::current_dir().unwrap().join("deps/kwui");
let final_build_configuration = build_from_source(
features.clone(),
&binaries_config,
&source_dir,
skia_debug,
false,
);
generate_bindings(
&binaries_config,
&source_dir,
final_build_configuration.target,
);
}
};
binaries_config.commit_to_cargo();
if let Some(staging_directory) = build_support::binary_cache::should_export() {
build_support::binary_cache::publish(&binaries_config, &staging_directory);
}
println!("cargo::rerun-if-env-changed=BUILD_ARTIFACTSTAGINGDIRECTORY");
println!("cargo:root={}", std::env::var("OUT_DIR").unwrap());
Ok(())
}
fn build_from_source(
features: features::Features,
binaries_config: &binaries_config::BinariesConfiguration,
kwui_source_dir: &std::path::Path,
kwui_debug: bool,
offline: bool,
) -> kwui::FinalBuildConfiguration {
let build_config = kwui::BuildConfiguration::from_features(features, kwui_debug);
let final_configuration = kwui::FinalBuildConfiguration::from_build_configuration(
&build_config,
kwui::env::use_system_libraries(),
kwui_source_dir,
);
kwui::build(
&final_configuration,
binaries_config,
kwui::env::ninja_command(),
kwui::env::cmake_command(),
offline,
);
final_configuration
}
fn find_clang_include_dir(android_ndk_home: &str) -> Option<PathBuf> {
let path = globmatch::Builder::new("toolchains/llvm/prebuilt/windows-x86_64/lib/clang/*/include")
.build(android_ndk_home).ok()?;
if let Some(Ok(p)) = path.into_iter().next() {
Some(p)
} else {
None
}
}
fn generate_bindings(
binaries_config: &binaries_config::BinariesConfiguration,
_kwui_source_dir: &std::path::Path,
target: Target,
) {
let clang_args: Vec<String> = match target.system.as_str() {
"android" => {
let android_ndk_home = std::env::var("ANDROID_NDK_HOME").unwrap();
let clang_include_dir = find_clang_include_dir(&android_ndk_home);
let clang_include_dir = clang_include_dir.expect("lib/clang/*/include directory not found")
.display()
.to_string()
.replace('\\', "/");
vec![
"-DKWUI_SHARED_LIBRARY=1".to_string(),
format!("--sysroot={}/toolchains/llvm/prebuilt/windows-x86_64/sysroot", android_ndk_home),
format!("-I{}", clang_include_dir),
]
}
_ => vec!["-DKWUI_STATIC_LIBRARY=1".to_string()],
};
let bindings = bindgen::Builder::default()
.header(format!("{}/include/kwui_capi.h", binaries_config.output_directory.display()))
.allowlist_function("kwui_.*")
.layout_tests(false)
.clang_args(clang_args)
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
.generate()
.expect("Unable to generate bindings");
let out_path = std::path::PathBuf::from(std::env::var("OUT_DIR").unwrap());
bindings
.write_to_file(out_path.join("bindings.rs"))
.expect("Couldn't write bindings!");
}
fn fake_bindings() -> Result<(), io::Error> {
println!("COPYING bindings_docs.rs to OUT_DIR/bindings.rs");
let bindings_target = cargo::output_directory()
.join("bindings.rs");
std::fs::copy("bindings_docs.rs", bindings_target).map(|_| ())
}
mod env {
use crate::build_support::cargo;
use std::path::PathBuf;
pub fn source_dir() -> Option<PathBuf> {
cargo::env_var("KWUI_SOURCE_DIR").map(PathBuf::from)
}
pub fn kwui_lib_search_path() -> Option<PathBuf> {
cargo::env_var("KWUI_LIBRARY_SEARCH_PATH").map(PathBuf::from)
}
pub fn is_kwui_debug() -> bool {
matches!(cargo::env_var("KWUI_DEBUG"), Some(v) if v != "0")
}
pub fn is_docs_rs_build() -> bool {
matches!(cargo::env_var("DOCS_RS"), Some(v) if v != "0")
}
}