diff --git a/crates/tauri-bundler/src/bundle/linux/appimage.rs b/crates/tauri-bundler/src/bundle/linux/appimage.rs index 02fe710d394a..533f3fbe0a90 100644 --- a/crates/tauri-bundler/src/bundle/linux/appimage.rs +++ b/crates/tauri-bundler/src/bundle/linux/appimage.rs @@ -12,7 +12,6 @@ use crate::{ use anyhow::Context; use std::{ fs, - io::Write, path::{Path, PathBuf}, process::Command, }; diff --git a/crates/tauri-bundler/src/bundle/macos/dmg/mod.rs b/crates/tauri-bundler/src/bundle/macos/dmg/mod.rs index 7df50a055276..747b3963c09c 100644 --- a/crates/tauri-bundler/src/bundle/macos/dmg/mod.rs +++ b/crates/tauri-bundler/src/bundle/macos/dmg/mod.rs @@ -178,7 +178,6 @@ pub fn bundle_project(settings: &Settings, bundles: &[Bundle]) -> crate::Result< if let Some(value) = env::var_os("CI") { if value == "true" { bundle_dmg_cmd.arg("--skip-jenkins"); - } else { } } } diff --git a/crates/tauri-cli/src/dev.rs b/crates/tauri-cli/src/dev.rs index fdeaabe9cea0..09e7a4b67ad5 100644 --- a/crates/tauri-cli/src/dev.rs +++ b/crates/tauri-cli/src/dev.rs @@ -10,7 +10,7 @@ use crate::{ get as get_config, reload as reload_config, BeforeDevCommand, ConfigHandle, FrontendDist, }, }, - interface::{AppInterface, DevProcess, ExitReason, Interface}, + interface::{AppInterface, ExitReason, Interface}, CommandExt, ConfigValue, Result, }; @@ -338,35 +338,8 @@ pub fn setup(interface: &AppInterface, options: &mut Options, config: ConfigHand Ok(()) } -pub fn wait_dev_process< - C: DevProcess + Send + 'static, - F: Fn(Option, ExitReason) + Send + Sync + 'static, ->( - child: C, - on_exit: F, -) { - std::thread::spawn(move || { - let code = child - .wait() - .ok() - .and_then(|status| status.code()) - .or(Some(1)); - on_exit( - code, - if child.manually_killed_process() { - ExitReason::TriggeredKill - } else { - ExitReason::NormalExit - }, - ); - }); -} - pub fn on_app_exit(code: Option, reason: ExitReason, exit_on_panic: bool, no_watch: bool) { - if no_watch - || (!matches!(reason, ExitReason::TriggeredKill) - && (exit_on_panic || matches!(reason, ExitReason::NormalExit))) - { + if no_watch || exit_on_panic || matches!(reason, ExitReason::NormalExit) { kill_before_dev_process(); exit(code.unwrap_or(0)); } diff --git a/crates/tauri-cli/src/interface/mod.rs b/crates/tauri-cli/src/interface/mod.rs index 3c3bc7b30291..1b2ad7be8a56 100644 --- a/crates/tauri-cli/src/interface/mod.rs +++ b/crates/tauri-cli/src/interface/mod.rs @@ -20,7 +20,10 @@ pub use rust::{MobileOptions, Options, Rust as AppInterface}; pub trait DevProcess { fn kill(&self) -> std::io::Result<()>; fn try_wait(&self) -> std::io::Result>; + // TODO: + #[allow(unused)] fn wait(&self) -> std::io::Result; + #[allow(unused)] fn manually_killed_process(&self) -> bool; } @@ -84,7 +87,7 @@ pub trait AppSettings { #[derive(Debug)] pub enum ExitReason { /// Killed manually. - TriggeredKill, + // TriggeredKill, /// App compilation failed. CompilationFailed, /// Regular exit. diff --git a/crates/tauri-cli/src/interface/rust.rs b/crates/tauri-cli/src/interface/rust.rs index 918729a30862..b6542466da18 100644 --- a/crates/tauri-cli/src/interface/rust.rs +++ b/crates/tauri-cli/src/interface/rust.rs @@ -363,6 +363,7 @@ fn lookup(dir: &Path, mut f: F) { } fn shared_options( + desktop_dev: bool, mobile: bool, args: &mut Vec, features: &mut Option>, @@ -374,7 +375,9 @@ fn shared_options( .get_or_insert(Vec::new()) .push("tauri/rustls-tls".into()); } else { - args.push("--bins".into()); + if !desktop_dev { + args.push("--bins".into()); + } let all_features = app_settings .manifest .lock() @@ -408,7 +411,7 @@ fn dev_options( } *args = dev_args; - shared_options(mobile, args, features, app_settings); + shared_options(true, mobile, args, features, app_settings); if !args.contains(&"--no-default-features".into()) { let manifest_features = app_settings.manifest.lock().unwrap().features(); @@ -488,7 +491,7 @@ impl Rust { features .get_or_insert(Vec::new()) .push("tauri/custom-protocol".into()); - shared_options(mobile, args, features, &self.app_settings); + shared_options(false, mobile, args, features, &self.app_settings); } fn run_dev, ExitReason) + Send + Sync + 'static>( @@ -502,8 +505,6 @@ impl Rust { run_args, &mut self.available_targets, self.config_features.clone(), - &self.app_settings, - self.main_binary_name.clone(), on_exit, ) .map(|c| Box::new(c) as Box) diff --git a/crates/tauri-cli/src/interface/rust/desktop.rs b/crates/tauri-cli/src/interface/rust/desktop.rs index a1825fff99cd..70fbbea511c6 100644 --- a/crates/tauri-cli/src/interface/rust/desktop.rs +++ b/crates/tauri-cli/src/interface/rust/desktop.rs @@ -20,39 +20,22 @@ use std::{ pub struct DevChild { manually_killed_app: Arc, - build_child: Option>, - app_child: Arc>>>, + dev_child: Arc, } impl DevProcess for DevChild { fn kill(&self) -> std::io::Result<()> { - if let Some(child) = &*self.app_child.lock().unwrap() { - child.kill()?; - } else if let Some(child) = &self.build_child { - child.kill()?; - } + self.dev_child.kill()?; self.manually_killed_app.store(true, Ordering::Relaxed); Ok(()) } fn try_wait(&self) -> std::io::Result> { - if let Some(child) = &*self.app_child.lock().unwrap() { - child.try_wait() - } else if let Some(child) = &self.build_child { - child.try_wait() - } else { - unreachable!() - } + self.dev_child.try_wait() } fn wait(&self) -> std::io::Result { - if let Some(child) = &*self.app_child.lock().unwrap() { - child.wait() - } else if let Some(child) = &self.build_child { - child.wait() - } else { - unreachable!() - } + self.dev_child.wait() } fn manually_killed_process(&self) -> bool { @@ -65,122 +48,12 @@ pub fn run_dev, ExitReason) + Send + Sync + 'static>( run_args: Vec, available_targets: &mut Option>, config_features: Vec, - app_settings: &RustAppSettings, - main_binary_name: Option, on_exit: F, ) -> crate::Result { - let bin_path = app_settings.app_binary_path(&options)?; - - let manually_killed_app = Arc::new(AtomicBool::default()); - let manually_killed_app_ = manually_killed_app.clone(); - let app_child = Arc::new(Mutex::new(None)); - let app_child_ = app_child.clone(); - - let build_child = build_dev_app( - options, - available_targets, - config_features, - move |status, reason| { - if status == Some(0) { - let main_binary_name = main_binary_name.as_deref(); - let bin_path = rename_app(bin_path, main_binary_name).expect("failed to rename app"); - - let mut app = Command::new(bin_path); - app.stdout(os_pipe::dup_stdout().unwrap()); - app.stderr(os_pipe::dup_stderr().unwrap()); - app.args(run_args); - let app_child = Arc::new(SharedChild::spawn(&mut app).unwrap()); - crate::dev::wait_dev_process( - DevChild { - manually_killed_app: manually_killed_app_, - build_child: None, - app_child: Arc::new(Mutex::new(Some(app_child.clone()))), - }, - on_exit, - ); - - app_child_.lock().unwrap().replace(app_child); - } else { - on_exit( - status, - if manually_killed_app_.load(Ordering::Relaxed) { - ExitReason::TriggeredKill - } else { - reason - }, - ); - } - }, - )?; - - Ok(DevChild { - manually_killed_app, - build_child: Some(build_child), - app_child, - }) -} - -pub fn build( - options: Options, - app_settings: &RustAppSettings, - available_targets: &mut Option>, - config_features: Vec, - main_binary_name: Option<&str>, -) -> crate::Result { - let out_dir = app_settings.out_dir(&options)?; - let bin_path = app_settings.app_binary_path(&options)?; - - if !std::env::var("STATIC_VCRUNTIME").map_or(false, |v| v == "false") { - std::env::set_var("STATIC_VCRUNTIME", "true"); - } - - if options.target == Some("universal-apple-darwin".into()) { - std::fs::create_dir_all(&out_dir).with_context(|| "failed to create project out directory")?; - - let bin_name = bin_path.file_stem().unwrap(); - - let mut lipo_cmd = Command::new("lipo"); - lipo_cmd - .arg("-create") - .arg("-output") - .arg(out_dir.join(bin_name)); - for triple in ["aarch64-apple-darwin", "x86_64-apple-darwin"] { - let mut options = options.clone(); - options.target.replace(triple.into()); - - let triple_out_dir = app_settings - .out_dir(&options) - .with_context(|| format!("failed to get {triple} out dir"))?; - - build_production_app(options, available_targets, config_features.clone()) - .with_context(|| format!("failed to build {triple} binary"))?; - - lipo_cmd.arg(triple_out_dir.join(bin_name)); - } - - let lipo_status = lipo_cmd.output_ok()?.status; - if !lipo_status.success() { - return Err(anyhow::anyhow!(format!( - "Result of `lipo` command was unsuccessful: {lipo_status}. (Is `lipo` installed?)" - ))); - } - } else { - build_production_app(options, available_targets, config_features) - .with_context(|| "failed to build app")?; - } - - rename_app(bin_path, main_binary_name) -} + let mut dev_cmd = cargo_command(true, options, available_targets, config_features)?; + let runner = dev_cmd.get_program().to_string_lossy().into_owned(); -fn build_dev_app, ExitReason) + Send + 'static>( - options: Options, - available_targets: &mut Option>, - config_features: Vec, - on_exit: F, -) -> crate::Result> { - let mut build_cmd = build_command(options, available_targets, config_features)?; - let runner = build_cmd.get_program().to_string_lossy().into_owned(); - build_cmd + dev_cmd .env( "CARGO_TERM_PROGRESS_WIDTH", terminal::stderr_width() @@ -195,13 +68,17 @@ fn build_dev_app, ExitReason) + Send + 'static>( .to_string(), ) .env("CARGO_TERM_PROGRESS_WHEN", "always"); - build_cmd.arg("--color"); - build_cmd.arg("always"); + dev_cmd.arg("--color"); + dev_cmd.arg("always"); - build_cmd.stdout(os_pipe::dup_stdout()?); - build_cmd.stderr(Stdio::piped()); + // TODO: double check this + dev_cmd.stdout(os_pipe::dup_stdout()?); + dev_cmd.stderr(Stdio::piped()); - let build_child = match SharedChild::spawn(&mut build_cmd) { + dev_cmd.arg("--"); + dev_cmd.args(run_args); + + let dev_child = match SharedChild::spawn(&mut dev_cmd) { Ok(c) => Ok(c), Err(e) if e.kind() == ErrorKind::NotFound => Err(anyhow::anyhow!( "`{}` command not found.{}", @@ -214,9 +91,9 @@ fn build_dev_app, ExitReason) + Send + 'static>( )), Err(e) => Err(e.into()), }?; - let build_child = Arc::new(build_child); - let build_child_stderr = build_child.take_stderr().unwrap(); - let mut stderr = BufReader::new(build_child_stderr); + let dev_child = Arc::new(dev_child); + let dev_child_stderr = dev_child.take_stderr().unwrap(); + let mut stderr = BufReader::new(dev_child_stderr); let stderr_lines = Arc::new(Mutex::new(Vec::new())); let stderr_lines_ = stderr_lines.clone(); std::thread::spawn(move || { @@ -232,10 +109,9 @@ fn build_dev_app, ExitReason) + Send + 'static>( lines.push(String::from_utf8_lossy(&buf).into_owned()); } }); - - let build_child_ = build_child.clone(); + let dev_child_ = dev_child.clone(); std::thread::spawn(move || { - let status = build_child_.wait().expect("failed to build app"); + let status = dev_child_.wait().expect("failed to build app"); if status.success() { on_exit(status.code(), ExitReason::NormalExit); @@ -259,7 +135,65 @@ fn build_dev_app, ExitReason) + Send + 'static>( } }); - Ok(build_child) + // TODO: remove this and DevChild (requires refactor for code shared between mobile and desktop) + let manually_killed_app = Arc::new(AtomicBool::default()); + + Ok(DevChild { + manually_killed_app, + dev_child, + }) +} + +pub fn build( + options: Options, + app_settings: &RustAppSettings, + available_targets: &mut Option>, + config_features: Vec, + main_binary_name: Option<&str>, +) -> crate::Result { + let out_dir = app_settings.out_dir(&options)?; + let bin_path = app_settings.app_binary_path(&options)?; + + if !std::env::var("STATIC_VCRUNTIME").map_or(false, |v| v == "false") { + std::env::set_var("STATIC_VCRUNTIME", "true"); + } + + if options.target == Some("universal-apple-darwin".into()) { + std::fs::create_dir_all(&out_dir).with_context(|| "failed to create project out directory")?; + + let bin_name = bin_path.file_stem().unwrap(); + + let mut lipo_cmd = Command::new("lipo"); + lipo_cmd + .arg("-create") + .arg("-output") + .arg(out_dir.join(bin_name)); + for triple in ["aarch64-apple-darwin", "x86_64-apple-darwin"] { + let mut options = options.clone(); + options.target.replace(triple.into()); + + let triple_out_dir = app_settings + .out_dir(&options) + .with_context(|| format!("failed to get {triple} out dir"))?; + + build_production_app(options, available_targets, config_features.clone()) + .with_context(|| format!("failed to build {triple} binary"))?; + + lipo_cmd.arg(triple_out_dir.join(bin_name)); + } + + let lipo_status = lipo_cmd.output_ok()?.status; + if !lipo_status.success() { + return Err(anyhow::anyhow!(format!( + "Result of `lipo` command was unsuccessful: {lipo_status}. (Is `lipo` installed?)" + ))); + } + } else { + build_production_app(options, available_targets, config_features) + .with_context(|| "failed to build app")?; + } + + rename_app(bin_path, main_binary_name) } fn build_production_app( @@ -267,7 +201,7 @@ fn build_production_app( available_targets: &mut Option>, config_features: Vec, ) -> crate::Result<()> { - let mut build_cmd = build_command(options, available_targets, config_features)?; + let mut build_cmd = cargo_command(false, options, available_targets, config_features)?; let runner = build_cmd.get_program().to_string_lossy().into_owned(); match build_cmd.piped() { Ok(status) if status.success() => Ok(()), @@ -285,13 +219,17 @@ fn build_production_app( } } -fn build_command( +fn cargo_command( + dev: bool, options: Options, available_targets: &mut Option>, config_features: Vec, ) -> crate::Result { let runner = options.runner.unwrap_or_else(|| "cargo".into()); + let mut build_cmd = Command::new(runner); + build_cmd.arg(if dev { "run" } else { "build" }); + if let Some(target) = &options.target { if available_targets.is_none() { *available_targets = fetch_available_targets(); @@ -299,33 +237,26 @@ fn build_command( validate_target(available_targets, target)?; } - let mut args = Vec::new(); - if !options.args.is_empty() { - args.extend(options.args); - } + build_cmd.args(&options.args); let mut features = config_features; if let Some(f) = options.features { features.extend(f); } if !features.is_empty() { - args.push("--features".into()); - args.push(features.join(",")); + build_cmd.arg("--features"); + build_cmd.arg(features.join(",")); } - if !options.debug && !args.contains(&"--profile".to_string()) { - args.push("--release".into()); + if !options.debug && !options.args.contains(&"--profile".to_string()) { + build_cmd.arg("--release"); } if let Some(target) = options.target { - args.push("--target".into()); - args.push(target); + build_cmd.arg("--target"); + build_cmd.arg(target); } - let mut build_cmd = Command::new(runner); - build_cmd.arg("build"); - build_cmd.args(args); - Ok(build_cmd) }