From 091100acbb507b51de39fb1446f685926f888fd2 Mon Sep 17 00:00:00 2001 From: Olivier Lemasle Date: Sat, 23 Dec 2023 18:38:15 +0100 Subject: [PATCH] feat(bundler): Add RPM packaging, closes #4402 (#5202) * feat(bundler): Add RPM packaging * feat(bundler): Update 'rpm' to 0.13.1 * Fix fmt --- .changes/bundler-rpm.md | 7 + README.md | 2 +- core/tauri-config-schema/schema.json | 83 +- core/tauri-utils/src/config.rs | 55 +- tooling/bundler/Cargo.toml | 1 + tooling/bundler/src/bundle.rs | 2 +- tooling/bundler/src/bundle/category.rs | 6 +- tooling/bundler/src/bundle/linux/appimage.rs | 1 - tooling/bundler/src/bundle/linux/debian.rs | 134 +-- .../bundler/src/bundle/linux/freedesktop.rs | 160 ++++ tooling/bundler/src/bundle/linux/mod.rs | 1 + tooling/bundler/src/bundle/linux/rpm.rs | 145 +++- tooling/bundler/src/bundle/settings.rs | 42 +- tooling/bundler/src/error.rs | 4 + tooling/bundler/src/lib.rs | 2 +- tooling/cli/Cargo.lock | 789 +++++++++++++++++- tooling/cli/ENVIRONMENT_VARIABLES.md | 2 + tooling/cli/schema.json | 83 +- tooling/cli/src/build.rs | 2 +- tooling/cli/src/interface/rust.rs | 59 +- 20 files changed, 1419 insertions(+), 161 deletions(-) create mode 100644 .changes/bundler-rpm.md create mode 100644 tooling/bundler/src/bundle/linux/freedesktop.rs diff --git a/.changes/bundler-rpm.md b/.changes/bundler-rpm.md new file mode 100644 index 000000000000..770ca78c2056 --- /dev/null +++ b/.changes/bundler-rpm.md @@ -0,0 +1,7 @@ +--- +"tauri-bundler": 'patch:enhance' +"tauri-cli": 'patch:enhance' +"@tauri-apps/cli": 'patch:enhance' +--- + +Add RPM packaging diff --git a/README.md b/README.md index 25a4c7218184..64d67e47073a 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ npm create tauri-app@latest The list of Tauri's features includes, but is not limited to: -- Built-in app bundler to create app bundles in formats like `.app`, `.dmg`, `.deb`, `.AppImage` and Windows installers like `.exe` (via NSIS) and `.msi` (via WiX). +- Built-in app bundler to create app bundles in formats like `.app`, `.dmg`, `.deb`, `.rpm`, `.AppImage` and Windows installers like `.exe` (via NSIS) and `.msi` (via WiX). - Built-in self updater (desktop only) - System tray icons - Native notifications diff --git a/core/tauri-config-schema/schema.json b/core/tauri-config-schema/schema.json index 573d37924808..20bb882b5f50 100644 --- a/core/tauri-config-schema/schema.json +++ b/core/tauri-config-schema/schema.json @@ -57,6 +57,11 @@ "macOS": { "minimumSystemVersion": "10.13" }, + "rpm": { + "epoch": 0, + "files": {}, + "release": "1" + }, "targets": "all", "updater": { "active": false, @@ -205,6 +210,11 @@ "macOS": { "minimumSystemVersion": "10.13" }, + "rpm": { + "epoch": 0, + "files": {}, + "release": "1" + }, "targets": "all", "updater": { "active": false, @@ -933,7 +943,7 @@ "type": "boolean" }, "targets": { - "description": "The bundle targets, currently supports [\"deb\", \"appimage\", \"nsis\", \"msi\", \"app\", \"dmg\", \"updater\"] or \"all\".", + "description": "The bundle targets, currently supports [\"deb\", \"rpm\", \"appimage\", \"nsis\", \"msi\", \"app\", \"dmg\", \"updater\"] or \"all\".", "default": "all", "allOf": [ { @@ -1031,6 +1041,19 @@ } ] }, + "rpm": { + "description": "Configuration for the RPM bundle.", + "default": { + "epoch": 0, + "files": {}, + "release": "1" + }, + "allOf": [ + { + "$ref": "#/definitions/RpmConfig" + } + ] + }, "dmg": { "description": "DMG-specific settings.", "default": { @@ -1170,6 +1193,13 @@ "deb" ] }, + { + "description": "The RPM bundle (.rpm).", + "type": "string", + "enum": [ + "rpm" + ] + }, { "description": "The AppImage bundle (.appimage).", "type": "string", @@ -1368,6 +1398,57 @@ }, "additionalProperties": false }, + "RpmConfig": { + "description": "Configuration for RPM bundles.", + "type": "object", + "properties": { + "license": { + "description": "The package's license identifier. If not set, defaults to the license from the Cargo.toml file.", + "type": [ + "string", + "null" + ] + }, + "depends": { + "description": "The list of RPM dependencies your application relies on.", + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + } + }, + "release": { + "description": "The RPM release tag.", + "default": "1", + "type": "string" + }, + "epoch": { + "description": "The RPM epoch.", + "default": 0, + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "files": { + "description": "The files to include on the package.", + "default": {}, + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "desktopTemplate": { + "description": "Path to a custom desktop file Handlebars template.\n\nAvailable variables: `categories`, `comment` (optional), `exec`, `icon` and `name`.", + "type": [ + "string", + "null" + ] + } + }, + "additionalProperties": false + }, "DmgConfig": { "description": "Configuration for Apple Disk Image (.dmg) bundles.\n\nSee more: https://tauri.app/v1/api/config#dmgconfig", "type": "object", diff --git a/core/tauri-utils/src/config.rs b/core/tauri-utils/src/config.rs index c4920de3962c..d39d2c82ce06 100644 --- a/core/tauri-utils/src/config.rs +++ b/core/tauri-utils/src/config.rs @@ -78,6 +78,8 @@ impl Default for WindowUrl { pub enum BundleType { /// The debian bundle (.deb). Deb, + /// The RPM bundle (.rpm). + Rpm, /// The AppImage bundle (.appimage). AppImage, /// The Microsoft Installer bundle (.msi). @@ -99,6 +101,7 @@ impl Display for BundleType { "{}", match self { Self::Deb => "deb", + Self::Rpm => "rpm", Self::AppImage => "appimage", Self::Msi => "msi", Self::Nsis => "nsis", @@ -127,6 +130,7 @@ impl<'de> Deserialize<'de> for BundleType { let s = String::deserialize(deserializer)?; match s.to_lowercase().as_str() { "deb" => Ok(Self::Deb), + "rpm" => Ok(Self::Rpm), "appimage" => Ok(Self::AppImage), "msi" => Ok(Self::Msi), "nsis" => Ok(Self::Nsis), @@ -282,6 +286,49 @@ pub struct DebConfig { pub desktop_template: Option, } +/// Configuration for RPM bundles. +#[skip_serializing_none] +#[derive(Debug, PartialEq, Eq, Clone, Deserialize, Serialize)] +#[cfg_attr(feature = "schema", derive(JsonSchema))] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +pub struct RpmConfig { + /// The package's license identifier. If not set, defaults to the license from + /// the Cargo.toml file. + pub license: Option, + /// The list of RPM dependencies your application relies on. + pub depends: Option>, + /// The RPM release tag. + #[serde(default = "default_release")] + pub release: String, + /// The RPM epoch. + #[serde(default)] + pub epoch: u32, + /// The files to include on the package. + #[serde(default)] + pub files: HashMap, + /// Path to a custom desktop file Handlebars template. + /// + /// Available variables: `categories`, `comment` (optional), `exec`, `icon` and `name`. + pub desktop_template: Option, +} + +impl Default for RpmConfig { + fn default() -> Self { + Self { + license: None, + depends: None, + release: default_release(), + epoch: 0, + files: Default::default(), + desktop_template: None, + } + } +} + +fn default_release() -> String { + "1".into() +} + /// Position coordinates struct. #[derive(Default, Debug, PartialEq, Eq, Clone, Deserialize, Serialize)] #[cfg_attr(feature = "schema", derive(JsonSchema))] @@ -885,7 +932,7 @@ pub struct BundleConfig { /// Whether Tauri should bundle your application or just output the executable. #[serde(default)] pub active: bool, - /// The bundle targets, currently supports ["deb", "appimage", "nsis", "msi", "app", "dmg", "updater"] or "all". + /// The bundle targets, currently supports ["deb", "rpm", "appimage", "nsis", "msi", "app", "dmg", "updater"] or "all". #[serde(default)] pub targets: BundleTarget, /// The application identifier in reverse domain name notation (e.g. `com.tauri.example`). @@ -925,6 +972,9 @@ pub struct BundleConfig { /// Configuration for the Debian bundle. #[serde(default)] pub deb: DebConfig, + /// Configuration for the RPM bundle. + #[serde(default)] + pub rpm: RpmConfig, /// DMG-specific settings. #[serde(default)] pub dmg: DmgConfig, @@ -2518,6 +2568,7 @@ mod build { let long_description = quote!(None); let appimage = quote!(Default::default()); let deb = quote!(Default::default()); + let rpm = quote!(Default::default()); let dmg = quote!(Default::default()); let macos = quote!(Default::default()); let external_bin = opt_vec_str_lit(self.external_bin.as_ref()); @@ -2542,6 +2593,7 @@ mod build { long_description, appimage, deb, + rpm, dmg, macos, external_bin, @@ -2851,6 +2903,7 @@ mod test { long_description: None, appimage: Default::default(), deb: Default::default(), + rpm: Default::default(), dmg: Default::default(), macos: Default::default(), external_bin: None, diff --git a/tooling/bundler/Cargo.toml b/tooling/bundler/Cargo.toml index 2d7b75f989c9..22a989458273 100644 --- a/tooling/bundler/Cargo.toml +++ b/tooling/bundler/Cargo.toml @@ -66,6 +66,7 @@ regex = "1" heck = "0.4" ar = "0.9.0" md5 = "0.7.0" +rpm = "0.13.1" [lib] name = "tauri_bundler" diff --git a/tooling/bundler/src/bundle.rs b/tooling/bundler/src/bundle.rs index ae26b0d7d8fa..89d9948c7eb9 100644 --- a/tooling/bundler/src/bundle.rs +++ b/tooling/bundler/src/bundle.rs @@ -21,7 +21,7 @@ pub use self::{ category::AppCategory, settings::{ BundleBinary, BundleSettings, DebianSettings, DmgSettings, MacOsSettings, PackageSettings, - PackageType, Position, Settings, SettingsBuilder, Size, UpdaterSettings, + PackageType, Position, RpmSettings, Settings, SettingsBuilder, Size, UpdaterSettings, }, }; #[cfg(target_os = "macos")] diff --git a/tooling/bundler/src/bundle/category.rs b/tooling/bundler/src/bundle/category.rs index 4aced1656244..3772a2768143 100644 --- a/tooling/bundler/src/bundle/category.rs +++ b/tooling/bundler/src/bundle/category.rs @@ -142,9 +142,11 @@ impl AppCategory { } } - /// Map an AppCategory to the closest set of GNOME desktop registered + /// Map an AppCategory to the closest set of Freedesktop registered /// categories that matches that category. - pub fn gnome_desktop_categories(self) -> &'static str { + /// + /// Cf https://specifications.freedesktop.org/menu-spec/latest/ + pub fn freedesktop_categories(self) -> &'static str { match &self { AppCategory::Business => "Office;", AppCategory::DeveloperTool => "Development;", diff --git a/tooling/bundler/src/bundle/linux/appimage.rs b/tooling/bundler/src/bundle/linux/appimage.rs index 90f6665ab0cc..331a83303f3b 100644 --- a/tooling/bundler/src/bundle/linux/appimage.rs +++ b/tooling/bundler/src/bundle/linux/appimage.rs @@ -31,7 +31,6 @@ pub fn bundle_project(settings: &Settings) -> crate::Result> { // generate deb_folder structure let (_, icons) = debian::generate_data(settings, &package_dir)?; - let icons: Vec = icons.into_iter().collect(); let output_path = settings.project_out_directory().join("bundle/appimage"); if output_path.exists() { diff --git a/tooling/bundler/src/bundle/linux/debian.rs b/tooling/bundler/src/bundle/linux/debian.rs index 000c83415b4d..91b31653d214 100644 --- a/tooling/bundler/src/bundle/linux/debian.rs +++ b/tooling/bundler/src/bundle/linux/debian.rs @@ -23,33 +23,20 @@ // metadata, as well as generating the md5sums file. Currently we do not // generate postinst or prerm files. -use super::super::common; +use super::{super::common, freedesktop}; use crate::Settings; use anyhow::Context; -use handlebars::Handlebars; use heck::AsKebabCase; -use image::{self, codecs::png::PngDecoder, ImageDecoder}; use libflate::gzip; use log::info; -use serde::Serialize; use walkdir::WalkDir; use std::{ - collections::BTreeSet, - ffi::OsStr, - fs::{self, read_to_string, File}, + fs::{self, File}, io::{self, Write}, path::{Path, PathBuf}, }; -#[derive(PartialEq, Eq, PartialOrd, Ord)] -pub struct DebIcon { - pub width: u32, - pub height: u32, - pub is_high_density: bool, - pub path: PathBuf, -} - /// Bundles the project. /// Returns a vector of PathBuf that shows where the DEB was created. pub fn bundle_project(settings: &Settings) -> crate::Result> { @@ -112,7 +99,7 @@ pub fn bundle_project(settings: &Settings) -> crate::Result> { pub fn generate_data( settings: &Settings, package_dir: &Path, -) -> crate::Result<(PathBuf, BTreeSet)> { +) -> crate::Result<(PathBuf, Vec)> { // Generate data files. let data_dir = package_dir.join("data"); let bin_dir = data_dir.join("usr/bin"); @@ -129,81 +116,14 @@ pub fn generate_data( .copy_binaries(&bin_dir) .with_context(|| "Failed to copy external binaries")?; - let icons = - generate_icon_files(settings, &data_dir).with_context(|| "Failed to create icon files")?; - generate_desktop_file(settings, &data_dir).with_context(|| "Failed to create desktop file")?; + let icons = freedesktop::copy_icon_files(settings, &data_dir) + .with_context(|| "Failed to create icon files")?; + freedesktop::generate_desktop_file(settings, &settings.deb().desktop_template, &data_dir) + .with_context(|| "Failed to create desktop file")?; Ok((data_dir, icons)) } -/// Generate the application desktop file and store it under the `data_dir`. -fn generate_desktop_file(settings: &Settings, data_dir: &Path) -> crate::Result<()> { - let bin_name = settings.main_binary_name(); - let desktop_file_name = format!("{bin_name}.desktop"); - let desktop_file_path = data_dir - .join("usr/share/applications") - .join(desktop_file_name); - - // For more information about the format of this file, see - // https://developer.gnome.org/integration-guide/stable/desktop-files.html.en - let file = &mut common::create_file(&desktop_file_path)?; - - let mut handlebars = Handlebars::new(); - handlebars.register_escape_fn(handlebars::no_escape); - if let Some(template) = &settings.deb().desktop_template { - handlebars - .register_template_string("main.desktop", read_to_string(template)?) - .with_context(|| "Failed to setup custom handlebar template")?; - } else { - handlebars - .register_template_string("main.desktop", include_str!("./templates/main.desktop")) - .with_context(|| "Failed to setup custom handlebar template")?; - } - - #[derive(Serialize)] - struct DesktopTemplateParams<'a> { - categories: &'a str, - comment: Option<&'a str>, - exec: &'a str, - icon: &'a str, - name: &'a str, - mime_type: Option, - } - - let mime_type = if let Some(associations) = settings.file_associations() { - let mime_types: Vec<&str> = associations - .iter() - .filter_map(|association| association.mime_type.as_ref()) - .map(|s| s.as_str()) - .collect(); - Some(mime_types.join(";")) - } else { - None - }; - - handlebars.render_to_write( - "main.desktop", - &DesktopTemplateParams { - categories: settings - .app_category() - .map(|app_category| app_category.gnome_desktop_categories()) - .unwrap_or(""), - comment: if !settings.short_description().is_empty() { - Some(settings.short_description()) - } else { - None - }, - exec: bin_name, - icon: bin_name, - name: settings.product_name(), - mime_type, - }, - file, - )?; - - Ok(()) -} - /// Generates the debian control file and stores it under the `control_dir`. fn generate_control_file( settings: &Settings, @@ -309,46 +229,6 @@ fn copy_custom_files(settings: &Settings, data_dir: &Path) -> crate::Result<()> Ok(()) } -/// Generate the icon files and store them under the `data_dir`. -fn generate_icon_files(settings: &Settings, data_dir: &Path) -> crate::Result> { - let base_dir = data_dir.join("usr/share/icons/hicolor"); - let get_dest_path = |width: u32, height: u32, is_high_density: bool| { - base_dir.join(format!( - "{}x{}{}/apps/{}.png", - width, - height, - if is_high_density { "@2" } else { "" }, - settings.main_binary_name() - )) - }; - let mut icons = BTreeSet::new(); - for icon_path in settings.icon_files() { - let icon_path = icon_path?; - if icon_path.extension() != Some(OsStr::new("png")) { - continue; - } - // Put file in scope so that it's closed when copying it - let deb_icon = { - let decoder = PngDecoder::new(File::open(&icon_path)?)?; - let width = decoder.dimensions().0; - let height = decoder.dimensions().1; - let is_high_density = common::is_retina(&icon_path); - let dest_path = get_dest_path(width, height, is_high_density); - DebIcon { - width, - height, - is_high_density, - path: dest_path, - } - }; - if !icons.contains(&deb_icon) { - common::copy_file(&icon_path, &deb_icon.path)?; - icons.insert(deb_icon); - } - } - Ok(icons) -} - /// Create an empty file at the given path, creating any parent directories as /// needed, then write `data` into the file. fn create_file_with_data>(path: P, data: &str) -> crate::Result<()> { diff --git a/tooling/bundler/src/bundle/linux/freedesktop.rs b/tooling/bundler/src/bundle/linux/freedesktop.rs new file mode 100644 index 000000000000..f03606906f6e --- /dev/null +++ b/tooling/bundler/src/bundle/linux/freedesktop.rs @@ -0,0 +1,160 @@ +// Copyright 2016-2019 Cargo-Bundle developers +// Copyright 2019-2023 Tauri Programme within The Commons Conservancy +// SPDX-License-Identifier: Apache-2.0 +// SPDX-License-Identifier: MIT + +//! This module provides utilities helping the packaging of desktop +//! applications for Linux: +//! +//! - Generation of [desktop entries] (`.desktop` files) +//! - Copy of icons in the [icons file hierarchy] +//! +//! The specifications are developed and hosted at [freedesktop.org]. +//! +//! [freedesktop.org]: https://www.freedesktop.org +//! [desktop entries]: https://www.freedesktop.org/wiki/Specifications/desktop-entry-spec/ +//! [icons file hierarchy]: https://specifications.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html#icon_lookup + +use std::collections::BTreeMap; +use std::ffi::OsStr; +use std::fs::{read_to_string, File}; +use std::path::{Path, PathBuf}; + +use anyhow::Context; +use handlebars::Handlebars; +use image::{self, codecs::png::PngDecoder, ImageDecoder}; +use serde::Serialize; + +use crate::bundle::common; +use crate::Settings; + +#[derive(PartialEq, Eq, PartialOrd, Ord)] +pub struct Icon { + pub width: u32, + pub height: u32, + pub is_high_density: bool, + pub path: PathBuf, +} + +/// Generate the icon files, and returns a map where keys are the icons and +/// values are their current (source) path. +pub fn list_icon_files( + settings: &Settings, + data_dir: &Path, +) -> crate::Result> { + let base_dir = data_dir.join("usr/share/icons/hicolor"); + let get_dest_path = |width: u32, height: u32, is_high_density: bool| { + base_dir.join(format!( + "{}x{}{}/apps/{}.png", + width, + height, + if is_high_density { "@2" } else { "" }, + settings.main_binary_name() + )) + }; + let mut icons = BTreeMap::new(); + for icon_path in settings.icon_files() { + let icon_path = icon_path?; + if icon_path.extension() != Some(OsStr::new("png")) { + continue; + } + // Put file in scope so that it's closed when copying it + let icon = { + let decoder = PngDecoder::new(File::open(&icon_path)?)?; + let width = decoder.dimensions().0; + let height = decoder.dimensions().1; + let is_high_density = common::is_retina(&icon_path); + let dest_path = get_dest_path(width, height, is_high_density); + Icon { + width, + height, + is_high_density, + path: dest_path, + } + }; + icons.entry(icon).or_insert(icon_path); + } + + Ok(icons) +} + +/// Generate the icon files and store them under the `data_dir`. +pub fn copy_icon_files(settings: &Settings, data_dir: &Path) -> crate::Result> { + let icons = self::list_icon_files(settings, data_dir)?; + for (icon, src) in &icons { + common::copy_file(src, &icon.path)?; + } + + Ok(icons.into_keys().collect()) +} + +/// Generate the application desktop file and store it under the `data_dir`. +/// Returns the path of the resulting file (source path) and the destination +/// path in the package. +pub fn generate_desktop_file( + settings: &Settings, + template_settings: &Option, + data_dir: &Path, +) -> crate::Result<(PathBuf, PathBuf)> { + let bin_name = settings.main_binary_name(); + let desktop_file_name = format!("{bin_name}.desktop"); + let path = PathBuf::from("usr/share/applications").join(desktop_file_name); + let dest_path = PathBuf::from("/").join(&path); + let file_path = data_dir.join(&path); + let file = &mut common::create_file(&file_path)?; + + let mut handlebars = Handlebars::new(); + handlebars.register_escape_fn(handlebars::no_escape); + if let Some(template) = template_settings { + handlebars + .register_template_string("main.desktop", read_to_string(template)?) + .with_context(|| "Failed to setup custom handlebar template")?; + } else { + handlebars + .register_template_string("main.desktop", include_str!("./templates/main.desktop")) + .with_context(|| "Failed to setup default handlebar template")?; + } + + #[derive(Serialize)] + struct DesktopTemplateParams<'a> { + categories: &'a str, + comment: Option<&'a str>, + exec: &'a str, + icon: &'a str, + name: &'a str, + mime_type: Option, + } + + let mime_type = if let Some(associations) = settings.file_associations() { + let mime_types: Vec<&str> = associations + .iter() + .filter_map(|association| association.mime_type.as_ref()) + .map(|s| s.as_str()) + .collect(); + Some(mime_types.join(";")) + } else { + None + }; + + handlebars.render_to_write( + "main.desktop", + &DesktopTemplateParams { + categories: settings + .app_category() + .map(|app_category| app_category.freedesktop_categories()) + .unwrap_or(""), + comment: if !settings.short_description().is_empty() { + Some(settings.short_description()) + } else { + None + }, + exec: bin_name, + icon: bin_name, + name: settings.product_name(), + mime_type, + }, + file, + )?; + + Ok((file_path, dest_path)) +} diff --git a/tooling/bundler/src/bundle/linux/mod.rs b/tooling/bundler/src/bundle/linux/mod.rs index 5c745aebd363..c25b0e77d310 100644 --- a/tooling/bundler/src/bundle/linux/mod.rs +++ b/tooling/bundler/src/bundle/linux/mod.rs @@ -5,4 +5,5 @@ pub mod appimage; pub mod debian; +pub mod freedesktop; pub mod rpm; diff --git a/tooling/bundler/src/bundle/linux/rpm.rs b/tooling/bundler/src/bundle/linux/rpm.rs index 169c3c4c57d3..6338a48cc53c 100644 --- a/tooling/bundler/src/bundle/linux/rpm.rs +++ b/tooling/bundler/src/bundle/linux/rpm.rs @@ -5,10 +5,147 @@ use crate::Settings; -use std::path::PathBuf; +use anyhow::Context; +use log::info; +use rpm::{self, signature::pgp, Dependency, FileMode, FileOptions}; +use std::{ + env, + fs::{self, File}, + path::{Path, PathBuf}, +}; + +use super::freedesktop; /// Bundles the project. -/// Not implemented yet. -pub fn bundle_project(_settings: &Settings) -> crate::Result> { - unimplemented!(); +/// Returns a vector of PathBuf that shows where the RPM was created. +pub fn bundle_project(settings: &Settings) -> crate::Result> { + let name = settings.main_binary_name(); + let version = settings.version_string(); + let release = settings.rpm().release.as_str(); + let epoch = settings.rpm().epoch; + let arch = match settings.binary_arch() { + "x86" => "i386", + "arm" => "armhfp", + other => other, + }; + + let license = settings + .rpm() + .license + .as_deref() + .or_else(|| settings.license()) + .unwrap_or_default(); + + let summary = settings.short_description().trim(); + + let package_base_name = format!("{name}-{version}-{release}.{arch}"); + let package_name = format!("{package_base_name}.rpm"); + + let base_dir = settings.project_out_directory().join("bundle/rpm"); + let package_dir = base_dir.join(&package_base_name); + if package_dir.exists() { + fs::remove_dir_all(&package_dir) + .with_context(|| format!("Failed to remove old {package_base_name}"))?; + } + fs::create_dir_all(&package_dir)?; + let package_path = base_dir.join(&package_name); + + info!(action = "Bundling"; "{} ({})", package_name, package_path.display()); + + let mut builder = rpm::PackageBuilder::new(name, version, license, arch, summary) + .epoch(epoch) + .release(release); + + if let Some(description) = settings.long_description() { + builder = builder.description(description.trim()) + } + + // Add requirements + for dep in settings.rpm().depends.as_ref().cloned().unwrap_or_default() { + builder = builder.requires(Dependency::any(dep)); + } + + // Add binaries + for bin in settings.binaries() { + let src = settings.binary_path(bin); + let dest = Path::new("/usr/bin").join(bin.name()); + builder = builder.with_file(src, FileOptions::new(dest.to_string_lossy()))?; + } + + // Add external binaries + for src in settings.external_binaries() { + let src = src?; + let dest = Path::new("/usr/bin").join( + src + .file_name() + .expect("failed to extract external binary filename") + .to_string_lossy() + .replace(&format!("-{}", settings.target()), ""), + ); + builder = builder.with_file(&src, FileOptions::new(dest.to_string_lossy()))?; + } + + // Add resources + if settings.resource_files().count() > 0 { + let resource_dir = Path::new("/usr/lib").join(settings.main_binary_name()); + // Create an empty file, needed to add a directory to the RPM package + // (cf https://github.com/rpm-rs/rpm/issues/177) + let empty_file_path = &package_dir.join("empty"); + File::create(empty_file_path)?; + // Then add the resource directory `/usr/lib/` to the package. + builder = builder.with_file( + empty_file_path, + FileOptions::new(resource_dir.to_string_lossy()).mode(FileMode::Dir { permissions: 0o755 }), + )?; + // Then add the resources files in that directory + for src in settings.resource_files() { + let src = src?; + let dest = resource_dir.join(tauri_utils::resources::resource_relpath(&src)); + builder = builder.with_file(&src, FileOptions::new(dest.to_string_lossy()))?; + } + } + + // Add Desktop entry file + let (desktop_src_path, desktop_dest_path) = + freedesktop::generate_desktop_file(settings, &settings.rpm().desktop_template, &package_dir)?; + builder = builder.with_file( + desktop_src_path, + FileOptions::new(desktop_dest_path.to_string_lossy()), + )?; + + // Add icons + for (icon, src) in &freedesktop::list_icon_files(settings, &PathBuf::from("/"))? { + builder = builder.with_file(src, FileOptions::new(icon.path.to_string_lossy()))?; + } + + // Add custom files + for (rpm_path, src_path) in settings.rpm().files.iter() { + if src_path.is_file() { + builder = builder.with_file(src_path, FileOptions::new(rpm_path.to_string_lossy()))?; + } else { + for entry in walkdir::WalkDir::new(src_path) { + let entry_path = entry?.into_path(); + if entry_path.is_file() { + let dest_path = rpm_path.join(entry_path.strip_prefix(src_path).unwrap()); + builder = + builder.with_file(&entry_path, FileOptions::new(dest_path.to_string_lossy()))?; + } + } + } + } + + let pkg = if let Ok(raw_secret_key) = env::var("RPM_SIGN_KEY") { + let mut signer = pgp::Signer::load_from_asc(&raw_secret_key)?; + if let Ok(passphrase) = env::var("RPM_SIGN_KEY_PASSPHRASE") { + signer = signer.with_key_passphrase(passphrase); + } + builder.build_and_sign(signer)? + } else { + builder.build()? + }; + + let mut f = fs::File::create(&package_path)?; + pkg.write(&mut f)?; + + Ok(vec![package_path]) } diff --git a/tooling/bundler/src/bundle/settings.rs b/tooling/bundler/src/bundle/settings.rs index 68934ded1f5e..fc47ed63e442 100644 --- a/tooling/bundler/src/bundle/settings.rs +++ b/tooling/bundler/src/bundle/settings.rs @@ -44,6 +44,7 @@ impl From for PackageType { fn from(bundle: BundleType) -> Self { match bundle { BundleType::Deb => Self::Deb, + BundleType::Rpm => Self::Rpm, BundleType::AppImage => Self::AppImage, BundleType::Msi => Self::WindowsMsi, BundleType::Nsis => Self::Nsis, @@ -148,6 +149,8 @@ pub struct PackageSettings { pub homepage: Option, /// the package's authors. pub authors: Option>, + /// the package's license. + pub license: Option, /// the default binary to run. pub default_run: Option, } @@ -183,6 +186,31 @@ pub struct DebianSettings { pub desktop_template: Option, } +/// The RPM bundle settings. +#[derive(Clone, Debug, Default)] +pub struct RpmSettings { + /// The name of the package's license. + pub license: Option, + /// The list of RPM dependencies your application relies on. + pub depends: Option>, + /// The RPM release tag. + pub release: String, + /// The RPM epoch. + pub epoch: u32, + /// List of custom files to add to the RPM package. + /// Maps the path on the RPM package to the path of the file to include (relative to the current working directory). + pub files: HashMap, + /// Path to a custom desktop file Handlebars template. + /// + /// Available variables: `categories`, `comment` (optional), `exec`, `icon` and `name`. + /// + /// Default file contents: + /// ```text + #[doc = include_str!("./linux/templates/main.desktop")] + /// ``` + pub desktop_template: Option, +} + /// Position coordinates struct. #[derive(Clone, Debug, Default)] pub struct Position { @@ -449,6 +477,8 @@ pub struct BundleSettings { pub external_bin: Option>, /// Debian-specific settings. pub deb: DebianSettings, + /// Rpm-specific settings. + pub rpm: RpmSettings, /// DMG-specific settings. pub dmg: DmgSettings, /// MacOS-specific settings. @@ -714,7 +744,7 @@ impl Settings { let mut platform_types = match target_os.as_str() { "macos" => vec![PackageType::MacOsBundle, PackageType::Dmg], "ios" => vec![PackageType::IosBundle], - "linux" => vec![PackageType::Deb, PackageType::AppImage], + "linux" => vec![PackageType::Deb, PackageType::Rpm, PackageType::AppImage], "windows" => vec![PackageType::WindowsMsi, PackageType::Nsis], os => { return Err(crate::Error::GenericError(format!( @@ -851,6 +881,11 @@ impl Settings { } } + /// Returns the package's license. + pub fn license(&self) -> Option<&str> { + self.package.license.as_deref() + } + /// Returns the package's homepage URL, defaulting to "" if not defined. pub fn homepage_url(&self) -> &str { self.package.homepage.as_deref().unwrap_or("") @@ -885,6 +920,11 @@ impl Settings { &self.bundle_settings.deb } + /// Returns the RPM settings. + pub fn rpm(&self) -> &RpmSettings { + &self.bundle_settings.rpm + } + /// Returns the DMG settings. pub fn dmg(&self) -> &DmgSettings { &self.bundle_settings.dmg diff --git a/tooling/bundler/src/error.rs b/tooling/bundler/src/error.rs index cc412d85bce1..d93adaadd2bd 100644 --- a/tooling/bundler/src/error.rs +++ b/tooling/bundler/src/error.rs @@ -108,6 +108,10 @@ pub enum Error { #[cfg(target_os = "macos")] #[error(transparent)] Plist(#[from] plist::Error), + /// Rpm error. + #[cfg(target_os = "linux")] + #[error("{0}")] + RpmError(#[from] rpm::Error), } /// Convenient type alias of Result type. diff --git a/tooling/bundler/src/lib.rs b/tooling/bundler/src/lib.rs index a43a0d1b2fb0..15d3e54d6132 100644 --- a/tooling/bundler/src/lib.rs +++ b/tooling/bundler/src/lib.rs @@ -12,7 +12,7 @@ //! - macOS //! - DMG and App bundles //! - Linux -//! - Appimage and Debian packages +//! - Appimage, Debian and RPM packages //! - Windows //! - MSI using WiX diff --git a/tooling/cli/Cargo.lock b/tooling/cli/Cargo.lock index 904dfe7f17f5..b02b41f939fc 100644 --- a/tooling/cli/Cargo.lock +++ b/tooling/cli/Cargo.lock @@ -261,6 +261,12 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + [[package]] name = "base64" version = "0.13.1" @@ -273,6 +279,12 @@ version = "0.21.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + [[package]] name = "beef" version = "0.5.2" @@ -303,6 +315,12 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" +[[package]] +name = "bitfield" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d7e60934ceec538daadb9d8432424ed043a904d8e0243f3c6446bce549a46ac" + [[package]] name = "bitflags" version = "1.3.2" @@ -345,6 +363,25 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-padding" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" +dependencies = [ + "generic-array", +] + +[[package]] +name = "blowfish" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e412e2cd0f2b2d93e02543ceae7917b3c70331573df19ee046bcbc35e45e87d7" +dependencies = [ + "byteorder", + "cipher", +] + [[package]] name = "bstr" version = "1.8.0" @@ -355,6 +392,16 @@ dependencies = [ "serde", ] +[[package]] +name = "buffer-redux" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2886ea01509598caac116942abd33ab5a88fa32acdf7e4abfa0fc489ca520c9" +dependencies = [ + "memchr", + "safemem", +] + [[package]] name = "bumpalo" version = "3.14.0" @@ -385,6 +432,37 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +[[package]] +name = "bzip2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" +dependencies = [ + "bzip2-sys", + "libc", +] + +[[package]] +name = "bzip2-sys" +version = "0.1.11+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + +[[package]] +name = "camellia" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3264e2574e9ef2b53ce6f536dea83a69ac0bc600b762d1523ff83fe07230ce30" +dependencies = [ + "byteorder", + "cipher", +] + [[package]] name = "cargo-mobile2" version = "0.8.0" @@ -420,12 +498,22 @@ dependencies = [ "windows 0.51.1", ] +[[package]] +name = "cast5" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b07d673db1ccf000e90f54b819db9e75a8348d6eb056e9b8ab53231b7a9911" +dependencies = [ + "cipher", +] + [[package]] name = "cc" version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" dependencies = [ + "jobserver", "libc", ] @@ -440,6 +528,15 @@ dependencies = [ "uuid", ] +[[package]] +name = "cfb-mode" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "738b8d467867f80a71351933f70461f5b56f24d5c93e0cf216e59229c968d330" +dependencies = [ + "cipher", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -454,8 +551,10 @@ checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" dependencies = [ "android-tzdata", "iana-time-zone", + "js-sys", "num-traits", "serde", + "wasm-bindgen", "windows-targets 0.48.5", ] @@ -560,6 +659,12 @@ dependencies = [ "windows-sys 0.45.0", ] +[[package]] +name = "const-oid" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" + [[package]] name = "convert_case" version = "0.4.0" @@ -600,6 +705,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "cpio" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27e77cfc4543efb4837662cb7cd53464ae66f0fd5c708d71e0f338b1c11d62d3" + [[package]] name = "cpufeatures" version = "0.2.11" @@ -609,6 +720,12 @@ dependencies = [ "libc", ] +[[package]] +name = "crc24" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd121741cf3eb82c08dd3023eb55bf2665e5f60ec20f89760cf836ae4562e6a0" + [[package]] name = "crc32fast" version = "1.3.2" @@ -667,6 +784,18 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + [[package]] name = "crypto-common" version = "0.1.6" @@ -750,14 +879,66 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "curve25519-dalek" +version = "4.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest 0.10.7", + "fiat-crypto", + "platforms", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + +[[package]] +name = "darling" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +dependencies = [ + "darling_core 0.14.4", + "darling_macro 0.14.4", +] + [[package]] name = "darling" version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.20.3", + "darling_macro 0.20.3", +] + +[[package]] +name = "darling_core" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 1.0.109", ] [[package]] @@ -774,13 +955,24 @@ dependencies = [ "syn 2.0.39", ] +[[package]] +name = "darling_macro" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +dependencies = [ + "darling_core 0.14.4", + "quote", + "syn 1.0.109", +] + [[package]] name = "darling_macro" version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ - "darling_core", + "darling_core 0.20.3", "quote", "syn 2.0.39", ] @@ -803,6 +995,17 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41b319d1b62ffbd002e057f36bebd1f42b9f97927c9577461d855f3513c4289f" +[[package]] +name = "der" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + [[package]] name = "deranged" version = "0.3.9" @@ -813,6 +1016,37 @@ dependencies = [ "serde", ] +[[package]] +name = "derive_builder" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d67778784b508018359cbc8696edb3db78160bab2c2a28ba7f56ef6932997f8" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f" +dependencies = [ + "darling 0.14.4", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_builder_macro" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebcda35c7a396850a55ffeac740804b40ffec779b98fffbb1738f4033f0ee79e" +dependencies = [ + "derive_builder_core", + "syn 1.0.109", +] + [[package]] name = "derive_more" version = "0.99.17" @@ -826,6 +1060,15 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "des" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffdd80ce8ce993de27e9f063a444a4d53ce8e8db4c1f00cc03af5ad5a9867a1e" +dependencies = [ + "cipher", +] + [[package]] name = "deunicode" version = "1.4.1" @@ -861,6 +1104,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", + "const-oid", "crypto-common", "subtle", ] @@ -925,12 +1169,71 @@ version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d" +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest 0.10.7", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0" +dependencies = [ + "curve25519-dalek", + "ed25519", + "serde", + "sha2", + "subtle", + "zeroize", +] + [[package]] name = "either" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest 0.10.7", + "ff", + "generic-array", + "group", + "hkdf", + "pem-rfc7468", + "pkcs8", + "rand_core 0.6.4", + "sec1", + "subtle", + "zeroize", +] + [[package]] name = "embed-resource" version = "2.4.0" @@ -965,6 +1268,28 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e4f5d6e192964d498b45abee72ca445e91909094bc8e8791259e82c2a0d1aa6" +[[package]] +name = "enum-display-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f16ef37b2a9b242295d61a154ee91ae884afff6b8b933b486b12481cc58310ca" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "enum-primitive-derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba7795da175654fe16979af73f81f26a8ea27638d8d9823d317016888a63dc4c" +dependencies = [ + "num-traits", + "quote", + "syn 2.0.39", +] + [[package]] name = "env_logger" version = "0.10.1" @@ -1050,6 +1375,22 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "fiat-crypto" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27573eac26f4dd11e2b1916c3fe1baa56407c83c71a773a8ba17ec0bca03b6b7" + [[package]] name = "filetime" version = "0.2.22" @@ -1084,7 +1425,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" dependencies = [ - "spin", + "spin 0.9.8", ] [[package]] @@ -1279,6 +1620,7 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", + "zeroize", ] [[package]] @@ -1350,6 +1692,17 @@ dependencies = [ "regex-syntax", ] +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "h2" version = "0.3.22" @@ -1434,6 +1787,15 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + [[package]] name = "hmac" version = "0.12.1" @@ -1553,6 +1915,15 @@ dependencies = [ "cc", ] +[[package]] +name = "idea" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "075557004419d7f2031b8bb7f44bb43e55a83ca7b63076a8fb8fe75753836477" +dependencies = [ + "cipher", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -1737,9 +2108,18 @@ dependencies = [ [[package]] name = "itertools" -version = "0.11.0" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" dependencies = [ "either", ] @@ -1767,6 +2147,15 @@ dependencies = [ "regex", ] +[[package]] +name = "jobserver" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" +dependencies = [ + "libc", +] + [[package]] name = "jpeg-decoder" version = "0.3.0" @@ -1943,6 +2332,15 @@ dependencies = [ "uuid", ] +[[package]] +name = "keccak" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +dependencies = [ + "cpufeatures", +] + [[package]] name = "kqueue" version = "1.0.8" @@ -1990,6 +2388,9 @@ name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +dependencies = [ + "spin 0.5.2", +] [[package]] name = "lebe" @@ -2037,6 +2438,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + [[package]] name = "libredox" version = "0.0.1" @@ -2100,6 +2507,17 @@ dependencies = [ "value-bag", ] +[[package]] +name = "lzma-sys" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fda04ab3764e6cde78b9974eec4f779acaba7c4e84b36eca3cf77c581b85d27" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + [[package]] name = "mac" version = "0.1.1" @@ -2132,6 +2550,16 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest 0.10.7", +] + [[package]] name = "md5" version = "0.7.0" @@ -2395,6 +2823,24 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-bigint-dig" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" +dependencies = [ + "byteorder", + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand 0.8.5", + "serde", + "smallvec", + "zeroize", +] + [[package]] name = "num-cmp" version = "0.1.0" @@ -2410,6 +2856,17 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-derive" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfb77679af88f8b125209d354a202862602672222e7f2313fdd6dc349bad4712" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] + [[package]] name = "num-integer" version = "0.1.45" @@ -2450,6 +2907,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -2577,6 +3035,30 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "p256" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + +[[package]] +name = "p384" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70786f51bcc69f6a4c0360e063a4cac5419ef7c5cd5b3c99ad70f3be5ba79209" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + [[package]] name = "parking_lot" version = "0.12.1" @@ -2622,6 +3104,15 @@ dependencies = [ "hmac", ] +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + [[package]] name = "percent-encoding" version = "2.3.1" @@ -2673,6 +3164,58 @@ dependencies = [ "sha2", ] +[[package]] +name = "pgp" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27e1f8e085bfa9b85763fe3ddaacbe90a09cd847b3833129153a6cb063bbe132" +dependencies = [ + "aes", + "base64 0.21.5", + "bitfield", + "block-padding", + "blowfish", + "bstr", + "buffer-redux", + "byteorder", + "camellia", + "cast5", + "cfb-mode", + "chrono", + "cipher", + "crc24", + "curve25519-dalek", + "derive_builder", + "des", + "digest 0.10.7", + "ed25519-dalek", + "elliptic-curve", + "flate2", + "generic-array", + "hex", + "idea", + "log", + "md-5", + "nom", + "num-bigint-dig", + "num-derive", + "num-traits", + "p256", + "p384", + "rand 0.8.5", + "ripemd", + "rsa", + "sha1", + "sha2", + "sha3", + "signature", + "smallvec", + "thiserror", + "twofish", + "x25519-dalek", + "zeroize", +] + [[package]] name = "phf" version = "0.8.0" @@ -2861,12 +3404,39 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der", + "pkcs8", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "pkg-config" version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +[[package]] +name = "platforms" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14e6ab3f592e6fb464fc9712d8d6e6912de6473954635fd76a589d832cffcbb0" + [[package]] name = "plist" version = "1.6.0" @@ -2924,6 +3494,15 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" +[[package]] +name = "primeorder" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +dependencies = [ + "elliptic-curve", +] + [[package]] name = "proc-macro-hack" version = "0.5.20+deprecated" @@ -3183,6 +3762,16 @@ dependencies = [ "usvg", ] +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + [[package]] name = "rgb" version = "0.8.37" @@ -3201,11 +3790,20 @@ dependencies = [ "cc", "getrandom 0.2.11", "libc", - "spin", + "spin 0.9.8", "untrusted", "windows-sys 0.48.0", ] +[[package]] +name = "ripemd" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" +dependencies = [ + "digest 0.10.7", +] + [[package]] name = "rle-decode-fast" version = "1.0.3" @@ -3238,6 +3836,56 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "rpm" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a681f5d3dc43f62b636c8e2d0b709e85673cf12eb036cde5a48b26e930a6777" +dependencies = [ + "bitflags 2.4.1", + "bzip2", + "chrono", + "cpio", + "digest 0.10.7", + "enum-display-derive", + "enum-primitive-derive", + "flate2", + "hex", + "itertools 0.12.0", + "log", + "md-5", + "nom", + "num", + "num-derive", + "num-traits", + "pgp", + "sha1", + "sha2", + "thiserror", + "xz2", + "zstd", +] + +[[package]] +name = "rsa" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc" +dependencies = [ + "const-oid", + "digest 0.10.7", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core 0.6.4", + "signature", + "spki", + "subtle", + "zeroize", +] + [[package]] name = "rtoolbox" version = "0.0.2" @@ -3431,6 +4079,20 @@ dependencies = [ "untrusted", ] +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + [[package]] name = "security-framework" version = "2.9.2" @@ -3595,7 +4257,7 @@ version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93634eb5f75a2323b16de4748022ac4297f9e76b6dced2be287a099f41b5e788" dependencies = [ - "darling", + "darling 0.20.3", "proc-macro2", "quote", "syn 2.0.39", @@ -3674,6 +4336,16 @@ dependencies = [ "digest 0.10.7", ] +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest 0.10.7", + "keccak", +] + [[package]] name = "shared_child" version = "1.0.0" @@ -3690,6 +4362,16 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest 0.10.7", + "rand_core 0.6.4", +] + [[package]] name = "simd-adler32" version = "0.3.7" @@ -3777,6 +4459,12 @@ dependencies = [ "sha-1", ] +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + [[package]] name = "spin" version = "0.9.8" @@ -3786,6 +4474,16 @@ dependencies = [ "lock_api", ] +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -4033,6 +4731,7 @@ dependencies = [ "os_pipe", "plist", "regex", + "rpm", "semver", "serde", "serde_json", @@ -4077,7 +4776,7 @@ dependencies = [ "ignore", "image", "include_dir", - "itertools", + "itertools 0.11.0", "json-patch", "jsonrpsee", "jsonrpsee-client-transport", @@ -4571,6 +5270,15 @@ dependencies = [ "utf-8", ] +[[package]] +name = "twofish" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a78e83a30223c757c3947cd144a31014ff04298d8719ae10d03c31c0448c8013" +dependencies = [ + "cipher", +] + [[package]] name = "typenum" version = "1.17.0" @@ -5260,6 +5968,18 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "x25519-dalek" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb66477291e7e8d2b0ff1bcb900bf29489a9692816d79874bea351e7a8b6de96" +dependencies = [ + "curve25519-dalek", + "rand_core 0.6.4", + "serde", + "zeroize", +] + [[package]] name = "xattr" version = "1.0.1" @@ -5281,6 +6001,15 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9" +[[package]] +name = "xz2" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388c44dc09d76f1536602ead6d325eb532f5c122f17782bd57fb47baeeb767e2" +dependencies = [ + "lzma-sys", +] + [[package]] name = "zerocopy" version = "0.7.26" @@ -5306,6 +6035,20 @@ name = "zeroize" version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] [[package]] name = "zip" @@ -5319,6 +6062,34 @@ dependencies = [ "flate2", ] +[[package]] +name = "zstd" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bffb3309596d527cfcba7dfc6ed6052f1d39dfbd7c867aa2e865e4a449c10110" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43747c7422e2924c11144d5229878b98180ef8b06cca4ab5af37afc8a8d8ea3e" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.9+zstd.1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" +dependencies = [ + "cc", + "pkg-config", +] + [[package]] name = "zune-inflate" version = "0.2.54" diff --git a/tooling/cli/ENVIRONMENT_VARIABLES.md b/tooling/cli/ENVIRONMENT_VARIABLES.md index f4d4b195bd8b..b4611a276661 100644 --- a/tooling/cli/ENVIRONMENT_VARIABLES.md +++ b/tooling/cli/ENVIRONMENT_VARIABLES.md @@ -35,6 +35,8 @@ These environment variables are inputs to the CLI which may have an equivalent C - `TAURI_WEBVIEW_AUTOMATION` — Enables webview automation (Linux Only). - `TAURI_ANDROID_PROJECT_PATH` — Path of the tauri android project, usually will be `/src-tauri/gen/android`. - `TAURI_IOS_PROJECT_PATH` — Path of the tauri iOS project, usually will be `/src-tauri/gen/ios`. +- `RPM_SIGN_KEY` — The private GPG key used to sign the RPM bundle, exported to its ASCII-armored format. +- `RPM_SIGN_KEY_PASSPHRASE` — The GPG key passphrase for `RPM_SIGN_KEY`, if needed. ### Tauri CLI Hook Commands diff --git a/tooling/cli/schema.json b/tooling/cli/schema.json index 573d37924808..20bb882b5f50 100644 --- a/tooling/cli/schema.json +++ b/tooling/cli/schema.json @@ -57,6 +57,11 @@ "macOS": { "minimumSystemVersion": "10.13" }, + "rpm": { + "epoch": 0, + "files": {}, + "release": "1" + }, "targets": "all", "updater": { "active": false, @@ -205,6 +210,11 @@ "macOS": { "minimumSystemVersion": "10.13" }, + "rpm": { + "epoch": 0, + "files": {}, + "release": "1" + }, "targets": "all", "updater": { "active": false, @@ -933,7 +943,7 @@ "type": "boolean" }, "targets": { - "description": "The bundle targets, currently supports [\"deb\", \"appimage\", \"nsis\", \"msi\", \"app\", \"dmg\", \"updater\"] or \"all\".", + "description": "The bundle targets, currently supports [\"deb\", \"rpm\", \"appimage\", \"nsis\", \"msi\", \"app\", \"dmg\", \"updater\"] or \"all\".", "default": "all", "allOf": [ { @@ -1031,6 +1041,19 @@ } ] }, + "rpm": { + "description": "Configuration for the RPM bundle.", + "default": { + "epoch": 0, + "files": {}, + "release": "1" + }, + "allOf": [ + { + "$ref": "#/definitions/RpmConfig" + } + ] + }, "dmg": { "description": "DMG-specific settings.", "default": { @@ -1170,6 +1193,13 @@ "deb" ] }, + { + "description": "The RPM bundle (.rpm).", + "type": "string", + "enum": [ + "rpm" + ] + }, { "description": "The AppImage bundle (.appimage).", "type": "string", @@ -1368,6 +1398,57 @@ }, "additionalProperties": false }, + "RpmConfig": { + "description": "Configuration for RPM bundles.", + "type": "object", + "properties": { + "license": { + "description": "The package's license identifier. If not set, defaults to the license from the Cargo.toml file.", + "type": [ + "string", + "null" + ] + }, + "depends": { + "description": "The list of RPM dependencies your application relies on.", + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + } + }, + "release": { + "description": "The RPM release tag.", + "default": "1", + "type": "string" + }, + "epoch": { + "description": "The RPM epoch.", + "default": 0, + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "files": { + "description": "The files to include on the package.", + "default": {}, + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "desktopTemplate": { + "description": "Path to a custom desktop file Handlebars template.\n\nAvailable variables: `categories`, `comment` (optional), `exec`, `icon` and `name`.", + "type": [ + "string", + "null" + ] + } + }, + "additionalProperties": false + }, "DmgConfig": { "description": "Configuration for Apple Disk Image (.dmg) bundles.\n\nSee more: https://tauri.app/v1/api/config#dmgconfig", "type": "object", diff --git a/tooling/cli/src/build.rs b/tooling/cli/src/build.rs index 80d029a5f9cf..3909ad07937c 100644 --- a/tooling/cli/src/build.rs +++ b/tooling/cli/src/build.rs @@ -49,7 +49,7 @@ pub struct Options { pub features: Option>, /// Space or comma separated list of bundles to package. /// - /// Each bundle must be one of `deb`, `appimage`, `msi`, `app` or `dmg` on MacOS and `updater` on all platforms. + /// Each bundle must be one of `deb`, `rpm`, `appimage`, `msi`, `app` or `dmg` on MacOS and `updater` on all platforms. /// If `none` is specified, the bundler will be skipped. /// /// Note that the `updater` bundle is not automatically added so you must specify it if the updater is enabled. diff --git a/tooling/cli/src/interface/rust.rs b/tooling/cli/src/interface/rust.rs index 108dfeaaa446..4a1e7eb6dda7 100644 --- a/tooling/cli/src/interface/rust.rs +++ b/tooling/cli/src/interface/rust.rs @@ -23,7 +23,7 @@ use notify_debouncer_mini::new_debouncer; use serde::Deserialize; use tauri_bundler::{ AppCategory, BundleBinary, BundleSettings, DebianSettings, DmgSettings, MacOsSettings, - PackageSettings, Position, Size, UpdaterSettings, WindowsSettings, + PackageSettings, Position, RpmSettings, Size, UpdaterSettings, WindowsSettings, }; use tauri_utils::config::parse::is_configuration_file; @@ -650,6 +650,8 @@ pub struct CargoPackageSettings { pub homepage: Option>, /// the package's authors. pub authors: Option>>, + /// the package's license. + pub license: Option, /// the default binary to run. pub default_run: Option, } @@ -704,7 +706,15 @@ impl AppSettings for RustAppSettings { config: &Config, features: &[String], ) -> crate::Result { - tauri_config_to_bundle_settings(&self.manifest, features, config.tauri.bundle.clone()) + let arch64bits = + self.target_triple.starts_with("x86_64") || self.target_triple.starts_with("aarch64"); + + tauri_config_to_bundle_settings( + &self.manifest, + features, + config.tauri.bundle.clone(), + arch64bits, + ) } fn app_binary_path(&self, options: &Options) -> crate::Result { @@ -936,6 +946,7 @@ impl RustAppSettings { }) .unwrap() }), + license: cargo_package_settings.license.clone(), default_run: cargo_package_settings.default_run.clone(), }; @@ -1049,6 +1060,7 @@ fn tauri_config_to_bundle_settings( manifest: &Manifest, features: &[String], config: crate::helpers::config::BundleConfig, + arch64bits: bool, ) -> crate::Result { let enabled_features = manifest.all_enabled_features(features); @@ -1069,11 +1081,15 @@ fn tauri_config_to_bundle_settings( .resources .unwrap_or(BundleResources::List(Vec::new())); #[allow(unused_mut)] - let mut depends = config.deb.depends.unwrap_or_default(); + let mut depends_deb = config.deb.depends.unwrap_or_default(); + #[allow(unused_mut)] + let mut depends_rpm = config.rpm.depends.unwrap_or_default(); // set env vars used by the bundler and inject dependencies #[cfg(target_os = "linux")] { + let mut libs: Vec = Vec::new(); + if enabled_features.contains(&"tray-icon".into()) || enabled_features.contains(&"tauri/tray-icon".into()) { @@ -1102,19 +1118,30 @@ fn tauri_config_to_bundle_settings( .unwrap_or_else(|_| pkgconfig_utils::get_appindicator_library_path()); match tray_kind { pkgconfig_utils::TrayKind::Ayatana => { - depends.push("libayatana-appindicator3-1".into()); + depends_deb.push("libayatana-appindicator3-1".into()); } pkgconfig_utils::TrayKind::Libappindicator => { - depends.push("libappindicator3-1".into()); + depends_deb.push("libappindicator3-1".into()); + libs.push("libappindicator3.so.1".into()); } } std::env::set_var("TAURI_TRAY_LIBRARY_PATH", path); } - // provides `libwebkit2gtk-4.1.so.37` and all `4.0` versions have the -37 package name - depends.push("libwebkit2gtk-4.1-0".to_string()); - depends.push("libgtk-3-0".to_string()); + depends_deb.push("libwebkit2gtk-4.1-0".to_string()); + depends_deb.push("libgtk-3-0".to_string()); + + libs.push("libwebkit2gtk-4.1.so.0".into()); + libs.push("libgtk-3.so.0".into()); + + for lib in libs { + let mut requires = lib; + if arch64bits { + requires.push_str("()(64bit)"); + } + depends_rpm.push(requires); + } } #[cfg(windows)] @@ -1172,14 +1199,26 @@ fn tauri_config_to_bundle_settings( long_description: config.long_description, external_bin: config.external_bin, deb: DebianSettings { - depends: if depends.is_empty() { + depends: if depends_deb.is_empty() { None } else { - Some(depends) + Some(depends_deb) }, files: config.deb.files, desktop_template: config.deb.desktop_template, }, + rpm: RpmSettings { + license: config.rpm.license, + depends: if depends_rpm.is_empty() { + None + } else { + Some(depends_rpm) + }, + release: config.rpm.release, + epoch: config.rpm.epoch, + files: config.rpm.files, + desktop_template: config.rpm.desktop_template, + }, dmg: DmgSettings { background: config.dmg.background, window_position: config.dmg.window_position.map(|window_position| Position {