Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions PKGBUILD.template
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
17 changes: 13 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand All @@ -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
```

Expand Down Expand Up @@ -91,14 +96,18 @@ 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
./scripts/package.sh
```

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

Expand Down
8 changes: 7 additions & 1 deletion rust/limux-ghostty-sys/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
23 changes: 18 additions & 5 deletions rust/limux-host-linux/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
(
Expand Down Expand Up @@ -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();
Expand Down
10 changes: 8 additions & 2 deletions rust/limux-host-linux/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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()
Expand All @@ -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();
Expand Down
31 changes: 24 additions & 7 deletions scripts/package.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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[@]}")
Expand Down