diff --git a/fish-rust/Cargo.toml b/fish-rust/Cargo.toml index 7b6aec17d..458d1945f 100644 --- a/fish-rust/Cargo.toml +++ b/fish-rust/Cargo.toml @@ -4,7 +4,6 @@ version = "0.1.0" edition = "2021" rust-version = "1.67" - [dependencies] widestring-suffix = { path = "./widestring-suffix/" } @@ -29,7 +28,7 @@ cxx-gen = { git = "https://github.com/fish-shell/cxx", branch = "fish" } miette = { version = "5", features = ["fancy"] } [lib] -crate-type=["staticlib"] +crate-type = ["staticlib"] [features] # The fish-ffi-tests feature causes tests to be built which need to use the FFI. @@ -37,6 +36,9 @@ crate-type=["staticlib"] default = ["fish-ffi-tests"] fish-ffi-tests = ["inventory"] +# The following features are auto-detected by the build-script and should not be enabled manually. +bsd = [] + [patch.crates-io] cc = { git = "https://github.com/mqudsi/cc-rs", branch = "fish" } cxx = { git = "https://github.com/fish-shell/cxx", branch = "fish" } diff --git a/fish-rust/build.rs b/fish-rust/build.rs index 20a9fa374..6640d8fe1 100644 --- a/fish-rust/build.rs +++ b/fish-rust/build.rs @@ -1,3 +1,5 @@ +use miette::miette; + fn main() -> miette::Result<()> { let rust_dir = std::env::var("CARGO_MANIFEST_DIR").expect("Env var CARGO_MANIFEST_DIR missing"); let target_dir = @@ -15,6 +17,8 @@ fn main() -> miette::Result<()> { let autocxx_gen_dir = std::env::var("FISH_AUTOCXX_GEN_DIR") .unwrap_or(format!("{}/{}", fish_build_dir, "fish-autocxx-gen/")); + detect_features(); + // Emit cxx junk. // This allows "Rust to be used from C++" // This must come before autocxx so that cxx can emit its cxx.h header. @@ -68,3 +72,39 @@ fn main() -> miette::Result<()> { Ok(()) } + +/// Dynamically enables certain features at build-time, without their having to be explicitly +/// enabled in the `cargo build --features xxx` invocation. +/// +/// This can be used to enable features that we check for and conditionally compile according to in +/// our own codebase, but [can't be used to pull in dependencies](0) even if they're gated (in +/// `Cargo.toml`) behind a feature we just enabled. +/// +/// [0]: https://github.com/rust-lang/cargo/issues/5499 +fn detect_features() { + for (feature, detector) in [ + ("bsd", detect_bsd), + ] + { + match detector() { + Err(e) => eprintln!("{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. +/// +/// 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)) +}