2021-12-09 18:07:23 +03:00
|
|
|
#[cfg(feature = "build_unicorn_cmake")]
|
2021-10-18 22:39:59 +03:00
|
|
|
use bytes::Buf;
|
2021-12-09 18:07:23 +03:00
|
|
|
#[cfg(feature = "build_unicorn_cmake")]
|
2021-10-18 22:39:59 +03:00
|
|
|
use flate2::read::GzDecoder;
|
2021-12-09 18:07:23 +03:00
|
|
|
#[cfg(feature = "use_system_unicorn")]
|
|
|
|
use pkg_config;
|
|
|
|
#[cfg(feature = "build_unicorn_cmake")]
|
2021-10-18 22:39:59 +03:00
|
|
|
use reqwest::header::USER_AGENT;
|
2021-12-09 18:07:23 +03:00
|
|
|
#[cfg(feature = "build_unicorn_cmake")]
|
2021-11-09 17:34:22 +03:00
|
|
|
use std::path::{Path, PathBuf};
|
2021-12-09 18:07:23 +03:00
|
|
|
#[cfg(feature = "build_unicorn_cmake")]
|
2021-10-18 22:41:19 +03:00
|
|
|
use std::{env, process::Command};
|
2021-12-09 18:07:23 +03:00
|
|
|
#[cfg(feature = "build_unicorn_cmake")]
|
2021-10-18 22:39:59 +03:00
|
|
|
use tar::Archive;
|
2021-10-03 20:01:43 +03:00
|
|
|
|
2021-12-09 18:07:23 +03:00
|
|
|
#[cfg(feature = "build_unicorn_cmake")]
|
2021-11-09 17:34:22 +03:00
|
|
|
fn find_unicorn(unicorn_dir: &Path) -> Option<PathBuf> {
|
2021-10-18 22:39:59 +03:00
|
|
|
for entry in std::fs::read_dir(unicorn_dir).ok()? {
|
|
|
|
let entry = entry.unwrap();
|
|
|
|
let path = entry.path();
|
|
|
|
|
|
|
|
if path.is_dir() && path.file_name()?.to_str()?.contains("unicorn") {
|
|
|
|
return Some(path);
|
|
|
|
}
|
2021-10-16 22:21:12 +03:00
|
|
|
}
|
|
|
|
|
2021-10-18 22:39:59 +03:00
|
|
|
None
|
|
|
|
}
|
|
|
|
|
2021-12-09 18:07:23 +03:00
|
|
|
#[cfg(feature = "build_unicorn_cmake")]
|
2021-11-09 17:34:22 +03:00
|
|
|
fn out_dir() -> PathBuf {
|
|
|
|
let out_dir = env::var("OUT_DIR").unwrap();
|
|
|
|
Path::new(&out_dir).to_path_buf()
|
|
|
|
}
|
|
|
|
|
2021-12-09 18:07:23 +03:00
|
|
|
#[cfg(feature = "build_unicorn_cmake")]
|
2021-11-09 17:34:22 +03:00
|
|
|
fn download_unicorn() -> PathBuf {
|
2021-10-18 22:39:59 +03:00
|
|
|
// https://docs.github.com/en/rest/reference/repos#download-a-repository-archive-tar
|
|
|
|
let pkg_version;
|
|
|
|
if let Ok(unicorn_version) = env::var("UNICORN_VERSION") {
|
|
|
|
pkg_version = unicorn_version;
|
2021-10-16 22:45:18 +03:00
|
|
|
} else {
|
2021-10-18 22:39:59 +03:00
|
|
|
pkg_version = env::var("CARGO_PKG_VERSION").unwrap();
|
2021-10-16 22:45:18 +03:00
|
|
|
}
|
2021-11-09 17:34:22 +03:00
|
|
|
let out_dir = out_dir();
|
2021-10-18 22:39:59 +03:00
|
|
|
let client = reqwest::blocking::Client::new();
|
|
|
|
let resp = client
|
|
|
|
.get(format!(
|
|
|
|
"https://api.github.com/repos/unicorn-engine/unicorn/tarball/{}",
|
|
|
|
pkg_version
|
|
|
|
))
|
|
|
|
.header(USER_AGENT, "unicorn-engine-rust-bindings")
|
2021-10-18 22:41:19 +03:00
|
|
|
.send()
|
|
|
|
.unwrap()
|
|
|
|
.bytes()
|
|
|
|
.unwrap();
|
2021-10-18 22:39:59 +03:00
|
|
|
let tar = GzDecoder::new(resp.reader());
|
|
|
|
|
|
|
|
let mut archive = Archive::new(tar);
|
|
|
|
archive.unpack(&out_dir).unwrap();
|
|
|
|
|
2021-11-09 17:34:22 +03:00
|
|
|
find_unicorn(&out_dir).unwrap()
|
2021-10-18 22:39:59 +03:00
|
|
|
}
|
|
|
|
|
2021-12-09 18:07:23 +03:00
|
|
|
#[cfg(feature = "build_unicorn_cmake")]
|
2021-11-10 06:14:56 +03:00
|
|
|
#[allow(clippy::branches_sharing_code)]
|
2021-12-09 18:07:23 +03:00
|
|
|
fn build_with_cmake() {
|
2021-10-18 22:39:59 +03:00
|
|
|
let profile = env::var("PROFILE").unwrap();
|
|
|
|
|
2021-11-09 17:34:22 +03:00
|
|
|
if let Some(unicorn_dir) = find_unicorn(&out_dir()) {
|
2022-04-04 12:24:59 +03:00
|
|
|
let rust_build_path = unicorn_dir.join("build_rust");
|
2021-11-09 17:34:22 +03:00
|
|
|
println!(
|
|
|
|
"cargo:rustc-link-search={}",
|
|
|
|
rust_build_path.to_str().unwrap()
|
|
|
|
);
|
|
|
|
println!(
|
|
|
|
"cargo:rustc-link-search={}",
|
|
|
|
rust_build_path.join("Debug").to_str().unwrap()
|
|
|
|
);
|
|
|
|
println!(
|
|
|
|
"cargo:rustc-link-search={}",
|
|
|
|
rust_build_path.join("Release").to_str().unwrap()
|
|
|
|
);
|
2021-11-09 02:58:13 +03:00
|
|
|
} else {
|
2021-11-10 09:51:07 +03:00
|
|
|
let unicorn_dir = if let Result::Ok(_) = env::var("UNICORN_LOCAL") {
|
2021-11-09 17:34:22 +03:00
|
|
|
Path::new("..").join("..")
|
2021-10-16 22:45:18 +03:00
|
|
|
} else {
|
2021-11-09 17:34:22 +03:00
|
|
|
println!("cargo:warning=Unicorn not found. Downloading...");
|
|
|
|
download_unicorn()
|
|
|
|
};
|
2021-10-16 22:45:18 +03:00
|
|
|
|
2022-04-04 12:24:59 +03:00
|
|
|
let rust_build_path = unicorn_dir.join("build_rust");
|
2021-10-16 22:21:12 +03:00
|
|
|
|
|
|
|
let mut cmd = Command::new("cmake");
|
|
|
|
|
2021-11-09 17:34:22 +03:00
|
|
|
// We don't use TARGET since we can't cross-build.
|
|
|
|
if env::consts::OS == "windows" {
|
|
|
|
// Windows
|
|
|
|
cmd.current_dir(&unicorn_dir)
|
|
|
|
.arg("-B")
|
2022-04-04 12:24:59 +03:00
|
|
|
.arg("build_rust")
|
2022-01-18 23:33:22 +03:00
|
|
|
.arg("-DBUILD_SHARED_LIBS=OFF")
|
2021-11-09 17:34:22 +03:00
|
|
|
.arg("-G")
|
|
|
|
.arg("Visual Studio 16 2019");
|
|
|
|
|
|
|
|
if profile == "debug" {
|
|
|
|
cmd.arg("-DCMAKE_BUILD_TYPE=Debug");
|
|
|
|
} else {
|
|
|
|
cmd.arg("-DCMAKE_BUILD_TYPE=Release");
|
|
|
|
}
|
|
|
|
|
|
|
|
cmd.output()
|
|
|
|
.expect("Fail to create build directory on Windows.");
|
|
|
|
|
|
|
|
let mut platform = "x64";
|
|
|
|
let mut conf = "Release";
|
|
|
|
if std::mem::size_of::<usize>() == 4 {
|
|
|
|
platform = "Win32";
|
|
|
|
}
|
|
|
|
if profile == "debug" {
|
|
|
|
conf = "Debug";
|
|
|
|
}
|
|
|
|
|
|
|
|
Command::new("msbuild")
|
|
|
|
.current_dir(&rust_build_path)
|
|
|
|
.arg("unicorn.sln")
|
|
|
|
.arg("-m")
|
|
|
|
.arg("-p:Platform=".to_owned() + platform)
|
|
|
|
.arg("-p:Configuration=".to_owned() + conf)
|
|
|
|
.output()
|
|
|
|
.expect("Fail to build unicorn on Win32.");
|
|
|
|
println!(
|
|
|
|
"cargo:rustc-link-search={}",
|
|
|
|
rust_build_path.join(conf).to_str().unwrap()
|
|
|
|
);
|
2021-10-16 22:21:12 +03:00
|
|
|
} else {
|
2021-11-09 17:34:22 +03:00
|
|
|
// Most Unix-like systems
|
|
|
|
let mut cmd = Command::new("cmake");
|
|
|
|
cmd.current_dir(&unicorn_dir)
|
|
|
|
.arg("-B")
|
2022-04-04 12:24:59 +03:00
|
|
|
.arg("build_rust")
|
2022-01-18 23:33:22 +03:00
|
|
|
.arg("-DBUILD_SHARED_LIBS=OFF");
|
2021-11-09 17:34:22 +03:00
|
|
|
|
|
|
|
if profile == "debug" {
|
|
|
|
cmd.arg("-DCMAKE_BUILD_TYPE=Debug");
|
|
|
|
} else {
|
|
|
|
cmd.arg("-DCMAKE_BUILD_TYPE=Release");
|
|
|
|
}
|
|
|
|
|
|
|
|
cmd.output()
|
|
|
|
.expect("Fail to create build directory on *nix.");
|
|
|
|
|
|
|
|
Command::new("make")
|
|
|
|
.current_dir(&rust_build_path)
|
|
|
|
.arg("-j6")
|
|
|
|
.output()
|
|
|
|
.expect("Fail to build unicorn on *nix.");
|
|
|
|
|
|
|
|
println!(
|
|
|
|
"cargo:rustc-link-search={}",
|
|
|
|
rust_build_path.to_str().unwrap()
|
|
|
|
);
|
2021-10-16 22:21:12 +03:00
|
|
|
}
|
|
|
|
}
|
2021-10-16 22:45:18 +03:00
|
|
|
|
|
|
|
// Lazymio(@wtdcode): Why do I stick to static link? See: https://github.com/rust-lang/cargo/issues/5077
|
2022-04-04 12:24:59 +03:00
|
|
|
println!("cargo:rustc-link-lib=unicorn-static");
|
2021-11-09 17:34:22 +03:00
|
|
|
println!("cargo:rerun-if-changed=build.rs");
|
|
|
|
println!("cargo:rerun-if-changed=src");
|
2021-10-03 20:01:43 +03:00
|
|
|
}
|
2021-12-09 18:07:23 +03:00
|
|
|
|
|
|
|
fn main() {
|
|
|
|
if cfg!(feature = "use_system_unicorn") {
|
|
|
|
#[cfg(feature = "use_system_unicorn")]
|
|
|
|
pkg_config::Config::new()
|
|
|
|
.atleast_version("2")
|
|
|
|
.probe("unicorn")
|
|
|
|
.expect("Could not find system unicorn2");
|
|
|
|
} else {
|
|
|
|
#[cfg(feature = "build_unicorn_cmake")]
|
|
|
|
build_with_cmake();
|
|
|
|
}
|
|
|
|
}
|