Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Support custom CFBundleVersion for iOS and macOS #13030

Open
wants to merge 3 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changes/ios-macos-bundleversion.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"tauri": minor:feat
---

Added `bundleVersion` to iOS and macOS configuration to support specifying a `CFBundleVersion`.
4 changes: 2 additions & 2 deletions crates/tauri-bundler/src/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ pub use self::{
category::AppCategory,
settings::{
AppImageSettings, BundleBinary, BundleSettings, CustomSignCommandSettings, DebianSettings,
DmgSettings, MacOsSettings, PackageSettings, PackageType, Position, RpmSettings, Settings,
SettingsBuilder, Size, UpdaterSettings,
DmgSettings, IosSettings, MacOsSettings, PackageSettings, PackageType, Position, RpmSettings,
Settings, SettingsBuilder, Size, UpdaterSettings,
},
};
#[cfg(target_os = "macos")]
Expand Down
8 changes: 1 addition & 7 deletions crates/tauri-bundler/src/bundle/macos/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,12 +191,6 @@ fn create_info_plist(
bundle_icon_file: Option<PathBuf>,
settings: &Settings,
) -> crate::Result<()> {
let format = time::format_description::parse("[year][month][day].[hour][minute][second]")
.map_err(time::error::Error::from)?;
let build_number = time::OffsetDateTime::now_utc()
.format(&format)
.map_err(time::error::Error::from)?;

let mut plist = plist::Dictionary::new();
plist.insert("CFBundleDevelopmentRegion".into(), "English".into());
plist.insert("CFBundleDisplayName".into(), settings.product_name().into());
Expand Down Expand Up @@ -226,7 +220,7 @@ fn create_info_plist(
"CFBundleShortVersionString".into(),
settings.version_string().into(),
);
plist.insert("CFBundleVersion".into(), build_number.into());
plist.insert("CFBundleVersion".into(), settings.bundle_version().into());
plist.insert("CSResourcesFileMapped".into(), true.into());
if let Some(category) = settings.app_category() {
plist.insert(
Expand Down
2 changes: 1 addition & 1 deletion crates/tauri-bundler/src/bundle/macos/ios.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ fn generate_info_plist(
writeln!(
file,
" <key>CFBundleVersion</key>\n <string>{}</string>",
settings.version_string()
settings.bundle_version()
)?;
writeln!(
file,
Expand Down
23 changes: 23 additions & 0 deletions crates/tauri-bundler/src/bundle/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ pub struct PackageSettings {
pub product_name: String,
/// the package's version.
pub version: String,
/// the package's bundle version.
pub bundle_version: String,
/// the package's description.
pub description: String,
/// the package's homepage.
Expand Down Expand Up @@ -306,6 +308,13 @@ pub struct DmgSettings {
pub application_folder_position: Position,
}

/// The iOS bundle settings.
#[derive(Clone, Debug, Default)]
pub struct IosSettings {
/// The version of the build that identifies an iteration of the bundle.
pub bundle_version: Option<String>,
}

/// The macOS bundle settings.
#[derive(Clone, Debug, Default)]
pub struct MacOsSettings {
Expand All @@ -323,6 +332,8 @@ pub struct MacOsSettings {
/// List of custom files to add to the application bundle.
/// Maps the path in the Contents directory in the app to the path of the file to include (relative to the current working directory).
pub files: HashMap<PathBuf, PathBuf>,
/// The version of the build that identifies an iteration of the bundle.
pub bundle_version: Option<String>,
/// A version string indicating the minimum MacOS version that the bundled app supports (e.g. `"10.11"`).
/// If you are using this config field, you may also want have your `build.rs` script emit `cargo:rustc-env=MACOSX_DEPLOYMENT_TARGET=10.11`.
pub minimum_system_version: Option<String>,
Expand Down Expand Up @@ -643,6 +654,8 @@ pub struct BundleSettings {
pub rpm: RpmSettings,
/// DMG-specific settings.
pub dmg: DmgSettings,
/// iOS-specific settings.
pub ios: IosSettings,
/// MacOS-specific settings.
pub macos: MacOsSettings,
/// Updater configuration.
Expand Down Expand Up @@ -1093,6 +1106,11 @@ impl Settings {
&self.package.version
}

/// Returns the bundle version.
pub fn bundle_version(&self) -> &str {
&self.package.bundle_version
}

/// Returns the copyright text.
pub fn copyright_string(&self) -> Option<&str> {
self.bundle_settings.copyright.as_deref()
Expand Down Expand Up @@ -1190,6 +1208,11 @@ impl Settings {
&self.bundle_settings.dmg
}

/// Returns the iOS settings.
pub fn ios(&self) -> &IosSettings {
&self.bundle_settings.ios
}

/// Returns the MacOS settings.
pub fn macos(&self) -> &MacOsSettings {
&self.bundle_settings.macos
Expand Down
14 changes: 14 additions & 0 deletions crates/tauri-cli/config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -3292,6 +3292,13 @@
"type": "string"
}
},
"bundleVersion": {
"description": "The version of the build that identifies an iteration of the bundle.",
"type": [
"string",
"null"
]
},
"minimumSystemVersion": {
"description": "A version string indicating the minimum macOS X version that the bundled application supports. Defaults to `10.13`.\n\n Setting it to `null` completely removes the `LSMinimumSystemVersion` field on the bundle's `Info.plist`\n and the `MACOSX_DEPLOYMENT_TARGET` environment variable.\n\n An empty string is considered an invalid value so the default value is used.",
"default": "10.13",
Expand Down Expand Up @@ -3493,6 +3500,13 @@
"null"
]
},
"bundleVersion": {
"description": "The version of the build that identifies an iteration of the bundle.",
"type": [
"string",
"null"
]
},
"minimumSystemVersion": {
"description": "A version string indicating the minimum iOS version that the bundled application supports. Defaults to `13.0`.\n\n Maps to the IPHONEOS_DEPLOYMENT_TARGET value.",
"default": "13.0",
Expand Down
44 changes: 30 additions & 14 deletions crates/tauri-cli/src/interface/rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ use notify_debouncer_full::new_debouncer;
use serde::{Deserialize, Deserializer};
use tauri_bundler::{
AppCategory, AppImageSettings, BundleBinary, BundleSettings, DebianSettings, DmgSettings,
MacOsSettings, PackageSettings, Position, RpmSettings, Size, UpdaterSettings, WindowsSettings,
IosSettings, MacOsSettings, PackageSettings, Position, RpmSettings, Size, UpdaterSettings,
WindowsSettings,
};
use tauri_utils::config::{parse::is_configuration_file, DeepLinkProtocol, Updater};

Expand Down Expand Up @@ -1016,24 +1017,35 @@ impl RustAppSettings {
.workspace
.and_then(|v| v.package);

let version = config.version.clone().unwrap_or_else(|| {
cargo_package_settings
.version
.clone()
.expect("Cargo manifest must have the `package.version` field")
.resolve("version", || {
ws_package_settings
.as_ref()
.and_then(|p| p.version.clone())
.ok_or_else(|| anyhow::anyhow!("Couldn't inherit value for `version` from workspace"))
})
.expect("Cargo project does not have a version")
});

let bundle_version = if cfg!(target_os = "ios") {
config.bundle.ios.bundle_version.clone()
} else if cfg!(target_os = "macos") {
config.bundle.macos.bundle_version.clone()
} else {
None
};

let package_settings = PackageSettings {
product_name: config
.product_name
.clone()
.unwrap_or_else(|| cargo_package_settings.name.clone()),
version: config.version.clone().unwrap_or_else(|| {
cargo_package_settings
.version
.clone()
.expect("Cargo manifest must have the `package.version` field")
.resolve("version", || {
ws_package_settings
.as_ref()
.and_then(|p| p.version.clone())
.ok_or_else(|| anyhow::anyhow!("Couldn't inherit value for `version` from workspace"))
})
.expect("Cargo project does not have a version")
}),
version: version.clone(),
bundle_version: bundle_version.unwrap_or_else(|| version.clone()),
description: cargo_package_settings
.description
.clone()
Expand Down Expand Up @@ -1418,9 +1430,13 @@ fn tauri_config_to_bundle_settings(
y: config.macos.dmg.application_folder_position.y,
},
},
ios: IosSettings {
bundle_version: config.ios.bundle_version,
},
macos: MacOsSettings {
frameworks: config.macos.frameworks,
files: config.macos.files,
bundle_version: config.macos.bundle_version,
minimum_system_version: config.macos.minimum_system_version,
exception_domain: config.macos.exception_domain,
signing_identity,
Expand Down
6 changes: 5 additions & 1 deletion crates/tauri-cli/src/mobile/ios/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,12 @@ pub fn command(options: Options, noise_level: NoiseLevel) -> Result<()> {

let mut plist = plist::Dictionary::new();
let version = interface.app_settings().get_package_settings().version;
let bundle_version = interface
.app_settings()
.get_package_settings()
.bundle_version;
plist.insert("CFBundleShortVersionString".into(), version.clone().into());
plist.insert("CFBundleVersion".into(), version.into());
plist.insert("CFBundleVersion".into(), bundle_version.into());

let info_plist_path = config
.project_dir()
Expand Down
9 changes: 8 additions & 1 deletion crates/tauri-codegen/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,8 +313,15 @@ pub fn context_codegen(data: ContextData) -> EmbeddedAssetsResult<TokenStream> {
plist.insert("CFBundleName".into(), product_name.clone().into());
}
if let Some(version) = &config.version {
let bundle_version = &config.bundle.macos.bundle_version;
plist.insert("CFBundleShortVersionString".into(), version.clone().into());
plist.insert("CFBundleVersion".into(), version.clone().into());
plist.insert(
"CFBundleVersion".into(),
bundle_version
.clone()
.unwrap_or_else(|| version.clone())
.into(),
);
}
}

Expand Down
14 changes: 14 additions & 0 deletions crates/tauri-schema-generator/schemas/config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -3292,6 +3292,13 @@
"type": "string"
}
},
"bundleVersion": {
"description": "The version of the build that identifies an iteration of the bundle.",
"type": [
"string",
"null"
]
},
"minimumSystemVersion": {
"description": "A version string indicating the minimum macOS X version that the bundled application supports. Defaults to `10.13`.\n\n Setting it to `null` completely removes the `LSMinimumSystemVersion` field on the bundle's `Info.plist`\n and the `MACOSX_DEPLOYMENT_TARGET` environment variable.\n\n An empty string is considered an invalid value so the default value is used.",
"default": "10.13",
Expand Down Expand Up @@ -3493,6 +3500,13 @@
"null"
]
},
"bundleVersion": {
"description": "The version of the build that identifies an iteration of the bundle.",
"type": [
"string",
"null"
]
},
"minimumSystemVersion": {
"description": "A version string indicating the minimum iOS version that the bundled application supports. Defaults to `13.0`.\n\n Maps to the IPHONEOS_DEPLOYMENT_TARGET value.",
"default": "13.0",
Expand Down
8 changes: 8 additions & 0 deletions crates/tauri-utils/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,9 @@ pub struct MacConfig {
/// The files to include in the application relative to the Contents directory.
#[serde(default)]
pub files: HashMap<PathBuf, PathBuf>,
/// The version of the build that identifies an iteration of the bundle.
#[serde(alias = "bundle-version")]
pub bundle_version: Option<String>,
/// A version string indicating the minimum macOS X version that the bundled application supports. Defaults to `10.13`.
///
/// Setting it to `null` completely removes the `LSMinimumSystemVersion` field on the bundle's `Info.plist`
Expand Down Expand Up @@ -651,6 +654,7 @@ impl Default for MacConfig {
Self {
frameworks: None,
files: HashMap::new(),
bundle_version: None,
minimum_system_version: macos_minimum_system_version(),
exception_domain: None,
signing_identity: None,
Expand Down Expand Up @@ -2522,6 +2526,9 @@ pub struct IosConfig {
/// The `APPLE_DEVELOPMENT_TEAM` environment variable can be set to overwrite it.
#[serde(alias = "development-team")]
pub development_team: Option<String>,
/// The version of the build that identifies an iteration of the bundle.
#[serde(alias = "bundle-version")]
pub bundle_version: Option<String>,
/// A version string indicating the minimum iOS version that the bundled application supports. Defaults to `13.0`.
///
/// Maps to the IPHONEOS_DEPLOYMENT_TARGET value.
Expand All @@ -2538,6 +2545,7 @@ impl Default for IosConfig {
template: None,
frameworks: None,
development_team: None,
bundle_version: None,
minimum_system_version: ios_minimum_system_version(),
}
}
Expand Down
Loading