tauri_bundler/bundle/
settings.rs

1// Copyright 2016-2019 Cargo-Bundle developers <https://github.com/burtonageo/cargo-bundle>
2// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
3// SPDX-License-Identifier: Apache-2.0
4// SPDX-License-Identifier: MIT
5
6use super::category::AppCategory;
7use crate::{bundle::platform::target_triple, utils::fs_utils};
8use anyhow::Context;
9pub use tauri_utils::config::WebviewInstallMode;
10use tauri_utils::{
11  config::{
12    BundleType, DeepLinkProtocol, FileAssociation, NSISInstallerMode, NsisCompression,
13    RpmCompression,
14  },
15  resources::{external_binaries, ResourcePaths},
16};
17
18use std::{
19  collections::HashMap,
20  path::{Path, PathBuf},
21};
22
23/// The type of the package we're bundling.
24#[derive(Clone, Copy, Debug, Eq, PartialEq)]
25#[non_exhaustive]
26pub enum PackageType {
27  /// The macOS application bundle (.app).
28  MacOsBundle,
29  /// The iOS app bundle.
30  IosBundle,
31  /// The Windows bundle (.msi).
32  WindowsMsi,
33  /// The NSIS bundle (.exe).
34  Nsis,
35  /// The Linux Debian package bundle (.deb).
36  Deb,
37  /// The Linux RPM bundle (.rpm).
38  Rpm,
39  /// The Linux AppImage bundle (.AppImage).
40  AppImage,
41  /// The macOS DMG bundle (.dmg).
42  Dmg,
43  /// The Updater bundle.
44  Updater,
45}
46
47impl From<BundleType> for PackageType {
48  fn from(bundle: BundleType) -> Self {
49    match bundle {
50      BundleType::Deb => Self::Deb,
51      BundleType::Rpm => Self::Rpm,
52      BundleType::AppImage => Self::AppImage,
53      BundleType::Msi => Self::WindowsMsi,
54      BundleType::Nsis => Self::Nsis,
55      BundleType::App => Self::MacOsBundle,
56      BundleType::Dmg => Self::Dmg,
57    }
58  }
59}
60
61impl PackageType {
62  /// Maps a short name to a PackageType.
63  /// Possible values are "deb", "ios", "msi", "app", "rpm", "appimage", "dmg", "updater".
64  pub fn from_short_name(name: &str) -> Option<PackageType> {
65    // Other types we may eventually want to support: apk.
66    match name {
67      "deb" => Some(PackageType::Deb),
68      "ios" => Some(PackageType::IosBundle),
69      "msi" => Some(PackageType::WindowsMsi),
70      "nsis" => Some(PackageType::Nsis),
71      "app" => Some(PackageType::MacOsBundle),
72      "rpm" => Some(PackageType::Rpm),
73      "appimage" => Some(PackageType::AppImage),
74      "dmg" => Some(PackageType::Dmg),
75      "updater" => Some(PackageType::Updater),
76      _ => None,
77    }
78  }
79
80  /// Gets the short name of this PackageType.
81  #[allow(clippy::trivially_copy_pass_by_ref)]
82  pub fn short_name(&self) -> &'static str {
83    match *self {
84      PackageType::Deb => "deb",
85      PackageType::IosBundle => "ios",
86      PackageType::WindowsMsi => "msi",
87      PackageType::Nsis => "nsis",
88      PackageType::MacOsBundle => "app",
89      PackageType::Rpm => "rpm",
90      PackageType::AppImage => "appimage",
91      PackageType::Dmg => "dmg",
92      PackageType::Updater => "updater",
93    }
94  }
95
96  /// Gets the list of the possible package types.
97  pub fn all() -> &'static [PackageType] {
98    ALL_PACKAGE_TYPES
99  }
100
101  /// Gets a number representing priority which used to sort package types
102  /// in an order that guarantees that if a certain package type
103  /// depends on another (like Dmg depending on MacOsBundle), the dependency
104  /// will be built first
105  ///
106  /// The lower the number, the higher the priority
107  pub fn priority(&self) -> u32 {
108    match self {
109      PackageType::MacOsBundle => 0,
110      PackageType::IosBundle => 0,
111      PackageType::WindowsMsi => 0,
112      PackageType::Nsis => 0,
113      PackageType::Deb => 0,
114      PackageType::Rpm => 0,
115      PackageType::AppImage => 0,
116      PackageType::Dmg => 1,
117      PackageType::Updater => 2,
118    }
119  }
120}
121
122const ALL_PACKAGE_TYPES: &[PackageType] = &[
123  #[cfg(target_os = "linux")]
124  PackageType::Deb,
125  #[cfg(target_os = "macos")]
126  PackageType::IosBundle,
127  #[cfg(target_os = "windows")]
128  PackageType::WindowsMsi,
129  #[cfg(target_os = "windows")]
130  PackageType::Nsis,
131  #[cfg(target_os = "macos")]
132  PackageType::MacOsBundle,
133  #[cfg(target_os = "linux")]
134  PackageType::Rpm,
135  #[cfg(target_os = "macos")]
136  PackageType::Dmg,
137  #[cfg(target_os = "linux")]
138  PackageType::AppImage,
139  PackageType::Updater,
140];
141
142/// The package settings.
143#[derive(Debug, Clone)]
144pub struct PackageSettings {
145  /// the package's product name.
146  pub product_name: String,
147  /// the package's version.
148  pub version: String,
149  /// the package's description.
150  pub description: String,
151  /// the package's homepage.
152  pub homepage: Option<String>,
153  /// the package's authors.
154  pub authors: Option<Vec<String>>,
155  /// the default binary to run.
156  pub default_run: Option<String>,
157}
158
159/// The updater settings.
160#[derive(Debug, Default, Clone)]
161pub struct UpdaterSettings {
162  /// Should generate v1 compatible zipped updater
163  pub v1_compatible: bool,
164  /// Signature public key.
165  pub pubkey: String,
166  /// Args to pass to `msiexec.exe` to run the updater on Windows.
167  pub msiexec_args: &'static [&'static str],
168}
169
170/// The Linux debian bundle settings.
171#[derive(Clone, Debug, Default)]
172pub struct DebianSettings {
173  // OS-specific settings:
174  /// the list of debian dependencies.
175  pub depends: Option<Vec<String>>,
176  /// the list of debian dependencies recommendations.
177  pub recommends: Option<Vec<String>>,
178  /// the list of dependencies the package provides.
179  pub provides: Option<Vec<String>>,
180  /// the list of package conflicts.
181  pub conflicts: Option<Vec<String>>,
182  /// the list of package replaces.
183  pub replaces: Option<Vec<String>>,
184  /// List of custom files to add to the deb package.
185  /// Maps the path on the debian package to the path of the file to include (relative to the current working directory).
186  pub files: HashMap<PathBuf, PathBuf>,
187  /// Path to a custom desktop file Handlebars template.
188  ///
189  /// Available variables: `categories`, `comment` (optional), `exec`, `icon` and `name`.
190  ///
191  /// Default file contents:
192  /// ```text
193  #[doc = include_str!("./linux/freedesktop/main.desktop")]
194  /// ```
195  pub desktop_template: Option<PathBuf>,
196  /// Define the section in Debian Control file. See : <https://www.debian.org/doc/debian-policy/ch-archive.html#s-subsections>
197  pub section: Option<String>,
198  /// Change the priority of the Debian Package. By default, it is set to `optional`.
199  /// Recognized Priorities as of now are :  `required`, `important`, `standard`, `optional`, `extra`
200  pub priority: Option<String>,
201  /// Path of the uncompressed Changelog file, to be stored at /usr/share/doc/package-name/changelog.gz. See
202  /// <https://www.debian.org/doc/debian-policy/ch-docs.html#changelog-files-and-release-notes>
203  pub changelog: Option<PathBuf>,
204  /// Path to script that will be executed before the package is unpacked. See
205  /// <https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html>
206  pub pre_install_script: Option<PathBuf>,
207  /// Path to script that will be executed after the package is unpacked. See
208  /// <https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html>
209  pub post_install_script: Option<PathBuf>,
210  /// Path to script that will be executed before the package is removed. See
211  /// <https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html>
212  pub pre_remove_script: Option<PathBuf>,
213  /// Path to script that will be executed after the package is removed. See
214  /// <https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html>
215  pub post_remove_script: Option<PathBuf>,
216}
217
218/// The Linux AppImage bundle settings.
219#[derive(Clone, Debug, Default)]
220pub struct AppImageSettings {
221  /// The files to include in the Appimage Binary.
222  pub files: HashMap<PathBuf, PathBuf>,
223  /// Whether to include gstreamer plugins for audio/media support.
224  pub bundle_media_framework: bool,
225  /// Whether to include the `xdg-open` binary.
226  pub bundle_xdg_open: bool,
227}
228
229/// The RPM bundle settings.
230#[derive(Clone, Debug, Default)]
231pub struct RpmSettings {
232  /// The list of RPM dependencies your application relies on.
233  pub depends: Option<Vec<String>>,
234  /// the list of of RPM dependencies your application recommends.
235  pub recommends: Option<Vec<String>>,
236  /// The list of RPM dependencies your application provides.
237  pub provides: Option<Vec<String>>,
238  /// The list of RPM dependencies your application conflicts with. They must not be present
239  /// in order for the package to be installed.
240  pub conflicts: Option<Vec<String>>,
241  /// The list of RPM dependencies your application supersedes - if this package is installed,
242  /// packages listed as "obsoletes" will be automatically removed (if they are present).
243  pub obsoletes: Option<Vec<String>>,
244  /// The RPM release tag.
245  pub release: String,
246  /// The RPM epoch.
247  pub epoch: u32,
248  /// List of custom files to add to the RPM package.
249  /// Maps the path on the RPM package to the path of the file to include (relative to the current working directory).
250  pub files: HashMap<PathBuf, PathBuf>,
251  /// Path to a custom desktop file Handlebars template.
252  ///
253  /// Available variables: `categories`, `comment` (optional), `exec`, `icon` and `name`.
254  ///
255  /// Default file contents:
256  /// ```text
257  #[doc = include_str!("./linux/freedesktop/main.desktop")]
258  /// ```
259  pub desktop_template: Option<PathBuf>,
260  /// Path to script that will be executed before the package is unpacked. See
261  /// <http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html>
262  pub pre_install_script: Option<PathBuf>,
263  /// Path to script that will be executed after the package is unpacked. See
264  /// <http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html>
265  pub post_install_script: Option<PathBuf>,
266  /// Path to script that will be executed before the package is removed. See
267  /// <http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html>
268  pub pre_remove_script: Option<PathBuf>,
269  /// Path to script that will be executed after the package is removed. See
270  /// <http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html>
271  pub post_remove_script: Option<PathBuf>,
272  /// Compression algorithm and level. Defaults to `Gzip` with level 6.
273  pub compression: Option<RpmCompression>,
274}
275
276/// Position coordinates struct.
277#[derive(Clone, Debug, Default)]
278pub struct Position {
279  /// X coordinate.
280  pub x: u32,
281  /// Y coordinate.
282  pub y: u32,
283}
284
285/// Size of the window.
286#[derive(Clone, Debug, Default)]
287pub struct Size {
288  /// Width of the window.
289  pub width: u32,
290  /// Height of the window.
291  pub height: u32,
292}
293
294/// The DMG bundle settings.
295#[derive(Clone, Debug, Default)]
296pub struct DmgSettings {
297  /// Image to use as the background in dmg file. Accepted formats: `png`/`jpg`/`gif`.
298  pub background: Option<PathBuf>,
299  /// Position of volume window on screen.
300  pub window_position: Option<Position>,
301  /// Size of volume window.
302  pub window_size: Size,
303  /// Position of app file on window.
304  pub app_position: Position,
305  /// Position of application folder on window.
306  pub application_folder_position: Position,
307}
308
309/// The macOS bundle settings.
310#[derive(Clone, Debug, Default)]
311pub struct MacOsSettings {
312  /// MacOS frameworks that need to be bundled with the app.
313  ///
314  /// Each string can either be the name of a framework (without the `.framework` extension, e.g. `"SDL2"`),
315  /// in which case we will search for that framework in the standard install locations (`~/Library/Frameworks/`, `/Library/Frameworks/`, and `/Network/Library/Frameworks/`),
316  /// or a path to a specific framework bundle (e.g. `./data/frameworks/SDL2.framework`).  Note that this setting just makes tauri-bundler copy the specified frameworks into the OS X app bundle
317  /// (under `Foobar.app/Contents/Frameworks/`); you are still responsible for:
318  ///
319  /// - arranging for the compiled binary to link against those frameworks (e.g. by emitting lines like `cargo:rustc-link-lib=framework=SDL2` from your `build.rs` script)
320  ///
321  /// - embedding the correct rpath in your binary (e.g. by running `install_name_tool -add_rpath "@executable_path/../Frameworks" path/to/binary` after compiling)
322  pub frameworks: Option<Vec<String>>,
323  /// List of custom files to add to the application bundle.
324  /// Maps the path in the Contents directory in the app to the path of the file to include (relative to the current working directory).
325  pub files: HashMap<PathBuf, PathBuf>,
326  /// A version string indicating the minimum MacOS version that the bundled app supports (e.g. `"10.11"`).
327  /// 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`.
328  pub minimum_system_version: Option<String>,
329  /// The exception domain to use on the macOS .app bundle.
330  ///
331  /// This allows communication to the outside world e.g. a web server you're shipping.
332  pub exception_domain: Option<String>,
333  /// Code signing identity.
334  pub signing_identity: Option<String>,
335  /// Preserve the hardened runtime version flag, see <https://developer.apple.com/documentation/security/hardened_runtime>
336  ///
337  /// Settings this to `false` is useful when using an ad-hoc signature, making it less strict.
338  pub hardened_runtime: bool,
339  /// Provider short name for notarization.
340  pub provider_short_name: Option<String>,
341  /// Path to the entitlements.plist file.
342  pub entitlements: Option<String>,
343  /// Path to the Info.plist file for the bundle.
344  pub info_plist_path: Option<PathBuf>,
345}
346
347/// Configuration for a target language for the WiX build.
348#[derive(Debug, Clone, Default)]
349pub struct WixLanguageConfig {
350  /// The path to a locale (`.wxl`) file. See <https://wixtoolset.org/documentation/manual/v3/howtos/ui_and_localization/build_a_localized_version.html>.
351  pub locale_path: Option<PathBuf>,
352}
353
354/// The languages to build using WiX.
355#[derive(Debug, Clone)]
356pub struct WixLanguage(pub Vec<(String, WixLanguageConfig)>);
357
358impl Default for WixLanguage {
359  fn default() -> Self {
360    Self(vec![("en-US".into(), Default::default())])
361  }
362}
363
364/// Settings specific to the WiX implementation.
365#[derive(Clone, Debug, Default)]
366pub struct WixSettings {
367  /// MSI installer version in the format `major.minor.patch.build` (build is optional).
368  ///
369  /// Because a valid version is required for MSI installer, it will be derived from [`PackageSettings::version`] if this field is not set.
370  ///
371  /// The first field is the major version and has a maximum value of 255. The second field is the minor version and has a maximum value of 255.
372  /// The third and fourth fields have a maximum value of 65,535.
373  ///
374  /// See <https://learn.microsoft.com/en-us/windows/win32/msi/productversion> for more info.
375  pub version: Option<String>,
376  /// A GUID upgrade code for MSI installer. This code **_must stay the same across all of your updates_**,
377  /// otherwise, Windows will treat your update as a different app and your users will have duplicate versions of your app.
378  ///
379  /// By default, tauri generates this code by generating a Uuid v5 using the string `<productName>.exe.app.x64` in the DNS namespace.
380  /// You can use Tauri's CLI to generate and print this code for you by running `tauri inspect wix-upgrade-code`.
381  ///
382  /// It is recommended that you set this value in your tauri config file to avoid accidental changes in your upgrade code
383  /// whenever you want to change your product name.
384  pub upgrade_code: Option<uuid::Uuid>,
385  /// The app languages to build. See <https://docs.microsoft.com/en-us/windows/win32/msi/localizing-the-error-and-actiontext-tables>.
386  pub language: WixLanguage,
387  /// By default, the bundler uses an internal template.
388  /// This option allows you to define your own wix file.
389  pub template: Option<PathBuf>,
390  /// A list of paths to .wxs files with WiX fragments to use.
391  pub fragment_paths: Vec<PathBuf>,
392  /// The ComponentGroup element ids you want to reference from the fragments.
393  pub component_group_refs: Vec<String>,
394  /// The Component element ids you want to reference from the fragments.
395  pub component_refs: Vec<String>,
396  /// The FeatureGroup element ids you want to reference from the fragments.
397  pub feature_group_refs: Vec<String>,
398  /// The Feature element ids you want to reference from the fragments.
399  pub feature_refs: Vec<String>,
400  /// The Merge element ids you want to reference from the fragments.
401  pub merge_refs: Vec<String>,
402  /// Create an elevated update task within Windows Task Scheduler.
403  pub enable_elevated_update_task: bool,
404  /// Path to a bitmap file to use as the installation user interface banner.
405  /// This bitmap will appear at the top of all but the first page of the installer.
406  ///
407  /// The required dimensions are 493px × 58px.
408  pub banner_path: Option<PathBuf>,
409  /// Path to a bitmap file to use on the installation user interface dialogs.
410  /// It is used on the welcome and completion dialogs.
411  ///
412  /// The required dimensions are 493px × 312px.
413  pub dialog_image_path: Option<PathBuf>,
414  /// Enables FIPS compliant algorithms.
415  pub fips_compliant: bool,
416}
417
418/// Settings specific to the NSIS implementation.
419#[derive(Clone, Debug, Default)]
420pub struct NsisSettings {
421  /// A custom .nsi template to use.
422  pub template: Option<PathBuf>,
423  /// The path to a bitmap file to display on the header of installers pages.
424  ///
425  /// The recommended dimensions are 150px x 57px.
426  pub header_image: Option<PathBuf>,
427  /// The path to a bitmap file for the Welcome page and the Finish page.
428  ///
429  /// The recommended dimensions are 164px x 314px.
430  pub sidebar_image: Option<PathBuf>,
431  /// The path to an icon file used as the installer icon.
432  pub installer_icon: Option<PathBuf>,
433  /// Whether the installation will be for all users or just the current user.
434  pub install_mode: NSISInstallerMode,
435  /// A list of installer languages.
436  /// By default the OS language is used. If the OS language is not in the list of languages, the first language will be used.
437  /// To allow the user to select the language, set `display_language_selector` to `true`.
438  ///
439  /// See <https://github.com/kichik/nsis/tree/9465c08046f00ccb6eda985abbdbf52c275c6c4d/Contrib/Language%20files> for the complete list of languages.
440  pub languages: Option<Vec<String>>,
441  /// An key-value pair where the key is the language and the
442  /// value is the path to a custom `.nsi` file that holds the translated text for tauri's custom messages.
443  ///
444  /// See <https://github.com/tauri-apps/tauri/blob/dev/crates/tauri-bundler/src/bundle/windows/nsis/languages/English.nsh> for an example `.nsi` file.
445  ///
446  /// **Note**: the key must be a valid NSIS language and it must be added to [`NsisConfig`]languages array,
447  pub custom_language_files: Option<HashMap<String, PathBuf>>,
448  /// Whether to display a language selector dialog before the installer and uninstaller windows are rendered or not.
449  /// By default the OS language is selected, with a fallback to the first language in the `languages` array.
450  pub display_language_selector: bool,
451  /// Set compression algorithm used to compress files in the installer.
452  pub compression: NsisCompression,
453  /// Set the folder name for the start menu shortcut.
454  ///
455  /// Use this option if you have multiple apps and wish to group their shortcuts under one folder
456  /// or if you generally prefer to set your shortcut inside a folder.
457  ///
458  /// Examples:
459  /// - `AwesomePublisher`, shortcut will be placed in `%AppData%\Microsoft\Windows\Start Menu\Programs\AwesomePublisher\<your-app>.lnk`
460  /// - If unset, shortcut will be placed in `%AppData%\Microsoft\Windows\Start Menu\Programs\<your-app>.lnk`
461  pub start_menu_folder: Option<String>,
462  /// A path to a `.nsh` file that contains special NSIS macros to be hooked into the
463  /// main installer.nsi script.
464  ///
465  /// Supported hooks are:
466  /// - `NSIS_HOOK_PREINSTALL`: This hook runs before copying files, setting registry key values and creating shortcuts.
467  /// - `NSIS_HOOK_POSTINSTALL`: This hook runs after the installer has finished copying all files, setting the registry keys and created shortcuts.
468  /// - `NSIS_HOOK_PREUNINSTALL`: This hook runs before removing any files, registry keys and shortcuts.
469  /// - `NSIS_HOOK_POSTUNINSTALL`: This hook runs after files, registry keys and shortcuts have been removed.
470  ///
471  ///
472  /// ### Example
473  ///
474  /// ```nsh
475  /// !macro NSIS_HOOK_PREINSTALL
476  ///   MessageBox MB_OK "PreInstall"
477  /// !macroend
478  ///
479  /// !macro NSIS_HOOK_POSTINSTALL
480  ///   MessageBox MB_OK "PostInstall"
481  /// !macroend
482  ///
483  /// !macro NSIS_HOOK_PREUNINSTALL
484  ///   MessageBox MB_OK "PreUnInstall"
485  /// !macroend
486  ///
487  /// !macro NSIS_HOOK_POSTUNINSTALL
488  ///   MessageBox MB_OK "PostUninstall"
489  /// !macroend
490  /// ```
491  pub installer_hooks: Option<PathBuf>,
492  /// Try to ensure that the WebView2 version is equal to or newer than this version,
493  /// if the user's WebView2 is older than this version,
494  /// the installer will try to trigger a WebView2 update.
495  pub minimum_webview2_version: Option<String>,
496}
497
498/// The Custom Signing Command Settings for Windows exe
499#[derive(Clone, Debug)]
500pub struct CustomSignCommandSettings {
501  /// The command to run to sign the binary.
502  pub cmd: String,
503  /// The arguments to pass to the command.
504  ///
505  /// "%1" will be replaced with the path to the binary to be signed.
506  pub args: Vec<String>,
507}
508
509/// The Windows bundle settings.
510#[derive(Clone, Debug)]
511pub struct WindowsSettings {
512  /// The file digest algorithm to use for creating file signatures. Required for code signing. SHA-256 is recommended.
513  pub digest_algorithm: Option<String>,
514  /// The SHA1 hash of the signing certificate.
515  pub certificate_thumbprint: Option<String>,
516  /// Server to use during timestamping.
517  pub timestamp_url: Option<String>,
518  /// Whether to use Time-Stamp Protocol (TSP, a.k.a. RFC 3161) for the timestamp server. Your code signing provider may
519  /// use a TSP timestamp server, like e.g. SSL.com does. If so, enable TSP by setting to true.
520  pub tsp: bool,
521  /// WiX configuration.
522  pub wix: Option<WixSettings>,
523  /// Nsis configuration.
524  pub nsis: Option<NsisSettings>,
525  /// The path to the application icon. Defaults to `./icons/icon.ico`.
526  #[deprecated = "This is used for the MSI installer and will be removed in 3.0.0, use `BundleSettings::icon` field and make sure a `.ico` icon exists instead."]
527  pub icon_path: PathBuf,
528  /// The installation mode for the Webview2 runtime.
529  pub webview_install_mode: WebviewInstallMode,
530  /// Validates a second app installation, blocking the user from installing an older version if set to `false`.
531  ///
532  /// For instance, if `1.2.1` is installed, the user won't be able to install app version `1.2.0` or `1.1.5`.
533  ///
534  /// /// The default value of this flag is `true`.
535  pub allow_downgrades: bool,
536
537  /// Specify a custom command to sign the binaries.
538  /// This command needs to have a `%1` in it which is just a placeholder for the binary path,
539  /// which we will detect and replace before calling the command.
540  ///
541  /// Example:
542  /// ```text
543  /// sign-cli --arg1 --arg2 %1
544  /// ```
545  ///
546  /// By Default we use `signtool.exe` which can be found only on Windows so
547  /// if you are on another platform and want to cross-compile and sign you will
548  /// need to use another tool like `osslsigncode`.
549  pub sign_command: Option<CustomSignCommandSettings>,
550}
551
552#[allow(deprecated)]
553mod _default {
554  use super::*;
555
556  impl Default for WindowsSettings {
557    fn default() -> Self {
558      Self {
559        digest_algorithm: None,
560        certificate_thumbprint: None,
561        timestamp_url: None,
562        tsp: false,
563        wix: None,
564        nsis: None,
565        icon_path: PathBuf::from("icons/icon.ico"),
566        webview_install_mode: Default::default(),
567        allow_downgrades: true,
568        sign_command: None,
569      }
570    }
571  }
572}
573
574/// The bundle settings of the BuildArtifact we're bundling.
575#[derive(Clone, Debug, Default)]
576pub struct BundleSettings {
577  /// the app's identifier.
578  pub identifier: Option<String>,
579  /// The app's publisher. Defaults to the second element in the identifier string.
580  ///
581  /// Currently maps to the Manufacturer property of the Windows Installer
582  /// and the Maintainer field of debian packages if the Cargo.toml does not have the authors field.
583  pub publisher: Option<String>,
584  /// A url to the home page of your application. If None, will
585  /// fallback to [PackageSettings::homepage].
586  ///
587  /// Supported bundle targets: `deb`, `rpm`, `nsis` and `msi`
588  pub homepage: Option<String>,
589  /// the app's icon list.
590  pub icon: Option<Vec<String>>,
591  /// the app's resources to bundle.
592  ///
593  /// each item can be a path to a file or a path to a folder.
594  ///
595  /// supports glob patterns.
596  pub resources: Option<Vec<String>>,
597  /// The app's resources to bundle. Takes precedence over `Self::resources` when specified.
598  ///
599  /// Maps each resource path to its target directory in the bundle resources directory.
600  ///
601  /// Supports glob patterns.
602  pub resources_map: Option<HashMap<String, String>>,
603  /// the app's copyright.
604  pub copyright: Option<String>,
605  /// The package's license identifier to be included in the appropriate bundles.
606  /// If not set, defaults to the license from the Cargo.toml file.
607  pub license: Option<String>,
608  /// The path to the license file to be included in the appropriate bundles.
609  pub license_file: Option<PathBuf>,
610  /// the app's category.
611  pub category: Option<AppCategory>,
612  /// the file associations
613  pub file_associations: Option<Vec<FileAssociation>>,
614  /// the app's short description.
615  pub short_description: Option<String>,
616  /// the app's long description.
617  pub long_description: Option<String>,
618  // Bundles for other binaries:
619  /// Configuration map for the apps to bundle.
620  pub bin: Option<HashMap<String, BundleSettings>>,
621  /// External binaries to add to the bundle.
622  ///
623  /// Note that each binary name should have the target platform's target triple appended,
624  /// as well as `.exe` for Windows.
625  /// For example, if you're bundling a sidecar called `sqlite3`, the bundler expects
626  /// a binary named `sqlite3-x86_64-unknown-linux-gnu` on linux,
627  /// and `sqlite3-x86_64-pc-windows-gnu.exe` on windows.
628  ///
629  /// Run `tauri build --help` for more info on targets.
630  ///
631  /// If you are building a universal binary for MacOS, the bundler expects
632  /// your external binary to also be universal, and named after the target triple,
633  /// e.g. `sqlite3-universal-apple-darwin`. See
634  /// <https://developer.apple.com/documentation/apple-silicon/building-a-universal-macos-binary>
635  pub external_bin: Option<Vec<String>>,
636  /// Deep-link protocols.
637  pub deep_link_protocols: Option<Vec<DeepLinkProtocol>>,
638  /// Debian-specific settings.
639  pub deb: DebianSettings,
640  /// AppImage-specific settings.
641  pub appimage: AppImageSettings,
642  /// Rpm-specific settings.
643  pub rpm: RpmSettings,
644  /// DMG-specific settings.
645  pub dmg: DmgSettings,
646  /// MacOS-specific settings.
647  pub macos: MacOsSettings,
648  /// Updater configuration.
649  pub updater: Option<UpdaterSettings>,
650  /// Windows-specific settings.
651  pub windows: WindowsSettings,
652}
653
654/// A binary to bundle.
655#[derive(Clone, Debug)]
656pub struct BundleBinary {
657  name: String,
658  main: bool,
659  src_path: Option<String>,
660}
661
662impl BundleBinary {
663  /// Creates a new bundle binary.
664  pub fn new(name: String, main: bool) -> Self {
665    Self {
666      name,
667      main,
668      src_path: None,
669    }
670  }
671
672  /// Creates a new bundle binary with path.
673  pub fn with_path(name: String, main: bool, src_path: Option<String>) -> Self {
674    Self {
675      name,
676      src_path,
677      main,
678    }
679  }
680
681  /// Mark the binary as the main executable.
682  pub fn set_main(&mut self, main: bool) {
683    self.main = main;
684  }
685
686  /// Sets the binary name.
687  pub fn set_name(&mut self, name: String) {
688    self.name = name;
689  }
690
691  /// Sets the src path of the binary.
692  #[must_use]
693  pub fn set_src_path(mut self, src_path: Option<String>) -> Self {
694    self.src_path = src_path;
695    self
696  }
697
698  /// Returns the binary `main` flag.
699  pub fn main(&self) -> bool {
700    self.main
701  }
702
703  /// Returns the binary name.
704  pub fn name(&self) -> &str {
705    &self.name
706  }
707
708  /// Returns the binary source path.
709  pub fn src_path(&self) -> Option<&String> {
710    self.src_path.as_ref()
711  }
712}
713
714#[derive(Clone, Copy, Debug, Eq, PartialEq)]
715pub enum Arch {
716  /// For the x86_64 / x64 / AMD64 instruction sets (64 bits).
717  X86_64,
718  /// For the x86 / i686 / i686 / 8086 instruction sets (32 bits).
719  X86,
720  /// For the AArch64 / ARM64 instruction sets (64 bits).
721  AArch64,
722  /// For the AArch32 / ARM32 instruction sets with hard-float (32 bits).
723  Armhf,
724  /// For the AArch32 / ARM32 instruction sets with soft-float (32 bits).
725  Armel,
726  /// For universal macOS applications.
727  Universal,
728}
729
730/// The Settings exposed by the module.
731#[derive(Clone, Debug)]
732pub struct Settings {
733  /// The log level.
734  log_level: log::Level,
735  /// the package settings.
736  package: PackageSettings,
737  /// the package types we're bundling.
738  ///
739  /// if not present, we'll use the PackageType list for the target OS.
740  package_types: Option<Vec<PackageType>>,
741  /// the directory where the bundles will be placed.
742  project_out_directory: PathBuf,
743  /// the directory to place tools used by the bundler,
744  /// if `None`, tools are placed in the current user's platform-specific cache directory.
745  local_tools_directory: Option<PathBuf>,
746  /// the bundle settings.
747  bundle_settings: BundleSettings,
748  /// the binaries to bundle.
749  binaries: Vec<BundleBinary>,
750  /// The target triple.
751  target: String,
752}
753
754/// A builder for [`Settings`].
755#[derive(Default)]
756pub struct SettingsBuilder {
757  log_level: Option<log::Level>,
758  project_out_directory: Option<PathBuf>,
759  package_types: Option<Vec<PackageType>>,
760  package_settings: Option<PackageSettings>,
761  bundle_settings: BundleSettings,
762  binaries: Vec<BundleBinary>,
763  target: Option<String>,
764  local_tools_directory: Option<PathBuf>,
765}
766
767impl SettingsBuilder {
768  /// Creates the default settings builder.
769  pub fn new() -> Self {
770    Default::default()
771  }
772
773  /// Sets the project output directory. It's used as current working directory.
774  #[must_use]
775  pub fn project_out_directory<P: AsRef<Path>>(mut self, path: P) -> Self {
776    self
777      .project_out_directory
778      .replace(path.as_ref().to_path_buf());
779    self
780  }
781
782  /// Sets the directory to place tools used by the bundler
783  /// when [`BundleSettings::use_local_tools_dir`] is true.
784  #[must_use]
785  pub fn local_tools_directory<P: AsRef<Path>>(mut self, path: P) -> Self {
786    self
787      .local_tools_directory
788      .replace(path.as_ref().to_path_buf());
789    self
790  }
791
792  /// Sets the package types to create.
793  #[must_use]
794  pub fn package_types(mut self, package_types: Vec<PackageType>) -> Self {
795    self.package_types = Some(package_types);
796    self
797  }
798
799  /// Sets the package settings.
800  #[must_use]
801  pub fn package_settings(mut self, settings: PackageSettings) -> Self {
802    self.package_settings.replace(settings);
803    self
804  }
805
806  /// Sets the bundle settings.
807  #[must_use]
808  pub fn bundle_settings(mut self, settings: BundleSettings) -> Self {
809    self.bundle_settings = settings;
810    self
811  }
812
813  /// Sets the binaries to bundle.
814  #[must_use]
815  pub fn binaries(mut self, binaries: Vec<BundleBinary>) -> Self {
816    self.binaries = binaries;
817    self
818  }
819
820  /// Sets the target triple.
821  #[must_use]
822  pub fn target(mut self, target: String) -> Self {
823    self.target.replace(target);
824    self
825  }
826
827  /// Sets the log level for spawned commands. Defaults to [`log::Level::Error`].
828  #[must_use]
829  pub fn log_level(mut self, level: log::Level) -> Self {
830    self.log_level.replace(level);
831    self
832  }
833
834  /// Builds a Settings from the CLI args.
835  ///
836  /// Package settings will be read from Cargo.toml.
837  ///
838  /// Bundle settings will be read from $TAURI_DIR/tauri.conf.json if it exists and fallback to Cargo.toml's [package.metadata.bundle].
839  pub fn build(self) -> crate::Result<Settings> {
840    let target = if let Some(t) = self.target {
841      t
842    } else {
843      target_triple()?
844    };
845
846    Ok(Settings {
847      log_level: self.log_level.unwrap_or(log::Level::Error),
848      package: self
849        .package_settings
850        .ok_or_else(|| crate::Error::GenericError("package settings is required".into()))?,
851      package_types: self.package_types,
852      project_out_directory: self
853        .project_out_directory
854        .ok_or_else(|| crate::Error::GenericError("out directory is required".into()))?,
855      local_tools_directory: self.local_tools_directory,
856      binaries: self.binaries,
857      bundle_settings: BundleSettings {
858        external_bin: self
859          .bundle_settings
860          .external_bin
861          .as_ref()
862          .map(|bins| external_binaries(bins, &target)),
863        ..self.bundle_settings
864      },
865      target,
866    })
867  }
868}
869
870impl Settings {
871  /// Sets the log level for spawned commands.
872  pub fn set_log_level(&mut self, level: log::Level) {
873    self.log_level = level;
874  }
875
876  /// Returns the log level for spawned commands.
877  pub fn log_level(&self) -> log::Level {
878    self.log_level
879  }
880
881  /// Returns the directory where the bundle should be placed.
882  pub fn project_out_directory(&self) -> &Path {
883    &self.project_out_directory
884  }
885
886  /// Returns the target triple.
887  pub fn target(&self) -> &str {
888    &self.target
889  }
890
891  /// Returns the architecture for the binary being bundled (e.g. "arm", "x86" or "x86_64").
892  pub fn binary_arch(&self) -> Arch {
893    if self.target.starts_with("x86_64") {
894      Arch::X86_64
895    } else if self.target.starts_with('i') {
896      Arch::X86
897    } else if self.target.starts_with("arm") && self.target.ends_with("hf") {
898      Arch::Armhf
899    } else if self.target.starts_with("arm") {
900      Arch::Armel
901    } else if self.target.starts_with("aarch64") {
902      Arch::AArch64
903    } else if self.target.starts_with("universal") {
904      Arch::Universal
905    } else {
906      panic!("Unexpected target triple {}", self.target)
907    }
908  }
909
910  /// Returns the file name of the binary being bundled.
911  pub fn main_binary(&self) -> crate::Result<&BundleBinary> {
912    self
913      .binaries
914      .iter()
915      .find(|bin| bin.main)
916      .context("failed to find main binary, make sure you have a `package > default-run` in the Cargo.toml file")
917      .map_err(Into::into)
918  }
919
920  /// Returns the file name of the binary being bundled.
921  pub fn main_binary_mut(&mut self) -> crate::Result<&mut BundleBinary> {
922    self
923      .binaries
924      .iter_mut()
925      .find(|bin| bin.main)
926      .context("failed to find main binary, make sure you have a `package > default-run` in the Cargo.toml file")
927      .map_err(Into::into)
928  }
929
930  /// Returns the file name of the binary being bundled.
931  pub fn main_binary_name(&self) -> crate::Result<&str> {
932    self
933      .binaries
934      .iter()
935      .find(|bin| bin.main)
936      .context("failed to find main binary, make sure you have a `package > default-run` in the Cargo.toml file")
937      .map(|b| b.name())
938      .map_err(Into::into)
939  }
940
941  /// Returns the path to the specified binary.
942  pub fn binary_path(&self, binary: &BundleBinary) -> PathBuf {
943    let target_os = self
944      .target()
945      .split('-')
946      .nth(2)
947      .unwrap_or(std::env::consts::OS);
948
949    let path = self.project_out_directory.join(binary.name());
950
951    if target_os == "windows" {
952      path.with_extension("exe")
953    } else {
954      path
955    }
956  }
957
958  /// Returns the list of binaries to bundle.
959  pub fn binaries(&self) -> &Vec<BundleBinary> {
960    &self.binaries
961  }
962
963  /// If a list of package types was specified by the command-line, returns
964  /// that list filtered by the current target OS available targets.
965  ///
966  /// If a target triple was specified by the
967  /// command-line, returns the native package type(s) for that target.
968  ///
969  /// Otherwise returns the native package type(s) for the host platform.
970  ///
971  /// Fails if the host/target's native package type is not supported.
972  pub fn package_types(&self) -> crate::Result<Vec<PackageType>> {
973    let target_os = self
974      .target
975      .split('-')
976      .nth(2)
977      .unwrap_or(std::env::consts::OS)
978      .replace("darwin", "macos");
979
980    let platform_types = match target_os.as_str() {
981      "macos" => vec![PackageType::MacOsBundle, PackageType::Dmg],
982      "ios" => vec![PackageType::IosBundle],
983      "linux" => vec![PackageType::Deb, PackageType::Rpm, PackageType::AppImage],
984      "windows" => vec![PackageType::WindowsMsi, PackageType::Nsis],
985      os => {
986        return Err(crate::Error::GenericError(format!(
987          "Native {os} bundles not yet supported."
988        )))
989      }
990    };
991
992    if let Some(package_types) = &self.package_types {
993      let mut types = vec![];
994      for package_type in package_types {
995        let package_type = *package_type;
996        if platform_types
997          .clone()
998          .into_iter()
999          .any(|t| t == package_type)
1000        {
1001          types.push(package_type);
1002        }
1003      }
1004      Ok(types)
1005    } else {
1006      Ok(platform_types)
1007    }
1008  }
1009
1010  /// Returns the product name.
1011  pub fn product_name(&self) -> &str {
1012    &self.package.product_name
1013  }
1014
1015  /// Returns the bundle's identifier
1016  pub fn bundle_identifier(&self) -> &str {
1017    self.bundle_settings.identifier.as_deref().unwrap_or("")
1018  }
1019
1020  /// Returns the bundle's publisher
1021  pub fn publisher(&self) -> Option<&str> {
1022    self.bundle_settings.publisher.as_deref()
1023  }
1024
1025  /// Returns an iterator over the icon files to be used for this bundle.
1026  pub fn icon_files(&self) -> ResourcePaths<'_> {
1027    match self.bundle_settings.icon {
1028      Some(ref paths) => ResourcePaths::new(paths.as_slice(), false),
1029      None => ResourcePaths::new(&[], false),
1030    }
1031  }
1032
1033  /// Returns an iterator over the resource files to be included in this
1034  /// bundle.
1035  pub fn resource_files(&self) -> ResourcePaths<'_> {
1036    match (
1037      &self.bundle_settings.resources,
1038      &self.bundle_settings.resources_map,
1039    ) {
1040      (Some(paths), None) => ResourcePaths::new(paths.as_slice(), true),
1041      (None, Some(map)) => ResourcePaths::from_map(map, true),
1042      (Some(_), Some(_)) => panic!("cannot use both `resources` and `resources_map`"),
1043      (None, None) => ResourcePaths::new(&[], true),
1044    }
1045  }
1046
1047  /// Returns an iterator over the external binaries to be included in this
1048  /// bundle.
1049  pub fn external_binaries(&self) -> ResourcePaths<'_> {
1050    match self.bundle_settings.external_bin {
1051      Some(ref paths) => ResourcePaths::new(paths.as_slice(), true),
1052      None => ResourcePaths::new(&[], true),
1053    }
1054  }
1055
1056  /// Copies external binaries to a path.
1057  ///
1058  /// Returns the list of destination paths.
1059  pub fn copy_binaries(&self, path: &Path) -> crate::Result<Vec<PathBuf>> {
1060    let mut paths = Vec::new();
1061
1062    for src in self.external_binaries() {
1063      let src = src?;
1064      let dest = path.join(
1065        src
1066          .file_name()
1067          .expect("failed to extract external binary filename")
1068          .to_string_lossy()
1069          .replace(&format!("-{}", self.target), ""),
1070      );
1071      fs_utils::copy_file(&src, &dest)?;
1072      paths.push(dest);
1073    }
1074    Ok(paths)
1075  }
1076
1077  /// Copies resources to a path.
1078  pub fn copy_resources(&self, path: &Path) -> crate::Result<()> {
1079    for resource in self.resource_files().iter() {
1080      let resource = resource?;
1081      let dest = path.join(resource.target());
1082      fs_utils::copy_file(resource.path(), &dest)?;
1083    }
1084    Ok(())
1085  }
1086
1087  /// Returns the version string of the bundle.
1088  pub fn version_string(&self) -> &str {
1089    &self.package.version
1090  }
1091
1092  /// Returns the copyright text.
1093  pub fn copyright_string(&self) -> Option<&str> {
1094    self.bundle_settings.copyright.as_deref()
1095  }
1096
1097  /// Returns the list of authors name.
1098  pub fn author_names(&self) -> &[String] {
1099    match self.package.authors {
1100      Some(ref names) => names.as_slice(),
1101      None => &[],
1102    }
1103  }
1104
1105  /// Returns the authors as a comma-separated string.
1106  pub fn authors_comma_separated(&self) -> Option<String> {
1107    let names = self.author_names();
1108    if names.is_empty() {
1109      None
1110    } else {
1111      Some(names.join(", "))
1112    }
1113  }
1114
1115  /// Returns the bundle license.
1116  pub fn license(&self) -> Option<String> {
1117    self.bundle_settings.license.clone()
1118  }
1119
1120  /// Returns the bundle license file.
1121  pub fn license_file(&self) -> Option<PathBuf> {
1122    self.bundle_settings.license_file.clone()
1123  }
1124
1125  /// Returns the package's homepage URL, defaulting to "" if not defined.
1126  pub fn homepage_url(&self) -> Option<&str> {
1127    self
1128      .bundle_settings
1129      .homepage
1130      .as_deref()
1131      .or(self.package.homepage.as_deref())
1132  }
1133
1134  /// Returns the app's category.
1135  pub fn app_category(&self) -> Option<AppCategory> {
1136    self.bundle_settings.category
1137  }
1138
1139  /// Return file associations.
1140  pub fn file_associations(&self) -> Option<&Vec<FileAssociation>> {
1141    self.bundle_settings.file_associations.as_ref()
1142  }
1143
1144  /// Return the list of deep link protocols to be registered for
1145  /// this bundle.
1146  pub fn deep_link_protocols(&self) -> Option<&Vec<DeepLinkProtocol>> {
1147    self.bundle_settings.deep_link_protocols.as_ref()
1148  }
1149
1150  /// Returns the app's short description.
1151  pub fn short_description(&self) -> &str {
1152    self
1153      .bundle_settings
1154      .short_description
1155      .as_ref()
1156      .unwrap_or(&self.package.description)
1157  }
1158
1159  /// Returns the app's long description.
1160  pub fn long_description(&self) -> Option<&str> {
1161    self.bundle_settings.long_description.as_deref()
1162  }
1163
1164  /// Returns the directory for local tools path.
1165  pub fn local_tools_directory(&self) -> Option<&Path> {
1166    self.local_tools_directory.as_deref()
1167  }
1168
1169  /// Returns the debian settings.
1170  pub fn deb(&self) -> &DebianSettings {
1171    &self.bundle_settings.deb
1172  }
1173
1174  /// Returns the appimage settings.
1175  pub fn appimage(&self) -> &AppImageSettings {
1176    &self.bundle_settings.appimage
1177  }
1178
1179  /// Returns the RPM settings.
1180  pub fn rpm(&self) -> &RpmSettings {
1181    &self.bundle_settings.rpm
1182  }
1183
1184  /// Returns the DMG settings.
1185  pub fn dmg(&self) -> &DmgSettings {
1186    &self.bundle_settings.dmg
1187  }
1188
1189  /// Returns the MacOS settings.
1190  pub fn macos(&self) -> &MacOsSettings {
1191    &self.bundle_settings.macos
1192  }
1193
1194  /// Returns the Windows settings.
1195  pub fn windows(&self) -> &WindowsSettings {
1196    &self.bundle_settings.windows
1197  }
1198
1199  /// Returns the Updater settings.
1200  pub fn updater(&self) -> Option<&UpdaterSettings> {
1201    self.bundle_settings.updater.as_ref()
1202  }
1203}