From 8a6216bccb392ee9e9d625bc23a7eaf541506c81 Mon Sep 17 00:00:00 2001 From: Aleksandr Bogomiakov Date: Wed, 21 Oct 2026 17:05:25 +0100 Subject: [PATCH] Expose tray runtime libraries in the Nix development shell The development shell inherited build dependencies but Cargo-built tray binaries lack the installed package's wrapper. AppIndicator was present in the store yet its dlopen lookup failed because the runtime library path was missing. The same problem affected dynamically loaded graphics libraries. Expose the package's existing trayRuntimeLibs through passthru and reuse that list in mkShell packages and its LD_LIBRARY_PATH hook. Include the existing NixOS OpenGL driver path and preserve any caller-supplied library paths. The development shell and installed tray now share one dependency list. Document direct execution of Cargo-built tray binaries inside nix develop. No agent, protocol, package version or system configuration changes. Validation on Linux: - Reproduced the missing AppIndicator dlopen failure before the change. - Loaded libayatana-appindicator3.so.1, libxkbcommon-x11.so.0, libEGL.so.1, libGL.so.1 and libwayland-client.so.0 inside the updated shell. - Verified AppIndicator still loads with an inherited LD_LIBRARY_PATH and that the existing value is preserved. The first probe used an older host Python with an incompatible glibc; probes using Python from the pinned nixpkgs input passed. - Evaluated the x86_64-linux CLI package and shared runtime dependency list, and the aarch64-linux development shell; no aarch64 execution claimed. - nixfmt --check flake.nix nix/package.nix - cargo fmt --all -- --check - cargo clippy --locked --workspace --all-targets -- -D warnings - cargo test --locked --workspace --all-targets: 566 passed, 3 ignored Cargo checks ran through nix develop, with TSUNAGI_CONTROL_SOCKET unset for Clippy and tests. Existing agent and tray processes were not restarted. --- README.md | 5 +++++ flake.nix | 30 +++++++++++++++++++++--------- nix/package.nix | 9 ++++++++- 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 6ad0336..37ee180 100644 --- a/README.md +++ b/README.md @@ -207,6 +207,11 @@ Just trying it: `nix run github:house-of-vanity/tsunagi#tsunagi-cli -- --help`. `packages..tsunagi` (with the tray) and `tsunagi-cli` are also exported, along with `overlays.default`. +For development from a checkout, `nix develop` also exposes the tray's native +runtime libraries, including AppIndicator and graphics/windowing libraries. +Cargo-built binaries such as `target/debug/tsunagi-tray` can run directly inside +this shell, without installing the packaged wrapper. + ## Build from source Rust 1.91 or newer. diff --git a/flake.nix b/flake.nix index ac4a232..4906d4f 100644 --- a/flake.nix +++ b/flake.nix @@ -26,14 +26,26 @@ nixosModules.default = import ./nix/module.nix self; - devShells = forAllSystems (pkgs: { - default = pkgs.mkShell { - inputsFrom = [ self.packages.${pkgs.stdenv.hostPlatform.system}.tsunagi ]; - packages = [ - pkgs.rustfmt - pkgs.clippy - ]; - }; - }); + devShells = forAllSystems ( + pkgs: + let + trayPackage = self.packages.${pkgs.stdenv.hostPlatform.system}.tsunagi; + in + { + default = pkgs.mkShell { + inputsFrom = [ trayPackage ]; + packages = [ + pkgs.rustfmt + pkgs.clippy + ] + ++ trayPackage.trayRuntimeLibs; + # Cargo binaries have no installed wrapper. Expose runtime-loaded + # libraries here too, while preserving the caller's library path. + shellHook = '' + export LD_LIBRARY_PATH="${pkgs.lib.makeLibraryPath trayPackage.trayRuntimeLibs}:/run/opengl-driver/lib''${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" + ''; + }; + } + ); }; } diff --git a/nix/package.nix b/nix/package.nix index 7cf1e05..87553b7 100644 --- a/nix/package.nix +++ b/nix/package.nix @@ -52,7 +52,10 @@ rustPlatform.buildRustPackage { # The suite opens real sockets and interfaces; it runs in CI instead. doCheck = false; - nativeBuildInputs = [ pkg-config ] ++ lib.optionals withTray [ + nativeBuildInputs = [ + pkg-config + ] + ++ lib.optionals withTray [ copyDesktopItems wrapGAppsHook3 ]; @@ -64,6 +67,10 @@ rustPlatform.buildRustPackage { dontWrapGApps = true; + # The development shell runs unwrapped Cargo binaries and needs the same + # dynamically loaded libraries as the installed tray wrapper. + passthru = { inherit trayRuntimeLibs; }; + postInstall = '' install -Dm644 dist/linux/50-tsunagi-resolved.rules \ "$out/share/doc/tsunagi/50-tsunagi-resolved.rules"