Skip to content

Commit f67a9eb

Browse files
feat(cli): synchronize Tauri config and lib name with iOS Xcode project (#10802)
- the Xcode project now uses a fixed output library name, which means changes to the Cargo.toml lib name won't affect it (backwards compatible change, we're checking if this new format is being used or not by reading the project.pbxproj) - sync config identifier with the pbxproj - sync development team config with the pbxproj the sync runs both on dev and on build Co-authored-by: Amr Bashir <amr.bashir2015@gmail.com>
1 parent 4312082 commit f67a9eb

File tree

11 files changed

+112
-37
lines changed

11 files changed

+112
-37
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"tauri-cli": patch:enhance
3+
"@tauri-apps/cli": patch:enhance
4+
---
5+
6+
Synchronize identifier, development team and lib name with the iOS Xcode project.

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/tauri-cli/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ name = "cargo-tauri"
3636
path = "src/main.rs"
3737

3838
[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]
39-
cargo-mobile2 = { version = "0.15", default-features = false }
39+
cargo-mobile2 = { version = "0.15.1", default-features = false }
4040

4141
[dependencies]
4242
jsonrpsee = { version = "0.24", features = ["server"] }

crates/tauri-cli/src/helpers/pbxproj.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -230,12 +230,14 @@ impl Pbxproj {
230230
.iter_mut()
231231
.find(|s| s.key == key)
232232
{
233-
let Some(line) = self.raw_lines.get_mut(build_setting.line_number) else {
234-
return;
235-
};
233+
if build_setting.value != value {
234+
let Some(line) = self.raw_lines.get_mut(build_setting.line_number) else {
235+
return;
236+
};
236237

237-
*line = format!("{}{key} = {value};", build_setting.identation);
238-
self.has_changes = true;
238+
*line = format!("{}{key} = {value};", build_setting.identation);
239+
self.has_changes = true;
240+
}
239241
} else {
240242
let Some(last_build_setting) = build_configuration.build_settings.last().cloned() else {
241243
return;

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ pub fn command(options: Options, noise_level: NoiseLevel) -> Result<()> {
146146
tauri_utils::platform::Target::Ios,
147147
options.config.as_ref().map(|c| &c.0),
148148
)?;
149-
let (interface, app, mut config) = {
149+
let (interface, mut config) = {
150150
let tauri_config_guard = tauri_config.lock().unwrap();
151151
let tauri_config_ = tauri_config_guard.as_ref().unwrap();
152152

@@ -160,7 +160,7 @@ pub fn command(options: Options, noise_level: NoiseLevel) -> Result<()> {
160160
build_options.features.as_ref(),
161161
&Default::default(),
162162
);
163-
(interface, app, config)
163+
(interface, config)
164164
};
165165

166166
let tauri_path = tauri_dir();
@@ -198,7 +198,8 @@ pub fn command(options: Options, noise_level: NoiseLevel) -> Result<()> {
198198

199199
// synchronize pbxproj and exportoptions
200200
synchronize_project_config(
201-
&app,
201+
&config,
202+
&tauri_config,
202203
&mut pbxproj,
203204
&mut export_options_plist,
204205
&project_config,

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

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
// SPDX-License-Identifier: MIT
44

55
use super::{
6-
device_prompt, ensure_init, env, get_app, get_config, inject_resources, merge_plist,
7-
open_and_wait, MobileTarget,
6+
device_prompt, ensure_init, env, get_app, get_config, inject_resources, load_pbxproj,
7+
merge_plist, open_and_wait, synchronize_project_config, MobileTarget, ProjectConfig,
88
};
99
use crate::{
1010
dev::Options as DevOptions,
@@ -191,6 +191,25 @@ fn run_command(options: Options, noise_level: NoiseLevel) -> Result<()> {
191191
])?;
192192
merged_info_plist.to_file_xml(&info_plist_path)?;
193193

194+
let mut pbxproj = load_pbxproj(&config)?;
195+
196+
// synchronize pbxproj
197+
synchronize_project_config(
198+
&config,
199+
&tauri_config,
200+
&mut pbxproj,
201+
&mut plist::Dictionary::new(),
202+
&ProjectConfig {
203+
code_sign_identity: None,
204+
team_id: None,
205+
provisioning_profile_uuid: None,
206+
},
207+
!options.release_mode,
208+
)?;
209+
if pbxproj.has_changes() {
210+
pbxproj.save()?;
211+
}
212+
194213
run_dev(
195214
interface,
196215
options,

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

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use super::{
2929
use crate::{
3030
helpers::{
3131
app_paths::tauri_dir,
32-
config::{BundleResources, Config as TauriConfig},
32+
config::{BundleResources, Config as TauriConfig, ConfigHandle},
3333
pbxproj,
3434
},
3535
Result,
@@ -49,6 +49,7 @@ pub(crate) mod project;
4949
mod xcode_script;
5050

5151
pub const APPLE_DEVELOPMENT_TEAM_ENV_VAR_NAME: &str = "APPLE_DEVELOPMENT_TEAM";
52+
pub const LIB_OUTPUT_FILE_NAME: &str = "libapp.a";
5253

5354
#[derive(Parser)]
5455
#[clap(
@@ -131,7 +132,7 @@ pub fn get_config(
131132
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`.");
132133
None
133134
}
134-
1 => Some(teams.first().unwrap().id.clone()),
135+
1 =>None,
135136
_ => {
136137
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::<Vec<String>>().join(", "));
137138
None
@@ -421,12 +422,21 @@ pub fn load_pbxproj(config: &AppleConfig) -> Result<pbxproj::Pbxproj> {
421422
}
422423

423424
pub fn synchronize_project_config(
424-
app: &App,
425+
config: &AppleConfig,
426+
tauri_config: &ConfigHandle,
425427
pbxproj: &mut pbxproj::Pbxproj,
426428
export_options_list: &mut plist::Dictionary,
427429
project_config: &ProjectConfig,
428430
debug: bool,
429431
) -> Result<()> {
432+
let identifier = tauri_config
433+
.lock()
434+
.unwrap()
435+
.as_ref()
436+
.unwrap()
437+
.identifier
438+
.clone();
439+
430440
let manual_signing = project_config.code_sign_identity.is_some()
431441
|| project_config.provisioning_profile_uuid.is_some();
432442

@@ -437,10 +447,26 @@ pub fn synchronize_project_config(
437447
.find(|l| l.comment.contains("_iOS"))
438448
{
439449
for build_configuration_ref in xc_configuration_list.build_configurations {
440-
if manual_signing {
441-
pbxproj.set_build_settings(&build_configuration_ref.id, "CODE_SIGN_STYLE", "Manual");
450+
pbxproj.set_build_settings(
451+
&build_configuration_ref.id,
452+
"CODE_SIGN_STYLE",
453+
if manual_signing {
454+
"Manual"
455+
} else {
456+
"Automatic"
457+
},
458+
);
459+
460+
if let Some(team) = config.development_team() {
461+
pbxproj.set_build_settings(&build_configuration_ref.id, "DEVELOPMENT_TEAM", team);
442462
}
443463

464+
pbxproj.set_build_settings(
465+
&build_configuration_ref.id,
466+
"PRODUCT_BUNDLE_IDENTIFIER",
467+
&identifier,
468+
);
469+
444470
if let Some(identity) = &project_config.code_sign_identity {
445471
let identity = format!("\"{identity}\"");
446472
pbxproj.set_build_settings(&build_configuration_ref.id, "CODE_SIGN_IDENTITY", &identity);
@@ -536,7 +562,7 @@ pub fn synchronize_project_config(
536562
});
537563
if let Some(profile_uuid) = profile_uuid {
538564
let mut provisioning_profiles = plist::Dictionary::new();
539-
provisioning_profiles.insert(app.identifier().to_string(), profile_uuid.into());
565+
provisioning_profiles.insert(config.app().identifier().to_string(), profile_uuid.into());
540566
export_options_list.insert(
541567
"provisioningProfiles".to_string(),
542568
provisioning_profiles.into(),

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use crate::{
66
helpers::{config::Config as TauriConfig, template},
7+
mobile::ios::LIB_OUTPUT_FILE_NAME,
78
Result,
89
};
910
use anyhow::Context;
@@ -76,6 +77,8 @@ pub fn gen(
7677
#[cfg(not(target_arch = "aarch64"))]
7778
let default_archs = ["arm64", "x86_64"];
7879

80+
map.insert("lib-output-file-name", LIB_OUTPUT_FILE_NAME);
81+
7982
map.insert("file-groups", &source_dirs);
8083
map.insert("ios-frameworks", metadata.ios().frameworks());
8184
map.insert("ios-valid-archs", default_archs);

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

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,19 @@ use super::{ensure_init, env, get_app, get_config, read_options, MobileTarget};
66
use crate::{
77
helpers::config::get as get_tauri_config,
88
interface::{AppInterface, AppSettings, Interface, Options as InterfaceOptions},
9+
mobile::ios::LIB_OUTPUT_FILE_NAME,
910
Result,
1011
};
1112

13+
use anyhow::Context;
1214
use cargo_mobile2::{apple::target::Target, opts::Profile};
1315
use clap::Parser;
1416

1517
use std::{
1618
collections::HashMap,
1719
env::{current_dir, set_current_dir, var, var_os},
1820
ffi::OsStr,
21+
fs::read_to_string,
1922
path::{Path, PathBuf},
2023
process::Command,
2124
};
@@ -233,10 +236,26 @@ pub fn command(options: Options) -> Result<()> {
233236
let project_dir = config.project_dir();
234237
let externals_lib_dir = project_dir.join(format!("Externals/{arch}/{}", profile.as_str()));
235238
std::fs::create_dir_all(&externals_lib_dir)?;
236-
std::fs::copy(
237-
lib_path,
238-
externals_lib_dir.join(format!("lib{}.a", config.app().lib_name())),
239-
)?;
239+
240+
// backwards compatible lib output file name
241+
let uses_new_lib_output_file_name = {
242+
let pbxproj_contents = read_to_string(
243+
project_dir
244+
.join(format!("{}.xcodeproj", config.app().name()))
245+
.join("project.pbxproj"),
246+
)
247+
.context("missing project.pbxproj file in the Xcode project")?;
248+
249+
pbxproj_contents.contains(LIB_OUTPUT_FILE_NAME)
250+
};
251+
252+
let lib_output_file_name = if uses_new_lib_output_file_name {
253+
LIB_OUTPUT_FILE_NAME.to_string()
254+
} else {
255+
format!("lib{}.a", config.app().lib_name())
256+
};
257+
258+
std::fs::copy(lib_path, externals_lib_dir.join(lib_output_file_name))?;
240259
}
241260
Ok(())
242261
}

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

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -329,17 +329,16 @@ fn ensure_init(
329329
}
330330
#[cfg(target_os = "macos")]
331331
Target::Ios => {
332-
let project_yml = read_to_string(project_dir.join("project.yml"))
333-
.context("missing project.yml file in the Xcode project directory")?;
334-
if !project_yml.contains(&format!(
335-
"PRODUCT_BUNDLE_IDENTIFIER: {}",
336-
tauri_config_.identifier.replace('_', "-")
337-
)) {
338-
project_outdated_reasons
339-
.push("you have modified your \"identifier\" in the Tauri configuration");
340-
}
332+
let pbxproj_contents = read_to_string(
333+
project_dir
334+
.join(format!("{}.xcodeproj", app.name()))
335+
.join("project.pbxproj"),
336+
)
337+
.context("missing project.yml file in the Xcode project directory")?;
341338

342-
if !project_yml.contains(&format!("framework: lib{}.a", app.lib_name())) {
339+
if !(pbxproj_contents.contains(ios::LIB_OUTPUT_FILE_NAME)
340+
|| pbxproj_contents.contains(&format!("lib{}.a", app.lib_name())))
341+
{
343342
project_outdated_reasons
344343
.push("you have modified your [lib.name] or [package.name] in the Cargo.toml file");
345344
}

0 commit comments

Comments
 (0)