build: add an incremental GUI type-check via the nix devShell
Verifying a GUI change meant `nix build .#syn-gui`, which starts from a clean sandbox every time: crane caches the ~600 dependencies, but the workspace crates rebuild from scratch in release, then a 107 MB binary is copied back from the remote builder. Fifteen minutes to learn whether a one-line change type-checks. The devShell already had the Rust toolchain but none of the GUI's native libraries — those were declared only inside the syn-gui derivation — so a plain `cargo check -p gui-app` there died on fontconfig or alsa, which is what forced the hermetic build in the first place. Factors those into a shared `guiBuildInputs` used by both syn-gui and the devShell, adds pkg-config and bindgenHook (for mupdf-sys's build.rs), and sets LD_LIBRARY_PATH so a binary built in the shell can also run — gpui dlopen()s wayland/X11/Vulkan/ALSA rather than linking them, which the packaged build handles with an rpath instead. `just check-gui-nix` then runs a normal incremental cargo check against rust/target: measured 4m30s cold, 14s warm, against ~15 minutes for the hermetic build. `build-gui-nix` stays for final verification and for producing a binary you can actually run. Worth noting the gnarly mupdf postPatch workaround in syn-gui does not apply here: it exists only because crane vendors dependencies into the read-only Nix store, and a devShell build uses the normal writable cargo registry. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014qebJeotZq6FvrDeTDBzeT
This commit is contained in:
co-authored by
Claude Opus 5
parent
2525c1a461
commit
ba8fe6d042
@@ -84,6 +84,22 @@
|
||||
];
|
||||
};
|
||||
|
||||
# Native libraries the gpui desktop app needs on top of `commonArgs`.
|
||||
# Shared with `devShells.default` so a plain `cargo check -p gui-app`
|
||||
# works there too — without these a local build dies on fontconfig or
|
||||
# alsa, which is exactly the thing that forces a full hermetic rebuild
|
||||
# just to type-check a GUI change.
|
||||
guiBuildInputs = pkgs.lib.optionals pkgs.stdenv.isLinux [
|
||||
pkgs.libX11
|
||||
pkgs.libxcursor
|
||||
pkgs.libxrandr
|
||||
pkgs.libxi
|
||||
pkgs.libGL
|
||||
pkgs.alsa-lib
|
||||
pkgs.vulkan-loader
|
||||
pkgs.libxcb
|
||||
];
|
||||
|
||||
# Build workspace deps once (shared across all binaries)
|
||||
cargoArtifacts = craneLib.buildDepsOnly commonArgs;
|
||||
|
||||
@@ -137,16 +153,7 @@
|
||||
pkgs.rustPlatform.bindgenHook
|
||||
];
|
||||
|
||||
buildInputs = commonArgs.buildInputs ++ pkgs.lib.optionals pkgs.stdenv.isLinux [
|
||||
pkgs.libX11
|
||||
pkgs.libxcursor
|
||||
pkgs.libxrandr
|
||||
pkgs.libxi
|
||||
pkgs.libGL
|
||||
pkgs.alsa-lib
|
||||
pkgs.vulkan-loader
|
||||
pkgs.libxcb
|
||||
];
|
||||
buildInputs = commonArgs.buildInputs ++ guiBuildInputs;
|
||||
|
||||
# gpui needs to find wayland/X11/Vulkan/ALSA libs at runtime
|
||||
postFixup = pkgs.lib.optionalString pkgs.stdenv.isLinux ''
|
||||
@@ -186,6 +193,19 @@
|
||||
};
|
||||
|
||||
devShells.default = pkgs.mkShell {
|
||||
# `bindgenHook` sets LIBCLANG_PATH etc. for mupdf-sys's build.rs. It
|
||||
# belongs in nativeBuildInputs so its setup hook actually runs.
|
||||
nativeBuildInputs = [
|
||||
pkgs.pkg-config
|
||||
pkgs.rustPlatform.bindgenHook
|
||||
];
|
||||
|
||||
# commonArgs.buildInputs + guiBuildInputs mirror what the `syn-gui`
|
||||
# derivation links against, so `cargo build`/`cargo check` inside this
|
||||
# shell finds the same native libraries the hermetic build does. The
|
||||
# payoff is incremental compilation: the hermetic build starts from a
|
||||
# clean sandbox every time, so type-checking a one-line GUI change
|
||||
# costs a full release rebuild of the workspace.
|
||||
buildInputs = [
|
||||
buildApkCi
|
||||
createReleaseCi
|
||||
@@ -194,7 +214,13 @@
|
||||
androidSdk
|
||||
pkgs.jdk17
|
||||
pkgs.just
|
||||
];
|
||||
] ++ commonArgs.buildInputs ++ guiBuildInputs;
|
||||
|
||||
# gpui dlopen()s wayland/X11/Vulkan/ALSA at runtime rather than
|
||||
# linking them, so a binary built in this shell needs them on the
|
||||
# library path to actually run (the packaged build patchelfs an rpath
|
||||
# in instead).
|
||||
LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath (commonArgs.buildInputs ++ guiBuildInputs);
|
||||
|
||||
ANDROID_HOME = "${androidSdk}/libexec/android-sdk";
|
||||
ANDROID_SDK_ROOT = "${androidSdk}/libexec/android-sdk";
|
||||
|
||||
@@ -199,6 +199,21 @@ build-gui-nix:
|
||||
nix build .#syn-gui --max-jobs auto --cores 0
|
||||
|
||||
|
||||
# Type-check the gpui desktop GUI inside the nix devShell.
|
||||
#
|
||||
# Prefer this over `build-gui-nix` while iterating: the hermetic build starts
|
||||
# from a clean sandbox every time, so it rebuilds the whole workspace in
|
||||
# release just to check a one-line change. This runs a normal incremental
|
||||
# `cargo check` against `rust/target`, with the same native libraries the
|
||||
# packaged build links against — seconds instead of minutes, after the first
|
||||
# run warms the cache. Use `build-gui-nix` for final verification, or when you
|
||||
# need a binary you can actually run.
|
||||
[doc: "Type-check the gpui GUI incrementally in the nix devShell"]
|
||||
[group: "build"]
|
||||
check-gui-nix *args:
|
||||
nix develop -c cargo check --manifest-path rust/gui-app/Cargo.toml {{args}}
|
||||
|
||||
|
||||
# Run all formatters
|
||||
[group: "format"]
|
||||
fmt-all: fmt-kotlin fmt-rust
|
||||
|
||||
Reference in New Issue
Block a user