Build Linux packages

This commit is contained in:
Skyler Lehmkuhl 2026-02-19 15:47:11 -05:00
parent c344e11e42
commit 116db01805
12 changed files with 477 additions and 6 deletions

43
.gitignore vendored Normal file
View File

@ -0,0 +1,43 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
# Git
.gitignore
# Build
src-tauri/gen
src-tauri/target
lightningbeam-core/target
daw-backend/target
target/
# Packaging build artifacts
packaging/output/
packaging/AppDir/
packaging/squashfs-root/
# Wrapper script (generated, not needed with static FFmpeg)
lightningbeam-ui/lightningbeam-editor/debian/

View File

@ -2,6 +2,8 @@
name = "lightningbeam-editor" name = "lightningbeam-editor"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
description = "Multimedia editor for audio, video and 2D animation"
license = "GPL-3.0-or-later"
[dependencies] [dependencies]
lightningbeam-core = { path = "../lightningbeam-core" } lightningbeam-core = { path = "../lightningbeam-core" }
@ -60,3 +62,62 @@ notify-rust = { workspace = true }
# Debug overlay - memory tracking # Debug overlay - memory tracking
memory-stats = "1.1" memory-stats = "1.1"
[package.metadata.deb]
name = "lightningbeam-editor"
maintainer = "Skyler"
copyright = "2025-2026"
extended-description = "GPU-accelerated multimedia editor for audio, video and 2D animation"
license-file = ["../../LICENSE", "0"]
section = "video"
priority = "optional"
depends = "libasound2, libwayland-client0, libx11-6, libvulkan1"
assets = [
["target/release/lightningbeam-editor", "usr/bin/", "755"],
["assets/com.lightningbeam.editor.desktop", "usr/share/applications/", "644"],
["assets/com.lightningbeam.editor.appdata.xml", "usr/share/metainfo/", "644"],
["assets/icons/32x32.png", "usr/share/icons/hicolor/32x32/apps/lightningbeam-editor.png", "644"],
["assets/icons/128x128.png", "usr/share/icons/hicolor/128x128/apps/lightningbeam-editor.png", "644"],
["assets/icons/256x256.png", "usr/share/icons/hicolor/256x256/apps/lightningbeam-editor.png", "644"],
]
[package.metadata.generate-rpm]
name = "lightningbeam-editor"
license = "GPL-3.0-or-later"
summary = "Multimedia editor for audio, video and 2D animation"
[package.metadata.generate-rpm.requires]
alsa-lib = "*"
wayland = "*"
libX11 = "*"
vulkan-loader = "*"
[[package.metadata.generate-rpm.assets]]
source = "target/release/lightningbeam-editor"
dest = "/usr/bin/lightningbeam-editor"
mode = "755"
[[package.metadata.generate-rpm.assets]]
source = "assets/com.lightningbeam.editor.desktop"
dest = "/usr/share/applications/com.lightningbeam.editor.desktop"
mode = "644"
[[package.metadata.generate-rpm.assets]]
source = "assets/com.lightningbeam.editor.appdata.xml"
dest = "/usr/share/metainfo/com.lightningbeam.editor.appdata.xml"
mode = "644"
[[package.metadata.generate-rpm.assets]]
source = "assets/icons/32x32.png"
dest = "/usr/share/icons/hicolor/32x32/apps/lightningbeam-editor.png"
mode = "644"
[[package.metadata.generate-rpm.assets]]
source = "assets/icons/128x128.png"
dest = "/usr/share/icons/hicolor/128x128/apps/lightningbeam-editor.png"
mode = "644"
[[package.metadata.generate-rpm.assets]]
source = "assets/icons/256x256.png"
dest = "/usr/share/icons/hicolor/256x256/apps/lightningbeam-editor.png"
mode = "644"

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop-application">
<id>com.lightningbeam.editor</id>
<metadata_license>CC0-1.0</metadata_license>
<project_license>GPL-3.0-or-later</project_license>
<name>Lightningbeam Editor</name>
<summary>Multimedia editor for audio, video and 2D animation</summary>
<description>
<p>
Lightningbeam is a GPU-accelerated multimedia editor for audio, video and
2D animation. It features timeline-based editing, audio mixing with a
node-based effects system, and a scriptable DSP engine.
</p>
</description>
<launchable type="desktop-id">com.lightningbeam.editor.desktop</launchable>
<provides>
<binary>lightningbeam-editor</binary>
</provides>
<content_rating type="oars-1.1" />
</component>

