diff --git a/.changes/synchronize-config-and-xcode-project.md b/.changes/synchronize-config-and-xcode-project.md new file mode 100644 index 000000000..2c7f2d11e --- /dev/null +++ b/.changes/synchronize-config-and-xcode-project.md @@ -0,0 +1,6 @@ +--- +"tauri-cli": patch:enhance +"@tauri-apps/cli": patch:enhance +--- + +Synchronize identifier, development team and lib name with the iOS Xcode project. diff --git a/Cargo.lock b/Cargo.lock index 22aeb514b..9e05f1913 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -747,9 +747,9 @@ dependencies = [ [[package]] name = "cargo-mobile2" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b1baf430f92ddf6e492c9186e4e97dc3051366345b8aa7ffdc0e0f952c9a35b" +checksum = "d0b8132519bea2d46174e777bd36d480d93afbe1df31c27cacfb411ff152bba1" dependencies = [ "colored", "core-foundation 0.10.0", diff --git a/crates/tauri-cli/Cargo.toml b/crates/tauri-cli/Cargo.toml index 8aff39ecf..7de08d9a1 100644 --- a/crates/tauri-cli/Cargo.toml +++ b/crates/tauri-cli/Cargo.toml @@ -36,7 +36,7 @@ name = "cargo-tauri" path = "src/main.rs" [target."cfg(any(target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\", target_os = \"windows\", target_os = \"macos\"))".dependencies] -cargo-mobile2 = { version = "0.15", default-features = false } +cargo-mobile2 = { version = "0.15.1", default-features = false } [dependencies] jsonrpsee = { version = "0.24", features = ["server"] } diff --git a/crates/tauri-cli/src/helpers/pbxproj.rs b/crates/tauri-cli/src/helpers/pbxproj.rs index 081f035f4..f449a089d 100644 --- a/crates/tauri-cli/src/helpers/pbxproj.rs +++ b/crates/tauri-cli/src/helpers/pbxproj.rs @@ -230,12 +230,14 @@ impl Pbxproj { .iter_mut() .find(|s| s.key == key) { - let Some(line) = self.raw_lines.get_mut(build_setting.line_number) else { - return; - }; + if build_setting.value != value { + let Some(line) = self.raw_lines.get_mut(build_setting.line_number) else { + return; + }; - *line = format!("{}{key} = {value};", build_setting.identation); - self.has_changes = true; + *line = format!("{}{key} = {value};", build_setting.identation); + self.has_changes = true; + } } else { let Some(last_build_setting) = build_configuration.build_settings.last().cloned() else { return; diff --git a/crates/tauri-cli/src/mobile/ios/build.rs b/crates/tauri-cli/src/mobile/ios/build.rs index 28c750b9c..fdcbc0f83 100644 --- a/crates/tauri-cli/src/mobile/ios/build.rs +++ b/crates/tauri-cli/src/mobile/ios/build.rs @@ -146,7 +146,7 @@ pub fn command(options: Options, noise_level: NoiseLevel) -> Result<()> { tauri_utils::platform::Target::Ios, options.config.as_ref().map(|c| &c.0), )?; - let (interface, app, mut config) = { + let (interface, mut config) = { let tauri_config_guard = tauri_config.lock().unwrap(); let tauri_config_ = tauri_config_guard.as_ref().unwrap(); @@ -160,7 +160,7 @@ pub fn command(options: Options, noise_level: NoiseLevel) -> Result<()> { build_options.features.as_ref(), &Default::default(), ); - (interface, app, config) + (interface, config) }; let tauri_path = tauri_dir(); @@ -198,7 +198,8 @@ pub fn command(options: Options, noise_level: NoiseLevel) -> Result<()> { // synchronize pbxproj and exportoptions synchronize_project_config( - &app, + &config, + &tauri_config, &mut pbxproj, &mut export_options_plist, &project_config, diff --git a/crates/tauri-cli/src/mobile/ios/dev.rs b/crates/tauri-cli/src/mobile/ios/dev.rs index a2ffeacac..1814f499f 100644 --- a/crates/tauri-cli/src/mobile/ios/dev.rs +++ b/crates/tauri-cli/src/mobile/ios/dev.rs @@ -3,8 +3,8 @@ // SPDX-License-Identifier: MIT use super::{ - device_prompt, ensure_init, env, get_app, get_config, inject_resources, merge_plist, - open_and_wait, MobileTarget, + device_prompt, ensure_init, env, get_app, get_config, inject_resources, load_pbxproj, + merge_plist, open_and_wait, synchronize_project_config, MobileTarget, ProjectConfig, }; use crate::{ dev::Options as DevOptions, @@ -191,6 +191,25 @@ fn run_command(options: Options, noise_level: NoiseLevel) -> Result<()> { ])?; merged_info_plist.to_file_xml(&info_plist_path)?; + let mut pbxproj = load_pbxproj(&config)?; + + // synchronize pbxproj + synchronize_project_config( + &config, + &tauri_config, + &mut pbxproj, + &mut plist::Dictionary::new(), + &ProjectConfig { + code_sign_identity: None, + team_id: None, + provisioning_profile_uuid: None, + }, + !options.release_mode, + )?; + if pbxproj.has_changes() { + pbxproj.save()?; + } + run_dev( interface, options, diff --git a/crates/tauri-cli/src/mobile/ios/mod.rs b/crates/tauri-cli/src/mobile/ios/mod.rs index d3e1e3303..3d2a329bb 100644 --- a/crates/tauri-cli/src/mobile/ios/mod.rs +++ b/crates/tauri-cli/src/mobile/ios/mod.rs @@ -29,7 +29,7 @@ use super::{ use crate::{ helpers::{ app_paths::tauri_dir, - config::{BundleResources, Config as TauriConfig}, + config::{BundleResources, Config as TauriConfig, ConfigHandle}, pbxproj, }, Result, @@ -49,6 +49,7 @@ pub(crate) mod project; mod xcode_script; pub const APPLE_DEVELOPMENT_TEAM_ENV_VAR_NAME: &str = "APPLE_DEVELOPMENT_TEAM"; +pub const LIB_OUTPUT_FILE_NAME: &str = "libapp.a"; #[derive(Parser)] #[clap( @@ -131,7 +132,7 @@ pub fn get_config( log::warn!("No code signing certificates found. You must add one and set the certificate development team ID on the `bundle > iOS > developmentTeam` config value or the `{APPLE_DEVELOPMENT_TEAM_ENV_VAR_NAME}` environment variable. To list the available certificates, run `tauri info`."); None } - 1 => Some(teams.first().unwrap().id.clone()), + 1 =>None, _ => { log::warn!("You must set the code signing certificate development team ID on the `bundle > iOS > developmentTeam` config value or the `{APPLE_DEVELOPMENT_TEAM_ENV_VAR_NAME}` environment variable. Available certificates: {}", teams.iter().map(|t| format!("{} (ID: {})", t.name, t.id)).collect::>().join(", ")); None @@ -421,12 +422,21 @@ pub fn load_pbxproj(config: &AppleConfig) -> Result { } pub fn synchronize_project_config( - app: &App, + config: &AppleConfig, + tauri_config: &ConfigHandle, pbxproj: &mut pbxproj::Pbxproj, export_options_list: &mut plist::Dictionary, project_config: &ProjectConfig, debug: bool, ) -> Result<()> { + let identifier = tauri_config + .lock() + .unwrap() + .as_ref() + .unwrap() + .identifier + .clone(); + let manual_signing = project_config.code_sign_identity.is_some() || project_config.provisioning_profile_uuid.is_some(); @@ -437,10 +447,26 @@ pub fn synchronize_project_config( .find(|l| l.comment.contains("_iOS")) { for build_configuration_ref in xc_configuration_list.build_configurations { - if manual_signing { - pbxproj.set_build_settings(&build_configuration_ref.id, "CODE_SIGN_STYLE", "Manual"); + pbxproj.set_build_settings( + &build_configuration_ref.id, + "CODE_SIGN_STYLE", + if manual_signing { + "Manual" + } else { + "Automatic" + }, + ); + + if let Some(team) = config.development_team() { + pbxproj.set_build_settings(&build_configuration_ref.id, "DEVELOPMENT_TEAM", team); } + pbxproj.set_build_settings( + &build_configuration_ref.id, + "PRODUCT_BUNDLE_IDENTIFIER", + &identifier, + ); + if let Some(identity) = &project_config.code_sign_identity { let identity = format!("\"{identity}\""); pbxproj.set_build_settings(&build_configuration_ref.id, "CODE_SIGN_IDENTITY", &identity); @@ -536,7 +562,7 @@ pub fn synchronize_project_config( }); if let Some(profile_uuid) = profile_uuid { let mut provisioning_profiles = plist::Dictionary::new(); - provisioning_profiles.insert(app.identifier().to_string(), profile_uuid.into()); + provisioning_profiles.insert(config.app().identifier().to_string(), profile_uuid.into()); export_options_list.insert( "provisioningProfiles".to_string(), provisioning_profiles.into(), diff --git a/crates/tauri-cli/src/mobile/ios/project.rs b/crates/tauri-cli/src/mobile/ios/project.rs index fcf5af924..f87b5ce02 100644 --- a/crates/tauri-cli/src/mobile/ios/project.rs +++ b/crates/tauri-cli/src/mobile/ios/project.rs @@ -4,6 +4,7 @@ use crate::{ helpers::{config::Config as TauriConfig, template}, + mobile::ios::LIB_OUTPUT_FILE_NAME, Result, }; use anyhow::Context; @@ -76,6 +77,8 @@ pub fn gen( #[cfg(not(target_arch = "aarch64"))] let default_archs = ["arm64", "x86_64"]; + map.insert("lib-output-file-name", LIB_OUTPUT_FILE_NAME); + map.insert("file-groups", &source_dirs); map.insert("ios-frameworks", metadata.ios().frameworks()); map.insert("ios-valid-archs", default_archs); diff --git a/crates/tauri-cli/src/mobile/ios/xcode_script.rs b/crates/tauri-cli/src/mobile/ios/xcode_script.rs index 49b2851d8..4bff5fa0d 100644 --- a/crates/tauri-cli/src/mobile/ios/xcode_script.rs +++ b/crates/tauri-cli/src/mobile/ios/xcode_script.rs @@ -6,9 +6,11 @@ use super::{ensure_init, env, get_app, get_config, read_options, MobileTarget}; use crate::{ helpers::config::get as get_tauri_config, interface::{AppInterface, AppSettings, Interface, Options as InterfaceOptions}, + mobile::ios::LIB_OUTPUT_FILE_NAME, Result, }; +use anyhow::Context; use cargo_mobile2::{apple::target::Target, opts::Profile}; use clap::Parser; @@ -16,6 +18,7 @@ use std::{ collections::HashMap, env::{current_dir, set_current_dir, var, var_os}, ffi::OsStr, + fs::read_to_string, path::{Path, PathBuf}, process::Command, }; @@ -233,10 +236,26 @@ pub fn command(options: Options) -> Result<()> { let project_dir = config.project_dir(); let externals_lib_dir = project_dir.join(format!("Externals/{arch}/{}", profile.as_str())); std::fs::create_dir_all(&externals_lib_dir)?; - std::fs::copy( - lib_path, - externals_lib_dir.join(format!("lib{}.a", config.app().lib_name())), - )?; + + // backwards compatible lib output file name + let uses_new_lib_output_file_name = { + let pbxproj_contents = read_to_string( + project_dir + .join(format!("{}.xcodeproj", config.app().name())) + .join("project.pbxproj"), + ) + .context("missing project.pbxproj file in the Xcode project")?; + + pbxproj_contents.contains(LIB_OUTPUT_FILE_NAME) + }; + + let lib_output_file_name = if uses_new_lib_output_file_name { + LIB_OUTPUT_FILE_NAME.to_string() + } else { + format!("lib{}.a", config.app().lib_name()) + }; + + std::fs::copy(lib_path, externals_lib_dir.join(lib_output_file_name))?; } Ok(()) } diff --git a/crates/tauri-cli/src/mobile/mod.rs b/crates/tauri-cli/src/mobile/mod.rs index d38e87fae..b4292a285 100644 --- a/crates/tauri-cli/src/mobile/mod.rs +++ b/crates/tauri-cli/src/mobile/mod.rs @@ -329,17 +329,16 @@ fn ensure_init( } #[cfg(target_os = "macos")] Target::Ios => { - let project_yml = read_to_string(project_dir.join("project.yml")) - .context("missing project.yml file in the Xcode project directory")?; - if !project_yml.contains(&format!( - "PRODUCT_BUNDLE_IDENTIFIER: {}", - tauri_config_.identifier.replace('_', "-") - )) { - project_outdated_reasons - .push("you have modified your \"identifier\" in the Tauri configuration"); - } + let pbxproj_contents = read_to_string( + project_dir + .join(format!("{}.xcodeproj", app.name())) + .join("project.pbxproj"), + ) + .context("missing project.yml file in the Xcode project directory")?; - if !project_yml.contains(&format!("framework: lib{}.a", app.lib_name())) { + if !(pbxproj_contents.contains(ios::LIB_OUTPUT_FILE_NAME) + || pbxproj_contents.contains(&format!("lib{}.a", app.lib_name()))) + { project_outdated_reasons .push("you have modified your [lib.name] or [package.name] in the Cargo.toml file"); } diff --git a/crates/tauri-cli/templates/mobile/ios/project.yml b/crates/tauri-cli/templates/mobile/ios/project.yml index 0f8d5d5f6..1a4712bae 100644 --- a/crates/tauri-cli/templates/mobile/ios/project.yml +++ b/crates/tauri-cli/templates/mobile/ios/project.yml @@ -86,7 +86,7 @@ targets: EXCLUDED_ARCHS[sdk=iphoneos*]: arm64-sim x86_64 groups: [app] dependencies: - - framework: lib{{app.lib-name}}.a + - framework: {{ lib-output-file-name }} embed: false {{~#each ios-libraries}} - framework: {{this}} @@ -125,9 +125,9 @@ targets: name: Build Rust Code basedOnDependencyAnalysis: false outputFiles: - - $(SRCROOT)/Externals/x86_64/${CONFIGURATION}/lib{{app.lib-name}}.a - - $(SRCROOT)/Externals/arm64/${CONFIGURATION}/lib{{app.lib-name}}.a - - $(SRCROOT)/Externals/arm64-sim/${CONFIGURATION}/lib{{app.lib-name}}.a + - $(SRCROOT)/Externals/x86_64/${CONFIGURATION}/{{ lib-output-file-name }} + - $(SRCROOT)/Externals/arm64/${CONFIGURATION}/{{ lib-output-file-name }} + - $(SRCROOT)/Externals/arm64-sim/${CONFIGURATION}/{{ lib-output-file-name }} {{~#if ios-post-compile-scripts}} postCompileScripts: {{~#each ios-post-compile-scripts}}{{#if this.path}}