settings.rs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955
  1. // Copyright 2016-2019 Cargo-Bundle developers <https://github.com/burtonageo/cargo-bundle>
  2. // Copyright 2019-2023 Tauri Programme within The Commons Conservancy
  3. // SPDX-License-Identifier: Apache-2.0
  4. // SPDX-License-Identifier: MIT
  5. use super::category::AppCategory;
  6. use crate::bundle::{common, platform::target_triple};
  7. pub use tauri_utils::config::WebviewInstallMode;
  8. use tauri_utils::{
  9. config::{BundleType, FileAssociation, NSISInstallerMode, NsisCompression},
  10. resources::{external_binaries, ResourcePaths},
  11. };
  12. use std::{
  13. collections::HashMap,
  14. path::{Path, PathBuf},
  15. };
  16. /// The type of the package we're bundling.
  17. #[derive(Clone, Copy, Debug, Eq, PartialEq)]
  18. #[non_exhaustive]
  19. pub enum PackageType {
  20. /// The macOS application bundle (.app).
  21. MacOsBundle,
  22. /// The iOS app bundle.
  23. IosBundle,
  24. /// The Windows bundle (.msi).
  25. WindowsMsi,
  26. /// The NSIS bundle (.exe).
  27. Nsis,
  28. /// The Linux Debian package bundle (.deb).
  29. Deb,
  30. /// The Linux RPM bundle (.rpm).
  31. Rpm,
  32. /// The Linux AppImage bundle (.AppImage).
  33. AppImage,
  34. /// The macOS DMG bundle (.dmg).
  35. Dmg,
  36. /// The Updater bundle.
  37. Updater,
  38. }
  39. impl From<BundleType> for PackageType {
  40. fn from(bundle: BundleType) -> Self {
  41. match bundle {
  42. BundleType::Deb => Self::Deb,
  43. BundleType::Rpm => Self::Rpm,
  44. BundleType::AppImage => Self::AppImage,
  45. BundleType::Msi => Self::WindowsMsi,
  46. BundleType::Nsis => Self::Nsis,
  47. BundleType::App => Self::MacOsBundle,
  48. BundleType::Dmg => Self::Dmg,
  49. BundleType::Updater => Self::Updater,
  50. }
  51. }
  52. }
  53. impl PackageType {
  54. /// Maps a short name to a PackageType.
  55. /// Possible values are "deb", "ios", "msi", "app", "rpm", "appimage", "dmg", "updater".
  56. pub fn from_short_name(name: &str) -> Option<PackageType> {
  57. // Other types we may eventually want to support: apk.
  58. match name {
  59. "deb" => Some(PackageType::Deb),
  60. "ios" => Some(PackageType::IosBundle),
  61. "msi" => Some(PackageType::WindowsMsi),
  62. "nsis" => Some(PackageType::Nsis),
  63. "app" => Some(PackageType::MacOsBundle),
  64. "rpm" => Some(PackageType::Rpm),
  65. "appimage" => Some(PackageType::AppImage),
  66. "dmg" => Some(PackageType::Dmg),
  67. "updater" => Some(PackageType::Updater),
  68. _ => None,
  69. }
  70. }
  71. /// Gets the short name of this PackageType.
  72. #[allow(clippy::trivially_copy_pass_by_ref)]
  73. pub fn short_name(&self) -> &'static str {
  74. match *self {
  75. PackageType::Deb => "deb",
  76. PackageType::IosBundle => "ios",
  77. PackageType::WindowsMsi => "msi",
  78. PackageType::Nsis => "nsis",
  79. PackageType::MacOsBundle => "app",
  80. PackageType::Rpm => "rpm",
  81. PackageType::AppImage => "appimage",
  82. PackageType::Dmg => "dmg",
  83. PackageType::Updater => "updater",
  84. }
  85. }
  86. /// Gets the list of the possible package types.
  87. pub fn all() -> &'static [PackageType] {
  88. ALL_PACKAGE_TYPES
  89. }
  90. /// Gets a number representing priority which used to sort package types
  91. /// in an order that guarantees that if a certain package type
  92. /// depends on another (like Dmg depending on MacOsBundle), the dependency
  93. /// will be built first
  94. ///
  95. /// The lower the number, the higher the priority
  96. pub fn priority(&self) -> u32 {
  97. match self {
  98. PackageType::MacOsBundle => 0,
  99. PackageType::IosBundle => 0,
  100. PackageType::WindowsMsi => 0,
  101. PackageType::Nsis => 0,
  102. PackageType::Deb => 0,
  103. PackageType::Rpm => 0,
  104. PackageType::AppImage => 0,
  105. PackageType::Dmg => 1,
  106. PackageType::Updater => 2,
  107. }
  108. }
  109. }
  110. const ALL_PACKAGE_TYPES: &[PackageType] = &[
  111. #[cfg(target_os = "linux")]
  112. PackageType::Deb,
  113. #[cfg(target_os = "macos")]
  114. PackageType::IosBundle,
  115. #[cfg(target_os = "windows")]
  116. PackageType::WindowsMsi,
  117. #[cfg(target_os = "windows")]
  118. PackageType::Nsis,
  119. #[cfg(target_os = "macos")]
  120. PackageType::MacOsBundle,
  121. #[cfg(target_os = "linux")]
  122. PackageType::Rpm,
  123. #[cfg(target_os = "macos")]
  124. PackageType::Dmg,
  125. #[cfg(target_os = "linux")]
  126. PackageType::AppImage,
  127. PackageType::Updater,
  128. ];
  129. /// The package settings.
  130. #[derive(Debug, Clone)]
  131. pub struct PackageSettings {
  132. /// the package's product name.
  133. pub product_name: String,
  134. /// the package's version.
  135. pub version: String,
  136. /// the package's description.
  137. pub description: String,
  138. /// the package's homepage.
  139. pub homepage: Option<String>,
  140. /// the package's authors.
  141. pub authors: Option<Vec<String>>,
  142. /// the package's license.
  143. pub license: Option<String>,
  144. /// the default binary to run.
  145. pub default_run: Option<String>,
  146. }
  147. /// The updater settings.
  148. #[derive(Debug, Default, Clone)]
  149. pub struct UpdaterSettings {
  150. /// Whether the updater is active or not.
  151. pub active: bool,
  152. /// Signature public key.
  153. pub pubkey: String,
  154. /// Args to pass to `msiexec.exe` to run the updater on Windows.
  155. pub msiexec_args: Option<&'static [&'static str]>,
  156. }
  157. /// The Linux debian bundle settings.
  158. #[derive(Clone, Debug, Default)]
  159. pub struct DebianSettings {
  160. // OS-specific settings:
  161. /// the list of debian dependencies.
  162. pub depends: Option<Vec<String>>,
  163. /// List of custom files to add to the deb package.
  164. /// Maps the path on the debian package to the path of the file to include (relative to the current working directory).
  165. pub files: HashMap<PathBuf, PathBuf>,
  166. /// Path to a custom desktop file Handlebars template.
  167. ///
  168. /// Available variables: `categories`, `comment` (optional), `exec`, `icon` and `name`.
  169. ///
  170. /// Default file contents:
  171. /// ```text
  172. #[doc = include_str!("./linux/templates/main.desktop")]
  173. /// ```
  174. pub desktop_template: Option<PathBuf>,
  175. }
  176. /// The RPM bundle settings.
  177. #[derive(Clone, Debug, Default)]
  178. pub struct RpmSettings {
  179. /// The name of the package's license.
  180. pub license: Option<String>,
  181. /// The list of RPM dependencies your application relies on.
  182. pub depends: Option<Vec<String>>,
  183. /// The RPM release tag.
  184. pub release: String,
  185. /// The RPM epoch.
  186. pub epoch: u32,
  187. /// List of custom files to add to the RPM package.
  188. /// Maps the path on the RPM package to the path of the file to include (relative to the current working directory).
  189. pub files: HashMap<PathBuf, PathBuf>,
  190. /// Path to a custom desktop file Handlebars template.
  191. ///
  192. /// Available variables: `categories`, `comment` (optional), `exec`, `icon` and `name`.
  193. ///
  194. /// Default file contents:
  195. /// ```text
  196. #[doc = include_str!("./linux/templates/main.desktop")]
  197. /// ```
  198. pub desktop_template: Option<PathBuf>,
  199. }
  200. /// Position coordinates struct.
  201. #[derive(Clone, Debug, Default)]
  202. pub struct Position {
  203. /// X coordinate.
  204. pub x: u32,
  205. /// Y coordinate.
  206. pub y: u32,
  207. }
  208. /// Size of the window.
  209. #[derive(Clone, Debug, Default)]
  210. pub struct Size {
  211. /// Width of the window.
  212. pub width: u32,
  213. /// Height of the window.
  214. pub height: u32,
  215. }
  216. /// The DMG bundle settings.
  217. #[derive(Clone, Debug, Default)]
  218. pub struct DmgSettings {
  219. /// Image to use as the background in dmg file. Accepted formats: `png`/`jpg`/`gif`.
  220. pub background: Option<PathBuf>,
  221. /// Position of volume window on screen.
  222. pub window_position: Option<Position>,
  223. /// Size of volume window.
  224. pub window_size: Size,
  225. /// Position of app file on window.
  226. pub app_position: Position,
  227. /// Position of application folder on window.
  228. pub application_folder_position: Position,
  229. }
  230. /// The macOS bundle settings.
  231. #[derive(Clone, Debug, Default)]
  232. pub struct MacOsSettings {
  233. /// MacOS frameworks that need to be bundled with the app.
  234. ///
  235. /// Each string can either be the name of a framework (without the `.framework` extension, e.g. `"SDL2"`),
  236. /// in which case we will search for that framework in the standard install locations (`~/Library/Frameworks/`, `/Library/Frameworks/`, and `/Network/Library/Frameworks/`),
  237. /// 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
  238. /// (under `Foobar.app/Contents/Frameworks/`); you are still responsible for:
  239. ///
  240. /// - 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)
  241. ///
  242. /// - embedding the correct rpath in your binary (e.g. by running `install_name_tool -add_rpath "@executable_path/../Frameworks" path/to/binary` after compiling)
  243. pub frameworks: Option<Vec<String>>,
  244. /// A version string indicating the minimum MacOS version that the bundled app supports (e.g. `"10.11"`).
  245. /// 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`.
  246. pub minimum_system_version: Option<String>,
  247. /// The path to the LICENSE file for macOS apps.
  248. /// Currently only used by the dmg bundle.
  249. pub license: Option<String>,
  250. /// The exception domain to use on the macOS .app bundle.
  251. ///
  252. /// This allows communication to the outside world e.g. a web server you're shipping.
  253. pub exception_domain: Option<String>,
  254. /// Code signing identity.
  255. pub signing_identity: Option<String>,
  256. /// Provider short name for notarization.
  257. pub provider_short_name: Option<String>,
  258. /// Path to the entitlements.plist file.
  259. pub entitlements: Option<String>,
  260. /// Path to the Info.plist file for the bundle.
  261. pub info_plist_path: Option<PathBuf>,
  262. }
  263. /// Configuration for a target language for the WiX build.
  264. #[derive(Debug, Clone, Default)]
  265. pub struct WixLanguageConfig {
  266. /// The path to a locale (`.wxl`) file. See <https://wixtoolset.org/documentation/manual/v3/howtos/ui_and_localization/build_a_localized_version.html>.
  267. pub locale_path: Option<PathBuf>,
  268. }
  269. /// The languages to build using WiX.
  270. #[derive(Debug, Clone)]
  271. pub struct WixLanguage(pub Vec<(String, WixLanguageConfig)>);
  272. impl Default for WixLanguage {
  273. fn default() -> Self {
  274. Self(vec![("en-US".into(), Default::default())])
  275. }
  276. }
  277. /// Settings specific to the WiX implementation.
  278. #[derive(Clone, Debug, Default)]
  279. pub struct WixSettings {
  280. /// The app languages to build. See <https://docs.microsoft.com/en-us/windows/win32/msi/localizing-the-error-and-actiontext-tables>.
  281. pub language: WixLanguage,
  282. /// By default, the bundler uses an internal template.
  283. /// This option allows you to define your own wix file.
  284. pub template: Option<PathBuf>,
  285. /// A list of paths to .wxs files with WiX fragments to use.
  286. pub fragment_paths: Vec<PathBuf>,
  287. /// The ComponentGroup element ids you want to reference from the fragments.
  288. pub component_group_refs: Vec<String>,
  289. /// The Component element ids you want to reference from the fragments.
  290. pub component_refs: Vec<String>,
  291. /// The FeatureGroup element ids you want to reference from the fragments.
  292. pub feature_group_refs: Vec<String>,
  293. /// The Feature element ids you want to reference from the fragments.
  294. pub feature_refs: Vec<String>,
  295. /// The Merge element ids you want to reference from the fragments.
  296. pub merge_refs: Vec<String>,
  297. /// Disables the Webview2 runtime installation after app install. Will be removed in v2, use [`WindowsSettings::webview_install_mode`] instead.
  298. pub skip_webview_install: bool,
  299. /// The path to the LICENSE file.
  300. pub license: Option<PathBuf>,
  301. /// Create an elevated update task within Windows Task Scheduler.
  302. pub enable_elevated_update_task: bool,
  303. /// Path to a bitmap file to use as the installation user interface banner.
  304. /// This bitmap will appear at the top of all but the first page of the installer.
  305. ///
  306. /// The required dimensions are 493px × 58px.
  307. pub banner_path: Option<PathBuf>,
  308. /// Path to a bitmap file to use on the installation user interface dialogs.
  309. /// It is used on the welcome and completion dialogs.
  310. /// The required dimensions are 493px × 312px.
  311. pub dialog_image_path: Option<PathBuf>,
  312. /// Enables FIPS compliant algorithms.
  313. pub fips_compliant: bool,
  314. }
  315. /// Settings specific to the NSIS implementation.
  316. #[derive(Clone, Debug, Default)]
  317. pub struct NsisSettings {
  318. /// A custom .nsi template to use.
  319. pub template: Option<PathBuf>,
  320. /// The path to the license file to render on the installer.
  321. pub license: Option<PathBuf>,
  322. /// The path to a bitmap file to display on the header of installers pages.
  323. ///
  324. /// The recommended dimensions are 150px x 57px.
  325. pub header_image: Option<PathBuf>,
  326. /// The path to a bitmap file for the Welcome page and the Finish page.
  327. ///
  328. /// The recommended dimensions are 164px x 314px.
  329. pub sidebar_image: Option<PathBuf>,
  330. /// The path to an icon file used as the installer icon.
  331. pub installer_icon: Option<PathBuf>,
  332. /// Whether the installation will be for all users or just the current user.
  333. pub install_mode: NSISInstallerMode,
  334. /// A list of installer languages.
  335. /// By default the OS language is used. If the OS language is not in the list of languages, the first language will be used.
  336. /// To allow the user to select the language, set `display_language_selector` to `true`.
  337. ///
  338. /// See <https://github.com/kichik/nsis/tree/9465c08046f00ccb6eda985abbdbf52c275c6c4d/Contrib/Language%20files> for the complete list of languages.
  339. pub languages: Option<Vec<String>>,
  340. /// An key-value pair where the key is the language and the
  341. /// value is the path to a custom `.nsi` file that holds the translated text for tauri's custom messages.
  342. ///
  343. /// See <https://github.com/tauri-apps/tauri/blob/dev/tooling/bundler/src/bundle/windows/templates/nsis-languages/English.nsh> for an example `.nsi` file.
  344. ///
  345. /// **Note**: the key must be a valid NSIS language and it must be added to [`NsisConfig`]languages array,
  346. pub custom_language_files: Option<HashMap<String, PathBuf>>,
  347. /// Whether to display a language selector dialog before the installer and uninstaller windows are rendered or not.
  348. /// By default the OS language is selected, with a fallback to the first language in the `languages` array.
  349. pub display_language_selector: bool,
  350. /// Set compression algorithm used to compress files in the installer.
  351. pub compression: Option<NsisCompression>,
  352. }
  353. /// The Windows bundle settings.
  354. #[derive(Clone, Debug)]
  355. pub struct WindowsSettings {
  356. /// The file digest algorithm to use for creating file signatures. Required for code signing. SHA-256 is recommended.
  357. pub digest_algorithm: Option<String>,
  358. /// The SHA1 hash of the signing certificate.
  359. pub certificate_thumbprint: Option<String>,
  360. /// Server to use during timestamping.
  361. pub timestamp_url: Option<String>,
  362. /// Whether to use Time-Stamp Protocol (TSP, a.k.a. RFC 3161) for the timestamp server. Your code signing provider may
  363. /// use a TSP timestamp server, like e.g. SSL.com does. If so, enable TSP by setting to true.
  364. pub tsp: bool,
  365. /// WiX configuration.
  366. pub wix: Option<WixSettings>,
  367. /// Nsis configuration.
  368. pub nsis: Option<NsisSettings>,
  369. /// The path to the application icon. Defaults to `./icons/icon.ico`.
  370. pub icon_path: PathBuf,
  371. /// The installation mode for the Webview2 runtime.
  372. pub webview_install_mode: WebviewInstallMode,
  373. /// Path to the webview fixed runtime to use.
  374. ///
  375. /// Overwrites [`Self::webview_install_mode`] if set.
  376. ///
  377. /// Will be removed in v2, use [`Self::webview_install_mode`] instead.
  378. pub webview_fixed_runtime_path: Option<PathBuf>,
  379. /// Validates a second app installation, blocking the user from installing an older version if set to `false`.
  380. ///
  381. /// 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`.
  382. ///
  383. /// /// The default value of this flag is `true`.
  384. pub allow_downgrades: bool,
  385. }
  386. impl Default for WindowsSettings {
  387. fn default() -> Self {
  388. Self {
  389. digest_algorithm: None,
  390. certificate_thumbprint: None,
  391. timestamp_url: None,
  392. tsp: false,
  393. wix: None,
  394. nsis: None,
  395. icon_path: PathBuf::from("icons/icon.ico"),
  396. webview_install_mode: Default::default(),
  397. webview_fixed_runtime_path: None,
  398. allow_downgrades: true,
  399. }
  400. }
  401. }
  402. /// The bundle settings of the BuildArtifact we're bundling.
  403. #[derive(Clone, Debug, Default)]
  404. pub struct BundleSettings {
  405. /// the app's identifier.
  406. pub identifier: Option<String>,
  407. /// The app's publisher. Defaults to the second element in the identifier string.
  408. /// Currently maps to the Manufacturer property of the Windows Installer.
  409. pub publisher: Option<String>,
  410. /// the app's icon list.
  411. pub icon: Option<Vec<String>>,
  412. /// the app's resources to bundle.
  413. ///
  414. /// each item can be a path to a file or a path to a folder.
  415. ///
  416. /// supports glob patterns.
  417. pub resources: Option<Vec<String>>,
  418. /// The app's resources to bundle. Takes precedence over `Self::resources` when specified.
  419. ///
  420. /// Maps each resource path to its target directory in the bundle resources directory.
  421. ///
  422. /// Supports glob patterns.
  423. pub resources_map: Option<HashMap<String, String>>,
  424. /// the app's copyright.
  425. pub copyright: Option<String>,
  426. /// the app's category.
  427. pub category: Option<AppCategory>,
  428. /// the file associations
  429. pub file_associations: Option<Vec<FileAssociation>>,
  430. /// the app's short description.
  431. pub short_description: Option<String>,
  432. /// the app's long description.
  433. pub long_description: Option<String>,
  434. // Bundles for other binaries:
  435. /// Configuration map for the apps to bundle.
  436. pub bin: Option<HashMap<String, BundleSettings>>,
  437. /// External binaries to add to the bundle.
  438. ///
  439. /// Note that each binary name should have the target platform's target triple appended,
  440. /// as well as `.exe` for Windows.
  441. /// For example, if you're bundling a sidecar called `sqlite3`, the bundler expects
  442. /// a binary named `sqlite3-x86_64-unknown-linux-gnu` on linux,
  443. /// and `sqlite3-x86_64-pc-windows-gnu.exe` on windows.
  444. ///
  445. /// Run `tauri build --help` for more info on targets.
  446. ///
  447. /// If you are building a universal binary for MacOS, the bundler expects
  448. /// your external binary to also be universal, and named after the target triple,
  449. /// e.g. `sqlite3-universal-apple-darwin`. See
  450. /// <https://developer.apple.com/documentation/apple-silicon/building-a-universal-macos-binary>
  451. pub external_bin: Option<Vec<String>>,
  452. /// Debian-specific settings.
  453. pub deb: DebianSettings,
  454. /// Rpm-specific settings.
  455. pub rpm: RpmSettings,
  456. /// DMG-specific settings.
  457. pub dmg: DmgSettings,
  458. /// MacOS-specific settings.
  459. pub macos: MacOsSettings,
  460. /// Updater configuration.
  461. pub updater: Option<UpdaterSettings>,
  462. /// Windows-specific settings.
  463. pub windows: WindowsSettings,
  464. }
  465. /// A binary to bundle.
  466. #[derive(Clone, Debug)]
  467. pub struct BundleBinary {
  468. name: String,
  469. src_path: Option<String>,
  470. main: bool,
  471. }
  472. impl BundleBinary {
  473. /// Creates a new bundle binary.
  474. pub fn new(name: String, main: bool) -> Self {
  475. Self {
  476. name,
  477. src_path: None,
  478. main,
  479. }
  480. }
  481. /// Sets the src path of the binary.
  482. #[must_use]
  483. pub fn set_src_path(mut self, src_path: Option<String>) -> Self {
  484. self.src_path = src_path;
  485. self
  486. }
  487. /// Mark the binary as the main executable.
  488. pub fn set_main(&mut self, main: bool) {
  489. self.main = main;
  490. }
  491. /// Sets the binary name.
  492. pub fn set_name(&mut self, name: String) {
  493. self.name = name;
  494. }
  495. /// Returns the binary name.
  496. pub fn name(&self) -> &str {
  497. &self.name
  498. }
  499. /// Returns the binary `main` flag.
  500. pub fn main(&self) -> bool {
  501. self.main
  502. }
  503. /// Returns the binary source path.
  504. pub fn src_path(&self) -> Option<&String> {
  505. self.src_path.as_ref()
  506. }
  507. }
  508. /// The Settings exposed by the module.
  509. #[derive(Clone, Debug)]
  510. pub struct Settings {
  511. /// The log level.
  512. log_level: log::Level,
  513. /// the package settings.
  514. package: PackageSettings,
  515. /// the package types we're bundling.
  516. ///
  517. /// if not present, we'll use the PackageType list for the target OS.
  518. package_types: Option<Vec<PackageType>>,
  519. /// the directory where the bundles will be placed.
  520. project_out_directory: PathBuf,
  521. /// the bundle settings.
  522. bundle_settings: BundleSettings,
  523. /// the binaries to bundle.
  524. binaries: Vec<BundleBinary>,
  525. /// The target triple.
  526. target: String,
  527. }
  528. /// A builder for [`Settings`].
  529. #[derive(Default)]
  530. pub struct SettingsBuilder {
  531. log_level: Option<log::Level>,
  532. project_out_directory: Option<PathBuf>,
  533. package_types: Option<Vec<PackageType>>,
  534. package_settings: Option<PackageSettings>,
  535. bundle_settings: BundleSettings,
  536. binaries: Vec<BundleBinary>,
  537. target: Option<String>,
  538. }
  539. impl SettingsBuilder {
  540. /// Creates the default settings builder.
  541. pub fn new() -> Self {
  542. Default::default()
  543. }
  544. /// Sets the project output directory. It's used as current working directory.
  545. #[must_use]
  546. pub fn project_out_directory<P: AsRef<Path>>(mut self, path: P) -> Self {
  547. self
  548. .project_out_directory
  549. .replace(path.as_ref().to_path_buf());
  550. self
  551. }
  552. /// Sets the package types to create.
  553. #[must_use]
  554. pub fn package_types(mut self, package_types: Vec<PackageType>) -> Self {
  555. self.package_types = Some(package_types);
  556. self
  557. }
  558. /// Sets the package settings.
  559. #[must_use]
  560. pub fn package_settings(mut self, settings: PackageSettings) -> Self {
  561. self.package_settings.replace(settings);
  562. self
  563. }
  564. /// Sets the bundle settings.
  565. #[must_use]
  566. pub fn bundle_settings(mut self, settings: BundleSettings) -> Self {
  567. self.bundle_settings = settings;
  568. self
  569. }
  570. /// Sets the binaries to bundle.
  571. #[must_use]
  572. pub fn binaries(mut self, binaries: Vec<BundleBinary>) -> Self {
  573. self.binaries = binaries;
  574. self
  575. }
  576. /// Sets the target triple.
  577. #[must_use]
  578. pub fn target(mut self, target: String) -> Self {
  579. self.target.replace(target);
  580. self
  581. }
  582. /// Sets the log level for spawned commands. Defaults to [`log::Level::Error`].
  583. #[must_use]
  584. pub fn log_level(mut self, level: log::Level) -> Self {
  585. self.log_level.replace(level);
  586. self
  587. }
  588. /// Builds a Settings from the CLI args.
  589. ///
  590. /// Package settings will be read from Cargo.toml.
  591. ///
  592. /// Bundle settings will be read from $TAURI_DIR/tauri.conf.json if it exists and fallback to Cargo.toml's [package.metadata.bundle].
  593. pub fn build(self) -> crate::Result<Settings> {
  594. let target = if let Some(t) = self.target {
  595. t
  596. } else {
  597. target_triple()?
  598. };
  599. Ok(Settings {
  600. log_level: self.log_level.unwrap_or(log::Level::Error),
  601. package: self.package_settings.expect("package settings is required"),
  602. package_types: self.package_types,
  603. project_out_directory: self
  604. .project_out_directory
  605. .expect("out directory is required"),
  606. binaries: self.binaries,
  607. bundle_settings: BundleSettings {
  608. external_bin: self
  609. .bundle_settings
  610. .external_bin
  611. .as_ref()
  612. .map(|bins| external_binaries(bins, &target)),
  613. ..self.bundle_settings
  614. },
  615. target,
  616. })
  617. }
  618. }
  619. impl Settings {
  620. /// Sets the log level for spawned commands.
  621. pub fn set_log_level(&mut self, level: log::Level) {
  622. self.log_level = level;
  623. }
  624. /// Returns the log level for spawned commands.
  625. pub fn log_level(&self) -> log::Level {
  626. self.log_level
  627. }
  628. /// Returns the directory where the bundle should be placed.
  629. pub fn project_out_directory(&self) -> &Path {
  630. &self.project_out_directory
  631. }
  632. /// Returns the target triple.
  633. pub fn target(&self) -> &str {
  634. &self.target
  635. }
  636. /// Returns the architecture for the binary being bundled (e.g. "arm", "x86" or "x86_64").
  637. pub fn binary_arch(&self) -> &str {
  638. if self.target.starts_with("x86_64") {
  639. "x86_64"
  640. } else if self.target.starts_with('i') {
  641. "x86"
  642. } else if self.target.starts_with("arm") {
  643. "arm"
  644. } else if self.target.starts_with("aarch64") {
  645. "aarch64"
  646. } else if self.target.starts_with("universal") {
  647. "universal"
  648. } else {
  649. panic!("Unexpected target triple {}", self.target)
  650. }
  651. }
  652. /// Returns the file name of the binary being bundled.
  653. pub fn main_binary_name(&self) -> &str {
  654. self
  655. .binaries
  656. .iter()
  657. .find(|bin| bin.main)
  658. .expect("failed to find main binary")
  659. .name
  660. .as_str()
  661. }
  662. /// Returns the path to the specified binary.
  663. pub fn binary_path(&self, binary: &BundleBinary) -> PathBuf {
  664. let mut path = self.project_out_directory.clone();
  665. path.push(binary.name());
  666. path
  667. }
  668. /// Returns the list of binaries to bundle.
  669. pub fn binaries(&self) -> &Vec<BundleBinary> {
  670. &self.binaries
  671. }
  672. /// If a list of package types was specified by the command-line, returns
  673. /// that list filtered by the current target OS available targets.
  674. ///
  675. /// If a target triple was specified by the
  676. /// command-line, returns the native package type(s) for that target.
  677. ///
  678. /// Otherwise returns the native package type(s) for the host platform.
  679. ///
  680. /// Fails if the host/target's native package type is not supported.
  681. pub fn package_types(&self) -> crate::Result<Vec<PackageType>> {
  682. let target_os = self
  683. .target
  684. .split('-')
  685. .nth(2)
  686. .unwrap_or(std::env::consts::OS)
  687. .replace("darwin", "macos");
  688. let mut platform_types = match target_os.as_str() {
  689. "macos" => vec![PackageType::MacOsBundle, PackageType::Dmg],
  690. "ios" => vec![PackageType::IosBundle],
  691. "linux" => vec![PackageType::Deb, PackageType::Rpm, PackageType::AppImage],
  692. "windows" => vec![PackageType::WindowsMsi, PackageType::Nsis],
  693. os => {
  694. return Err(crate::Error::GenericError(format!(
  695. "Native {os} bundles not yet supported."
  696. )))
  697. }
  698. };
  699. // add updater if needed
  700. if self.is_update_enabled() {
  701. platform_types.push(PackageType::Updater)
  702. }
  703. if let Some(package_types) = &self.package_types {
  704. let mut types = vec![];
  705. for package_type in package_types {
  706. let package_type = *package_type;
  707. if platform_types
  708. .clone()
  709. .into_iter()
  710. .any(|t| t == package_type)
  711. {
  712. types.push(package_type);
  713. }
  714. }
  715. Ok(types)
  716. } else {
  717. Ok(platform_types)
  718. }
  719. }
  720. /// Returns the product name.
  721. pub fn product_name(&self) -> &str {
  722. &self.package.product_name
  723. }
  724. /// Returns the bundle's identifier
  725. pub fn bundle_identifier(&self) -> &str {
  726. self.bundle_settings.identifier.as_deref().unwrap_or("")
  727. }
  728. /// Returns the bundle's identifier
  729. pub fn publisher(&self) -> Option<&str> {
  730. self.bundle_settings.publisher.as_deref()
  731. }
  732. /// Returns an iterator over the icon files to be used for this bundle.
  733. pub fn icon_files(&self) -> ResourcePaths<'_> {
  734. match self.bundle_settings.icon {
  735. Some(ref paths) => ResourcePaths::new(paths.as_slice(), false),
  736. None => ResourcePaths::new(&[], false),
  737. }
  738. }
  739. /// Returns an iterator over the resource files to be included in this
  740. /// bundle.
  741. pub fn resource_files(&self) -> ResourcePaths<'_> {
  742. match (
  743. &self.bundle_settings.resources,
  744. &self.bundle_settings.resources_map,
  745. ) {
  746. (Some(paths), None) => ResourcePaths::new(paths.as_slice(), true),
  747. (None, Some(map)) => ResourcePaths::from_map(map, true),
  748. (Some(_), Some(_)) => panic!("cannot use both `resources` and `resources_map`"),
  749. (None, None) => ResourcePaths::new(&[], true),
  750. }
  751. }
  752. /// Returns an iterator over the external binaries to be included in this
  753. /// bundle.
  754. pub fn external_binaries(&self) -> ResourcePaths<'_> {
  755. match self.bundle_settings.external_bin {
  756. Some(ref paths) => ResourcePaths::new(paths.as_slice(), true),
  757. None => ResourcePaths::new(&[], true),
  758. }
  759. }
  760. /// Copies external binaries to a path.
  761. ///
  762. /// Returns the list of destination paths.
  763. pub fn copy_binaries(&self, path: &Path) -> crate::Result<Vec<PathBuf>> {
  764. let mut paths = Vec::new();
  765. for src in self.external_binaries() {
  766. let src = src?;
  767. let dest = path.join(
  768. src
  769. .file_name()
  770. .expect("failed to extract external binary filename")
  771. .to_string_lossy()
  772. .replace(&format!("-{}", self.target), ""),
  773. );
  774. common::copy_file(&src, &dest)?;
  775. paths.push(dest);
  776. }
  777. Ok(paths)
  778. }
  779. /// Copies resources to a path.
  780. pub fn copy_resources(&self, path: &Path) -> crate::Result<()> {
  781. for resource in self.resource_files().iter() {
  782. let resource = resource?;
  783. let dest = path.join(resource.target());
  784. common::copy_file(resource.path(), dest)?;
  785. }
  786. Ok(())
  787. }
  788. /// Returns the version string of the bundle.
  789. pub fn version_string(&self) -> &str {
  790. &self.package.version
  791. }
  792. /// Returns the copyright text.
  793. pub fn copyright_string(&self) -> Option<&str> {
  794. self.bundle_settings.copyright.as_deref()
  795. }
  796. /// Returns the list of authors name.
  797. pub fn author_names(&self) -> &[String] {
  798. match self.package.authors {
  799. Some(ref names) => names.as_slice(),
  800. None => &[],
  801. }
  802. }
  803. /// Returns the authors as a comma-separated string.
  804. pub fn authors_comma_separated(&self) -> Option<String> {
  805. let names = self.author_names();
  806. if names.is_empty() {
  807. None
  808. } else {
  809. Some(names.join(", "))
  810. }
  811. }
  812. /// Returns the package's license.
  813. pub fn license(&self) -> Option<&str> {
  814. self.package.license.as_deref()
  815. }
  816. /// Returns the package's homepage URL, defaulting to "" if not defined.
  817. pub fn homepage_url(&self) -> &str {
  818. self.package.homepage.as_deref().unwrap_or("")
  819. }
  820. /// Returns the app's category.
  821. pub fn app_category(&self) -> Option<AppCategory> {
  822. self.bundle_settings.category
  823. }
  824. /// Return file associations.
  825. pub fn file_associations(&self) -> &Option<Vec<FileAssociation>> {
  826. &self.bundle_settings.file_associations
  827. }
  828. /// Returns the app's short description.
  829. pub fn short_description(&self) -> &str {
  830. self
  831. .bundle_settings
  832. .short_description
  833. .as_ref()
  834. .unwrap_or(&self.package.description)
  835. }
  836. /// Returns the app's long description.
  837. pub fn long_description(&self) -> Option<&str> {
  838. self.bundle_settings.long_description.as_deref()
  839. }
  840. /// Returns the debian settings.
  841. pub fn deb(&self) -> &DebianSettings {
  842. &self.bundle_settings.deb
  843. }
  844. /// Returns the RPM settings.
  845. pub fn rpm(&self) -> &RpmSettings {
  846. &self.bundle_settings.rpm
  847. }
  848. /// Returns the DMG settings.
  849. pub fn dmg(&self) -> &DmgSettings {
  850. &self.bundle_settings.dmg
  851. }
  852. /// Returns the MacOS settings.
  853. pub fn macos(&self) -> &MacOsSettings {
  854. &self.bundle_settings.macos
  855. }
  856. /// Returns the Windows settings.
  857. pub fn windows(&self) -> &WindowsSettings {
  858. &self.bundle_settings.windows
  859. }
  860. /// Returns the Updater settings.
  861. pub fn updater(&self) -> Option<&UpdaterSettings> {
  862. self.bundle_settings.updater.as_ref()
  863. }
  864. /// Is update enabled
  865. pub fn is_update_enabled(&self) -> bool {
  866. match &self.bundle_settings.updater {
  867. Some(val) => val.active,
  868. None => false,
  869. }
  870. }
  871. }