From 7d617d7d580315591a85516a5fcc1d259f464cfe Mon Sep 17 00:00:00 2001 From: Mahmoud Al-Qudsi Date: Fri, 5 May 2023 18:38:52 -0500 Subject: [PATCH] Support cross-compilation w/ `detect_bsd()` check Also assert that the code works as expected by asserting the result under known BSD systems. --- fish-rust/build.rs | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/fish-rust/build.rs b/fish-rust/build.rs index 74f4b8263..76b14d351 100644 --- a/fish-rust/build.rs +++ b/fish-rust/build.rs @@ -1,5 +1,3 @@ -use miette::miette; - fn main() -> miette::Result<()> { cc::Build::new().file("src/compat.c").compile("libcompat.a"); @@ -101,25 +99,33 @@ fn detect_features() { ("bsd", &detect_bsd), ] { match detector() { - Err(e) => eprintln!("{feature} detect: {e}"), + Err(e) => eprintln!("ERROR: {feature} detect: {e}"), Ok(true) => println!("cargo:rustc-cfg=feature=\"{feature}\""), Ok(false) => (), } } } -/// Detect if we're being compiled on a BSD-derived OS. Does not yet play nicely with -/// cross-compilation. +/// Detect if we're being compiled for a BSD-derived OS, allowing targeting code conditionally with +/// `#[cfg(feature = "bsd")]`. /// /// 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 /// specific than "windows" vs "unix" so we can conditionally compile code for BSD systems. fn detect_bsd() -> miette::Result { - let uname = std::process::Command::new("uname") - .output() - .map_err(|_| miette!("Error executing uname!"))?; - Ok(std::str::from_utf8(&uname.stdout) - .map(|s| s.to_ascii_lowercase()) - .map(|s| s.contains("bsd")) - .unwrap_or(false)) + // Instead of using `uname`, we can inspect the TARGET env variable set by Cargo. This lets us + // support cross-compilation scenarios. + let mut target = std::env::var("TARGET").unwrap(); + if !target.chars().all(|c| c.is_ascii_lowercase()) { + target = target.to_ascii_lowercase(); + } + 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) }