View File

@ -2,7 +2,7 @@
Version=1.0 Version=1.0
Type=Application Type=Application
Name=Lightningbeam Editor Name=Lightningbeam Editor
Comment=Animation and video editing software Comment=Multimedia editor for audio, video and 2D animation
Exec=lightningbeam-editor Exec=lightningbeam-editor
Icon=lightningbeam-editor Icon=lightningbeam-editor
Terminal=false Terminal=false

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -65,12 +65,26 @@ impl PresetBrowserPane {
self.presets.clear(); self.presets.clear();
self.categories.clear(); self.categories.clear();
// Factory presets: resolve from CARGO_MANIFEST_DIR (lightningbeam-editor crate) // Factory presets: check installed location first, fall back to dev source tree
let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); let factory_dirs = [
let factory_dir = manifest_dir.join("../../src/assets/instruments"); // Installed location (Linux packages / AppImage)
PathBuf::from("/usr/share/lightningbeam-editor/presets"),
// Next to the binary (AppImage / portable)
std::env::current_exe()
.ok()
.and_then(|p| p.parent().map(|d| d.join("presets")))
.unwrap_or_default(),
// Development: relative to CARGO_MANIFEST_DIR
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../src/assets/instruments"),
];
if let Ok(factory_dir) = factory_dir.canonicalize() { for dir in &factory_dirs {
self.scan_directory(&factory_dir, &factory_dir, true); if let Ok(factory_dir) = dir.canonicalize() {
if factory_dir.is_dir() {
self.scan_directory(&factory_dir, &factory_dir, true);
break;
}
}
} }
// User presets // User presets

62
packaging/Containerfile Normal file
View File

