From 24ab294cda77c52cc8918c9dcd39b1cfc216ebd7 Mon Sep 17 00:00:00 2001 From: Piepmatz Date: Thu, 19 Jun 2025 12:58:37 +0200 Subject: [PATCH] Use `CARGO_CFG_FEATURE` to get feature list in `version` (#15972) --- Cargo.toml | 12 ++- crates/nu-cmd-lang/Cargo.toml | 5 -- crates/nu-cmd-lang/src/core_commands/mod.rs | 2 +- .../nu-cmd-lang/src/core_commands/version.rs | 83 +++++++++++-------- scripts/build.rs | 38 +++++---- src/main.rs | 8 +- 6 files changed, 86 insertions(+), 62 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d10a58251a..a960fab6d4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -264,12 +264,11 @@ full = ["plugin", "rustls-tls", "system-clipboard", "trash-support", "sqlite"] plugin = [ # crates - "nu-cmd-plugin", - "nu-plugin-engine", + "dep:nu-cmd-plugin", + "dep:nu-plugin-engine", # features "nu-cli/plugin", - "nu-cmd-lang/plugin", "nu-command/plugin", "nu-engine/plugin", "nu-engine/plugin", @@ -291,21 +290,20 @@ stable = ["default"] # Enable to statically link OpenSSL (perl is required, to build OpenSSL https://docs.rs/openssl/latest/openssl/); # otherwise the system version will be used. Not enabled by default because it takes a while to build -static-link-openssl = ["dep:openssl", "nu-cmd-lang/static-link-openssl"] +static-link-openssl = ["dep:openssl"] # Optional system clipboard support in `reedline`, this behavior has problematic compatibility with some systems. # Missing X server/ Wayland can cause issues system-clipboard = [ "reedline/system_clipboard", "nu-cli/system-clipboard", - "nu-cmd-lang/system-clipboard", ] # Stable (Default) -trash-support = ["nu-command/trash-support", "nu-cmd-lang/trash-support"] +trash-support = ["nu-command/trash-support"] # SQLite commands for nushell -sqlite = ["nu-command/sqlite", "nu-cmd-lang/sqlite", "nu-std/sqlite"] +sqlite = ["nu-command/sqlite", "nu-std/sqlite"] [profile.release] opt-level = "s" # Optimize for size diff --git a/crates/nu-cmd-lang/Cargo.toml b/crates/nu-cmd-lang/Cargo.toml index 582a91ed62..0f371cce50 100644 --- a/crates/nu-cmd-lang/Cargo.toml +++ b/crates/nu-cmd-lang/Cargo.toml @@ -43,8 +43,3 @@ plugin = [ "nu-protocol/plugin", "os", ] - -trash-support = [] -sqlite = [] -static-link-openssl = [] -system-clipboard = [] diff --git a/crates/nu-cmd-lang/src/core_commands/mod.rs b/crates/nu-cmd-lang/src/core_commands/mod.rs index 7ec42ea379..dd54fff9f7 100644 --- a/crates/nu-cmd-lang/src/core_commands/mod.rs +++ b/crates/nu-cmd-lang/src/core_commands/mod.rs @@ -69,5 +69,5 @@ pub use return_::Return; pub use scope::*; pub use try_::Try; pub use use_::Use; -pub use version::Version; +pub use version::{VERSION_NU_FEATURES, Version}; pub use while_::While; diff --git a/crates/nu-cmd-lang/src/core_commands/version.rs b/crates/nu-cmd-lang/src/core_commands/version.rs index 5ea4cfb4be..eee2d344eb 100644 --- a/crates/nu-cmd-lang/src/core_commands/version.rs +++ b/crates/nu-cmd-lang/src/core_commands/version.rs @@ -1,11 +1,48 @@ -use std::sync::OnceLock; +use std::{borrow::Cow, sync::OnceLock}; +use itertools::Itertools; use nu_engine::command_prelude::*; use nu_protocol::engine::StateWorkingSet; use shadow_rs::shadow; shadow!(build); +/// Static container for the cargo features used by the `version` command. +/// +/// This `OnceLock` holds the features from `nu`. +/// When you build `nu_cmd_lang`, Cargo doesn't pass along the same features that `nu` itself uses. +/// By setting this static before calling `version`, you make it show `nu`'s features instead +/// of `nu_cmd_lang`'s. +/// +/// Embedders can set this to any feature list they need, but in most cases you'll probably want to +/// pass the cargo features of your host binary. +/// +/// # How to get cargo features in your build script +/// +/// In your binary's build script: +/// ```rust,ignore +/// // Re-export CARGO_CFG_FEATURE to the main binary. +/// // It holds all the features that cargo sets for your binary as a comma-separated list. +/// println!( +/// "cargo:rustc-env=NU_FEATURES={}", +/// std::env::var("CARGO_CFG_FEATURE").expect("set by cargo") +/// ); +/// ``` +/// +/// Then, before you call `version`: +/// ```rust,ignore +/// // This uses static strings, but since we're using `Cow`, you can also pass owned strings. +/// let features = env!("NU_FEATURES") +/// .split(',') +/// .map(Cow::Borrowed) +/// .collect(); +/// +/// nu_cmd_lang::VERSION_NU_FEATURES +/// .set(features) +/// .expect("couldn't set VERSION_NU_FEATURES"); +/// ``` +pub static VERSION_NU_FEATURES: OnceLock>> = OnceLock::new(); + #[derive(Clone)] pub struct Version; @@ -113,7 +150,17 @@ pub fn version(engine_state: &EngineState, span: Span) -> Result &'static str { "standard" } -fn features_enabled() -> Vec { - let mut names = vec!["default".to_string()]; - - // NOTE: There should be another way to know features on. - - #[cfg(feature = "trash-support")] - { - names.push("trash".to_string()); - } - - #[cfg(feature = "sqlite")] - { - names.push("sqlite".to_string()); - } - - #[cfg(feature = "static-link-openssl")] - { - names.push("static-link-openssl".to_string()); - } - - #[cfg(feature = "system-clipboard")] - { - names.push("system-clipboard".to_string()); - } - - names.sort(); - - names -} - #[cfg(test)] mod test { #[test] fn test_examples() { use super::Version; use crate::test_examples; - test_examples(Version {}) + test_examples(Version) } } diff --git a/scripts/build.rs b/scripts/build.rs index 714f931bdd..a7b61bb757 100644 --- a/scripts/build.rs +++ b/scripts/build.rs @@ -1,18 +1,26 @@ -#[cfg(windows)] fn main() { - let mut res = winresource::WindowsResource::new(); - res.set("ProductName", "Nushell"); - res.set("FileDescription", "Nushell"); - res.set("LegalCopyright", "Copyright (C) 2025"); - res.set_icon("assets/nu_logo.ico"); - res.compile() - .expect("Failed to run the Windows resource compiler (rc.exe)"); -} - -#[cfg(not(windows))] -fn main() { - // Tango uses dynamic linking, to allow us to dynamically change between two bench suit at runtime. - // This is currently not supported on non nightly rust, on windows. - println!("cargo:rustc-link-arg-benches=-rdynamic"); println!("cargo:rerun-if-changed=scripts/build.rs"); + println!( + "cargo:rustc-env=NU_FEATURES={}", + std::env::var("CARGO_CFG_FEATURE").expect("set by cargo") + ); + + #[cfg(windows)] + { + println!("cargo:rerun-if-changed=assets/nu_logo.ico"); + let mut res = winresource::WindowsResource::new(); + res.set("ProductName", "Nushell"); + res.set("FileDescription", "Nushell"); + res.set("LegalCopyright", "Copyright (C) 2025"); + res.set_icon("assets/nu_logo.ico"); + res.compile() + .expect("Failed to run the Windows resource compiler (rc.exe)"); + } + + #[cfg(not(windows))] + { + // Tango uses dynamic linking, to allow us to dynamically change between two bench suit at runtime. + // This is currently not supported on non nightly rust, on windows. + println!("cargo:rustc-link-arg-benches=-rdynamic"); + } } diff --git a/src/main.rs b/src/main.rs index 09d53b1ebf..ec8bce7cfb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -29,7 +29,7 @@ use nu_std::load_standard_library; use nu_utils::perf; use run::{run_commands, run_file, run_repl}; use signals::ctrlc_protection; -use std::{path::PathBuf, str::FromStr, sync::Arc}; +use std::{borrow::Cow, path::PathBuf, str::FromStr, sync::Arc}; /// Get the directory where the Nushell executable is located. fn current_exe_directory() -> PathBuf { @@ -64,6 +64,12 @@ fn main() -> Result<()> { let mut engine_state = command_context::get_engine_state(); + // Provide `version` the features of this nu binary + let cargo_features = env!("NU_FEATURES").split(",").map(Cow::Borrowed).collect(); + nu_cmd_lang::VERSION_NU_FEATURES + .set(cargo_features) + .expect("unable to set VERSION_NU_FEATURES"); + // Get the current working directory from the environment. let init_cwd = current_dir_from_environment();