mirror of
https://github.com/tauri-apps/tauri.git
synced 2024-12-21 17:51:36 +03:00
feat(cli): add option to run on specific iOS simulator/device (#5098)
This commit is contained in:
parent
9f9e3ae54d
commit
68e80ffaa9
2
tooling/cli/Cargo.lock
generated
2
tooling/cli/Cargo.lock
generated
@ -293,7 +293,7 @@ checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c"
|
||||
[[package]]
|
||||
name = "cargo-mobile"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/tauri-apps/cargo-mobile?branch=dev#909edf9337ec0cb42c76e0a34af61e99b15ccfe0"
|
||||
source = "git+https://github.com/tauri-apps/cargo-mobile?branch=dev#ff88cc91fbf008ee0b9b33c8e4bcb5c9b5b743e6"
|
||||
dependencies = [
|
||||
"cocoa",
|
||||
"colored 1.9.3",
|
||||
|
@ -28,7 +28,7 @@ name = "cargo-tauri"
|
||||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
#cargo-mobile = { path = "../../../cargo-mobile/", default-features = false }
|
||||
# cargo-mobile = { path = "../../../cargo-mobile/", default-features = false }
|
||||
cargo-mobile = { git = "https://github.com/tauri-apps/cargo-mobile", branch = "dev", default-features = false }
|
||||
textwrap = { version = "0.11.0", features = ["term_size"] }
|
||||
interprocess = "1"
|
||||
|
@ -209,7 +209,7 @@ fn emulator_prompt(
|
||||
0
|
||||
};
|
||||
|
||||
Ok(emulator_list.iter().nth(index).cloned().unwrap())
|
||||
Ok(emulator_list.into_iter().nth(index).unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@ use cargo_mobile::{
|
||||
Raw as RawAppleConfig,
|
||||
},
|
||||
device::Device,
|
||||
ios_deploy,
|
||||
ios_deploy, simctl,
|
||||
target::Target,
|
||||
},
|
||||
config::app::App,
|
||||
@ -31,6 +31,11 @@ use crate::{
|
||||
Result,
|
||||
};
|
||||
|
||||
use std::{
|
||||
thread::{sleep, spawn},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
mod build;
|
||||
mod dev;
|
||||
mod open;
|
||||
@ -121,19 +126,30 @@ fn with_config<T>(
|
||||
f(&app, &config, &metadata, cli_options)
|
||||
}
|
||||
|
||||
fn device_prompt<'a>(env: &'_ Env) -> Result<Device<'a>, PromptError<ios_deploy::DeviceListError>> {
|
||||
fn ios_deploy_device_prompt<'a>(
|
||||
env: &'_ Env,
|
||||
target: Option<&str>,
|
||||
) -> Result<Device<'a>, PromptError<ios_deploy::DeviceListError>> {
|
||||
let device_list =
|
||||
ios_deploy::device_list(env).map_err(|cause| PromptError::detection_failed("iOS", cause))?;
|
||||
if !device_list.is_empty() {
|
||||
let index = if device_list.len() > 1 {
|
||||
prompt::list(
|
||||
concat!("Detected ", "iOS", " devices"),
|
||||
device_list.iter(),
|
||||
"device",
|
||||
None,
|
||||
"Device",
|
||||
)
|
||||
.map_err(|cause| PromptError::prompt_failed("iOS", cause))?
|
||||
if let Some(t) = target {
|
||||
let t = t.to_lowercase();
|
||||
device_list
|
||||
.iter()
|
||||
.position(|d| d.name().to_lowercase().starts_with(&t))
|
||||
.unwrap_or_default()
|
||||
} else {
|
||||
prompt::list(
|
||||
concat!("Detected ", "iOS", " devices"),
|
||||
device_list.iter(),
|
||||
"device",
|
||||
None,
|
||||
"Device",
|
||||
)
|
||||
.map_err(|cause| PromptError::prompt_failed("iOS", cause))?
|
||||
}
|
||||
} else {
|
||||
0
|
||||
};
|
||||
@ -149,8 +165,55 @@ fn device_prompt<'a>(env: &'_ Env) -> Result<Device<'a>, PromptError<ios_deploy:
|
||||
}
|
||||
}
|
||||
|
||||
fn simulator_prompt(
|
||||
env: &'_ Env,
|
||||
target: Option<&str>,
|
||||
) -> Result<simctl::Device, PromptError<simctl::DeviceListError>> {
|
||||
let simulator_list = simctl::device_list(env)
|
||||
.map_err(|cause| PromptError::detection_failed("iOS Simulator", cause))?;
|
||||
if !simulator_list.is_empty() {
|
||||
let index = if simulator_list.len() > 1 {
|
||||
if let Some(t) = target {
|
||||
let t = t.to_lowercase();
|
||||
simulator_list
|
||||
.iter()
|
||||
.position(|d| d.name().to_lowercase().starts_with(&t))
|
||||
.unwrap_or_default()
|
||||
} else {
|
||||
prompt::list(
|
||||
concat!("Detected ", "iOS", " simulators"),
|
||||
simulator_list.iter(),
|
||||
"simulator",
|
||||
None,
|
||||
"Simulator",
|
||||
)
|
||||
.map_err(|cause| PromptError::prompt_failed("iOS Simulator", cause))?
|
||||
}
|
||||
} else {
|
||||
0
|
||||
};
|
||||
let device = simulator_list.into_iter().nth(index).unwrap();
|
||||
Ok(device)
|
||||
} else {
|
||||
Err(PromptError::none_detected("iOS Simulator"))
|
||||
}
|
||||
}
|
||||
|
||||
fn device_prompt<'a>(env: &'_ Env, target: Option<&str>) -> Result<Device<'a>> {
|
||||
if let Ok(device) = ios_deploy_device_prompt(env, target) {
|
||||
Ok(device)
|
||||
} else {
|
||||
let simulator = simulator_prompt(env, target)?;
|
||||
let handle = simulator.start(env)?;
|
||||
spawn(move || {
|
||||
let _ = handle.wait();
|
||||
});
|
||||
Ok(simulator.into())
|
||||
}
|
||||
}
|
||||
|
||||
fn detect_target_ok<'a>(env: &Env) -> Option<&'a Target<'a>> {
|
||||
device_prompt(env).map(|device| device.target()).ok()
|
||||
device_prompt(env, None).map(|device| device.target()).ok()
|
||||
}
|
||||
|
||||
fn open_and_wait(config: &AppleConfig, env: &Env) -> ! {
|
||||
@ -159,6 +222,6 @@ fn open_and_wait(config: &AppleConfig, env: &Env) -> ! {
|
||||
log::error!("{}", e);
|
||||
}
|
||||
loop {
|
||||
std::thread::sleep(std::time::Duration::from_secs(24 * 60 * 60));
|
||||
sleep(Duration::from_secs(24 * 60 * 60));
|
||||
}
|
||||
}
|
||||
|
@ -10,13 +10,17 @@ use crate::{
|
||||
use clap::Parser;
|
||||
|
||||
use cargo_mobile::{
|
||||
apple::{config::Config as AppleConfig, device::RunError as DeviceRunError, ios_deploy},
|
||||
apple::{config::Config as AppleConfig, device::RunError as DeviceRunError, simctl},
|
||||
config::app::App,
|
||||
device::PromptError,
|
||||
env::Env,
|
||||
opts::{NoiseLevel, Profile},
|
||||
};
|
||||
|
||||
use std::{
|
||||
thread::{sleep, spawn},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Parser)]
|
||||
#[clap(about = "iOS dev")]
|
||||
pub struct Options {
|
||||
@ -38,6 +42,8 @@ pub struct Options {
|
||||
/// Open Xcode instead of trying to run on a connected device
|
||||
#[clap(short, long)]
|
||||
pub open: bool,
|
||||
/// Runs on the given device name
|
||||
pub device: Option<String>,
|
||||
}
|
||||
|
||||
impl From<Options> for crate::dev::Options {
|
||||
@ -92,9 +98,29 @@ fn run_dev(
|
||||
let env = env()?;
|
||||
init_dot_cargo(app, None)?;
|
||||
|
||||
if let Some(device) = &options.device {
|
||||
let simulators = simctl::device_list(&env).unwrap_or_default();
|
||||
for simulator in simulators {
|
||||
if simulator
|
||||
.name()
|
||||
.to_lowercase()
|
||||
.starts_with(&device.to_lowercase())
|
||||
{
|
||||
log::info!("Starting simulator {}", simulator.name());
|
||||
let handle = simulator.start(&env)?;
|
||||
spawn(move || {
|
||||
let _ = handle.wait();
|
||||
});
|
||||
sleep(Duration::from_secs(3));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let open = options.open;
|
||||
let exit_on_panic = options.exit_on_panic;
|
||||
let no_watch = options.no_watch;
|
||||
let device = options.device;
|
||||
interface.mobile_dev(
|
||||
MobileOptions {
|
||||
debug: true,
|
||||
@ -115,7 +141,7 @@ fn run_dev(
|
||||
if open {
|
||||
open_and_wait(config, &env)
|
||||
} else {
|
||||
match run(options, config, &env, noise_level) {
|
||||
match run(device.as_deref(), options, config, &env, noise_level) {
|
||||
Ok(c) => {
|
||||
crate::dev::wait_dev_process(c.clone(), move |status, reason| {
|
||||
crate::dev::on_app_exit(status, reason, exit_on_panic, no_watch)
|
||||
@ -135,12 +161,13 @@ fn run_dev(
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
enum RunError {
|
||||
#[error(transparent)]
|
||||
FailedToPromptForDevice(PromptError<ios_deploy::DeviceListError>),
|
||||
#[error("{0}")]
|
||||
FailedToPromptForDevice(String),
|
||||
#[error(transparent)]
|
||||
RunFailed(DeviceRunError),
|
||||
}
|
||||
fn run(
|
||||
device: Option<&str>,
|
||||
options: MobileOptions,
|
||||
config: &AppleConfig,
|
||||
env: &Env,
|
||||
@ -154,8 +181,8 @@ fn run(
|
||||
|
||||
let non_interactive = true; // ios-deploy --noninteractive (quit when app crashes or exits)
|
||||
|
||||
device_prompt(env)
|
||||
.map_err(RunError::FailedToPromptForDevice)?
|
||||
device_prompt(env, device)
|
||||
.map_err(|e| RunError::FailedToPromptForDevice(e.to_string()))?
|
||||
.run(config, env, noise_level, non_interactive, profile)
|
||||
.map(DevChild::new)
|
||||
.map_err(RunError::RunFailed)
|
||||
|
@ -50,7 +50,11 @@ pub fn gen(
|
||||
let ios_pods = metadata.ios().pods().unwrap_or_default();
|
||||
let macos_pods = metadata.macos().pods().unwrap_or_default();
|
||||
|
||||
let default_archs = [String::from("arm64"), String::from("x86_64")];
|
||||
let default_archs = [
|
||||
String::from("arm64"),
|
||||
String::from("arm64-sim"),
|
||||
String::from("x86_64"),
|
||||
];
|
||||
|
||||
map.insert("file-groups", &source_dirs);
|
||||
map.insert("ios-frameworks", metadata.ios().frameworks());
|
||||
|
@ -100,6 +100,7 @@ pub fn command(options: Options) -> Result<()> {
|
||||
// Set target-specific flags
|
||||
let triple = match arch.as_str() {
|
||||
"arm64" => "aarch64_apple_ios",
|
||||
"arm64-sim" => "aarch64_apple_ios_sim",
|
||||
"x86_64" => "x86_64_apple_ios",
|
||||
_ => {
|
||||
return Err(anyhow::anyhow!(
|
||||
|
@ -72,7 +72,7 @@ targets:
|
||||
ARCHS: [{{join ios-valid-archs}}]
|
||||
VALID_ARCHS: {{~#each ios-valid-archs}} {{this}} {{/each}}
|
||||
LIBRARY_SEARCH_PATHS[sdk=iphoneos*]: $(inherited) "{{prefix-path "target/aarch64-apple-ios/$(CONFIGURATION)"}}"
|
||||
LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*]: $(inherited) "{{prefix-path "target/x86_64-apple-ios/$(CONFIGURATION)"}}"
|
||||
LIBRARY_SEARCH_PATHS[sdk=iphonesimulator*]: $(inherited) "{{prefix-path "target/aarch64-apple-ios-sim/$(CONFIGURATION)"}}"
|
||||
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES: true
|
||||
groups: [app]
|
||||
dependencies:
|
||||
|
Loading…
Reference in New Issue
Block a user