@ -0,0 +1,62 @@
FROM ubuntu:24.04
# Avoid interactive prompts
ENV DEBIAN_FRONTEND=noninteractive
# Build essentials + Rust build deps
RUN apt-get update && apt-get install -y \
build-essential \
pkg-config \
clang \
nasm \
curl \
git \
rsync \
wget \
file \
squashfs-tools \
# ALSA (cpal)
libasound2-dev \
# Wayland (winit/eframe)
libwayland-dev \
libwayland-cursor0 \
# X11 (winit/eframe)
libx11-dev \
libxkbcommon-dev \
libxcb-shape0-dev \
libxcb-xfixes0-dev \
# Clipboard (arboard)
libxdo-dev \
# GLib (rfd/muda/gio)
libglib2.0-dev \
libgtk-3-dev \
# Vulkan headers (wgpu)
libvulkan-dev \
# FFmpeg build-from-source deps (ffmpeg-sys-next build feature)
yasm \
libx264-dev \
libx265-dev \
libvpx-dev \
libmp3lame-dev \
libopus-dev \
# PulseAudio (cpal optional backend)
libpulse-dev \
# Packaging tools
dpkg \
rpm \
&& rm -rf /var/lib/apt/lists/*
# Install Rust
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable
ENV PATH="/root/.cargo/bin:${PATH}"
# Install cargo packaging tools
RUN cargo install cargo-deb cargo-generate-rpm
# Download AppImage runtime for building AppImages
RUN wget "https://github.com/AppImage/AppImageKit/releases/download/continuous/runtime-x86_64" \
-O /opt/appimage-runtime && \
chmod +x /opt/appimage-runtime && \
echo "Runtime size: $(wc -c < /opt/appimage-runtime) bytes"
WORKDIR /build

30
packaging/Makefile Normal file
View File

@ -0,0 +1,30 @@
.PHONY: all deb rpm appimage pkgbuild setup-icons clean
SCRIPT_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
REPO_ROOT := $(realpath $(SCRIPT_DIR)/..)
EDITOR := $(REPO_ROOT)/lightningbeam-ui/lightningbeam-editor
OUTPUT := $(SCRIPT_DIR)/output
all: deb rpm appimage
deb rpm appimage:
bash $(SCRIPT_DIR)/container-build.sh $@
pkgbuild: setup-icons
@echo "==> Building Arch package..."
cd $(SCRIPT_DIR)/arch && makepkg -sf
@mkdir -p $(OUTPUT)
cp $(SCRIPT_DIR)/arch/*.pkg.tar.zst $(OUTPUT)/ 2>/dev/null || true
@echo "==> Done: $(OUTPUT)/*.pkg.tar.zst"
setup-icons:
@echo "==> Setting up icons..."
@mkdir -p $(EDITOR)/assets/icons
@cp -u $(REPO_ROOT)/src-tauri/icons/32x32.png $(EDITOR)/assets/icons/ 2>/dev/null || true
@cp -u $(REPO_ROOT)/src-tauri/icons/128x128.png $(EDITOR)/assets/icons/ 2>/dev/null || true
@cp -u $(REPO_ROOT)/src-tauri/icons/icon.png $(EDITOR)/assets/icons/256x256.png 2>/dev/null || true
@echo " Icons ready"
clean:
rm -rf $(OUTPUT)
rm -f $(SCRIPT_DIR)/arch/*.pkg.tar.zst 2>/dev/null || true

66
packaging/arch/PKGBUILD Normal file
View File

@ -0,0 +1,66 @@
# Maintainer: Skyler
pkgname=lightningbeam-editor
pkgver=0.1.0
pkgrel=1
pkgdesc="Multimedia editor for audio, video and 2D animation"
arch=('x86_64')
license=('GPL-3.0-or-later')
depends=(
'alsa-lib'
'wayland'
'libx11'
'vulkan-icd-loader'
'ffmpeg'
)
makedepends=(
'cargo'
'rust'
'clang'
'pkg-config'
'ffmpeg'
)
# Build from local git repo — adjust source for AUR publishing
source=()
sha256sums=()
# Set to the repo root (adjust as needed)
_repodir="${startdir}/../.."
build() {
cd "$_repodir/lightningbeam-ui"
export RUSTUP_TOOLCHAIN=stable
export CARGO_TARGET_DIR=target
cargo build --release --bin lightningbeam-editor
}
package() {
cd "$_repodir"
# Install binary
install -Dm755 lightningbeam-ui/target/release/lightningbeam-editor \
"$pkgdir/usr/bin/lightningbeam-editor"
# Desktop file
install -Dm644 lightningbeam-ui/lightningbeam-editor/assets/com.lightningbeam.editor.desktop \
"$pkgdir/usr/share/applications/com.lightningbeam.editor.desktop"
# AppStream metainfo
install -Dm644 lightningbeam-ui/lightningbeam-editor/assets/com.lightningbeam.editor.appdata.xml \
"$pkgdir/usr/share/metainfo/com.lightningbeam.editor.appdata.xml"
# Icons
install -Dm644 lightningbeam-ui/lightningbeam-editor/assets/icons/32x32.png \
"$pkgdir/usr/share/icons/hicolor/32x32/apps/lightningbeam-editor.png"
install -Dm644 lightningbeam-ui/lightningbeam-editor/assets/icons/128x128.png \
"$pkgdir/usr/share/icons/hicolor/128x128/apps/lightningbeam-editor.png"
install -Dm644 lightningbeam-ui/lightningbeam-editor/assets/icons/256x256.png \
"$pkgdir/usr/share/icons/hicolor/256x256/apps/lightningbeam-editor.png"
# Factory presets
cd src/assets/instruments
find . -type f ! -name 'README.md' | while read -r f; do
install -Dm644 "$f" "$pkgdir/usr/share/lightningbeam-editor/presets/$f"
done
}

171
packaging/container-build.sh Executable file
View File

@ -0,0 +1,171 @@
#!/bin/bash
# Build Lightningbeam packages inside a minimal container
set -e
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
IMAGE_NAME="lightningbeam-build"
# Detect container runtime
if command -v podman &>/dev/null; then
RUNTIME=podman
elif command -v docker &>/dev/null; then
RUNTIME=docker
else
echo "Error: Neither podman nor docker found"
exit 1
fi
echo "==> Using $RUNTIME"
# Build the container image (cached after first run)
echo "==> Building container image..."
$RUNTIME build -t "$IMAGE_NAME" -f "$SCRIPT_DIR/Containerfile" "$SCRIPT_DIR"
# Default: build all formats
TARGETS="${@:-deb rpm appimage}"
echo "==> Building packages: $TARGETS"
echo " (To stop: $RUNTIME kill lb-build)"
mkdir -p "$SCRIPT_DIR/output"
# Remove stale container if it exists
$RUNTIME rm -f lb-build 2>/dev/null || true
$RUNTIME run --rm --init \
--name lb-build \
-v "$REPO_ROOT:/build/lightningbeam:ro" \
-v "$SCRIPT_DIR/output:/output" \
-v lb-cargo-registry:/root/.cargo/registry \
-v lb-cargo-git:/root/.cargo/git \
-v lb-target:/build/src/lightningbeam-ui/target \
-v lb-egui-fork:/build/egui-fork \
"$IMAGE_NAME" \
bash -c "
set -e
# Clone egui fork if not already present
if [ ! -d /build/egui-fork/crates ]; then
echo '==> Cloning egui fork...'
rm -rf /build/egui-fork/*
git clone --depth 1 -b ibus-wayland-fix https://git.skyler.io/skyler/egui.git /tmp/egui-clone
mv /tmp/egui-clone/* /tmp/egui-clone/.* /build/egui-fork/ 2>/dev/null || true
rm -rf /tmp/egui-clone
fi
# Sync source (fast — skips target/ and .git/)
echo '==> Syncing source...'
mkdir -p /build/src
rsync -a --delete \
--exclude='/target' \
--exclude='/lightningbeam-ui/target' \
--exclude='/.git' \
/build/lightningbeam/ /build/src/
cd /build/src/lightningbeam-ui
# Build FFmpeg from source and link statically (no .so bundling needed)
sed -i 's/ffmpeg-next = { version = \"8.0\", features = \[\"static\"\] }/ffmpeg-next = { version = \"8.0\", features = [\"build\", \"static\"] }/' lightningbeam-editor/Cargo.toml
export FFMPEG_STATIC=1
# Stage factory presets for packaging
echo '==> Staging factory presets...'
mkdir -p lightningbeam-editor/assets/presets
cp -r ../src/assets/instruments/* lightningbeam-editor/assets/presets/
# Remove empty category dirs and README
find lightningbeam-editor/assets/presets -maxdepth 1 -type d -empty -delete
rm -f lightningbeam-editor/assets/presets/README.md
# Add preset entries to cargo-generate-rpm config
find lightningbeam-editor/assets/presets -type f | sort | while read -r f; do
rel=\"\${f#lightningbeam-editor/}\"
dest=\"/usr/share/lightningbeam-editor/presets/\${f#lightningbeam-editor/assets/presets/}\"
printf '\\n[[package.metadata.generate-rpm.assets]]\\nsource = \"%s\"\\ndest = \"%s\"\\nmode = \"644\"\\n' \"\$rel\" \"\$dest\" >> lightningbeam-editor/Cargo.toml
done
# Build release binary
echo '==> Building release binary...'
cargo build --release --bin lightningbeam-editor
for target in $TARGETS; do
case \"\$target\" in
deb)
echo '==> Building .deb package...'
cargo deb -p lightningbeam-editor --no-build --no-strip
# Add factory presets to .deb (cargo-deb doesn't handle recursive dirs well)
DEB=\$(ls target/debian/*.deb | head -1)
WORK=\$(mktemp -d)
dpkg-deb -R \"\$DEB\" \"\$WORK\"
mkdir -p \"\$WORK/usr/share/lightningbeam-editor/presets\"
cp -r lightningbeam-editor/assets/presets/* \"\$WORK/usr/share/lightningbeam-editor/presets/\"
dpkg-deb -b \"\$WORK\" \"\$DEB\"
rm -rf \"\$WORK\"
cp target/debian/*.deb /output/
echo ' .deb done'
;;
rpm)
echo '==> Building .rpm package...'
cargo generate-rpm -p lightningbeam-editor
cp target/generate-rpm/*.rpm /output/
echo ' .rpm done'
;;
appimage)
echo '==> Building AppImage...'
APPDIR=/tmp/AppDir
ASSETS=lightningbeam-editor/assets
rm -rf \"\$APPDIR\"
mkdir -p \"\$APPDIR/usr/bin\"
mkdir -p \"\$APPDIR/usr/share/applications\"
mkdir -p \"\$APPDIR/usr/share/metainfo\"
mkdir -p \"\$APPDIR/usr/share/icons/hicolor/32x32/apps\"
mkdir -p \"\$APPDIR/usr/share/icons/hicolor/128x128/apps\"
mkdir -p \"\$APPDIR/usr/share/icons/hicolor/256x256/apps\"
cp target/release/lightningbeam-editor \"\$APPDIR/usr/bin/\"
# Factory presets (next to binary for AppImage detection)
mkdir -p \"\$APPDIR/usr/bin/presets\"
cp -r lightningbeam-editor/assets/presets/* \"\$APPDIR/usr/bin/presets/\"
cp \"\$ASSETS/com.lightningbeam.editor.desktop\" \"\$APPDIR/usr/share/applications/\"
cp \"\$ASSETS/com.lightningbeam.editor.appdata.xml\" \"\$APPDIR/usr/share/metainfo/\"
cp \"\$ASSETS/icons/32x32.png\" \"\$APPDIR/usr/share/icons/hicolor/32x32/apps/lightningbeam-editor.png\"
cp \"\$ASSETS/icons/128x128.png\" \"\$APPDIR/usr/share/icons/hicolor/128x128/apps/lightningbeam-editor.png\"
cp \"\$ASSETS/icons/256x256.png\" \"\$APPDIR/usr/share/icons/hicolor/256x256/apps/lightningbeam-editor.png\"
ln -sf usr/share/icons/hicolor/256x256/apps/lightningbeam-editor.png \"\$APPDIR/lightningbeam-editor.png\"
ln -sf usr/share/applications/com.lightningbeam.editor.desktop \"\$APPDIR/lightningbeam-editor.desktop\"
cat > \"\$APPDIR/AppRun\" << 'APPRUN'
#!/bin/bash
SELF=\$(readlink -f \"\$0\")
HERE=\${SELF%/*}
export XDG_DATA_DIRS=\"\${HERE}/usr/share:\${XDG_DATA_DIRS:-/usr/local/share:/usr/share}\"
exec \"\${HERE}/usr/bin/lightningbeam-editor\" \"\$@\"
APPRUN
chmod +x \"\$APPDIR/AppRun\"
# Build squashfs from AppDir
rm -f /tmp/appimage.squashfs
mksquashfs \"\$APPDIR\" /tmp/appimage.squashfs \
-root-owned -noappend -no-exports -no-xattrs \
-comp gzip -b 131072
# Verify squashfs is valid
unsquashfs -s /tmp/appimage.squashfs
# Concatenate runtime + squashfs = AppImage
cat /opt/appimage-runtime /tmp/appimage.squashfs \
> /output/Lightningbeam_Editor-x86_64.AppImage
chmod +x /output/Lightningbeam_Editor-x86_64.AppImage
rm -f /tmp/appimage.squashfs
echo ' AppImage done'
;;
esac
done
echo '==> All done!'
ls -lh /output/
"