rustdesk/libs/scrap/build.rs
2023-04-18 18:28:12 +08:00

188 lines
6.1 KiB
Rust

use std::{
env, fs,
path::{Path, PathBuf},
};
/// Link vcppkg package.
fn link_vcpkg(mut path: PathBuf, name: &str) -> PathBuf {
let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap();
let mut target_arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap();
if target_arch == "x86_64" {
target_arch = "x64".to_owned();
} else if target_arch == "aarch64" {
target_arch = "arm64".to_owned();
}
let mut target = if target_os == "macos" {
if target_arch == "x64" {
"x64-osx".to_owned()
} else if target_arch == "arm64" {
"arm64-osx".to_owned()
} else {
format!("{}-{}", target_arch, target_os)
}
} else if target_os == "windows" {
"x64-windows-static".to_owned()
} else {
format!("{}-{}", target_arch, target_os)
};
if target_arch == "x86" {
target = target.replace("x64", "x86");
}
println!("cargo:info={}", target);
path.push("installed");
path.push(target);
println!(
"{}",
format!(
"cargo:rustc-link-lib=static={}",
name.trim_start_matches("lib")
)
);
println!(
"{}",
format!(
"cargo:rustc-link-search={}",
path.join("lib").to_str().unwrap()
)
);
let include = path.join("include");
println!("{}", format!("cargo:include={}", include.to_str().unwrap()));
include
}
/// Link homebrew package(for Mac M1).
fn link_homebrew_m1(name: &str) -> PathBuf {
let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap();
let target_arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap();
if target_os != "macos" || target_arch != "aarch64" {
panic!("Couldn't find VCPKG_ROOT, also can't fallback to homebrew because it's only for macos aarch64.");
}
let mut path = PathBuf::from("/opt/homebrew/Cellar");
path.push(name);
let entries = if let Ok(dir) = std::fs::read_dir(&path) {
dir
} else {
panic!("Could not find package in {}. Make sure your homebrew and package {} are all installed.", path.to_str().unwrap(),&name);
};
let mut directories = entries
.into_iter()
.filter(|x| x.is_ok())
.map(|x| x.unwrap().path())
.filter(|x| x.is_dir())
.collect::<Vec<_>>();
// Find the newest version.
directories.sort_unstable();
if directories.is_empty() {
panic!(
"There's no installed version of {} in /opt/homebrew/Cellar",
name
);
}
path.push(directories.pop().unwrap());
// Link the library.
println!(
"{}",
format!(
"cargo:rustc-link-lib=static={}",
name.trim_start_matches("lib")
)
);
// Add the library path.
println!(
"{}",
format!(
"cargo:rustc-link-search={}",
path.join("lib").to_str().unwrap()
)
);
// Add the include path.
let include = path.join("include");
println!("{}", format!("cargo:include={}", include.to_str().unwrap()));
include
}
/// Find package. By default, it will try to find vcpkg first, then homebrew(currently only for Mac M1).
fn find_package(name: &str) -> Vec<PathBuf> {
if let Ok(vcpkg_root) = std::env::var("VCPKG_ROOT") {
vec![link_vcpkg(vcpkg_root.into(), name)]
} else {
// Try using homebrew
vec![link_homebrew_m1(name)]
}
}
fn generate_bindings(
ffi_header: &Path,
include_paths: &[PathBuf],
ffi_rs: &Path,
exact_file: &Path,
) {
let mut b = bindgen::builder()
.header(ffi_header.to_str().unwrap())
.allowlist_type("^[vV].*")
.allowlist_var("^[vV].*")
.allowlist_function("^[vV].*")
.rustified_enum("^v.*")
.trust_clang_mangling(false)
.layout_tests(false) // breaks 32/64-bit compat
.generate_comments(false); // vpx comments have prefix /*!\
for dir in include_paths {
b = b.clang_arg(format!("-I{}", dir.display()));
}
b.generate().unwrap().write_to_file(ffi_rs).unwrap();
fs::copy(ffi_rs, exact_file).ok(); // ignore failure
}
fn gen_vpx() {
let includes = find_package("libvpx");
let src_dir = env::var_os("CARGO_MANIFEST_DIR").unwrap();
let src_dir = Path::new(&src_dir);
let out_dir = env::var_os("OUT_DIR").unwrap();
let out_dir = Path::new(&out_dir);
let ffi_header = src_dir.join("vpx_ffi.h");
println!("rerun-if-changed={}", ffi_header.display());
for dir in &includes {
println!("rerun-if-changed={}", dir.display());
}
let ffi_rs = out_dir.join("vpx_ffi.rs");
let exact_file = src_dir.join("generated").join("vpx_ffi.rs");
generate_bindings(&ffi_header, &includes, &ffi_rs, &exact_file);
}
fn main() {
// note: all link symbol names in x86 (32-bit) are prefixed wth "_".
// run "rustup show" to show current default toolchain, if it is stable-x86-pc-windows-msvc,
// please install x64 toolchain by "rustup toolchain install stable-x86_64-pc-windows-msvc",
// then set x64 to default by "rustup default stable-x86_64-pc-windows-msvc"
let target = target_build_utils::TargetInfo::new();
if target.unwrap().target_pointer_width() != "64" {
// panic!("Only support 64bit system");
}
env::remove_var("CARGO_CFG_TARGET_FEATURE");
env::set_var("CARGO_CFG_TARGET_FEATURE", "crt-static");
find_package("libyuv");
gen_vpx();
// there is problem with cfg(target_os) in build.rs, so use our workaround
let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap();
if target_os == "ios" {
// nothing
} else if target_os == "android" {
println!("cargo:rustc-cfg=android");
} else if cfg!(windows) {
// The first choice is Windows because DXGI is amazing.
println!("cargo:rustc-cfg=dxgi");
} else if cfg!(target_os = "macos") {
// Quartz is second because macOS is the (annoying) exception.
println!("cargo:rustc-cfg=quartz");
} else if cfg!(unix) {
// On UNIX we pray that X11 (with XCB) is available.
println!("cargo:rustc-cfg=x11");
}
}