mod build_support;
use build_support::{binaries, cargo, git, skia, utils};
use std::io::Cursor;
use std::path::Path;
use std::{fs, io};
mod env {
use crate::build_support::cargo;
use std::path::PathBuf;
pub fn force_skia_binaries_download() -> bool {
cargo::env_var("FORCE_SKIA_BINARIES_DOWNLOAD").is_some()
}
pub fn skia_binaries_url() -> Option<String> {
cargo::env_var("SKIA_BINARIES_URL")
}
pub fn skia_binaries_url_default() -> String {
"https://github.com/rust-skia/skia-binaries/releases/download/{tag}/skia-binaries-{key}.tar.gz".into()
}
pub fn force_skia_build() -> bool {
cargo::env_var("FORCE_SKIA_BUILD").is_some()
}
pub fn offline_source_dir() -> Option<PathBuf> {
cargo::env_var("SKIA_OFFLINE_SOURCE_DIR").map(PathBuf::from)
}
pub fn offline_ninja_command() -> Option<PathBuf> {
cargo::env_var("SKIA_OFFLINE_NINJA_COMMAND").map(PathBuf::from)
}
pub fn offline_gn_command() -> Option<PathBuf> {
cargo::env_var("SKIA_OFFLINE_GN_COMMAND").map(PathBuf::from)
}
}
const SRC_BINDINGS_RS: &str = "src/bindings.rs";
const SKIA_LICENSE: &str = "skia/LICENSE";
fn main() {
if cfg!(feature = "svg") {
cargo::warning("The feature 'svg' has been removed. SVG and XML support is available in all build configurations.");
}
if cfg!(feature = "shaper") {
cargo::warning("The feature 'shaper' has been removed. To use the SkShaper bindings, enable the feature 'textlayout'.");
}
let build_config = skia::BuildConfiguration::default();
let binaries_config = skia::BinariesConfiguration::from_cargo_env(&build_config);
if let Some(offline_source_dir) = env::offline_source_dir() {
println!("STARTING OFFLINE BUILD");
let final_configuration = skia::FinalBuildConfiguration::from_build_configuration(
&build_config,
&offline_source_dir,
);
skia::build_offline(
&final_configuration,
&binaries_config,
env::offline_ninja_command().as_deref(),
env::offline_gn_command().as_deref(),
);
} else {
let build_skia = env::force_skia_build() || {
let force_download = env::force_skia_binaries_download();
if let Some((tag, key)) = should_try_download_binaries(&binaries_config, force_download)
{
println!(
"TRYING TO DOWNLOAD AND INSTALL SKIA BINARIES: {}/{}",
tag, key
);
let url = binaries::download_url(
env::skia_binaries_url().unwrap_or_else(env::skia_binaries_url_default),
tag,
key,
);
println!(" FROM: {}", url);
if let Err(e) = download_and_install(url, &binaries_config.output_directory) {
println!("DOWNLOAD AND INSTALL FAILED: {}", e);
if force_download {
panic!("Downloading of binaries was forced but failed.")
}
true
} else {
println!("DOWNLOAD AND INSTALL SUCCEEDED");
false
}
} else {
true
}
};
if build_skia {
println!("STARTING A FULL BUILD");
let final_configuration = skia::FinalBuildConfiguration::from_build_configuration(
&build_config,
&std::env::current_dir().unwrap().join("skia"),
);
skia::build(&final_configuration, &binaries_config);
}
};
binaries_config.commit_to_cargo();
if let Some(staging_directory) = binaries::should_export() {
println!(
"DETECTED AZURE, exporting binaries to {}",
staging_directory.to_str().unwrap()
);
println!("EXPORTING BINARIES");
let source_files = &[
(SRC_BINDINGS_RS, "bindings.rs"),
(SKIA_LICENSE, "LICENSE_SKIA"),
];
binaries::export(&binaries_config, source_files, &staging_directory)
.expect("EXPORTING BINARIES FAILED")
}
}
fn should_try_download_binaries(
config: &skia::BinariesConfiguration,
force: bool,
) -> Option<(String, String)> {
let tag = cargo::package_version();
if force {
let half_hash = git::half_hash()?;
return Some((tag, config.key(&half_hash)));
}
if let Ok(ref full_hash) = cargo::crate_repository_hash() {
let half_hash = git::trim_hash(full_hash);
return Some((tag, config.key(&half_hash)));
}
None
}
fn download_and_install(url: impl AsRef<str>, output_directory: &Path) -> io::Result<()> {
let archive = utils::download(url)?;
println!(
"UNPACKING ARCHIVE INTO: {}",
output_directory.to_str().unwrap()
);
binaries::unpack(Cursor::new(archive), output_directory)?;
println!("INSTALLING BINDINGS");
fs::copy(output_directory.join("bindings.rs"), SRC_BINDINGS_RS)?;
Ok(())
}