Support cross-compilation w/ detect_bsd() check

Also assert that the code works as expected by asserting the result under known
BSD systems.
This commit is contained in:
Mahmoud Al-Qudsi 2023-05-05 18:38:52 -05:00
parent 220ffaeb65
commit 7d617d7d58

View file

@ -1,5 +1,3 @@
use miette::miette;
fn main() -> miette::Result<()> { fn main() -> miette::Result<()> {
cc::Build::new().file("src/compat.c").compile("libcompat.a"); cc::Build::new().file("src/compat.c").compile("libcompat.a");
@ -101,25 +99,33 @@ fn detect_features() {
("bsd", &detect_bsd), ("bsd", &detect_bsd),
] { ] {
match detector() { match detector() {
Err(e) => eprintln!("{feature} detect: {e}"), Err(e) => eprintln!("ERROR: {feature} detect: {e}"),
Ok(true) => println!("cargo:rustc-cfg=feature=\"{feature}\""), Ok(true) => println!("cargo:rustc-cfg=feature=\"{feature}\""),
Ok(false) => (), Ok(false) => (),
} }
} }
} }
/// Detect if we're being compiled on a BSD-derived OS. Does not yet play nicely with /// Detect if we're being compiled for a BSD-derived OS, allowing targeting code conditionally with
/// cross-compilation. /// `#[cfg(feature = "bsd")]`.
/// ///
/// Rust offers fine-grained conditional compilation per-os for the popular operating systems, but /// Rust offers fine-grained conditional compilation per-os for the popular operating systems, but
/// doesn't necessarily include less-popular forks nor does it group them into families more /// doesn't necessarily include less-popular forks nor does it group them into families more
/// specific than "windows" vs "unix" so we can conditionally compile code for BSD systems. /// specific than "windows" vs "unix" so we can conditionally compile code for BSD systems.
fn detect_bsd() -> miette::Result<bool> { fn detect_bsd() -> miette::Result<bool> {
let uname = std::process::Command::new("uname") // Instead of using `uname`, we can inspect the TARGET env variable set by Cargo. This lets us
.output() // support cross-compilation scenarios.
.map_err(|_| miette!("Error executing uname!"))?; let mut target = std::env::var("TARGET").unwrap();
Ok(std::str::from_utf8(&uname.stdout) if !target.chars().all(|c| c.is_ascii_lowercase()) {
.map(|s| s.to_ascii_lowercase()) target = target.to_ascii_lowercase();
.map(|s| s.contains("bsd")) }
.unwrap_or(false)) let result = target.ends_with("bsd") || target.ends_with("dragonfly");
#[cfg(any(
target_os = "dragonfly",
target_os = "freebsd",
target_os = "netbsd",
target_os = "openbsd",
))]
assert!(result, "Target incorrectly detected as not BSD!");
Ok(result)
} }