From 1f90734b129e71efe0608ec6f4e623fb9fa9a1ab Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Tue, 9 Nov 2021 15:34:22 +0100 Subject: [PATCH] No longer redownloads unicorn each cargo build --- bindings/rust/build.rs | 179 +++++++++++++++++++++++------------------ 1 file changed, 102 insertions(+), 77 deletions(-) diff --git a/bindings/rust/build.rs b/bindings/rust/build.rs index 5bae38ba..bb4e6d7d 100644 --- a/bindings/rust/build.rs +++ b/bindings/rust/build.rs @@ -1,11 +1,11 @@ use bytes::Buf; use flate2::read::GzDecoder; use reqwest::header::USER_AGENT; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::{env, process::Command}; use tar::Archive; -fn find_unicorn(unicorn_dir: &PathBuf) -> Option { +fn find_unicorn(unicorn_dir: &Path) -> Option { for entry in std::fs::read_dir(unicorn_dir).ok()? { let entry = entry.unwrap(); let path = entry.path(); @@ -18,7 +18,12 @@ fn find_unicorn(unicorn_dir: &PathBuf) -> Option { None } -fn download_unicorn() -> Option { +fn out_dir() -> PathBuf { + let out_dir = env::var("OUT_DIR").unwrap(); + Path::new(&out_dir).to_path_buf() +} + +fn download_unicorn() -> PathBuf { // 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") { @@ -26,7 +31,7 @@ fn download_unicorn() -> Option { } else { pkg_version = env::var("CARGO_PKG_VERSION").unwrap(); } - let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); + let out_dir = out_dir(); let client = reqwest::blocking::Client::new(); let resp = client .get(format!( @@ -43,89 +48,106 @@ fn download_unicorn() -> Option { let mut archive = Archive::new(tar); archive.unpack(&out_dir).unwrap(); - match find_unicorn(&out_dir) { - Some(dir) => Some(String::from(out_dir.join(dir).to_str()?)), - None => None, - } + find_unicorn(&out_dir).unwrap() } fn main() { let profile = env::var("PROFILE").unwrap(); - let unicorn_dir; - if let Result::Ok(_) = env::var("CI") { - unicorn_dir = format!("../.."); - } else { - unicorn_dir = download_unicorn().unwrap(); - } - - println!("cargo:rerun-if-changed={}", &unicorn_dir); - - // We don't use TARGET since we can't cross-build. - if env::consts::OS == "windows" { - // Windows - let mut cmd = Command::new("cmake"); - cmd.current_dir(&unicorn_dir) - .arg("-B") - .arg("rust_build") - .arg("-DUNICORN_BUILD_SHARED=off") - .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::() == 4 { - platform = "Win32"; - } - if profile == "debug" { - conf = "Debug"; - } - - Command::new("msbuild") - .current_dir(format!("{}/rust_build", &unicorn_dir)) - .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."); + if let Some(unicorn_dir) = find_unicorn(&out_dir()) { + let rust_build_path = unicorn_dir.join("rust_build"); println!( - "cargo:rustc-link-search={}/rust_build/{}", - unicorn_dir, conf + "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() ); } else { - // Most Unix-like systems - let mut cmd = Command::new("cmake"); - cmd.current_dir(&unicorn_dir) - .arg("-B") - .arg("rust_build") - .arg("-DUNICORN_BUILD_SHARED=off"); - - if profile == "debug" { - cmd.arg("-DCMAKE_BUILD_TYPE=Debug"); + let unicorn_dir = if let Result::Ok(_) = env::var("CI") { + Path::new("..").join("..") } else { - cmd.arg("-DCMAKE_BUILD_TYPE=Release"); + println!("cargo:warning=Unicorn not found. Downloading..."); + download_unicorn() + }; + + let rust_build_path = unicorn_dir.join("rust_build"); + + let mut cmd = Command::new("cmake"); + + // We don't use TARGET since we can't cross-build. + if env::consts::OS == "windows" { + // Windows + cmd.current_dir(&unicorn_dir) + .arg("-B") + .arg("rust_build") + .arg("-DUNICORN_BUILD_SHARED=off") + .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::() == 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() + ); + } else { + // Most Unix-like systems + let mut cmd = Command::new("cmake"); + cmd.current_dir(&unicorn_dir) + .arg("-B") + .arg("rust_build") + .arg("-DUNICORN_BUILD_SHARED=off"); + + 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() + ); } - - cmd.output() - .expect("Fail to create build directory on *nix."); - - Command::new("make") - .current_dir(format!("{}/rust_build", &unicorn_dir)) - .arg("-j6") - .output() - .expect("Fail to build unicorn on *nix."); - - println!("cargo:rustc-link-search={}/rust_build", unicorn_dir); } // This is a workaround for Unicorn static link since libunicorn.a is also linked again lib*-softmmu.a. @@ -157,4 +179,7 @@ fn main() { println!("cargo:rustc-link-lib={}-softmmu", arch); } println!("cargo:rustc-link-lib=unicorn-common"); + + println!("cargo:rerun-if-changed=build.rs"); + println!("cargo:rerun-if-changed=src"); }