From fac4300d29d04daec4e4e9e7c67561beec708fcc Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Sun, 31 Aug 2025 11:04:20 -0300 Subject: [PATCH 1/4] feat(cli): prompt to install iOS runtime if needed, closes #9186 --- .changes/install-ios-platform.md | 6 ++++++ crates/tauri-cli/src/mobile/ios/mod.rs | 13 +++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 .changes/install-ios-platform.md diff --git a/.changes/install-ios-platform.md b/.changes/install-ios-platform.md new file mode 100644 index 000000000000..a87b6229d767 --- /dev/null +++ b/.changes/install-ios-platform.md @@ -0,0 +1,6 @@ +--- +"@tauri-apps/cli": minor:enhance +"tauri-cli": minor:enhance +--- + +Prompt to install the iOS platform if it isn't installed yet (no simulator found). diff --git a/crates/tauri-cli/src/mobile/ios/mod.rs b/crates/tauri-cli/src/mobile/ios/mod.rs index 93e2a8edec3e..0423709d7a0e 100644 --- a/crates/tauri-cli/src/mobile/ios/mod.rs +++ b/crates/tauri-cli/src/mobile/ios/mod.rs @@ -367,6 +367,19 @@ fn simulator_prompt(env: &'_ Env, target: Option<&str>) -> Result Date: Sun, 31 Aug 2025 11:24:15 -0300 Subject: [PATCH 2/4] ensure runtime is installed --- crates/tauri-cli/src/mobile/ios/build.rs | 4 ++- crates/tauri-cli/src/mobile/ios/dev.rs | 5 +++- crates/tauri-cli/src/mobile/ios/mod.rs | 36 ++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/crates/tauri-cli/src/mobile/ios/build.rs b/crates/tauri-cli/src/mobile/ios/build.rs index 7145a8ebe93b..c375f138fc7b 100644 --- a/crates/tauri-cli/src/mobile/ios/build.rs +++ b/crates/tauri-cli/src/mobile/ios/build.rs @@ -15,7 +15,7 @@ use crate::{ flock, }, interface::{AppInterface, Interface, Options as InterfaceOptions}, - mobile::{write_options, CliOptions}, + mobile::{ios::ensure_ios_runtime_installed, write_options, CliOptions}, ConfigValue, Result, }; use clap::{ArgAction, Parser, ValueEnum}; @@ -224,6 +224,8 @@ pub fn command(options: Options, noise_level: NoiseLevel) -> Result<()> { let mut env = env()?; + ensure_ios_runtime_installed()?; + let mut export_options_plist = plist::Dictionary::new(); if let Some(method) = options.export_method { let xcode_version = diff --git a/crates/tauri-cli/src/mobile/ios/dev.rs b/crates/tauri-cli/src/mobile/ios/dev.rs index 67608a84de35..4401120d4f05 100644 --- a/crates/tauri-cli/src/mobile/ios/dev.rs +++ b/crates/tauri-cli/src/mobile/ios/dev.rs @@ -15,7 +15,8 @@ use crate::{ }, interface::{AppInterface, Interface, MobileOptions, Options as InterfaceOptions}, mobile::{ - use_network_address_for_dev_url, write_options, CliOptions, DevChild, DevHost, DevProcess, + ios::ensure_ios_runtime_installed, use_network_address_for_dev_url, write_options, CliOptions, + DevChild, DevHost, DevProcess, }, ConfigValue, Result, }; @@ -166,6 +167,8 @@ fn run_command(options: Options, noise_level: NoiseLevel) -> Result<()> { } }; + ensure_ios_runtime_installed()?; + let mut dev_options: DevOptions = options.clone().into(); let target_triple = device .as_ref() diff --git a/crates/tauri-cli/src/mobile/ios/mod.rs b/crates/tauri-cli/src/mobile/ios/mod.rs index 0423709d7a0e..24d5e78424b8 100644 --- a/crates/tauri-cli/src/mobile/ios/mod.rs +++ b/crates/tauri-cli/src/mobile/ios/mod.rs @@ -19,6 +19,7 @@ use cargo_mobile2::{ util::{prompt, relativize_path}, }; use clap::{Parser, Subcommand}; +use serde::Deserialize; use sublime_fuzzy::best_match; use tauri_utils::resources::ResourcePaths; @@ -325,12 +326,23 @@ fn connected_device_prompt<'a>(env: &'_ Env, target: Option<&str>) -> Result, +} + +#[derive(Deserialize)] +struct InstalledRuntime { + name: String, +} + fn simulator_prompt(env: &'_ Env, target: Option<&str>) -> Result { let simulator_list = device::list_simulators(env).map_err(|cause| { anyhow::anyhow!("Failed to detect connected iOS Simulator devices: {cause}") @@ -395,6 +407,30 @@ fn device_prompt<'a>(env: &'_ Env, target: Option<&str>) -> Result> { } } +fn ensure_ios_runtime_installed() -> Result<()> { + let installed_platforms_json = + duct::cmd("xcrun", ["simctl", "list", "runtimes", "--json"]).read()?; + let installed_platforms: InstalledRuntimesList = + serde_json::from_str(&installed_platforms_json).unwrap_or_default(); + if !installed_platforms.runtimes.iter().any(|r| r.name == "iOS") { + log::warn!("iOS platform not installed"); + let install_ios = crate::helpers::prompts::confirm( + "Would you like to install the latest iOS runtime?", + Some(false), + ) + .unwrap_or_default(); + if install_ios { + duct::cmd("xcodebuild", ["-downloadPlatform", "iOS"]) + .stdout_file(os_pipe::dup_stdout().unwrap()) + .stderr_file(os_pipe::dup_stderr().unwrap()) + .run()?; + } else { + anyhow::bail!("iOS platform not installed"); + } + } + Ok(()) +} + fn detect_target_ok<'a>(env: &Env) -> Option<&'a Target<'a>> { device_prompt(env, None).map(|device| device.target()).ok() } From f0706c4d0d8b3730593fb92bf3feee8919469421 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Sun, 31 Aug 2025 11:25:26 -0300 Subject: [PATCH 3/4] only when running directly --- .changes/install-ios-platform.md | 2 +- crates/tauri-cli/src/mobile/ios/build.rs | 4 +++- crates/tauri-cli/src/mobile/ios/dev.rs | 4 +++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.changes/install-ios-platform.md b/.changes/install-ios-platform.md index a87b6229d767..907f411e5da9 100644 --- a/.changes/install-ios-platform.md +++ b/.changes/install-ios-platform.md @@ -3,4 +3,4 @@ "tauri-cli": minor:enhance --- -Prompt to install the iOS platform if it isn't installed yet (no simulator found). +Prompt to install the iOS platform if it isn't installed yet. diff --git a/crates/tauri-cli/src/mobile/ios/build.rs b/crates/tauri-cli/src/mobile/ios/build.rs index c375f138fc7b..4f0de4f37757 100644 --- a/crates/tauri-cli/src/mobile/ios/build.rs +++ b/crates/tauri-cli/src/mobile/ios/build.rs @@ -224,7 +224,9 @@ pub fn command(options: Options, noise_level: NoiseLevel) -> Result<()> { let mut env = env()?; - ensure_ios_runtime_installed()?; + if !options.open { + ensure_ios_runtime_installed()?; + } let mut export_options_plist = plist::Dictionary::new(); if let Some(method) = options.export_method { diff --git a/crates/tauri-cli/src/mobile/ios/dev.rs b/crates/tauri-cli/src/mobile/ios/dev.rs index 4401120d4f05..5b48e710176b 100644 --- a/crates/tauri-cli/src/mobile/ios/dev.rs +++ b/crates/tauri-cli/src/mobile/ios/dev.rs @@ -167,7 +167,9 @@ fn run_command(options: Options, noise_level: NoiseLevel) -> Result<()> { } }; - ensure_ios_runtime_installed()?; + if device.is_some() { + ensure_ios_runtime_installed()?; + } let mut dev_options: DevOptions = options.clone().into(); let target_triple = device From a4a30cc52bd59c7919255afea6fee425973cb530 Mon Sep 17 00:00:00 2001 From: Lucas Nogueira Date: Sun, 31 Aug 2025 15:52:26 -0300 Subject: [PATCH 4/4] use starts_with --- crates/tauri-cli/src/mobile/ios/mod.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/tauri-cli/src/mobile/ios/mod.rs b/crates/tauri-cli/src/mobile/ios/mod.rs index 24d5e78424b8..ea55d9862d59 100644 --- a/crates/tauri-cli/src/mobile/ios/mod.rs +++ b/crates/tauri-cli/src/mobile/ios/mod.rs @@ -412,7 +412,11 @@ fn ensure_ios_runtime_installed() -> Result<()> { duct::cmd("xcrun", ["simctl", "list", "runtimes", "--json"]).read()?; let installed_platforms: InstalledRuntimesList = serde_json::from_str(&installed_platforms_json).unwrap_or_default(); - if !installed_platforms.runtimes.iter().any(|r| r.name == "iOS") { + if !installed_platforms + .runtimes + .iter() + .any(|r| r.name.starts_with("iOS")) + { log::warn!("iOS platform not installed"); let install_ios = crate::helpers::prompts::confirm( "Would you like to install the latest iOS runtime?",