added packaging / bundling
This commit is contained in:
4
.cargo/config.toml
Normal file
4
.cargo/config.toml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[alias]
|
||||||
|
bundle-macos = "packager --release --packages bds-ui --formats app --formats dmg"
|
||||||
|
bundle-windows = "packager --release --packages bds-ui --formats nsis"
|
||||||
|
bundle-linux = "packager --release --packages bds-ui --formats deb --formats appimage"
|
||||||
22
BUILD.md
22
BUILD.md
@@ -1,5 +1,25 @@
|
|||||||
# RuDS — Build Prerequisites
|
# RuDS — Build Prerequisites
|
||||||
|
|
||||||
|
## Native desktop packages
|
||||||
|
|
||||||
|
Install the pinned Cargo Packager CLI once:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cargo install cargo-packager --locked --version 0.11.8
|
||||||
|
```
|
||||||
|
|
||||||
|
Build packages on their native operating system from the repository root:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cargo bundle-macos # Blogging Desktop Server.app and .dmg
|
||||||
|
cargo bundle-windows # NSIS .exe installer
|
||||||
|
cargo bundle-linux # .deb and .AppImage
|
||||||
|
```
|
||||||
|
|
||||||
|
Packages are written below `target/release`. The macOS bundle uses the ICNS icon, Windows embeds the ICO in the application executable and installer, and Linux packages install the 1024×1024 PNG with their desktop entry.
|
||||||
|
|
||||||
|
Windows packaging requires the MSVC Rust toolchain, Visual Studio Build Tools with C++ support, and the Windows SDK. Build each package on its target operating system; these commands do not cross-package installers.
|
||||||
|
|
||||||
## macOS system requirements
|
## macOS system requirements
|
||||||
|
|
||||||
- macOS 13 (Ventura) or later
|
- macOS 13 (Ventura) or later
|
||||||
@@ -12,7 +32,7 @@
|
|||||||
|
|
||||||
```sh
|
```sh
|
||||||
# Debian/Ubuntu
|
# Debian/Ubuntu
|
||||||
sudo apt install build-essential cmake pkg-config libgtk-3-dev libxdo-dev libdbus-1-dev
|
sudo apt install build-essential cmake pkg-config libgtk-3-dev libxdo-dev libdbus-1-dev libwebkit2gtk-4.1-dev
|
||||||
```
|
```
|
||||||
|
|
||||||
## Install Homebrew packages (macOS)
|
## Install Homebrew packages (macOS)
|
||||||
|
|||||||
32
Cargo.lock
generated
32
Cargo.lock
generated
@@ -858,6 +858,7 @@ dependencies = [
|
|||||||
"tempfile",
|
"tempfile",
|
||||||
"tokio",
|
"tokio",
|
||||||
"uuid",
|
"uuid",
|
||||||
|
"winresource",
|
||||||
"wry",
|
"wry",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -7461,6 +7462,21 @@ dependencies = [
|
|||||||
"winnow 0.7.15",
|
"winnow 0.7.15",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml"
|
||||||
|
version = "1.1.3+spec-1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "53c96ecdfa941c8fc4fcaed14f99ada8ebed502eef533015095a07e3301d4c3c"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap 2.13.0",
|
||||||
|
"serde_core",
|
||||||
|
"serde_spanned 1.1.1",
|
||||||
|
"toml_datetime 1.1.1+spec-1.1.0",
|
||||||
|
"toml_parser",
|
||||||
|
"toml_writer",
|
||||||
|
"winnow 1.0.4",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_datetime"
|
name = "toml_datetime"
|
||||||
version = "0.6.3"
|
version = "0.6.3"
|
||||||
@@ -7533,6 +7549,12 @@ dependencies = [
|
|||||||
"winnow 1.0.4",
|
"winnow 1.0.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_writer"
|
||||||
|
version = "1.1.2+spec-1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tower"
|
name = "tower"
|
||||||
version = "0.5.3"
|
version = "0.5.3"
|
||||||
@@ -9081,6 +9103,16 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winresource"
|
||||||
|
version = "0.1.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0986a8b1d586b7d3e4fe3d9ea39fb451ae22869dcea4aa109d287a374d866087"
|
||||||
|
dependencies = [
|
||||||
|
"toml 1.1.3+spec-1.1.0",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wit-bindgen"
|
name = "wit-bindgen"
|
||||||
version = "0.51.0"
|
version = "0.51.0"
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ impl Database {
|
|||||||
let mut conn = SqliteConnection::establish(database_url)?;
|
let mut conn = SqliteConnection::establish(database_url)?;
|
||||||
// SQLite connection configuration is backend-specific and not expressible in Diesel's DSL.
|
// SQLite connection configuration is backend-specific and not expressible in Diesel's DSL.
|
||||||
conn.batch_execute(if wal {
|
conn.batch_execute(if wal {
|
||||||
"PRAGMA journal_mode=WAL; PRAGMA synchronous=NORMAL; PRAGMA foreign_keys=ON;"
|
"PRAGMA busy_timeout=5000; PRAGMA journal_mode=WAL; PRAGMA synchronous=NORMAL; PRAGMA foreign_keys=ON;"
|
||||||
} else {
|
} else {
|
||||||
"PRAGMA foreign_keys=ON;"
|
"PRAGMA foreign_keys=ON;"
|
||||||
})?;
|
})?;
|
||||||
|
|||||||
@@ -29,3 +29,24 @@ objc2-app-kit = "0.3"
|
|||||||
fluent-syntax = "0.12"
|
fluent-syntax = "0.12"
|
||||||
syn = { version = "2", features = ["full", "visit"] }
|
syn = { version = "2", features = ["full", "visit"] }
|
||||||
tempfile = "3"
|
tempfile = "3"
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
winresource = "0.1"
|
||||||
|
|
||||||
|
[package.metadata.packager]
|
||||||
|
product-name = "Blogging Desktop Server"
|
||||||
|
identifier = "de.rfc1437.bds2"
|
||||||
|
description = "A desktop application for writing and publishing static blogs."
|
||||||
|
before-packaging-command = "cargo build --release -p bds-ui"
|
||||||
|
icons = [
|
||||||
|
"assets/app-icons/bds.icns",
|
||||||
|
"assets/app-icons/bds.ico",
|
||||||
|
"assets/app-icons/bds.png",
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.metadata.packager.macos]
|
||||||
|
minimum-system-version = "13.0"
|
||||||
|
signing-identity = "-"
|
||||||
|
|
||||||
|
[package.metadata.packager.nsis]
|
||||||
|
installer-icon = "assets/app-icons/bds.ico"
|
||||||
|
|||||||
BIN
crates/bds-ui/assets/app-icons/bds.icns
Normal file
BIN
crates/bds-ui/assets/app-icons/bds.icns
Normal file
Binary file not shown.
BIN
crates/bds-ui/assets/app-icons/bds.ico
Normal file
BIN
crates/bds-ui/assets/app-icons/bds.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 78 KiB |
BIN
crates/bds-ui/assets/app-icons/bds.png
Normal file
BIN
crates/bds-ui/assets/app-icons/bds.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 809 KiB |
10
crates/bds-ui/build.rs
Normal file
10
crates/bds-ui/build.rs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
fn main() {
|
||||||
|
println!("cargo:rerun-if-changed=assets/app-icons/bds.ico");
|
||||||
|
|
||||||
|
if std::env::var("CARGO_CFG_TARGET_OS").as_deref() == Ok("windows") {
|
||||||
|
winresource::WindowsResource::new()
|
||||||
|
.set_icon("assets/app-icons/bds.ico")
|
||||||
|
.compile()
|
||||||
|
.expect("compile Windows application icon");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,19 @@
|
|||||||
|
#![cfg_attr(target_os = "windows", windows_subsystem = "windows")]
|
||||||
|
|
||||||
use bds_ui::BdsApp;
|
use bds_ui::BdsApp;
|
||||||
|
|
||||||
fn main() -> iced::Result {
|
fn main() -> iced::Result {
|
||||||
|
let icon =
|
||||||
|
iced::window::icon::from_file_data(include_bytes!("../assets/app-icons/bds.png"), None)
|
||||||
|
.expect("bundled application icon must be valid");
|
||||||
|
|
||||||
iced::application("bDS", BdsApp::update, BdsApp::view)
|
iced::application("bDS", BdsApp::update, BdsApp::view)
|
||||||
.subscription(BdsApp::subscription)
|
.subscription(BdsApp::subscription)
|
||||||
.theme(|_| iced::Theme::Dark)
|
.theme(|_| iced::Theme::Dark)
|
||||||
.window_size((1200.0, 800.0))
|
.window(iced::window::Settings {
|
||||||
|
size: iced::Size::new(1200.0, 800.0),
|
||||||
|
icon: Some(icon),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
.run_with(BdsApp::new)
|
.run_with(BdsApp::new)
|
||||||
}
|
}
|
||||||
|
|||||||
41
crates/bds-ui/tests/packaging_assets.rs
Normal file
41
crates/bds-ui/tests/packaging_assets.rs
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
use std::{fs, path::Path};
|
||||||
|
|
||||||
|
const CRATE_DIR: &str = env!("CARGO_MANIFEST_DIR");
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn desktop_packages_have_native_icons_and_cargo_commands() {
|
||||||
|
let assets = Path::new(CRATE_DIR).join("assets/app-icons");
|
||||||
|
let png = fs::read(assets.join("bds.png")).expect("Linux PNG icon");
|
||||||
|
let ico = fs::read(assets.join("bds.ico")).expect("Windows ICO icon");
|
||||||
|
let icns = fs::read(assets.join("bds.icns")).expect("macOS ICNS icon");
|
||||||
|
|
||||||
|
assert_eq!(&png[..8], b"\x89PNG\r\n\x1a\n");
|
||||||
|
assert_eq!(u32::from_be_bytes(png[16..20].try_into().unwrap()), 1024);
|
||||||
|
assert_eq!(u32::from_be_bytes(png[20..24].try_into().unwrap()), 1024);
|
||||||
|
assert_eq!(&ico[..4], &[0, 0, 1, 0]);
|
||||||
|
assert!(u16::from_le_bytes(ico[4..6].try_into().unwrap()) >= 6);
|
||||||
|
assert_eq!(&icns[..4], b"icns");
|
||||||
|
|
||||||
|
let manifest = fs::read_to_string(Path::new(CRATE_DIR).join("Cargo.toml")).unwrap();
|
||||||
|
for required in [
|
||||||
|
"[package.metadata.packager]",
|
||||||
|
"assets/app-icons/bds.png",
|
||||||
|
"assets/app-icons/bds.ico",
|
||||||
|
"assets/app-icons/bds.icns",
|
||||||
|
"signing-identity = \"-\"",
|
||||||
|
] {
|
||||||
|
assert!(manifest.contains(required), "missing {required}");
|
||||||
|
}
|
||||||
|
|
||||||
|
let cargo_config = fs::read_to_string(Path::new(CRATE_DIR).join("../../.cargo/config.toml"))
|
||||||
|
.expect("Cargo packaging aliases");
|
||||||
|
for alias in ["bundle-macos", "bundle-windows", "bundle-linux"] {
|
||||||
|
assert!(cargo_config.contains(alias), "missing cargo {alias}");
|
||||||
|
}
|
||||||
|
|
||||||
|
let main = fs::read_to_string(Path::new(CRATE_DIR).join("src/main.rs")).unwrap();
|
||||||
|
assert!(main.contains("assets/app-icons/bds.png"));
|
||||||
|
|
||||||
|
let build = fs::read_to_string(Path::new(CRATE_DIR).join("build.rs")).unwrap();
|
||||||
|
assert!(build.contains("set_icon(\"assets/app-icons/bds.ico\")"));
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user