extern crate pkg_config;
#[cfg(target_env = "msvc")]
extern crate vcpkg;
extern crate cc;
use std::env;
use std::fs;
use std::path::PathBuf;
use std::process::Command;
fn main() {
println!("cargo:rerun-if-env-changed=LIBZ_SYS_STATIC");
println!("cargo:rerun-if-changed=build.rs");
let host = env::var("HOST").unwrap();
let target = env::var("TARGET").unwrap();
let host_and_target_contain = |s| host.contains(s) && target.contains(s);
let want_static = env::var("LIBZ_SYS_STATIC").unwrap_or(String::new()) == "1";
if !want_static &&
!target.contains("msvc") && !(host_and_target_contain("apple") ||
host_and_target_contain("freebsd") ||
host_and_target_contain("dragonfly")) &&
pkg_config::Config::new().cargo_metadata(true).probe("zlib").is_ok() {
return
}
if target.contains("msvc") {
if try_vcpkg() {
return;
}
}
if target.contains("android") {
println!("cargo:rustc-link-lib=z");
return
}
let mut cfg = cc::Build::new();
if target.contains("msvc") ||
target.contains("pc-windows-gnu") ||
want_static ||
target != host ||
target.contains("musl")
{
return build_zlib(&mut cfg, &target);
}
if zlib_installed(&mut cfg) {
println!("cargo:rustc-link-lib=z");
return
}
build_zlib(&mut cfg, &target)
}
fn build_zlib(cfg: &mut cc::Build, target: &str) {
let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap());
let build = dst.join("build");
cfg.warnings(false)
.out_dir(&build)
.include("src/zlib");
cfg.file("src/zlib/adler32.c")
.file("src/zlib/compress.c")
.file("src/zlib/crc32.c")
.file("src/zlib/deflate.c")
.file("src/zlib/gzclose.c")
.file("src/zlib/gzlib.c")
.file("src/zlib/gzread.c")
.file("src/zlib/gzwrite.c")
.file("src/zlib/infback.c")
.file("src/zlib/inffast.c")
.file("src/zlib/inflate.c")
.file("src/zlib/inftrees.c")
.file("src/zlib/trees.c")
.file("src/zlib/uncompr.c")
.file("src/zlib/zutil.c");
if !target.contains("windows") {
cfg.define("STDC", None);
cfg.define("_LARGEFILE64_SOURCE", None);
cfg.define("_POSIX_SOURCE", None);
}
cfg.compile("z");
fs::create_dir_all(dst.join("lib/pkgconfig")).unwrap();
fs::create_dir_all(dst.join("include")).unwrap();
fs::copy("src/zlib/zlib.h", dst.join("include/zlib.h")).unwrap();
fs::copy("src/zlib/zconf.h", dst.join("include/zconf.h")).unwrap();
fs::write(
dst.join("lib/pkgconfig/zlib.pc"),
fs::read_to_string("src/zlib/zlib.pc.in")
.unwrap()
.replace("@prefix@", dst.to_str().unwrap()),
).unwrap();
println!("cargo:root={}", dst.to_str().unwrap());
println!("cargo:include={}/include", dst.to_str().unwrap());
}
#[cfg(not(target_env = "msvc"))]
fn try_vcpkg() -> bool {
false
}
#[cfg(target_env = "msvc")]
fn try_vcpkg() -> bool {
match vcpkg::Config::new()
.emit_includes(true)
.lib_names("zlib", "zlib1")
.probe("zlib") {
Ok(_) => { true },
Err(e) => {
println!("note, vcpkg did not find zlib: {}", e);
false
},
}
}
fn zlib_installed(cfg: &mut cc::Build) -> bool {
let compiler = cfg.get_compiler();
let mut cmd = Command::new(compiler.path());
cmd.arg("src/smoke.c")
.arg("-o").arg("/dev/null")
.arg("-lz");
println!("running {:?}", cmd);
if let Ok(status) = cmd.status() {
if status.success() {
return true
}
}
false
}