From fcb702ec4d924e81943efaeebea8d3edb7289c33 Mon Sep 17 00:00:00 2001 From: Sam Lidder Date: Tue, 17 Mar 2026 17:12:44 -0400 Subject: [PATCH] fix(cli): allow `build --bundles nsis` arg in linux+macOS (#14954) --- .changes/fix-build-bundles-arg.md | 7 ++++ crates/tauri-bundler/src/bundle.rs | 42 +++++++++++++-------- crates/tauri-bundler/src/bundle/kmp/mod.rs | 2 - crates/tauri-bundler/src/bundle/settings.rs | 2 +- crates/tauri-cli/src/bundle.rs | 2 +- 5 files changed, 36 insertions(+), 19 deletions(-) create mode 100644 .changes/fix-build-bundles-arg.md diff --git a/.changes/fix-build-bundles-arg.md b/.changes/fix-build-bundles-arg.md new file mode 100644 index 000000000..de735d18c --- /dev/null +++ b/.changes/fix-build-bundles-arg.md @@ -0,0 +1,7 @@ +--- +"tauri-bundler": patch:bug +"tauri-cli": patch:bug +"@tauri-apps/cli": patch:bug +--- + +Fix `build --bundles` to allow `nsis` arg in linux+macOS diff --git a/crates/tauri-bundler/src/bundle.rs b/crates/tauri-bundler/src/bundle.rs index e20fb19c8..ab0a45032 100644 --- a/crates/tauri-bundler/src/bundle.rs +++ b/crates/tauri-bundler/src/bundle.rs @@ -4,7 +4,6 @@ // SPDX-License-Identifier: MIT mod category; -#[cfg(any(target_os = "linux", target_os = "windows"))] mod kmp; #[cfg(target_os = "linux")] mod linux; @@ -17,26 +16,16 @@ mod windows; use tauri_utils::{display_path, platform::Target as TargetPlatform}; -#[cfg(any(target_os = "linux", target_os = "windows"))] const BUNDLE_VAR_TOKEN: &[u8] = b"__TAURI_BUNDLE_TYPE_VAR_UNK"; /// Patch a binary with bundle type information -#[cfg(any(target_os = "linux", target_os = "windows"))] fn patch_binary(binary: &PathBuf, package_type: &PackageType) -> crate::Result<()> { - log::info!( - "Patching {} with bundle type information: {}", - display_path(binary), - package_type.short_name() - ); - - let mut file_data = std::fs::read(binary).expect("Could not read binary file."); - - let bundle_var_index = - kmp::index_of(BUNDLE_VAR_TOKEN, &file_data).ok_or(crate::Error::MissingBundleTypeVar)?; #[cfg(target_os = "linux")] let bundle_type = match package_type { crate::PackageType::Deb => b"__TAURI_BUNDLE_TYPE_VAR_DEB", crate::PackageType::Rpm => b"__TAURI_BUNDLE_TYPE_VAR_RPM", crate::PackageType::AppImage => b"__TAURI_BUNDLE_TYPE_VAR_APP", + // NSIS installers can be built in linux using cargo-xwin + crate::PackageType::Nsis => b"__TAURI_BUNDLE_TYPE_VAR_NSS", _ => { return Err(crate::Error::InvalidPackageType( package_type.short_name().to_owned(), @@ -55,7 +44,31 @@ fn patch_binary(binary: &PathBuf, package_type: &PackageType) -> crate::Result<( )) } }; + #[cfg(target_os = "macos")] + let bundle_type = match package_type { + // NSIS installers can be built in macOS using cargo-xwin + crate::PackageType::Nsis => b"__TAURI_BUNDLE_TYPE_VAR_NSS", + crate::PackageType::MacOsBundle | crate::PackageType::Dmg => { + // skip patching for macOS-native bundles + return Ok(()); + } + _ => { + return Err(crate::Error::InvalidPackageType( + package_type.short_name().to_owned(), + "macOS".to_owned(), + )) + } + }; + log::info!( + "Patching {} with bundle type information: {}", + display_path(binary), + package_type.short_name() + ); + + let mut file_data = std::fs::read(binary).expect("Could not read binary file."); + let bundle_var_index = + kmp::index_of(BUNDLE_VAR_TOKEN, &file_data).ok_or(crate::Error::MissingBundleTypeVar)?; file_data[bundle_var_index..bundle_var_index + BUNDLE_VAR_TOKEN.len()] .copy_from_slice(bundle_type); @@ -133,7 +146,6 @@ pub fn bundle_project(settings: &Settings) -> crate::Result> { continue; } - #[cfg(any(target_os = "linux", target_os = "windows"))] if let Err(e) = patch_binary(&main_binary_path, package_type) { log::warn!("Failed to add bundler type to the binary: {e}. Updater plugin may not be able to update this package. This shouldn't normally happen, please report it to https://github.com/tauri-apps/tauri/issues"); } @@ -163,7 +175,7 @@ pub fn bundle_project(settings: &Settings) -> crate::Result> { #[cfg(target_os = "windows")] PackageType::WindowsMsi => windows::msi::bundle_project(settings, false)?, - // note: don't restrict to windows as NSIS installers can be built in linux using cargo-xwin + // don't restrict to windows as NSIS installers can be built in linux+macOS using cargo-xwin PackageType::Nsis => windows::nsis::bundle_project(settings, false)?, #[cfg(target_os = "linux")] diff --git a/crates/tauri-bundler/src/bundle/kmp/mod.rs b/crates/tauri-bundler/src/bundle/kmp/mod.rs index 3e8489023..863e4145c 100644 --- a/crates/tauri-bundler/src/bundle/kmp/mod.rs +++ b/crates/tauri-bundler/src/bundle/kmp/mod.rs @@ -5,7 +5,6 @@ // Knuth–Morris–Pratt algorithm // based on https://github.com/howeih/rust_kmp -#[cfg(any(target_os = "linux", target_os = "windows"))] pub fn index_of(pattern: &[u8], target: &[u8]) -> Option { let failure_function = find_failure_function(pattern); @@ -38,7 +37,6 @@ pub fn index_of(pattern: &[u8], target: &[u8]) -> Option { None } -#[cfg(any(target_os = "linux", target_os = "windows"))] fn find_failure_function(pattern: &[u8]) -> Vec { let mut i = 1; let mut j = 0; diff --git a/crates/tauri-bundler/src/bundle/settings.rs b/crates/tauri-bundler/src/bundle/settings.rs index 71321b293..5e2a81b38 100644 --- a/crates/tauri-bundler/src/bundle/settings.rs +++ b/crates/tauri-bundler/src/bundle/settings.rs @@ -126,7 +126,7 @@ const ALL_PACKAGE_TYPES: &[PackageType] = &[ PackageType::IosBundle, #[cfg(target_os = "windows")] PackageType::WindowsMsi, - #[cfg(target_os = "windows")] + // NSIS installers can be built on all platforms but it's hidden in the --help output on macOS/Linux. PackageType::Nsis, #[cfg(target_os = "macos")] PackageType::MacOsBundle, diff --git a/crates/tauri-cli/src/bundle.rs b/crates/tauri-cli/src/bundle.rs index d40dba652..4625eddc0 100644 --- a/crates/tauri-cli/src/bundle.rs +++ b/crates/tauri-cli/src/bundle.rs @@ -43,7 +43,7 @@ impl ValueEnum for BundleFormat { } fn to_possible_value(&self) -> Option { - let hide = self.0 == PackageType::Updater; + let hide = (!cfg!(windows) && self.0 == PackageType::Nsis) || self.0 == PackageType::Updater; Some(PossibleValue::new(self.0.short_name()).hide(hide)) } }