Skip to content

Latest commit

Β 

History

History
182 lines (141 loc) Β· 7.15 KB

File metadata and controls

182 lines (141 loc) Β· 7.15 KB

Developing OpenLogi

This document covers the local development workflow for OpenLogi. For end-user build instructions, see the README.

Toolchain

  • Stable Rust (Edition 2024, MSRV 1.88)
  • macOS: Xcode 16+ with the optional Metal Toolchain component (required by GPUI's gpui_macos build script to compile shaders)
  • Linux: system libraries β€” on Debian/Ubuntu: sudo apt-get install libudev-dev gcc g++ clang libfontconfig-dev libwayland-dev libxkbcommon-x11-dev libx11-xcb-dev libssl-dev libzstd-dev pkg-config
  • create-dmg for packaging (brew install create-dmg); cargo-bundle is installed automatically by cargo run -p xtask -- macos bundle

Building from source

CLI:

git clone https://github.com/AprilNEA/OpenLogi
cd OpenLogi
cargo run -p openlogi --release -- list

Desktop app:

cargo run -p openlogi-gui --release

On macOS the desktop binary is launched from inside a throwaway target/dev/OpenLogi.app β€” a Cargo runner wired in .cargo/config.toml (scripts/cargo-run-macos.sh). This makes the dev build show the real OpenLogi name in the menu bar and the app icon in the Dock; a bare cargo run binary has no bundle, so macOS would otherwise fall back to the openlogi-gui executable name and a generic icon. The binary is hardlinked in (no copy) and the icon is generated on demand by cargo run -p xtask -- macos icns. The runner is a transparent passthrough for everything else (the CLI, tests); set OPENLOGI_DEV_BUNDLE=0 to launch the raw openlogi-gui binary instead.

To install the CLI binary on PATH:

cargo install --path .

Using devenv (macOS)

The repo's devenv.nix provisions a Nix-based dev shell with sccache, the stable Rust toolchain, and the env overrides GPUI needs. It exposes tasks that mirror CI and packaging:

devenv tasks run openlogi:gui      # run the desktop app
devenv tasks run openlogi:check    # fmt + clippy + tests (run before committing)
devenv tasks run openlogi:dmg      # build the macOS DMG
devenv tasks run openlogi:i18n-upload    # upload English source strings to Crowdin
devenv tasks run openlogi:i18n-download  # download translations and run i18n tests

The first time you cd into the repo after pulling a change to devenv.nix, reload direnv so the new env vars (DEVELOPER_DIR, SDKROOT, the PATH filter that strips Nix's xcbuild xcrun stub) take effect:

direnv reload    # or: exit your shell and `cd` back in

Without that, GPUI's gpui_macos build script can't find Apple's metal shader compiler, and link errors about missing _write / _sysconf / _waitpid symbols show up because the Nix apple-sdk-14.4 stub doesn't expose libSystem the way Apple's real linker wants.

Project layout

src/                the `openlogi` binary (workspace root package) β€” a thin wrapper over openlogi-cli
crates/
  openlogi-core/    types, config (TOML), paths, button + action catalog β€” no HID, no async
  openlogi-hidpp/   vendored HID++ protocol crate (lib name `hidpp`)
  openlogi-hid/     hidpp + async-hid: enumerate(), DPI (0x2201) and SmartShift (0x2111) writes
  openlogi-assets/  device-render registry schema + cached HTTP fetch from assets.openlogi.org
  openlogi-cli/     CLI implementation: command tree + `run()`, called by the `openlogi` binary
  openlogi-agent-core/  headless orchestration shared by agent and GUI: hook runtime, HID++ writes, IPC
  openlogi-agent/   the `openlogi-agent` binary β€” background agent owning device I/O and the hook
  openlogi-hook/    OS mouse hook: macOS CGEventTap, Linux evdev/uinput, Windows WH_MOUSE_LL
  openlogi-gui/     the `openlogi-gui` binary β€” GPUI + gpui-component

Pre-commit checklist

Before committing, the following must pass:

cargo fmt --all -- --check
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace

Equivalent to devenv tasks run openlogi:check.

Packaging the macOS DMG

cargo run -p xtask -- macos package    # β†’ target/release/OpenLogi.dmg

Environment overrides:

  • OPENLOGI_BUNDLE_ASSETS=1 β€” bundle every device render into the .app for a fully offline build (default: fetched on demand at first launch).
  • OPENLOGI_SIGN_IDENTITY=<identity> β€” codesign the .app and .dmg with the given Developer ID.
  • OPENLOGI_DMG_BACKGROUND_URL=<url> β€” override the branded DMG background TIFF URL (default: https://assets.openlogi.org/dmg/dmg-background.tiff).

The local packaging command and release workflow both use the same branded DMG layout: a 760Γ—480 background image in a 760Γ—512 Finder window, with 128px icons positioned at (212, 250) for OpenLogi.app and (548, 250) for Applications.

Packaging Linux .deb / .rpm

Requires nfpm on PATH; the package arch is derived from the host (override with PKG_ARCH):

cargo run -p xtask -- linux package    # β†’ target/release/openlogi_*.deb / .rpm

The package contents (binaries, udev rules, systemd user unit, desktop entry, icon) are declared in packaging/linux/nfpm.yaml.

Release updater publishing

Tagged releases still attach DMGs and SHA256SUMS to GitHub Releases for manual downloads and the Homebrew cask. The release workflow also publishes the same DMGs to Cloudflare R2 and writes a static updater manifest at:

${OPENLOGI_UPDATE_BASE_URL}/channels/stable/latest.json

The app embeds that manifest URL at build time via OPENLOGI_UPDATE_MANIFEST_URL, derived from OPENLOGI_UPDATE_BASE_URL in the release workflow. Release builds also embed OPENLOGI_UPDATE_MINISIGN_PUBLIC_KEY and run with Verification::Strict: an update is installed only if the manifest asset carries a minisign signature that verifies against that key, plus a matching SHA-256. A build without the key embedded (local/dev) fails closed β€” the update check errors rather than installing an unverified artifact.

Configure the R2/update settings in one 1Password item referenced by the GitHub secret OP_R2_SECRET_ITEM. The item must contain:

  • OPENLOGI_UPDATE_BASE_URL β€” public HTTPS base URL, for example https://updates.openlogi.org.
  • OPENLOGI_UPDATE_MINISIGN_PUBLIC_KEY β€” base64 minisign public key embedded in the app and used to verify updater artifacts.
  • OPENLOGI_UPDATE_MINISIGN_SECRET_KEY β€” the passwordless minisign secret key file, base64-encoded (base64 < minisign.key), used only in the release publish job to sign DMGs before latest.json is generated. It is stored base64 (not raw) so its two lines survive 1Password's paste handling; the workflow decodes it, mirroring the GitHub App key.
  • CLOUDFLARE_R2_ACCOUNT_ID β€” Cloudflare account ID used for the S3 endpoint.
  • CLOUDFLARE_R2_BUCKET β€” bucket name.
  • CLOUDFLARE_R2_ACCESS_KEY_ID β€” R2 S3 access key.
  • CLOUDFLARE_R2_SECRET_ACCESS_KEY β€” R2 S3 secret key.

The workflow uploads immutable artifacts under /releases/<tag>/ and only the channel manifest under /channels/stable/latest.json is mutable.

The manifest is generated by the workspace xtask helper:

cargo run -p xtask -- release latest-json \
  --dist dist \
  --tag v0.2.0 \
  --base-url https://updates.openlogi.org \
  --output dist/latest.json