// Port of https://github.com/saghul/pyuv/blob/v1.x/setup_libuv.py extern crate pkg_config; use std::fs; use std::path::{Path, PathBuf}; use std::env; use std::process::Command; fn libuv_dir() -> PathBuf { Path::new("libuv").to_owned() } fn libuv_repo() -> String { "https://github.com/libuv/libuv.git".to_owned() } fn libuv_revision() -> String { "v1.7.5".to_owned() } fn libuv_lib() -> PathBuf { if cfg!(windows) { libuv_dir().join("Release").join("lib").join("libuv.lib") } else { libuv_dir().join(".libs").join("libuv.a") } } fn libuv_force_fetch() -> bool { env::var("LIBUV_SYS_FORCE_FETCH").is_ok() } fn libuv_clean_compile() -> bool { env::var("LIBUV_SYS_CLEAN_COMPILE").is_ok() } fn use_system_libuv() -> bool { env::var("LIBUV_SYS_USE_SYSTEM").is_ok() } fn download_libuv() { println!("Downloading libuv..."); fs::create_dir_all(libuv_dir()).unwrap(); Command::new("git") .arg("clone") .arg("-b") .arg(libuv_revision()) .arg(libuv_repo()) .arg(libuv_dir()) .spawn() .unwrap() .wait() .unwrap(); fs::create_dir_all("libuv.stamp").unwrap(); } fn build_libuv() { println!("Building libuv..."); // don't support cross-compiling ... if cfg!(windows) { let libuv_arch = if cfg!(target_arch = "x86") { "x86" } else if cfg!(target_arch = "x86_64") { "x64" } else { panic!("Unsupported Windows host architecture") }; // deleted some environment stuff ("setup_windows_env") that looked fairly // Python-specific Command::new("cmd.exe") .arg("/C") .arg("vcbuild.bat") .arg(libuv_arch) .arg("release") .current_dir(libuv_dir()) .spawn() .unwrap() .wait() .unwrap(); } else { Command::new("sh") .arg("autogen.sh") .current_dir(libuv_dir()) .spawn() .unwrap() .wait() .unwrap(); Command::new("./configure") .current_dir(libuv_dir()) .spawn() .unwrap() .wait() .unwrap(); Command::new("make") .current_dir(libuv_dir()) .spawn() .unwrap() .wait() .unwrap(); } } fn get_libuv() { if libuv_force_fetch() { fs::remove_dir_all(libuv_dir()).unwrap(); fs::remove_dir_all("libuv.stamp").unwrap(); } if fs::metadata("libuv.stamp").is_err() { download_libuv(); build_libuv(); } else { if libuv_clean_compile() { if cfg!(windows) { Command::new("cmd.exe") .arg("/C") .arg("vcbuild.bat") .arg("clean") .current_dir(libuv_dir()) .spawn() .unwrap() .wait() .unwrap(); fs::remove_dir_all(libuv_dir().join("Release")).unwrap(); } else { Command::new("make") .arg("clean") .current_dir(libuv_dir()) .spawn() .unwrap() .wait() .unwrap(); Command::new("make") .arg("distclean") .current_dir(libuv_dir()) .spawn() .unwrap() .wait() .unwrap(); } } if fs::metadata(libuv_lib()).is_err() { println!("libuv needs to be compiled."); build_libuv(); } else { println!("No need to build libuv."); } } } fn main() { let target = env::var("TARGET").unwrap(); if cfg!(windows) != target.contains("windows") { panic!("Cannot cross compile to/from Windows due to use of a batch file build"); } if use_system_libuv() { pkg_config::find_library("libuv").unwrap(); } else { get_libuv(); println!("cargo:rustc-link-lib=static=uv"); println!("cargo:rustc-link-search=native={}", env::current_dir().unwrap().join(libuv_lib().parent().unwrap()).to_str().unwrap()); if target.contains("linux") { println!("cargo:rustc-link-lib=rt"); } else if target.contains("windows") { println!("cargo:rustc-link-lib=advapi32"); println!("cargo:rustc-link-lib=iphlpapi"); println!("cargo:rustc-link-lib=psapi"); println!("cargo:rustc-link-lib=shell32"); println!("cargo:rustc-link-lib=userenv"); println!("cargo:rustc-link-lib=ws2_32"); } else if target.contains("freebsd") { println!("cargo:rustc-link-lib=kvm"); } } }