extern crate bindgen;
use std::{env, fs::canonicalize, path::PathBuf};
fn main() {
println!("cargo:rerun-if-changed=wrapper.h");
println!("cargo:rerun-if-changed=build.rs");
if cfg!(feature = "pls-generate") {
let gnutls_path = match env::consts::OS {
"linux" => "/usr/include",
"macos" => "/opt/homebrew/include",
"windows" => {
panic!("Generating bindings on Windows is broken, pls remove the pls-generate feature.");
}
_ => panic!("Unsupported OS"),
};
let bindings = bindgen::Builder::default()
.header("wrapper.h")
.clang_arg(format!("-I{}", gnutls_path))
.parse_callbacks(Box::new(bindgen::CargoCallbacks))
.generate()
.expect("Unable to generate bindings");
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
bindings
.write_to_file(out_path.join("bindings.rs"))
.expect("Couldn't write bindings!");
}
if cfg!(feature = "vendored") {
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
env::set_current_dir(&out_path).unwrap();
env::set_var("PKG_CONFIG_PATH", out_path.join("lib/pkgconfig"));
let lib_path = out_path.join("lib");
if !lib_path.exists() {
std::fs::create_dir(&lib_path).unwrap();
}
let mut lib_path = lib_path.canonicalize().unwrap().display().to_string();
env::set_var("LD_LIBRARY_PATH", lib_path.clone());
let include_path = out_path.join("include");
if !include_path.exists() {
std::fs::create_dir(&include_path).unwrap();
}
let mut include_path = include_path.canonicalize().unwrap().display().to_string();
env::set_current_dir("../../").unwrap();
let mut openssl_found = false;
loop {
for path in std::fs::read_dir(".").unwrap() {
let path = path.unwrap().path();
if !path.is_dir() {
continue;
}
if path.to_str().unwrap().contains("openssl-sys") {
let install_path = path.join("out").join("openssl-build").join("install");
if install_path.exists() {
println!(
"cargo:rustc-link-search=native={}",
install_path.join("lib").canonicalize().unwrap().display()
);
include_path = format!(
"{} -I{}",
include_path,
install_path
.join("include")
.canonicalize()
.unwrap()
.display()
);
lib_path = format!(
"{} -L{}",
lib_path,
install_path.join("lib").canonicalize().unwrap().display()
);
let ssl_pkg_config_path = install_path.join("lib").join("pkgconfig");
std::fs::create_dir_all(&ssl_pkg_config_path).unwrap();
let ssl_pkg_config_path = ssl_pkg_config_path.canonicalize().unwrap();
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap())
.join("lib")
.join("pkgconfig");
std::fs::create_dir_all(&out_path).unwrap();
let out_path = out_path.canonicalize().unwrap();
for path in std::fs::read_dir(&ssl_pkg_config_path).unwrap() {
let path = path.unwrap().path();
if !path.is_file() {
continue;
}
let file_name = path.file_name().unwrap().to_str().unwrap();
std::fs::copy(&path, out_path.join(file_name)).unwrap();
}
openssl_found = true;
}
}
}
if openssl_found {
break;
}
std::thread::sleep(std::time::Duration::from_secs(10));
}
if !openssl_found {
panic!("\nopenssl-src was not found, exiting\n");
}
repo_setup("https://github.com/libimobiledevice/libplist.git");
repo_setup("https://github.com/libimobiledevice/libimobiledevice-glue.git");
repo_setup("https://github.com/libimobiledevice/libusbmuxd.git");
repo_setup("https://github.com/libimobiledevice/libtatsu.git");
repo_setup("https://github.com/libimobiledevice/libimobiledevice.git");
let mut makefile = std::fs::read_to_string("libimobiledevice/Makefile.in").unwrap();
makefile = makefile.replace("tools", "");
std::fs::write("libimobiledevice/Makefile.in", makefile).unwrap();
let mut c_flags = vec![];
let mut cxx_flags = vec![];
if env::var("TARGET").unwrap().contains("windows") {
env::set_var("WINDOWS_BUILD", "1");
println!("cargo:rustc-link-lib=dylib=iphlpapi");
println!("cargo:rustc-link-lib=dylib=shell32");
println!("cargo:rustc-link-lib=dylib=ole32");
}
if env::var("TARGET").unwrap().contains("apple") {
println!("cargo:rustc-env=MACOSX_DEPLOYMENT_TARGET=10.13");
c_flags.push("-mmacosx-version-min=10.13".to_string());
cxx_flags.push("-mmacosx-version-min=10.13".to_string());
}
c_flags.push(format!("-L{} -I{}", lib_path, include_path));
let mut dst = autotools::Config::new("libplist");
let mut dst = dst.without("cython", None);
for flag in &c_flags {
dst = dst.cflag(flag);
}
for flag in &cxx_flags {
dst = dst.cxxflag(flag);
}
let dst = dst.build();
println!(
"cargo:rustc-link-search=native={}",
dst.join("lib").display()
);
let mut dst = autotools::Config::new("libimobiledevice-glue");
let dst = dst.without("cython", None);
let mut dst = dst.env("PKG_CONFIG_PATH", out_path.join("lib/pkgconfig"));
for flag in &c_flags {
dst = dst.cflag(flag);
}
for flag in &cxx_flags {
dst = dst.cxxflag(flag);
}
let dst = dst.build();
println!("cargo:rustc-link-search=native={}", dst.display());
let mut dst = autotools::Config::new("libusbmuxd");
let dst = dst.without("cython", None);
let mut dst = dst.env("PKG_CONFIG_PATH", out_path.join("lib/pkgconfig"));
for flag in &c_flags {
dst = dst.cflag(flag);
}
for flag in &cxx_flags {
dst = dst.cxxflag(flag);
}
let dst = dst.build();
println!(
"cargo:rustc-link-search=native={}",
dst.join("lib").display()
);
let mut dst = autotools::Config::new("libtatsu");
let dst = dst.without("cython", None);
let mut dst = dst.env("PKG_CONFIG_PATH", out_path.join("lib/pkgconfig"));
for flag in &c_flags {
dst = dst.cflag(flag);
}
for flag in &cxx_flags {
dst = dst.cxxflag(flag);
}
let dst = dst.build();
println!(
"cargo:rustc-link-search=native={}",
dst.join("lib").display()
);
let mut dst = autotools::Config::new("libimobiledevice");
let dst = dst.without("cython", None);
let mut dst = dst.env("PKG_CONFIG_PATH", out_path.join("lib/pkgconfig"));
for flag in &c_flags {
dst = dst.cflag(flag);
}
for flag in &cxx_flags {
dst = dst.cxxflag(flag);
}
let dst = dst.build();
println!(
"cargo:rustc-link-search=native={}",
dst.join("lib").display()
);
} else {
let override_path = PathBuf::from("./override").join(env::var("TARGET").unwrap());
if override_path.exists() {
println!(
"cargo:rustc-link-search={}",
canonicalize(&override_path).unwrap().display()
);
}
println!("cargo:rustc-link-search=/usr/local/lib");
println!("cargo:rustc-link-search=/usr/lib");
println!("cargo:rustc-link-search=/opt/homebrew/lib");
println!("cargo:rustc-link-search=/usr/local/opt/libimobiledevice/lib");
println!("cargo:rustc-link-search=/usr/local/opt/libusbmuxd/lib");
println!("cargo:rustc-link-search=/usr/local/opt/libimobiledevice-glue/lib");
}
let location_determinator = if cfg!(feature = "static") {
"static"
} else {
"dylib"
};
println!(
"cargo:rustc-link-lib={}=imobiledevice-1.0",
location_determinator
);
println!("cargo:rustc-link-lib={}=usbmuxd-2.0", location_determinator);
println!(
"cargo:rustc-link-lib={}=imobiledevice-glue-1.0",
location_determinator
);
println!("cargo:rustc-link-lib={}=plist-2.0", location_determinator);
println!("cargo:rustc-link-lib={location_determinator}=crypto");
println!("cargo:rustc-link-lib={location_determinator}=ssl");
}
fn repo_setup(url: &str) {
let mut cmd = std::process::Command::new("git");
cmd.arg("clone");
cmd.arg("--depth=1");
cmd.arg(url);
cmd.output().unwrap();
env::set_current_dir(url.split('/').last().unwrap().replace(".git", "")).unwrap();
env::set_var("NOCONFIGURE", "1");
let mut cmd = std::process::Command::new("./autogen.sh");
let _ = cmd.output();
env::remove_var("NOCONFIGURE");
env::set_current_dir("..").unwrap();
}