Skip to content

Commit f6622a3

Browse files
authored
feat(cli): prompt to install iOS runtime if needed, closes #9186 (#14129)
* feat(cli): prompt to install iOS runtime if needed, closes #9186 * ensure runtime is installed * only when running directly * use starts_with
1 parent 80eadb7 commit f6622a3

File tree

4 files changed

+70
-2
lines changed

4 files changed

+70
-2
lines changed

.changes/install-ios-platform.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@tauri-apps/cli": minor:enhance
3+
"tauri-cli": minor:enhance
4+
---
5+
6+
Prompt to install the iOS platform if it isn't installed yet.

crates/tauri-cli/src/mobile/ios/build.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use crate::{
1515
flock,
1616
},
1717
interface::{AppInterface, Interface, Options as InterfaceOptions},
18-
mobile::{write_options, CliOptions},
18+
mobile::{ios::ensure_ios_runtime_installed, write_options, CliOptions},
1919
ConfigValue, Result,
2020
};
2121
use clap::{ArgAction, Parser, ValueEnum};
@@ -224,6 +224,10 @@ pub fn command(options: Options, noise_level: NoiseLevel) -> Result<()> {
224224

225225
let mut env = env()?;
226226

227+
if !options.open {
228+
ensure_ios_runtime_installed()?;
229+
}
230+
227231
let mut export_options_plist = plist::Dictionary::new();
228232
if let Some(method) = options.export_method {
229233
let xcode_version =

crates/tauri-cli/src/mobile/ios/dev.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ use crate::{
1515
},
1616
interface::{AppInterface, Interface, MobileOptions, Options as InterfaceOptions},
1717
mobile::{
18-
use_network_address_for_dev_url, write_options, CliOptions, DevChild, DevHost, DevProcess,
18+
ios::ensure_ios_runtime_installed, use_network_address_for_dev_url, write_options, CliOptions,
19+
DevChild, DevHost, DevProcess,
1920
},
2021
ConfigValue, Result,
2122
};
@@ -166,6 +167,10 @@ fn run_command(options: Options, noise_level: NoiseLevel) -> Result<()> {
166167
}
167168
};
168169

170+
if device.is_some() {
171+
ensure_ios_runtime_installed()?;
172+
}
173+
169174
let mut dev_options: DevOptions = options.clone().into();
170175
let target_triple = device
171176
.as_ref()

crates/tauri-cli/src/mobile/ios/mod.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use cargo_mobile2::{
1919
util::{prompt, relativize_path},
2020
};
2121
use clap::{Parser, Subcommand};
22+
use serde::Deserialize;
2223
use sublime_fuzzy::best_match;
2324
use tauri_utils::resources::ResourcePaths;
2425

@@ -325,12 +326,23 @@ fn connected_device_prompt<'a>(env: &'_ Env, target: Option<&str>) -> Result<Dev
325326
device,
326327
device.target().triple,
327328
);
329+
328330
Ok(device)
329331
} else {
330332
Err(anyhow::anyhow!("No connected iOS devices detected"))
331333
}
332334
}
333335

336+
#[derive(Default, Deserialize)]
337+
struct InstalledRuntimesList {
338+
runtimes: Vec<InstalledRuntime>,
339+
}
340+
341+
#[derive(Deserialize)]
342+
struct InstalledRuntime {
343+
name: String,
344+
}
345+
334346
fn simulator_prompt(env: &'_ Env, target: Option<&str>) -> Result<device::Simulator> {
335347
let simulator_list = device::list_simulators(env).map_err(|cause| {
336348
anyhow::anyhow!("Failed to detect connected iOS Simulator devices: {cause}")
@@ -367,6 +379,19 @@ fn simulator_prompt(env: &'_ Env, target: Option<&str>) -> Result<device::Simula
367379
};
368380
Ok(device)
369381
} else {
382+
log::warn!("No available iOS Simulator detected");
383+
let install_ios = crate::helpers::prompts::confirm(
384+
"Would you like to install the latest iOS runtime?",
385+
Some(false),
386+
)
387+
.unwrap_or_default();
388+
if install_ios {
389+
duct::cmd("xcodebuild", ["-downloadPlatform", "iOS"])
390+
.stdout_file(os_pipe::dup_stdout().unwrap())
391+
.stderr_file(os_pipe::dup_stderr().unwrap())
392+
.run()?;
393+
return simulator_prompt(env, target);
394+
}
370395
Err(anyhow::anyhow!("No available iOS Simulator detected"))
371396
}
372397
}
@@ -382,6 +407,34 @@ fn device_prompt<'a>(env: &'_ Env, target: Option<&str>) -> Result<Device<'a>> {
382407
}
383408
}
384409

410+
fn ensure_ios_runtime_installed() -> Result<()> {
411+
let installed_platforms_json =
412+
duct::cmd("xcrun", ["simctl", "list", "runtimes", "--json"]).read()?;
413+
let installed_platforms: InstalledRuntimesList =
414+
serde_json::from_str(&installed_platforms_json).unwrap_or_default();
415+
if !installed_platforms
416+
.runtimes
417+
.iter()
418+
.any(|r| r.name.starts_with("iOS"))
419+
{
420+
log::warn!("iOS platform not installed");
421+
let install_ios = crate::helpers::prompts::confirm(
422+
"Would you like to install the latest iOS runtime?",
423+
Some(false),
424+
)
425+
.unwrap_or_default();
426+
if install_ios {
427+
duct::cmd("xcodebuild", ["-downloadPlatform", "iOS"])
428+
.stdout_file(os_pipe::dup_stdout().unwrap())
429+
.stderr_file(os_pipe::dup_stderr().unwrap())
430+
.run()?;
431+
} else {
432+
anyhow::bail!("iOS platform not installed");
433+
}
434+
}
435+
Ok(())
436+
}
437+
385438
fn detect_target_ok<'a>(env: &Env) -> Option<&'a Target<'a>> {
386439
device_prompt(env, None).map(|device| device.target()).ok()
387440
}

0 commit comments

Comments
 (0)