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}