const CRLIBM_INCLUDE_DIRECTORIES: &[&str] =
&["crlibm", "crlibm/scs_lib"];
const CRLIBM_FILES: &[&str] =
&["crlibm/crlibm_private.c",
"crlibm/triple-double.c",
"crlibm/exp-td.c",
"crlibm/exp-td-standalone.c",
"crlibm/expm1-standalone.c",
"crlibm/expm1.c",
"crlibm/log1p.c",
"crlibm/rem_pio2_accurate.c",
"crlibm/trigo_fast.c",
"crlibm/trigo_accurate.c",
"crlibm/trigpi.c",
"crlibm/asincos.c",
"crlibm/atan_fast.c",
"crlibm/atan_accurate.c",
"crlibm/csh_fast.c",
"crlibm/scs_lib/scs_private.c",
"crlibm/scs_lib/addition_scs.c",
"crlibm/scs_lib/division_scs.c",
"crlibm/scs_lib/double2scs.c",
"crlibm/scs_lib/multiplication_scs.c",
"crlibm/scs_lib/scs2double.c" ];
fn in_appropriate_dir(file: &str) -> std::path::PathBuf {
match std::env::var("OUT_DIR") {
Err(_) => std::path::PathBuf::from(file),
Ok(dir) => {
use std::path::PathBuf;
let mut path = PathBuf::new();
path.push(dir);
path.push(file);
path
}
}
}
fn add_has_header_flag(build: &mut cc::Build, name: &str)
-> std::io::Result<()> {
let tmp_file = in_appropriate_dir("build_has_header.c");
use std::fs::File;
use std::io::Write;
{ let mut file = File::create(&tmp_file)?;
write!(file, "#include \"{}.h\"\nint main() {{ return 0; }}\n", name)?; }
let mut local_build = cc::Build::new();
let header_exists = local_build.warnings(false)
.file(&tmp_file).try_expand().is_ok();
if header_exists {
let mut flag = String::from("HAVE_");
flag.push_str(name.to_uppercase().as_str());
flag.push_str("_H");
build.define(flag.as_str(), None);
}
std::fs::remove_file(tmp_file).expect("Cannot remove file.");
Ok(())
}
fn has_fpu_control() -> bool {
let tmp_file = in_appropriate_dir("has_fpu_control.c");
use std::fs::File;
use std::io::Write;
let file =
File::create(&tmp_file)
.and_then(|mut file| {
write!(file, "#include \"fpu_control.h\"\nint main() {{\n\
unsigned long long cw;\n\
_FPU_SETCW(cw); return 0; }}\n")
.and_then(|_| file.flush())
});
if file.is_err() { return false }
let res = cc::Build::new().cargo_warnings(false)
.file(&tmp_file).try_expand().is_ok();
std::fs::remove_file(tmp_file).expect("Cannot remove file.");
res
}
fn main() -> std::io::Result<()> {
let mut build = cc::Build::new();
let mut has_ia32_de = false;
if cfg!(target_os = "macos") || cfg!(target_os = "freebsd")
|| cfg!(target_os = "openbsd") || cfg!(target_os = "netbsd") {
build.define("CRLIBM_TYPEOS_BSD", None);
}
if cfg!(target_arch = "powerpc") || cfg!(target_arch = "powerpc64") {
build.define("CRLIBM_TYPECPU_POWERPC", None); }
if cfg!(target_arch = "x86") {
build.define("CRLIBM_TYPECPU_X86", None);
has_ia32_de = true; }
if cfg!(target_arch = "x86_64") {
build.define("CRLIBM_TYPECPU_AMD64", None);
has_ia32_de = true; }
add_has_header_flag(&mut build, "fenv")?;
add_has_header_flag(&mut build, "float")?;
add_has_header_flag(&mut build, "inttypes")?;
add_has_header_flag(&mut build, "stdlib")?;
add_has_header_flag(&mut build, "strings")?;
add_has_header_flag(&mut build, "unistd")?;
let has_fpu_control = has_fpu_control();
if has_fpu_control {
build.define("CRLIBM_HAS_FPU_CONTROL", None);
}
build.define("SCS_NB_BITS", "30"); build.define("SCS_NB_WORDS", "8"); build.includes(CRLIBM_INCLUDE_DIRECTORIES);
build.files(CRLIBM_FILES);
let use_hardware_de =
cfg!(feature = "log_double_extended") && has_ia32_de && has_fpu_control;
if use_hardware_de {
build.files(["crlibm/log-de.c", "crlibm/log2-td.c",
"crlibm/log10-td.c"]);
} else {
build.file("crlibm/log.c");
}
if cfg!(target_arch = "x86") && cfg!(target_os = "linux") {
build.flag("-znotext");
}
build.warnings(false);
build.compile("crlibm");
Ok(())
}