diff --git a/.changes/empty-vec-instead-of-none.md b/.changes/empty-vec-instead-of-none.md new file mode 100644 index 000000000..6b0dd9fd9 --- /dev/null +++ b/.changes/empty-vec-instead-of-none.md @@ -0,0 +1,6 @@ +--- +"@tauri-apps/cli": patch:enhance +"tauri-cli": patch:enhance +--- + +Simplified internal representation of `features: Option>` with `Vec`, no user facing changes diff --git a/crates/tauri-cli/src/build.rs b/crates/tauri-cli/src/build.rs index ac8c5552a..0bd5a5320 100644 --- a/crates/tauri-cli/src/build.rs +++ b/crates/tauri-cli/src/build.rs @@ -40,7 +40,7 @@ pub struct Options { pub target: Option, /// Space or comma separated list of features to activate #[clap(short, long, action = ArgAction::Append, num_args(0..))] - pub features: Option>, + pub features: Vec, /// Space or comma separated list of bundles to package. #[clap(short, long, action = ArgAction::Append, num_args(0..), value_delimiter = ',')] pub bundles: Option>, @@ -252,8 +252,7 @@ pub fn setup( options .features - .get_or_insert(Vec::new()) - .extend(config.build.features.clone().unwrap_or_default()); + .extend_from_slice(config.build.features.as_deref().unwrap_or_default()); interface.build_options(&mut options.args, &mut options.features, mobile); Ok(()) diff --git a/crates/tauri-cli/src/bundle.rs b/crates/tauri-cli/src/bundle.rs index 646f44ddb..8c1f320b5 100644 --- a/crates/tauri-cli/src/bundle.rs +++ b/crates/tauri-cli/src/bundle.rs @@ -71,7 +71,7 @@ pub struct Options { pub config: Vec, /// Space or comma separated list of features, should be the same features passed to `tauri build` if any. #[clap(short, long, action = ArgAction::Append, num_args(0..))] - pub features: Option>, + pub features: Vec, /// Target triple to build against. /// /// It must be one of the values outputted by `$rustc --print target-list` or `universal-apple-darwin` for an universal macOS application. diff --git a/crates/tauri-cli/src/dev.rs b/crates/tauri-cli/src/dev.rs index 7ebabb458..e2ac61fce 100644 --- a/crates/tauri-cli/src/dev.rs +++ b/crates/tauri-cli/src/dev.rs @@ -57,7 +57,7 @@ pub struct Options { pub target: Option, /// List of cargo features to activate #[clap(short, long, action = ArgAction::Append, num_args(0..))] - pub features: Option>, + pub features: Vec, /// Exit on panic #[clap(short, long)] pub exit_on_panic: bool, @@ -254,9 +254,7 @@ pub fn setup(interface: &AppInterface, options: &mut Options, config: ConfigHand .features .clone() .unwrap_or_default(); - if let Some(features) = &options.features { - cargo_features.extend(features.clone()); - } + cargo_features.extend(options.features.clone()); let mut dev_url = config .lock() diff --git a/crates/tauri-cli/src/interface/mod.rs b/crates/tauri-cli/src/interface/mod.rs index 00ca4c3d1..b153b33bf 100644 --- a/crates/tauri-cli/src/interface/mod.rs +++ b/crates/tauri-cli/src/interface/mod.rs @@ -46,7 +46,7 @@ pub trait AppSettings { package_types: Vec, ) -> crate::Result { let no_default_features = options.args.contains(&"--no-default-features".into()); - let mut enabled_features = options.features.clone().unwrap_or_default(); + let mut enabled_features = options.features.clone(); if !no_default_features { enabled_features.push("default".into()); } diff --git a/crates/tauri-cli/src/interface/rust.rs b/crates/tauri-cli/src/interface/rust.rs index 0f7d2fd02..801e18767 100644 --- a/crates/tauri-cli/src/interface/rust.rs +++ b/crates/tauri-cli/src/interface/rust.rs @@ -51,7 +51,7 @@ pub struct Options { pub runner: Option, pub debug: bool, pub target: Option, - pub features: Option>, + pub features: Vec, pub args: Vec, pub config: Vec, pub no_watch: bool, @@ -108,7 +108,7 @@ impl From for Options { #[derive(Debug, Clone)] pub struct MobileOptions { pub debug: bool, - pub features: Option>, + pub features: Vec, pub args: Vec, pub config: Vec, pub no_watch: bool, @@ -393,7 +393,7 @@ fn dev_options( mobile: bool, args: &mut Vec, run_args: &mut Vec, - features: &mut Option>, + features: &mut Vec, app_settings: &RustAppSettings, ) { let mut dev_args = Vec::new(); @@ -429,9 +429,7 @@ fn dev_options( }) .collect(); args.push("--no-default-features".into()); - if !enable_features.is_empty() { - features.get_or_insert(Vec::new()).extend(enable_features); - } + features.extend(enable_features); } } @@ -498,15 +496,8 @@ fn get_watch_folders(additional_watch_folders: &[PathBuf]) -> crate::Result, - features: &mut Option>, - mobile: bool, - ) { - features - .get_or_insert(Vec::new()) - .push("tauri/custom-protocol".into()); + pub fn build_options(&self, args: &mut Vec, features: &mut Vec, mobile: bool) { + features.push("tauri/custom-protocol".into()); if mobile { args.push("--lib".into()); } else { @@ -957,11 +948,12 @@ impl AppSettings for RustAppSettings { .clone() .unwrap_or_default(); for bin in bins { - if let (Some(req_features), Some(opt_features)) = - (&bin.required_features, &options.features) - { + if let Some(req_features) = &bin.required_features { // Check if all required features are enabled. - if !req_features.iter().all(|feat| opt_features.contains(feat)) { + if !req_features + .iter() + .all(|feat| options.features.contains(feat)) + { continue; } } diff --git a/crates/tauri-cli/src/interface/rust/desktop.rs b/crates/tauri-cli/src/interface/rust/desktop.rs index e747f236b..b372dc015 100644 --- a/crates/tauri-cli/src/interface/rust/desktop.rs +++ b/crates/tauri-cli/src/interface/rust/desktop.rs @@ -262,9 +262,7 @@ fn cargo_command( build_cmd.args(&options.args); let mut features = config_features; - if let Some(f) = options.features { - features.extend(f); - } + features.extend(options.features); if !features.is_empty() { build_cmd.arg("--features"); build_cmd.arg(features.join(",")); diff --git a/crates/tauri-cli/src/mobile/android/android_studio_script.rs b/crates/tauri-cli/src/mobile/android/android_studio_script.rs index c3dfdff4b..4657ac673 100644 --- a/crates/tauri-cli/src/mobile/android/android_studio_script.rs +++ b/crates/tauri-cli/src/mobile/android/android_studio_script.rs @@ -80,7 +80,7 @@ pub fn command(options: Options) -> Result<()> { &AppInterface::new(tauri_config_, None)?, ), tauri_config_, - None, + &[], &cli_options, ); (config, metadata) diff --git a/crates/tauri-cli/src/mobile/android/build.rs b/crates/tauri-cli/src/mobile/android/build.rs index 4aae6df68..c91ba73c1 100644 --- a/crates/tauri-cli/src/mobile/android/build.rs +++ b/crates/tauri-cli/src/mobile/android/build.rs @@ -48,7 +48,7 @@ pub struct Options { pub targets: Option>, /// List of cargo features to activate #[clap(short, long, action = ArgAction::Append, num_args(0..))] - pub features: Option>, + pub features: Vec, /// JSON strings or paths to JSON, JSON5 or TOML files to merge with the default configuration file /// /// Configurations are merged in the order they are provided, which means a particular value overwrites previous values when a config key-value pair conflicts. @@ -152,7 +152,7 @@ pub fn command(options: Options, noise_level: NoiseLevel) -> Result>, + pub features: Vec, /// Exit on panic #[clap(short, long)] exit_on_panic: bool, diff --git a/crates/tauri-cli/src/mobile/android/mod.rs b/crates/tauri-cli/src/mobile/android/mod.rs index 1990cf2f4..9a73f91e0 100644 --- a/crates/tauri-cli/src/mobile/android/mod.rs +++ b/crates/tauri-cli/src/mobile/android/mod.rs @@ -128,19 +128,14 @@ pub fn command(cli: Cli, verbosity: u8) -> Result<()> { pub fn get_config( app: &App, config: &TauriConfig, - features: Option<&Vec>, + features: &[String], cli_options: &CliOptions, ) -> (AndroidConfig, AndroidMetadata) { let mut android_options = cli_options.clone(); - if let Some(features) = features { - android_options - .features - .get_or_insert(Vec::new()) - .extend_from_slice(features); - } + android_options.features.extend_from_slice(features); let raw = RawAndroidConfig { - features: android_options.features.clone(), + features: Some(android_options.features.clone()), logcat_filter_specs: vec![ "RustStdoutStderr".into(), format!( @@ -161,7 +156,7 @@ pub fn get_config( let metadata = AndroidMetadata { supported: true, cargo_args: Some(android_options.args), - features: android_options.features, + features: Some(android_options.features), ..Default::default() }; @@ -257,8 +252,8 @@ fn ensure_java() -> Result<()> { fn ensure_sdk(non_interactive: bool) -> Result<()> { let android_home = std::env::var_os("ANDROID_HOME") - .map(PathBuf::from) - .or_else(|| std::env::var_os("ANDROID_SDK_ROOT").map(PathBuf::from)); + .or_else(|| std::env::var_os("ANDROID_SDK_ROOT")) + .map(PathBuf::from); if !android_home.as_ref().is_some_and(|v| v.exists()) { log::info!( "ANDROID_HOME {}, trying to locate Android SDK...", @@ -354,8 +349,8 @@ fn ensure_sdk(non_interactive: bool) -> Result<()> { fn ensure_ndk(non_interactive: bool) -> Result<()> { // re-evaluate ANDROID_HOME let android_home = std::env::var_os("ANDROID_HOME") + .or_else(|| std::env::var_os("ANDROID_SDK_ROOT")) .map(PathBuf::from) - .or_else(|| std::env::var_os("ANDROID_SDK_ROOT").map(PathBuf::from)) .context("Failed to locate Android SDK")?; let mut installed_ndks = read_dir(android_home.join("ndk")) .map(|dir| { diff --git a/crates/tauri-cli/src/mobile/android/run.rs b/crates/tauri-cli/src/mobile/android/run.rs index 9c276c4d9..8bab82b84 100644 --- a/crates/tauri-cli/src/mobile/android/run.rs +++ b/crates/tauri-cli/src/mobile/android/run.rs @@ -29,7 +29,7 @@ pub struct Options { pub release: bool, /// List of cargo features to activate #[clap(short, long, action = ArgAction::Append, num_args(0..))] - pub features: Option>, + pub features: Vec, /// JSON strings or paths to JSON, JSON5 or TOML files to merge with the default configuration file /// /// Configurations are merged in the order they are provided, which means a particular value overwrites previous values when a config key-value pair conflicts. diff --git a/crates/tauri-cli/src/mobile/init.rs b/crates/tauri-cli/src/mobile/init.rs index 2a3cab0b4..eef38d1e9 100644 --- a/crates/tauri-cli/src/mobile/init.rs +++ b/crates/tauri-cli/src/mobile/init.rs @@ -135,7 +135,7 @@ pub fn exec( Target::Android => { let _env = super::android::env(non_interactive)?; let (config, metadata) = - super::android::get_config(&app, tauri_config_, None, &Default::default()); + super::android::get_config(&app, tauri_config_, &[], &Default::default()); map.insert("android", &config); super::android::project::gen( &config, @@ -150,7 +150,7 @@ pub fn exec( // Generate Xcode project Target::Ios => { let (config, metadata) = - super::ios::get_config(&app, tauri_config_, None, &Default::default())?; + super::ios::get_config(&app, tauri_config_, &[], &Default::default())?; map.insert("apple", &config); super::ios::project::gen( tauri_config_, diff --git a/crates/tauri-cli/src/mobile/ios/build.rs b/crates/tauri-cli/src/mobile/ios/build.rs index f52f892d1..e8348726b 100644 --- a/crates/tauri-cli/src/mobile/ios/build.rs +++ b/crates/tauri-cli/src/mobile/ios/build.rs @@ -60,7 +60,7 @@ pub struct Options { pub targets: Option>, /// List of cargo features to activate #[clap(short, long, action = ArgAction::Append, num_args(0..))] - pub features: Option>, + pub features: Vec, /// JSON strings or paths to JSON, JSON5 or TOML files to merge with the default configuration file /// /// Configurations are merged in the order they are provided, which means a particular value overwrites previous values when a config key-value pair conflicts. @@ -201,7 +201,7 @@ pub fn command(options: Options, noise_level: NoiseLevel) -> Result>, + pub features: Vec, /// Exit on panic #[clap(short, long)] exit_on_panic: bool, @@ -197,7 +197,7 @@ fn run_command(options: Options, noise_level: NoiseLevel) -> Result<()> { let (config, _metadata) = get_config( &app, tauri_config_, - dev_options.features.as_ref(), + &dev_options.features, &Default::default(), )?; diff --git a/crates/tauri-cli/src/mobile/ios/mod.rs b/crates/tauri-cli/src/mobile/ios/mod.rs index ca4aade41..d589f76a6 100644 --- a/crates/tauri-cli/src/mobile/ios/mod.rs +++ b/crates/tauri-cli/src/mobile/ios/mod.rs @@ -40,7 +40,7 @@ use crate::{ use std::{ env::{set_var, var_os}, fs::create_dir_all, - path::PathBuf, + path::Path, str::FromStr, thread::sleep, time::Duration, @@ -126,16 +126,11 @@ pub fn command(cli: Cli, verbosity: u8) -> Result<()> { pub fn get_config( app: &App, tauri_config: &TauriConfig, - features: Option<&Vec>, + features: &[String], cli_options: &CliOptions, ) -> Result<(AppleConfig, AppleMetadata)> { let mut ios_options = cli_options.clone(); - if let Some(features) = features { - ios_options - .features - .get_or_insert(Vec::new()) - .extend_from_slice(features); - } + ios_options.features.extend_from_slice(features); let bundle_version = if let Some(bundle_version) = tauri_config .bundle @@ -232,7 +227,7 @@ pub fn get_config( } } }), - ios_features: ios_options.features.clone(), + ios_features: Some(ios_options.features.clone()), bundle_version, bundle_version_short, ios_version: Some(tauri_config.bundle.ios.minimum_system_version.clone()), @@ -252,7 +247,7 @@ pub fn get_config( .clone() .unwrap_or_default() { - let framework_path = PathBuf::from(&framework); + let framework_path = Path::new(&framework); let ext = framework_path.extension().unwrap_or_default(); if ext.is_empty() { frameworks.push(framework); @@ -277,7 +272,11 @@ pub fn get_config( supported: true, ios: ApplePlatform { cargo_args: Some(ios_options.args), - features: ios_options.features, + features: if ios_options.features.is_empty() { + None + } else { + Some(ios_options.features) + }, frameworks: Some(frameworks), vendor_frameworks: Some(vendor_frameworks), ..Default::default() diff --git a/crates/tauri-cli/src/mobile/ios/run.rs b/crates/tauri-cli/src/mobile/ios/run.rs index 0ae1cef12..844e2f4c8 100644 --- a/crates/tauri-cli/src/mobile/ios/run.rs +++ b/crates/tauri-cli/src/mobile/ios/run.rs @@ -26,7 +26,7 @@ pub struct Options { pub release: bool, /// List of cargo features to activate #[clap(short, long, action = ArgAction::Append, num_args(0..))] - pub features: Option>, + pub features: Vec, /// JSON strings or paths to JSON, JSON5 or TOML files to merge with the default configuration file /// /// Configurations are merged in the order they are provided, which means a particular value overwrites previous values when a config key-value pair conflicts. @@ -77,7 +77,7 @@ pub fn command(options: Options, noise_level: NoiseLevel) -> Result<()> { super::build::Options { debug: !options.release, targets: Some(vec![]), /* skips IPA build since there's no target */ - features: None, + features: Vec::new(), config: options.config.clone(), build_number: None, open: options.open, diff --git a/crates/tauri-cli/src/mobile/ios/xcode_script.rs b/crates/tauri-cli/src/mobile/ios/xcode_script.rs index 34d697614..25955c5ae 100644 --- a/crates/tauri-cli/src/mobile/ios/xcode_script.rs +++ b/crates/tauri-cli/src/mobile/ios/xcode_script.rs @@ -128,7 +128,7 @@ pub fn command(options: Options) -> Result<()> { &AppInterface::new(tauri_config_, None)?, ), tauri_config_, - None, + &[], &cli_options, )?; (config, metadata) diff --git a/crates/tauri-cli/src/mobile/mod.rs b/crates/tauri-cli/src/mobile/mod.rs index 2a20c66b6..b94543d65 100644 --- a/crates/tauri-cli/src/mobile/mod.rs +++ b/crates/tauri-cli/src/mobile/mod.rs @@ -181,7 +181,7 @@ impl Default for DevHost { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct CliOptions { pub dev: bool, - pub features: Option>, + pub features: Vec, pub args: Vec, pub noise_level: NoiseLevel, pub vars: HashMap, @@ -193,7 +193,7 @@ impl Default for CliOptions { fn default() -> Self { Self { dev: false, - features: None, + features: Vec::new(), args: vec!["--lib".into()], noise_level: Default::default(), vars: Default::default(),