mirror of
https://github.com/tauri-apps/tauri.git
synced 2026-01-31 00:35:19 +01:00
* feat(bundler): Add RPM packaging * feat(bundler): Update 'rpm' to 0.13.1 * Fix fmt
This commit is contained in:
7
.changes/bundler-rpm.md
Normal file
7
.changes/bundler-rpm.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
"tauri-bundler": 'patch:enhance'
|
||||
"tauri-cli": 'patch:enhance'
|
||||
"@tauri-apps/cli": 'patch:enhance'
|
||||
---
|
||||
|
||||
Add RPM packaging
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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<PathBuf>,
|
||||
}
|
||||
|
||||
/// 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<String>,
|
||||
/// The list of RPM dependencies your application relies on.
|
||||
pub depends: Option<Vec<String>>,
|
||||
/// 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<PathBuf, PathBuf>,
|
||||
/// Path to a custom desktop file Handlebars template.
|
||||
///
|
||||
/// Available variables: `categories`, `comment` (optional), `exec`, `icon` and `name`.
|
||||
pub desktop_template: Option<PathBuf>,
|
||||
}
|
||||
|
||||
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,
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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")]
|
||||
|
||||
@@ -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;",
|
||||
|
||||
@@ -31,7 +31,6 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
|
||||
|
||||
// generate deb_folder structure
|
||||
let (_, icons) = debian::generate_data(settings, &package_dir)?;
|
||||
let icons: Vec<debian::DebIcon> = icons.into_iter().collect();
|
||||
|
||||
let output_path = settings.project_out_directory().join("bundle/appimage");
|
||||
if output_path.exists() {
|
||||
|
||||
@@ -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<Vec<PathBuf>> {
|
||||
@@ -112,7 +99,7 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
|
||||
pub fn generate_data(
|
||||
settings: &Settings,
|
||||
package_dir: &Path,
|
||||
) -> crate::Result<(PathBuf, BTreeSet<DebIcon>)> {
|
||||
) -> crate::Result<(PathBuf, Vec<freedesktop::Icon>)> {
|
||||
// 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<String>,
|
||||
}
|
||||
|
||||
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<BTreeSet<DebIcon>> {
|
||||
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<P: AsRef<Path>>(path: P, data: &str) -> crate::Result<()> {
|
||||
|
||||
160
tooling/bundler/src/bundle/linux/freedesktop.rs
Normal file
160
tooling/bundler/src/bundle/linux/freedesktop.rs
Normal file
@@ -0,0 +1,160 @@
|
||||
// Copyright 2016-2019 Cargo-Bundle developers <https://github.com/burtonageo/cargo-bundle>
|
||||
// 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<BTreeMap<Icon, PathBuf>> {
|
||||
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<Vec<Icon>> {
|
||||
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<PathBuf>,
|
||||
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<String>,
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
@@ -5,4 +5,5 @@
|
||||
|
||||
pub mod appimage;
|
||||
pub mod debian;
|
||||
pub mod freedesktop;
|
||||
pub mod rpm;
|
||||
|
||||
@@ -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<Vec<PathBuf>> {
|
||||
unimplemented!();
|
||||
/// Returns a vector of PathBuf that shows where the RPM was created.
|
||||
pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
|
||||
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/<binary_name>` 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])
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ impl From<BundleType> 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<String>,
|
||||
/// the package's authors.
|
||||
pub authors: Option<Vec<String>>,
|
||||
/// the package's license.
|
||||
pub license: Option<String>,
|
||||
/// the default binary to run.
|
||||
pub default_run: Option<String>,
|
||||
}
|
||||
@@ -183,6 +186,31 @@ pub struct DebianSettings {
|
||||
pub desktop_template: Option<PathBuf>,
|
||||
}
|
||||
|
||||
/// The RPM bundle settings.
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct RpmSettings {
|
||||
/// The name of the package's license.
|
||||
pub license: Option<String>,
|
||||
/// The list of RPM dependencies your application relies on.
|
||||
pub depends: Option<Vec<String>>,
|
||||
/// 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<PathBuf, PathBuf>,
|
||||
/// 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<PathBuf>,
|
||||
}
|
||||
|
||||
/// Position coordinates struct.
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct Position {
|
||||
@@ -449,6 +477,8 @@ pub struct BundleSettings {
|
||||
pub external_bin: Option<Vec<String>>,
|
||||
/// 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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
//! - macOS
|
||||
//! - DMG and App bundles
|
||||
//! - Linux
|
||||
//! - Appimage and Debian packages
|
||||
//! - Appimage, Debian and RPM packages
|
||||
//! - Windows
|
||||
//! - MSI using WiX
|
||||
|
||||
|
||||
785
tooling/cli/Cargo.lock
generated
785
tooling/cli/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -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 `<project>/src-tauri/gen/android`.
|
||||
- `TAURI_IOS_PROJECT_PATH` — Path of the tauri iOS project, usually will be `<project>/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
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -49,7 +49,7 @@ pub struct Options {
|
||||
pub features: Option<Vec<String>>,
|
||||
/// 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.
|
||||
|
||||
@@ -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<MaybeWorkspace<String>>,
|
||||
/// the package's authors.
|
||||
pub authors: Option<MaybeWorkspace<Vec<String>>>,
|
||||
/// the package's license.
|
||||
pub license: Option<String>,
|
||||
/// the default binary to run.
|
||||
pub default_run: Option<String>,
|
||||
}
|
||||
@@ -704,7 +706,15 @@ impl AppSettings for RustAppSettings {
|
||||
config: &Config,
|
||||
features: &[String],
|
||||
) -> crate::Result<BundleSettings> {
|
||||
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<PathBuf> {
|
||||
@@ -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<BundleSettings> {
|
||||
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<String> = 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 {
|
||||
|
||||
Reference in New Issue
Block a user