Files
cef-rs/sys/build.rs
T

237 lines
8.3 KiB
Rust

#[cfg(not(feature = "dox"))]
fn main() -> anyhow::Result<()> {
use download_cef::{CefIndex, OsAndArch};
use std::{
env, fs,
path::{Path, PathBuf},
};
println!("cargo::rerun-if-changed=build.rs");
let target = env::var("TARGET")?;
let os_arch = OsAndArch::try_from(target.as_str())?;
println!("cargo::rerun-if-env-changed=FLATPAK");
println!("cargo::rerun-if-env-changed=CEF_PATH");
let package_version = env::var("CARGO_PKG_VERSION")?;
let cef_version = download_cef::default_version(&package_version);
let check_archive = |path: &Path| -> anyhow::Result<()> {
download_cef::check_archive_json(&package_version, &path.to_string_lossy())?;
Ok(())
};
let resolve_cef_dir = |location: &Path| -> anyhow::Result<PathBuf> {
let cef_dir = location.join(os_arch.to_string());
if !fs::exists(&cef_dir)? {
let download_url = download_cef::default_download_url();
let index = CefIndex::download_from(&download_url)?;
let platform = index.platform(&target)?;
let version = platform.version(&cef_version)?;
let archive = version.download_archive_from(&download_url, location, false)?;
let extracted_dir =
download_cef::extract_target_archive(&target, &archive, location, false)?;
let extracted_dir_canonical = fs::canonicalize(&extracted_dir)?;
let cef_dir_canonical = fs::canonicalize(&cef_dir)?;
if extracted_dir_canonical != cef_dir_canonical {
return Err(anyhow::anyhow!(
"extracted dir {extracted_dir_canonical:?} does not match cef_dir {cef_dir_canonical:?}",
));
}
version.write_archive_json(extracted_dir)?;
}
Ok(cef_dir)
};
let resolve_from_versioned = |configured_path: &Path| -> anyhow::Result<PathBuf> {
let versioned_location = configured_path.join(&cef_version);
let resolved = resolve_cef_dir(&versioned_location)?;
println!(
"Using versioned CEF path from environment: {}",
resolved.display()
);
check_archive(&resolved)?;
Ok(resolved)
};
let download_to_versioned = |configured_path: &Path, reason: &str| -> anyhow::Result<PathBuf> {
let versioned_location = configured_path.join(&cef_version);
println!(
"{reason}, downloading archive to: {}",
versioned_location.display()
);
let resolved = resolve_cef_dir(&versioned_location)?;
println!("Using downloaded CEF path: {}", resolved.display());
Ok(resolved)
};
let out_dir = PathBuf::from(env::var("OUT_DIR")?);
let cef_dir = if env::var("FLATPAK").is_ok() {
let cef_path = String::from("/usr/lib");
println!("Using CEF path from FLATPAK: {cef_path}");
let cef_path = PathBuf::from(cef_path);
check_archive(&cef_path)?;
cef_path
} else if let Ok(cef_path) = env::var("CEF_PATH") {
let configured_path = PathBuf::from(cef_path);
if fs::exists(&configured_path)? {
let versioned_location = configured_path.join(&cef_version);
if fs::exists(&versioned_location)? {
resolve_from_versioned(&configured_path)?
} else {
println!(
"Using CEF path from environment: {}",
configured_path.display()
);
match check_archive(&configured_path) {
Ok(()) => configured_path,
Err(error) => download_to_versioned(
&configured_path,
&format!("CEF_PATH is invalid ({error})"),
)?,
}
}
} else {
download_to_versioned(&configured_path, "CEF_PATH does not exist")?
}
} else {
resolve_cef_dir(&out_dir)?
};
// TODO: far from ideal, but there's no other way to get the target dir, see <https://github.com/rust-lang/cargo/issues/9661>
let target_dir = out_dir
.parent()
.unwrap()
.parent()
.unwrap()
.parent()
.unwrap();
let cef_dir_str = cef_dir.to_string_lossy().into_owned();
// Re-run when the resolved CEF directory changes/deletes.
println!("cargo::rerun-if-changed={cef_dir_str}");
println!("cargo::metadata=CEF_DIR={cef_dir_str}");
println!("cargo::rustc-link-search=native={cef_dir_str}");
let mut cef_dll_wrapper = cmake::Config::new(&cef_dir);
cef_dll_wrapper
.generator("Ninja")
.profile("RelWithDebInfo")
.build_target("libcef_dll_wrapper");
let project_arch = match os_arch.arch {
"aarch64" => "arm64",
arch => arch,
};
let sandbox = if cfg!(feature = "sandbox") {
"ON"
} else {
"OFF"
};
match os_arch.os {
"linux" => {
// On Windows and Linux the cef files usually have to be next to the main binary.
// On macOS it's more complicated so we'll leave it to tools like tauri-cli for now.
copy_cef_runtime_files(&cef_dir, target_dir)?;
println!("cargo::rustc-link-lib=dylib=cef");
}
"windows" => {
// On Windows and Linux the cef files usually have to be next to the main binary.
// On macOS it's more complicated so we'll leave it to tools like tauri-cli for now.
copy_cef_runtime_files(&cef_dir, target_dir)?;
if let Ok(wrapper_path) = std::env::var("CEF_RS_LIBCEF_DLL_WRAPPER_PATH") {
println!("cargo::rustc-link-search=native={wrapper_path}");
} else {
let sdk_libs = [
"comctl32.lib",
"delayimp.lib",
"mincore.lib",
"powrprof.lib",
"propsys.lib",
"runtimeobject.lib",
"setupapi.lib",
"shcore.lib",
"shell32.lib",
"shlwapi.lib",
"user32.lib",
"version.lib",
"wbemuuid.lib",
"winmm.lib",
]
.join(" ");
let build_dir = cef_dll_wrapper
.define("CMAKE_MSVC_RUNTIME_LIBRARY", "MultiThreaded")
.define("CMAKE_OBJECT_PATH_MAX", "500")
.define("CMAKE_STATIC_LINKER_FLAGS", &sdk_libs)
.define("PROJECT_ARCH", project_arch)
.define("USE_SANDBOX", sandbox)
.build()
.to_string_lossy()
.into_owned();
println!("cargo::rustc-link-search=native={build_dir}/build/libcef_dll_wrapper");
}
println!("cargo::rustc-link-lib=static=libcef_dll_wrapper");
println!("cargo::rustc-link-lib=dylib=libcef");
}
"macos" => {
println!("cargo::rustc-link-lib=framework=AppKit");
let build_dir = cef_dll_wrapper
.no_default_flags(true)
.define("PROJECT_ARCH", project_arch)
.define("USE_SANDBOX", sandbox)
.build()
.to_string_lossy()
.into_owned();
println!("cargo::rustc-link-search=native={build_dir}/build/libcef_dll_wrapper");
println!("cargo::rustc-link-lib=static=cef_dll_wrapper");
}
os => unimplemented!("unknown target {os}"),
}
Ok(())
}
#[cfg(not(feature = "dox"))]
fn copy_directory(src: &std::path::Path, dest: &std::path::Path) -> Result<(), std::io::Error> {
std::fs::create_dir_all(dest)?;
for entry in std::fs::read_dir(src)? {
let entry = entry?;
if entry.path().is_file() {
std::fs::copy(entry.path(), dest.join(entry.file_name()))?;
}
}
Ok(())
}
#[cfg(not(feature = "dox"))]
fn copy_cef_runtime_files(
cef_dir: &std::path::Path,
target_dir: &std::path::Path,
) -> Result<(), std::io::Error> {
copy_directory(cef_dir, target_dir)?;
const LOCALES_DIR: &str = "locales";
copy_directory(&cef_dir.join(LOCALES_DIR), &target_dir.join(LOCALES_DIR))?;
Ok(())
}
#[cfg(feature = "dox")]
fn main() {}