use std::{fs, io};
use build_support::{
binaries_config,
cargo::{self, Target},
features, skia, skia_bindgen,
};
mod build_support;
fn main() -> Result<(), io::Error> {
if cfg!(feature = "shaper") {
cargo::warning("The feature 'shaper' has been removed. To use the SkShaper bindings, enable the feature 'textlayout'.");
}
if env::is_docs_rs_build() {
println!("DETECTED DOCS_RS BUILD");
return fake_bindings();
}
let skia_debug = env::is_skia_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::skia_lib_search_path() {
println!("STARTING BIND AGAINST SYSTEM SKIA");
binaries_config.import(&search_path, false).unwrap();
let definitions = skia_bindgen::definitions::from_env();
generate_bindings(
&features,
definitions,
&binaries_config,
&source_dir,
cargo::target(),
None,
);
} else {
println!("STARTING OFFLINE BUILD");
let final_build_configuration = build_from_source(
features.clone(),
&binaries_config,
&source_dir,
skia_debug,
true,
);
let definitions = skia_bindgen::definitions::from_ninja_features(
&features,
final_build_configuration.use_system_libraries,
&binaries_config.output_directory,
);
generate_bindings(
&features,
definitions,
&binaries_config,
&source_dir,
final_build_configuration.target,
final_build_configuration
.sysroot
.as_ref()
.map(AsRef::as_ref),
);
}
} else {
#[allow(unused_variables)]
let build_skia = true;
#[cfg(feature = "binary-cache")]
let build_skia = build_support::binary_cache::try_prepare_download(&binaries_config);
if build_skia {
println!("STARTING A FULL BUILD");
println!("HOST: {}", cargo::host());
let source_dir = std::env::current_dir().unwrap().join("skia");
let final_build_configuration = build_from_source(
features.clone(),
&binaries_config,
&source_dir,
skia_debug,
false,
);
let definitions = skia_bindgen::definitions::from_ninja_features(
&features,
final_build_configuration.use_system_libraries,
&binaries_config.output_directory,
);
generate_bindings(
&features,
definitions,
&binaries_config,
&source_dir,
final_build_configuration.target,
final_build_configuration
.sysroot
.as_ref()
.map(AsRef::as_ref),
);
}
};
binaries_config.commit_to_cargo();
#[cfg(feature = "binary-cache")]
if let Some(staging_directory) = build_support::binary_cache::should_export() {
build_support::binary_cache::publish(&binaries_config, &staging_directory);
}
Ok(())
}
fn build_from_source(
features: features::Features,
binaries_config: &binaries_config::BinariesConfiguration,
skia_source_dir: &std::path::Path,
skia_debug: bool,
offline: bool,
) -> skia::FinalBuildConfiguration {
let build_config = skia::BuildConfiguration::from_features(features, skia_debug);
let final_configuration = skia::FinalBuildConfiguration::from_build_configuration(
&build_config,
skia::env::use_system_libraries(),
skia_source_dir,
);
skia::build(
&final_configuration,
binaries_config,
skia::env::ninja_command(),
skia::env::gn_command(),
offline,
);
final_configuration
}
fn generate_bindings(
features: &features::Features,
definitions: Vec<skia_bindgen::Definition>,
binaries_config: &binaries_config::BinariesConfiguration,
skia_source_dir: &std::path::Path,
target: Target,
sysroot: Option<&str>,
) {
skia_bindgen::definitions::save_definitions(&definitions, &binaries_config.output_directory)
.expect("failed to write Skia defines");
let bindings_config = skia_bindgen::Configuration::new(features, definitions, skia_source_dir);
skia_bindgen::generate_bindings(
&bindings_config,
&binaries_config.output_directory,
target,
sysroot,
);
}
fn fake_bindings() -> Result<(), io::Error> {
println!("COPYING bindings_docs.rs to OUT_DIR/skia/bindings.rs");
let bindings_target = cargo::output_directory()
.join(binaries_config::SKIA_OUTPUT_DIR)
.join("bindings.rs");
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("SKIA_SOURCE_DIR").map(PathBuf::from)
}
pub fn skia_lib_search_path() -> Option<PathBuf> {
cargo::env_var("SKIA_LIBRARY_SEARCH_PATH").map(PathBuf::from)
}
pub fn is_skia_debug() -> bool {
matches!(cargo::env_var("SKIA_DEBUG"), Some(v) if v != "0")
}
pub fn is_docs_rs_build() -> bool {
matches!(cargo::env_var("DOCS_RS"), Some(v) if v != "0")
}
}