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