From eaa66b7dae6e7603b3ecfafb7067169e16088a1c Mon Sep 17 00:00:00 2001 From: Ciprian Ursu Date: Mon, 25 May 2026 12:17:19 +0300 Subject: [PATCH] adding arm packaging and runtime support (ubuntu 24.04) --- PKGBUILD.template | 10 ++++++---- README.md | 17 ++++++++++++---- rust/limux-ghostty-sys/build.rs | 8 +++++++- rust/limux-host-linux/src/main.rs | 23 ++++++++++++++++----- rust/limux-host-linux/src/window.rs | 10 ++++++++-- scripts/package.sh | 31 ++++++++++++++++++++++------- 6 files changed, 76 insertions(+), 23 deletions(-) diff --git a/PKGBUILD.template b/PKGBUILD.template index cff03041..eead67ac 100644 --- a/PKGBUILD.template +++ b/PKGBUILD.template @@ -3,18 +3,20 @@ pkgname=limux-bin pkgver=@@VERSION@@ pkgrel=1 pkgdesc="GPU-accelerated terminal workspace manager for Linux, powered by Ghostty's rendering engine (cmux port)" -arch=('x86_64') +arch=('x86_64' 'aarch64') url="https://github.com/am-will/limux" license=('MIT') depends=('gtk4' 'libadwaita' 'webkitgtk-6.0') provides=('limux') conflicts=('limux') options=(!debug !strip) -source=("limux-${pkgver}.tar.gz::https://github.com/am-will/limux/releases/download/v${pkgver}/limux-${pkgver}-linux-x86_64.tar.gz") -sha256sums=('@@SHA256@@') +source_x86_64=("limux-${pkgver}-linux-x86_64.tar.gz::https://github.com/am-will/limux/releases/download/v${pkgver}/limux-${pkgver}-linux-x86_64.tar.gz") +source_aarch64=("limux-${pkgver}-linux-aarch64.tar.gz::https://github.com/am-will/limux/releases/download/v${pkgver}/limux-${pkgver}-linux-aarch64.tar.gz") +sha256sums_x86_64=('@@SHA256_X86_64@@') +sha256sums_aarch64=('@@SHA256_AARCH64@@') package() { - cd "limux-${pkgver}-linux-x86_64" + cd "limux-${pkgver}-linux-${CARCH}" install -Dm755 limux "${pkgdir}/usr/bin/limux" install -Dm755 libexec/limux/limux-host "${pkgdir}/usr/libexec/limux/limux-host" diff --git a/README.md b/README.md index 11660afb..09e1c7f6 100644 --- a/README.md +++ b/README.md @@ -23,13 +23,17 @@ Download the latest release from [GitHub Releases](https://github.com/am-will/li **Debian/Ubuntu (.deb)** — recommended: ```bash -sudo dpkg -i ./limux_0.1.19_amd64.deb +sudo dpkg -i ./limux_0.1.19_amd64.deb # Intel/AMD +sudo dpkg -i ./limux_0.1.19_arm64.deb # Ubuntu ARM64/aarch64 ``` **AppImage** — portable across Ubuntu 24.04-era desktops and newer, no install needed: ```bash chmod +x Limux-0.1.19-x86_64.AppImage ./Limux-0.1.19-x86_64.AppImage + +chmod +x Limux-0.1.19-aarch64.AppImage # Ubuntu ARM64/aarch64 +./Limux-0.1.19-aarch64.AppImage ``` Release AppImages are built and checked on the Ubuntu 24.04 `GLIBC_2.39` @@ -39,8 +43,9 @@ build with matching system packages instead. **Tarball** — manual install: ```bash -tar xzf limux-*-linux-x86_64.tar.gz -cd limux-*-linux-x86_64 +tar xzf limux-*-linux-x86_64.tar.gz # Intel/AMD +tar xzf limux-*-linux-aarch64.tar.gz # Ubuntu ARM64/aarch64 +cd limux-*-linux-* sudo ./install.sh ``` @@ -91,6 +96,10 @@ cargo build --release LD_LIBRARY_PATH=../ghostty/zig-out/lib:$LD_LIBRARY_PATH ./target/release/limux ``` +Ubuntu ARM64/aarch64 uses the same source build steps and system packages. +Release packaging maps `aarch64`/`arm64` hosts to `limux_*_arm64.deb`, +`limux-*-linux-aarch64.tar.gz`, and `Limux-*-aarch64.AppImage`. + ### Package a release tarball ```bash @@ -98,7 +107,7 @@ LD_LIBRARY_PATH=../ghostty/zig-out/lib:$LD_LIBRARY_PATH ./target/release/limux ``` This builds the binary, bundles `libghostty.so`, icons, and an install script into a tarball. -`package.sh` also rebuilds `libghostty.so` with `ReleaseFast` and `-Dcpu=baseline`, so Zig and the initialized Ghostty submodule must be present. +`package.sh` also rebuilds `libghostty.so` with `ReleaseFast` and `-Dcpu=baseline`, so Zig and the initialized Ghostty submodule must be present. Run it on the target architecture, or set `LIMUX_ARCH=x86_64`/`LIMUX_ARCH=aarch64` only when your build toolchain is already targeting that architecture. ## Development diff --git a/rust/limux-ghostty-sys/build.rs b/rust/limux-ghostty-sys/build.rs index 0ff2a58f..cc19d67e 100644 --- a/rust/limux-ghostty-sys/build.rs +++ b/rust/limux-ghostty-sys/build.rs @@ -14,14 +14,20 @@ fn main() { println!("cargo:rustc-link-lib=dylib=epoxy"); // Compile glad (GL loader) which libghostty depends on but doesn't - // include when built as a shared library. + // include when built as a shared library. Force the archive in because + // libghostty is linked after Rust rlibs and otherwise these objects may be + // skipped before libghostty's undefined gladLoader* symbols are seen. let glad_src = ghostty_root.join("vendor/glad/src/gl.c"); let glad_include = ghostty_root.join("vendor/glad/include"); if glad_src.exists() { cc::Build::new() + .cargo_metadata(false) .file(&glad_src) .include(&glad_include) .compile("glad"); + let out_dir = PathBuf::from(std::env::var_os("OUT_DIR").expect("OUT_DIR is set by Cargo")); + println!("cargo:rustc-link-search=native={}", out_dir.display()); + println!("cargo:rustc-link-lib=static:+whole-archive=glad"); } // Re-run if libghostty changes diff --git a/rust/limux-host-linux/src/main.rs b/rust/limux-host-linux/src/main.rs index 5440df6b..d1983a61 100644 --- a/rust/limux-host-linux/src/main.rs +++ b/rust/limux-host-linux/src/main.rs @@ -127,6 +127,23 @@ fn sanitize_terminal_child_env() { std::env::remove_var("NO_COLOR"); } +fn set_env_if_missing(key: &str, value: &str) { + if std::env::var_os(key).is_none() { + std::env::set_var(key, value); + } +} + +fn set_webkit_runtime_env() { + // WebKitGTK's DMABUF/GBM renderer can fail on restricted DRM devices, + // especially NVIDIA ARM desktops, leaving browser panes blank. + set_env_if_missing("WEBKIT_DISABLE_DMABUF_RENDERER", "1"); + set_env_if_missing("WEBKIT_WEBGL_DISABLE_GBM", "1"); + + // WebKitGTK's bubblewrap sandbox requires unprivileged user namespaces, + // which may not be available. Disable it to prevent crashes on launch. + set_env_if_missing("WEBKIT_DISABLE_SANDBOX_THIS_IS_DANGEROUS", "1"); +} + fn gtk_runtime_version() -> (u32, u32, u32) { unsafe { ( @@ -166,11 +183,7 @@ fn main() { set_ghostty_runtime_env(); sanitize_terminal_child_env(); - // WebKitGTK's bubblewrap sandbox requires unprivileged user namespaces, - // which may not be available. Disable it to prevent crashes on launch. - if std::env::var("WEBKIT_DISABLE_SANDBOX_THIS_IS_DANGEROUS").is_err() { - std::env::set_var("WEBKIT_DISABLE_SANDBOX_THIS_IS_DANGEROUS", "1"); - } + set_webkit_runtime_env(); // Initialize Ghostty before GTK app starts terminal::init_ghostty(); diff --git a/rust/limux-host-linux/src/window.rs b/rust/limux-host-linux/src/window.rs index d089b3b5..4bbb415f 100644 --- a/rust/limux-host-linux/src/window.rs +++ b/rust/limux-host-linux/src/window.rs @@ -1376,12 +1376,12 @@ pub fn build_window(app: &adw::Application) { &config.borrow().appearance, ); - // Register custom icons — look for icons dir relative to the executable + // Register custom icons. Installed packages provide `limux` in the hicolor + // app theme; development runs also expose source-tree PNGs under `icons/app`. let icon_theme = gtk::IconTheme::for_display(&display); let exe_dir = std::env::current_exe() .ok() .and_then(|p| p.parent().map(|d| d.to_path_buf())); - // Try several possible icon locations for path in [ exe_dir .as_ref() @@ -1391,6 +1391,10 @@ pub fn build_window(app: &adw::Application) { env!("CARGO_MANIFEST_DIR"), "/icons" ))), + Some(std::path::PathBuf::from(concat!( + env!("CARGO_MANIFEST_DIR"), + "/icons/app" + ))), ] .iter() .flatten() @@ -1399,11 +1403,13 @@ pub fn build_window(app: &adw::Application) { icon_theme.add_search_path(path); } } + gtk::Window::set_default_icon_name("limux"); let title = format!("Limux v{}", crate::VERSION); let window = adw::ApplicationWindow::builder() .application(app) .title(&title) + .icon_name("limux") .default_width(1400) .default_height(900) .build(); diff --git a/scripts/package.sh b/scripts/package.sh index 8f389908..98680408 100755 --- a/scripts/package.sh +++ b/scripts/package.sh @@ -5,11 +5,23 @@ ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)" # Read version from workspace Cargo.toml (single source of truth) VERSION="${1:-$(grep '^version' "$ROOT_DIR/Cargo.toml" | head -1 | sed 's/.*"\(.*\)"/\1/')}" -ARCH="$(uname -m)" -DEB_ARCH="amd64" -[ "$ARCH" = "aarch64" ] && DEB_ARCH="arm64" -RPM_ARCH="x86_64" -[ "$ARCH" = "aarch64" ] && RPM_ARCH="aarch64" +HOST_ARCH="${LIMUX_ARCH:-$(uname -m)}" +case "$HOST_ARCH" in + x86_64|amd64) + ARCH="x86_64" + DEB_ARCH="amd64" + RPM_ARCH="x86_64" + ;; + aarch64|arm64) + ARCH="aarch64" + DEB_ARCH="arm64" + RPM_ARCH="aarch64" + ;; + *) + echo "ERROR: unsupported architecture '${HOST_ARCH}'. Supported architectures: x86_64, aarch64." + exit 1 + ;; +esac PKG_BASE="limux-${VERSION}-linux-${ARCH}" STAGE="/tmp/limux-staging" @@ -172,6 +184,11 @@ copy_ghostty_terminfo_entries() { . "${ROOT_DIR}/scripts/appimage-webkit.sh" configure_ghostty_build_args() { + if ! command -v pkg-config >/dev/null 2>&1 || ! pkg-config --exists fontconfig; then + echo "fontconfig not available via pkg-config; building Ghostty with bundled fontconfig." + GHOSTTY_ZIG_ARGS+=(-fno-sys=fontconfig) + fi + if ! command -v pkg-config >/dev/null 2>&1 || ! pkg-config --exists gtk4-layer-shell-0; then echo "gtk4-layer-shell not available via pkg-config; building Ghostty with bundled gtk4-layer-shell." GHOSTTY_ZIG_ARGS+=(-fno-sys=gtk4-layer-shell) @@ -217,8 +234,8 @@ if [ ! -f "${ROOT_DIR}/ghostty/build.zig" ]; then fi # Always build libghostty with ReleaseFast to guarantee optimized output. -# Pinning cpu=baseline keeps the shipped library portable across x86_64 CPUs -# that do not expose the builder's ISA extensions, such as AVX-512. +# Pinning cpu=baseline keeps the shipped library portable across machines +# that do not expose the builder's architecture-specific ISA extensions. configure_ghostty_build_args echo "Building libghostty (ReleaseFast, cpu=baseline)..." (cd "${ROOT_DIR}/ghostty" && zig build -Dapp-runtime=none "${GHOSTTY_ZIG_ARGS[@]}")