Jelajahi Sumber

fix(cli): config issues on macos (#5075)

Co-authored-by: Lucas Nogueira <lucas@tauri.studio>
Jeffrey Hutchins 2 tahun lalu
induk
melakukan
0a203a13ae

+ 48 - 9
tooling/cli/src/mobile/android.rs

@@ -5,12 +5,12 @@
 use cargo_mobile::{
   android::{
     adb,
-    config::{Config as AndroidConfig, Metadata as AndroidMetadata},
+    config::{Config as AndroidConfig, Metadata as AndroidMetadata, Raw as RawAndroidConfig},
     device::{Device, RunError},
     env::{Env, Error as AndroidEnvError},
     target::{BuildError, Target},
   },
-  config::Config,
+  config::app::App,
   device::PromptError,
   env::Error as EnvError,
   opts::NoiseLevel,
@@ -18,13 +18,17 @@ use cargo_mobile::{
   util::prompt,
 };
 use clap::{Parser, Subcommand};
+use std::env::set_var;
 
 use super::{
-  ensure_init, get_config,
+  ensure_init, get_app,
   init::{command as init_command, init_dot_cargo, Options as InitOptions},
   log_finished, read_options, CliOptions, Target as MobileTarget,
 };
-use crate::{helpers::config::get as get_tauri_config, Result};
+use crate::{
+  helpers::config::{get as get_tauri_config, Config as TauriConfig},
+  Result,
+};
 
 mod android_studio_script;
 mod build;
@@ -97,21 +101,56 @@ pub fn command(cli: Cli, verbosity: usize) -> Result<()> {
   Ok(())
 }
 
+pub fn get_config(
+  app: Option<App>,
+  config: &TauriConfig,
+  cli_options: &CliOptions,
+) -> (App, AndroidConfig, AndroidMetadata) {
+  let app = app.unwrap_or_else(|| get_app(config));
+  let android_options = cli_options.clone();
+
+  let raw = RawAndroidConfig {
+    features: android_options.features.clone(),
+    ..Default::default()
+  };
+  let config = AndroidConfig::from_raw(app.clone(), Some(raw)).unwrap();
+
+  let metadata = AndroidMetadata {
+    supported: true,
+    cargo_args: Some(android_options.args),
+    features: android_options.features,
+    ..Default::default()
+  };
+
+  set_var("WRY_ANDROID_REVERSED_DOMAIN", app.reverse_domain());
+  set_var("WRY_ANDROID_APP_NAME_SNAKE_CASE", app.name());
+  set_var(
+    "WRY_ANDROID_KOTLIN_FILES_OUT_DIR",
+    config.project_dir().join("app/src/main").join(format!(
+      "java/{}/{}",
+      app.reverse_domain().replace('.', "/"),
+      app.name()
+    )),
+  );
+
+  (app, config, metadata)
+}
+
 fn with_config<T>(
   cli_options: Option<CliOptions>,
-  f: impl FnOnce(&Config, &AndroidConfig, &AndroidMetadata, CliOptions) -> Result<T, Error>,
+  f: impl FnOnce(&App, &AndroidConfig, &AndroidMetadata, CliOptions) -> Result<T, Error>,
 ) -> Result<T, Error> {
-  let (config, metadata, cli_options) = {
+  let (app, config, metadata, cli_options) = {
     let tauri_config =
       get_tauri_config(None).map_err(|e| Error::InvalidTauriConfig(e.to_string()))?;
     let tauri_config_guard = tauri_config.lock().unwrap();
     let tauri_config_ = tauri_config_guard.as_ref().unwrap();
     let cli_options =
       cli_options.unwrap_or_else(|| read_options(tauri_config_, MobileTarget::Android));
-    let (config, metadata) = get_config(tauri_config_, &cli_options, MobileTarget::Android);
-    (config, metadata, cli_options)
+    let (app, config, metadata) = get_config(None, tauri_config_, &cli_options);
+    (app, config, metadata, cli_options)
   };
-  f(&config, config.android(), metadata.android(), cli_options)
+  f(&app, &config, &metadata, cli_options)
 }
 
 fn env() -> Result<Env, Error> {

+ 2 - 2
tooling/cli/src/mobile/android/android_studio_script.rs

@@ -32,12 +32,12 @@ pub fn command(options: Options) -> Result<()> {
     Profile::Debug
   };
 
-  with_config(None, |root_conf, config, metadata, cli_options| {
+  with_config(None, |app, config, metadata, cli_options| {
     ensure_init(config.project_dir(), MobileTarget::Android)
       .map_err(|e| Error::ProjectNotInitialized(e.to_string()))?;
 
     let env = env()?;
-    init_dot_cargo(root_conf, Some(&env)).map_err(Error::InitDotCargo)?;
+    init_dot_cargo(app, Some((&env, config))).map_err(Error::InitDotCargo)?;
 
     call_for_targets_with_fallback(
       options.targets.unwrap_or_default().iter(),

+ 2 - 2
tooling/cli/src/mobile/android/build.rs

@@ -71,7 +71,7 @@ pub fn command(options: Options, noise_level: NoiseLevel) -> Result<()> {
   delete_codegen_vars();
   with_config(
     Some(Default::default()),
-    |root_conf, config, _metadata, _cli_options| {
+    |app, config, _metadata, _cli_options| {
       set_var("WRY_RUSTWEBVIEWCLIENT_CLASS_EXTENSION", "");
       set_var("WRY_RUSTWEBVIEW_CLASS_INIT", "");
 
@@ -79,7 +79,7 @@ pub fn command(options: Options, noise_level: NoiseLevel) -> Result<()> {
         .map_err(|e| Error::ProjectNotInitialized(e.to_string()))?;
 
       let env = env()?;
-      init_dot_cargo(root_conf, Some(&env)).map_err(Error::InitDotCargo)?;
+      init_dot_cargo(app, Some((&env, config))).map_err(Error::InitDotCargo)?;
 
       let open = options.open;
       run_build(options, config, &env, noise_level)

+ 5 - 5
tooling/cli/src/mobile/android/dev.rs

@@ -15,7 +15,7 @@ use cargo_mobile::{
     config::{Config as AndroidConfig, Metadata as AndroidMetadata},
     env::Env,
   },
-  config::Config,
+  config::app::App,
   opts::{NoiseLevel, Profile},
 };
 
@@ -69,7 +69,7 @@ pub fn command(options: Options, noise_level: NoiseLevel) -> Result<()> {
   delete_codegen_vars();
   with_config(
     Some(Default::default()),
-    |root_conf, config, metadata, _cli_options| {
+    |app, config, metadata, _cli_options| {
       set_var(
         "WRY_RUSTWEBVIEWCLIENT_CLASS_EXTENSION",
         WEBVIEW_CLIENT_CLASS_EXTENSION,
@@ -77,7 +77,7 @@ pub fn command(options: Options, noise_level: NoiseLevel) -> Result<()> {
       set_var("WRY_RUSTWEBVIEW_CLASS_INIT", WEBVIEW_CLASS_INIT);
       ensure_init(config.project_dir(), MobileTarget::Android)
         .map_err(|e| Error::ProjectNotInitialized(e.to_string()))?;
-      run_dev(options, root_conf, config, metadata, noise_level)
+      run_dev(options, app, config, metadata, noise_level)
         .map_err(|e| Error::DevFailed(format!("{:#}", e)))
     },
   )
@@ -86,7 +86,7 @@ pub fn command(options: Options, noise_level: NoiseLevel) -> Result<()> {
 
 fn run_dev(
   options: Options,
-  root_conf: &Config,
+  app: &App,
   config: &AndroidConfig,
   metadata: &AndroidMetadata,
   noise_level: NoiseLevel,
@@ -110,7 +110,7 @@ fn run_dev(
   let _lock = flock::open_rw(&out_dir.join("lock").with_extension("android"), "Android")?;
 
   let env = env()?;
-  init_dot_cargo(root_conf, Some(&env)).map_err(Error::InitDotCargo)?;
+  init_dot_cargo(app, Some((&env, config))).map_err(Error::InitDotCargo)?;
 
   let open = options.open;
   let exit_on_panic = options.exit_on_panic;

+ 43 - 39
tooling/cli/src/mobile/init.rs

@@ -2,13 +2,16 @@
 // SPDX-License-Identifier: Apache-2.0
 // SPDX-License-Identifier: MIT
 
-use super::{get_config, Target};
+use super::{get_app, Target};
 use crate::helpers::{config::get as get_tauri_config, template::JsonMap};
 use crate::Result;
 use cargo_mobile::{
-  android::{self, env::Env as AndroidEnv, ndk, target::Target as AndroidTarget},
+  android::{
+    self, config::Config as AndroidConfig, env::Env as AndroidEnv, ndk,
+    target::Target as AndroidTarget,
+  },
   bossy,
-  config::Config,
+  config::app::App,
   dot_cargo,
   os::code_command,
   target::TargetTrait as _,
@@ -66,8 +69,11 @@ pub enum Error {
   DotCargoWrite(dot_cargo::WriteError),
 }
 
-pub fn init_dot_cargo(config: &Config, android_env: Option<&AndroidEnv>) -> Result<(), Error> {
-  let mut dot_cargo = dot_cargo::DotCargo::load(config.app()).map_err(Error::DotCargoLoad)?;
+pub fn init_dot_cargo(
+  app: &App,
+  android: Option<(&AndroidEnv, &AndroidConfig)>,
+) -> Result<(), Error> {
+  let mut dot_cargo = dot_cargo::DotCargo::load(app).map_err(Error::DotCargoLoad)?;
   // Mysteriously, builds that don't specify `--target` seem to fight over
   // the build cache with builds that use `--target`! This means that
   // alternating between i.e. `cargo run` and `cargo apple run` would
@@ -81,18 +87,18 @@ pub fn init_dot_cargo(config: &Config, android_env: Option<&AndroidEnv>) -> Resu
   dot_cargo
     .set_default_target(util::host_target_triple().map_err(Error::HostTargetTripleDetection)?);
 
-  if let Some(env) = android_env {
+  if let Some((env, config)) = android {
     for target in AndroidTarget::all().values() {
       dot_cargo.insert_target(
         target.triple.to_owned(),
         target
-          .generate_cargo_config(config.android(), env)
+          .generate_cargo_config(config, env)
           .map_err(Error::DotCargoGenFailed)?,
       );
     }
   }
 
-  dot_cargo.write(config.app()).map_err(Error::DotCargoWrite)
+  dot_cargo.write(app).map_err(Error::DotCargoWrite)
 }
 
 pub fn exec(
@@ -101,15 +107,15 @@ pub fn exec(
   non_interactive: bool,
   skip_dev_tools: bool,
   #[allow(unused_variables)] reinstall_deps: bool,
-) -> Result<Config, Error> {
+) -> Result<App, Error> {
   let tauri_config =
     get_tauri_config(None).map_err(|e| Error::InvalidTauriConfig(e.to_string()))?;
   let tauri_config_guard = tauri_config.lock().unwrap();
   let tauri_config_ = tauri_config_guard.as_ref().unwrap();
 
-  let (config, metadata) = get_config(tauri_config_, &Default::default(), target);
+  let app = get_app(tauri_config_);
 
-  let asset_dir = config.app().asset_dir();
+  let asset_dir = app.asset_dir();
   if !asset_dir.is_dir() {
     fs::create_dir_all(&asset_dir).map_err(|cause| Error::AssetDirCreation { asset_dir, cause })?;
   }
@@ -124,7 +130,7 @@ pub fn exec(
       .map_err(Error::LldbExtensionInstall)?;
   }
 
-  let (handlebars, mut map) = handlebars(&config);
+  let (handlebars, mut map) = handlebars(&app);
 
   let mut args = std::env::args_os();
   let tauri_binary = args
@@ -160,18 +166,17 @@ pub fn exec(
   map.insert("tauri-binary-args", &build_args);
   map.insert("tauri-binary-args-str", build_args.join(" "));
 
-  // Generate Android Studio project
-  let android_env = if target == Target::Android {
-    match AndroidEnv::new() {
+  let app = match target {
+    // Generate Android Studio project
+    Target::Android => match AndroidEnv::new() {
       Ok(env) => {
-        super::android::project::gen(
-          config.android(),
-          metadata.android(),
-          (handlebars, map),
-          wrapper,
-        )
-        .map_err(Error::AndroidInit)?;
-        Some(env)
+        let (app, config, metadata) =
+          super::android::get_config(Some(app), tauri_config_, &Default::default());
+        map.insert("android", &config);
+        super::android::project::gen(&config, &metadata, (handlebars, map), wrapper)
+          .map_err(Error::AndroidInit)?;
+        init_dot_cargo(&app, Some((&env, &config)))?;
+        app
       }
       Err(err) => {
         if err.sdk_or_ndk_issue() {
@@ -180,19 +185,22 @@ pub fn exec(
             err,
           )
           .print(wrapper);
-          None
+          init_dot_cargo(&app, None)?;
+          app
         } else {
           return Err(Error::AndroidEnv(err));
         }
       }
-    }
-  } else {
-    // Generate Xcode project
+    },
     #[cfg(target_os = "macos")]
-    if target == Target::Ios {
+    // Generate Xcode project
+    Target::Ios => {
+      let (app, config, metadata) =
+        super::ios::get_config(Some(app), tauri_config_, &Default::default());
+      map.insert("apple", &config);
       super::ios::project::gen(
-        config.apple(),
-        metadata.apple(),
+        &config,
+        &metadata,
         (handlebars, map),
         wrapper,
         non_interactive,
@@ -200,21 +208,20 @@ pub fn exec(
         reinstall_deps,
       )
       .map_err(Error::IosInit)?;
+      init_dot_cargo(&app, None)?;
+      app
     }
-    None
   };
 
-  init_dot_cargo(&config, android_env.as_ref())?;
-
   Report::victory(
     "Project generated successfully!",
     "Make cool apps! 🌻 🐕 🎉",
   )
   .print(wrapper);
-  Ok(config)
+  Ok(app)
 }
 
-fn handlebars(config: &Config) -> (Handlebars<'static>, JsonMap) {
+fn handlebars(app: &App) -> (Handlebars<'static>, JsonMap) {
   let mut h = Handlebars::new();
   h.register_escape_fn(handlebars::no_escape);
 
@@ -236,10 +243,7 @@ fn handlebars(config: &Config) -> (Handlebars<'static>, JsonMap) {
   h.register_helper("unprefix-path", Box::new(unprefix_path));
 
   let mut map = JsonMap::default();
-  map.insert("app", config.app());
-  #[cfg(target_os = "macos")]
-  map.insert("apple", config.apple());
-  map.insert("android", config.android());
+  map.insert("app", app);
 
   (h, map)
 }

+ 48 - 9
tooling/cli/src/mobile/ios.rs

@@ -4,12 +4,15 @@
 
 use cargo_mobile::{
   apple::{
-    config::{Config as AppleConfig, Metadata as AppleMetadata},
+    config::{
+      Config as AppleConfig, Metadata as AppleMetadata, Platform as ApplePlatform,
+      Raw as RawAppleConfig,
+    },
     device::{Device, RunError},
     ios_deploy,
     target::{CompileLibError, Target},
   },
-  config::Config,
+  config::app::App,
   device::PromptError,
   env::{Env, Error as EnvError},
   opts::NoiseLevel,
@@ -19,11 +22,14 @@ use cargo_mobile::{
 use clap::{Parser, Subcommand};
 
 use super::{
-  ensure_init, env, get_config,
+  ensure_init, env, get_app,
   init::{command as init_command, init_dot_cargo, Options as InitOptions},
   log_finished, read_options, CliOptions, Target as MobileTarget,
 };
-use crate::{helpers::config::get as get_tauri_config, Result};
+use crate::{
+  helpers::config::{get as get_tauri_config, Config as TauriConfig},
+  Result,
+};
 
 use std::path::PathBuf;
 
@@ -105,20 +111,53 @@ pub fn command(cli: Cli, verbosity: usize) -> Result<()> {
   Ok(())
 }
 
+pub fn get_config(
+  app: Option<App>,
+  config: &TauriConfig,
+  cli_options: &CliOptions,
+) -> (App, AppleConfig, AppleMetadata) {
+  let app = app.unwrap_or_else(|| get_app(config));
+  let ios_options = cli_options.clone();
+
+  let raw = RawAppleConfig {
+    development_team: std::env::var("TAURI_APPLE_DEVELOPMENT_TEAM")
+        .ok()
+        .or_else(|| config.tauri.ios.development_team.clone())
+        .expect("you must set `tauri > iOS > developmentTeam` config value or the `TAURI_APPLE_DEVELOPMENT_TEAM` environment variable"),
+    ios_features: ios_options.features.clone(),
+    bundle_version: config.package.version.clone(),
+    bundle_version_short: config.package.version.clone(),
+    ..Default::default()
+  };
+  let config = AppleConfig::from_raw(app.clone(), Some(raw)).unwrap();
+
+  let metadata = AppleMetadata {
+    supported: true,
+    ios: ApplePlatform {
+      cargo_args: Some(ios_options.args),
+      features: ios_options.features,
+      ..Default::default()
+    },
+    macos: Default::default(),
+  };
+
+  (app, config, metadata)
+}
+
 fn with_config<T>(
   cli_options: Option<CliOptions>,
-  f: impl FnOnce(&Config, &AppleConfig, &AppleMetadata, CliOptions) -> Result<T, Error>,
+  f: impl FnOnce(&App, &AppleConfig, &AppleMetadata, CliOptions) -> Result<T, Error>,
 ) -> Result<T, Error> {
-  let (config, metadata, cli_options) = {
+  let (app, config, metadata, cli_options) = {
     let tauri_config =
       get_tauri_config(None).map_err(|e| Error::InvalidTauriConfig(e.to_string()))?;
     let tauri_config_guard = tauri_config.lock().unwrap();
     let tauri_config_ = tauri_config_guard.as_ref().unwrap();
     let cli_options = cli_options.unwrap_or_else(|| read_options(tauri_config_, MobileTarget::Ios));
-    let (config, metadata) = get_config(tauri_config_, &cli_options, MobileTarget::Ios);
-    (config, metadata, cli_options)
+    let (app, config, metadata) = get_config(None, tauri_config_, &cli_options);
+    (app, config, metadata, cli_options)
   };
-  f(&config, config.apple(), metadata.apple(), cli_options)
+  f(&app, &config, &metadata, cli_options)
 }
 
 fn device_prompt<'a>(env: &'_ Env) -> Result<Device<'a>, PromptError<ios_deploy::DeviceListError>> {

+ 2 - 2
tooling/cli/src/mobile/ios/build.rs

@@ -66,12 +66,12 @@ impl From<Options> for crate::build::Options {
 pub fn command(options: Options, noise_level: NoiseLevel) -> Result<()> {
   with_config(
     Some(Default::default()),
-    |root_conf, config, _metadata, _cli_options| {
+    |app, config, _metadata, _cli_options| {
       ensure_init(config.project_dir(), MobileTarget::Ios)
         .map_err(|e| Error::ProjectNotInitialized(e.to_string()))?;
 
       let env = env()?;
-      init_dot_cargo(root_conf, None).map_err(Error::InitDotCargo)?;
+      init_dot_cargo(app, None).map_err(Error::InitDotCargo)?;
 
       let open = options.open;
       run_build(options, config, &env, noise_level)

+ 5 - 6
tooling/cli/src/mobile/ios/dev.rs

@@ -11,7 +11,7 @@ use clap::Parser;
 
 use cargo_mobile::{
   apple::config::Config as AppleConfig,
-  config::Config,
+  config::app::App,
   env::Env,
   opts::{NoiseLevel, Profile},
 };
@@ -57,11 +57,10 @@ impl From<Options> for crate::dev::Options {
 pub fn command(options: Options, noise_level: NoiseLevel) -> Result<()> {
   with_config(
     Some(Default::default()),
-    |root_conf, config, _metadata, _cli_options| {
+    |app, config, _metadata, _cli_options| {
       ensure_init(config.project_dir(), MobileTarget::Ios)
         .map_err(|e| Error::ProjectNotInitialized(e.to_string()))?;
-      run_dev(options, root_conf, config, noise_level)
-        .map_err(|e| Error::DevFailed(format!("{:#}", e)))
+      run_dev(options, app, config, noise_level).map_err(|e| Error::DevFailed(format!("{:#}", e)))
     },
   )
   .map_err(Into::into)
@@ -69,7 +68,7 @@ pub fn command(options: Options, noise_level: NoiseLevel) -> Result<()> {
 
 fn run_dev(
   options: Options,
-  root_conf: &Config,
+  app: &App,
   config: &AppleConfig,
   noise_level: NoiseLevel,
 ) -> Result<()> {
@@ -93,7 +92,7 @@ fn run_dev(
   let _lock = flock::open_rw(&out_dir.join("lock").with_extension("ios"), "iOS")?;
 
   let env = env()?;
-  init_dot_cargo(root_conf, None).map_err(Error::InitDotCargo)?;
+  init_dot_cargo(app, None).map_err(Error::InitDotCargo)?;
 
   let open = options.open;
   let exit_on_panic = options.exit_on_panic;

+ 9 - 79
tooling/cli/src/mobile/mod.rs

@@ -7,14 +7,9 @@ use crate::{
   interface::DevProcess,
 };
 use anyhow::{bail, Result};
-#[cfg(target_os = "macos")]
-use cargo_mobile::apple::config::{
-  Metadata as AppleMetadata, Platform as ApplePlatform, Raw as RawAppleConfig,
-};
 use cargo_mobile::{
-  android::config::{Metadata as AndroidMetadata, Raw as RawAndroidConfig},
   bossy,
-  config::{app::Raw as RawAppConfig, metadata::Metadata, Config, Raw},
+  config::app::{App, Raw as RawAppConfig},
   env::Error as EnvError,
   opts::NoiseLevel,
 };
@@ -199,11 +194,7 @@ fn read_options(config: &TauriConfig, target: Target) -> CliOptions {
   options
 }
 
-fn get_config(
-  config: &TauriConfig,
-  cli_options: &CliOptions,
-  #[allow(unused_variables)] target: Target,
-) -> (Config, Metadata) {
+fn get_app(config: &TauriConfig) -> App {
   let mut s = config.tauri.bundle.identifier.rsplit('.');
   let app_name = s.next().unwrap_or("app").to_string();
   let mut domain = String::new();
@@ -238,75 +229,14 @@ fn get_config(
     app_name
   };
 
-  #[cfg(target_os = "macos")]
-  let ios_options = cli_options.clone();
-  let android_options = cli_options.clone();
-
-  let raw = Raw {
-    app: RawAppConfig {
-      name: app_name.clone(),
-      stylized_name: config.package.product_name.clone(),
-      domain,
-      asset_dir: None,
-      template_pack: None,
-    },
-    #[cfg(target_os = "macos")]
-    apple: Some(RawAppleConfig {
-      development_team: if target == Target::Ios {
-        std::env::var("TAURI_APPLE_DEVELOPMENT_TEAM")
-        .ok()
-        .or_else(|| config.tauri.ios.development_team.clone())
-        .expect("you must set `tauri > iOS > developmentTeam` config value or the `TAURI_APPLE_DEVELOPMENT_TEAM` environment variable")
-      } else {
-        Default::default()
-      },
-      ios_features: ios_options.features.clone(),
-      bundle_version: config.package.version.clone(),
-      bundle_version_short: config.package.version.clone(),
-      ..Default::default()
-    }),
-    android: Some(RawAndroidConfig {
-      features: android_options.features.clone(),
-      ..Default::default()
-    }),
-  };
-  let config = Config::from_raw(tauri_dir(), raw).unwrap();
-
-  let metadata = Metadata {
-    #[cfg(target_os = "macos")]
-    apple: AppleMetadata {
-      supported: true,
-      ios: ApplePlatform {
-        cargo_args: Some(ios_options.args),
-        features: ios_options.features,
-        ..Default::default()
-      },
-      macos: Default::default(),
-    },
-    android: AndroidMetadata {
-      supported: true,
-      cargo_args: Some(android_options.args),
-      features: android_options.features,
-      ..Default::default()
-    },
+  let raw = RawAppConfig {
+    name: app_name,
+    stylized_name: config.package.product_name.clone(),
+    domain,
+    asset_dir: None,
+    template_pack: None,
   };
-
-  set_var("WRY_ANDROID_REVERSED_DOMAIN", &reverse_domain);
-  set_var("WRY_ANDROID_APP_NAME_SNAKE_CASE", &app_name);
-  set_var(
-    "WRY_ANDROID_KOTLIN_FILES_OUT_DIR",
-    config
-      .android()
-      .project_dir()
-      .join("app/src/main")
-      .join(format!(
-        "java/{}/{}",
-        config.app().reverse_domain().replace('.', "/"),
-        config.app().name()
-      )),
-  );
-
-  (config, metadata)
+  App::from_raw(tauri_dir(), raw).unwrap()
 }
 
 fn ensure_init(project_dir: PathBuf, target: Target) -> Result<()> {