use crate::common::*;
use std::{
path::{Path, PathBuf},
process::Command,
};
pub fn build_and_link() {
let out_dir = env::var("OUT_DIR").unwrap();
let build_dir = Path::new(&out_dir).join("libffi-build");
let prefix = Path::new(&out_dir).join("libffi-root");
let libdir = Path::new(&prefix).join("lib");
let libdir32 = Path::new(&prefix).join("lib32");
let libdir64 = Path::new(&prefix).join("lib64");
if let Err(e) = fs::remove_dir_all(&build_dir) {
assert_eq!(
e.kind(),
std::io::ErrorKind::NotFound,
"can't remove the build directory: {e}",
);
}
let mut command = Command::new("cp");
let has_no_preserve_flag = {
let output = Command::new("cp").arg("--help").output().unwrap().stdout;
String::from_utf8(output).unwrap().contains("--no-preserve")
};
if has_no_preserve_flag {
command.arg("--no-preserve=mode,ownership");
}
run_command(
"Copying libffi into the build directory",
command.arg("-R").arg("libffi").arg(&build_dir),
);
configure_libffi(prefix, &build_dir);
let make_command = if cfg!(target_os = "aix") || cfg!(target_os = "illumos") {
"gmake"
} else {
"make"
};
run_command(
"Building libffi",
Command::new(make_command)
.env_remove("DESTDIR")
.arg("install")
.current_dir(build_dir),
);
println!("cargo:rustc-link-lib=static=ffi");
println!("cargo:rustc-link-search={}", libdir.display());
println!("cargo:rustc-link-search={}", libdir32.display());
println!("cargo:rustc-link-search={}", libdir64.display());
}
pub fn probe_and_link() {
println!("cargo:rustc-link-lib=dylib=ffi");
}
pub fn configure_libffi(prefix: PathBuf, build_dir: &Path) {
let mut command = Command::new("sh");
command
.arg("./configure")
.arg("--with-pic")
.arg("--disable-shared")
.arg("--disable-docs");
let target = std::env::var("TARGET").unwrap();
let host = std::env::var("HOST").unwrap();
if target != host {
let cross_host = match target.as_str() {
"riscv64gc-unknown-linux-gnu" | "riscv64a23-unknown-linux-gnu" => {
"riscv64-unknown-linux-gnu"
}
"riscv64gc-unknown-linux-musl" => "riscv64-unknown-linux-musl",
"x86_64-unknown-illumos" => "x86_64-unknown-solaris",
"aarch64-apple-ios-sim" => "aarch64-apple-ios",
"x86_64-pc-windows-gnu" | "x86_64-pc-windows-gnullvm" => "x86_64-w64-mingw32",
"i686-pc-windows-gnu" | "i686-pc-windows-gnullvm" => "i686-w64-mingw32",
"aarch64-pc-windows-gnullvm" => "aarch64-w64-mingw32",
other => other,
};
command.arg(format!("--host={cross_host}"));
}
let mut c_cfg = cc::Build::new();
c_cfg
.cargo_metadata(false)
.target(&target)
.warnings(false)
.host(&host);
let c_compiler = c_cfg.get_compiler();
command.env("CC", c_compiler.path());
let mut cflags = c_compiler.cflags_env();
match env::var_os("CFLAGS") {
None => (),
Some(flags) => {
cflags.push(" ");
cflags.push(&flags);
}
}
command.env("CFLAGS", cflags);
for (k, v) in c_compiler.env() {
command.env(k, v);
}
command.current_dir(build_dir);
if cfg!(windows) {
let mut msys_prefix = prefix
.to_str()
.unwrap()
.replace(":\\", "/")
.replace('\\', "/");
msys_prefix.insert(0, '/');
command.arg("--prefix").arg(msys_prefix);
} else {
command.arg("--prefix").arg(prefix);
}
if cfg!(target_os = "aix") || cfg!(target_os = "illumos") {
command.env("MAKE", "gmake");
}
run_command("Configuring libffi", &mut command);
}