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...");
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")
};
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");
}
}
}