use std::path::{Path, PathBuf};
fn main() {
println!("cargo:rerun-if-changed=shim.c");
println!("cargo:rerun-if-changed=include");
println!("cargo:rerun-if-changed=build.rs");
let out_dir = PathBuf::from(std::env::var("OUT_DIR").expect("OUT_DIR"));
let manifest_dir =
PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR"));
let vendored_include = manifest_dir.join("include");
let have_float16 = probe_float16();
let generated_include = out_dir.join("include");
write_config_h(&generated_include, have_float16);
let mut build = cc::Build::new();
build
.file("shim.c")
.include(&vendored_include)
.include(&generated_include)
.std("c11")
.warnings(true)
.flag_if_supported("-fvisibility=hidden");
if have_float16 {
build.define("ASDF_HAVE_FLOAT16", "1");
}
build.cargo_metadata(false);
build.compile("asdf_shim");
println!("cargo:rustc-link-search=native={}", out_dir.display());
println!("cargo:rustc-link-lib=static:+whole-archive=asdf_shim");
println!("cargo:include={}", vendored_include.display());
println!("cargo:generated_include={}", generated_include.display());
println!("cargo:rustc-env=ASDF_VENDORED_INCLUDE={}", vendored_include.display());
println!("cargo:rustc-env=ASDF_GENERATED_INCLUDE={}", generated_include.display());
if have_float16 {
println!("cargo:rustc-cfg=asdf_have_float16");
}
println!("cargo::rustc-check-cfg=cfg(asdf_have_float16)");
}
fn probe_float16() -> bool {
let probe = r#"
_Float16 probe(_Float16 x) { return x + (_Float16)1.0f; }
int main(void) { return (int)probe((_Float16)1.0f) == 2 ? 0 : 1; }
"#;
let out_dir = PathBuf::from(std::env::var("OUT_DIR").expect("OUT_DIR"));
let src = out_dir.join("probe_float16.c");
if std::fs::write(&src, probe).is_err() {
return false;
}
let mut build = cc::Build::new();
build.file(&src).warnings(false).cargo_metadata(false).cargo_warnings(false);
build.try_compile("probe_float16").is_ok()
}
fn write_config_h(include_dir: &Path, have_float16: bool) {
let dir = include_dir.join("asdf");
std::fs::create_dir_all(&dir).expect("create generated include dir");
let float16 =
if have_float16 { "#define ASDF_HAVE_FLOAT16 1" } else { "/* #undef ASDF_HAVE_FLOAT16 */" };
let contents = format!(
"\
/*
* Generated by libasdf-rs's build.rs. Do not edit.
*
* Records the build-time configuration of this libasdf implementation, in the
* same shape upstream's `config.h.in` produces, because the vendored public
* headers include it and gate declarations on it.
*/
#ifndef ASDF_CONFIG_H
#define ASDF_CONFIG_H
/* libasdf's internal log statements are compiled in. */
#define ASDF_LOG_ENABLED 1
/* Default runtime log level when none is set explicitly. */
#define ASDF_LOG_DEFAULT_LEVEL ASDF_LOG_WARN
/* Compile-time minimum log level. */
#define ASDF_LOG_MIN_LEVEL ASDF_LOG_TRACE
/* Log output is colorized when written to a terminal. */
#define ASDF_LOG_COLOR 1
/* Whether the `_Float16` type is usable on this target. */
{float16}
#endif /* ASDF_CONFIG_H */
"
);
let path = dir.join("config.h");
if std::fs::read_to_string(&path).ok().as_deref() != Some(contents.as_str()) {
std::fs::write(&path, contents).expect("write config.h");
}
}