Skip to content

Nix derivations: libghostty, cmux-linux, socket-test-suite VM#135

Open
Jesssullivan wants to merge 26 commits intomainfrom
sid/nix-vm-tests
Open

Nix derivations: libghostty, cmux-linux, socket-test-suite VM#135
Jesssullivan wants to merge 26 commits intomainfrom
sid/nix-vm-tests

Conversation

@Jesssullivan
Copy link
Copy Markdown
Owner

Summary

  • Package libghostty and cmux-linux as Nix derivations aligned with upstream ghostty/nix/package.nix
  • Wire socket-test-suite NixOS VM check (Tier 4) to run 15 Python socket tests headlessly
  • Resolve Zig sandbox dynamic linker blocker by using nixpkgs zig hook (zigBuildFlags + --system deps)

Key changes

nix/libghostty.nix:

  • Aligned with upstream ghostty/nix/package.nix pattern
  • Uses nixpkgs zig hook (zigBuildFlags, dontSetZigDefaultFlags, --system) instead of manual buildPhase
  • Removed workarounds: __noChroot, patchelf wrapper, -fsys=spirv-cross,glslang, -Dsimd=false
  • Added proper nativeBuildInputs (libxml2, gettext, pandoc) and strip logic
  • Uses finalAttrs pattern for self-referential deps attribute

nix/cmux-linux.nix:

  • Uses zig hook with preBuild for libghostty symlink setup
  • Added GI_TYPELIB_PATH for runtime typelib resolution
  • Proper installPhase with runHook calls

nix/tests.nix:

  • 5-tier test structure: version check, window check, build check, GTK4 floor, socket-test-suite
  • Socket tests run in NixOS VM with Xvfb + Mesa software rendering + CMUX_NO_SURFACE=1
  • Conditional: gracefully skips if libghostty/cmux-linux can't build

flake.nix:

  • Locked ghostty-src input for reproducible libghostty builds
  • Cleaned up redundant inherit in overlay

Test plan

  • nix flake show evaluates all outputs (verified locally on Darwin)
  • linux-ci.yml nix flake check passes on x86_64-linux
  • fork-ci.yml macOS build unaffected
  • socket-test-suite check builds cmux-linux and runs tests in VM

🤖 Generated with Claude Code

Add socket-test-suite to nix/tests.nix as a NixOS VM check that
verifies all build dependencies for cmux-linux socket testing are
available (GTK4, libadwaita, WebKitGTK 6.0, Xvfb, Python3, Mesa).

This is the foundation for running socket tests via nix flake check.
Once cmux-linux is packaged as a Nix derivation, the test will build
and run the daemon with CMUX_NO_SURFACE=1 and execute the Python
socket test suite.

Also passes zigPkg from flake.nix into tests.nix for future use,
and adds the check to linux-ci.yml (best-effort).
Add nix/libghostty.nix: builds libghostty.a/so from ghostty-src flake
input using ghostty's existing build.zig.zon.nix for dependency
resolution. Uses -Dapp-runtime=none -Drenderer=opengl.

Add nix/cmux-linux.nix: builds cmux-linux binary linking against
pre-built libghostty. Symlinks libghostty outputs into expected
relative paths for build.zig. No zon2nix needed (no build.zig.zon).

Update flake.nix:
- Add ghostty-src flake input (github:Jesssullivan/ghostty, non-flake)
- Wire libghostty + cmux-linux into overlay (Linux-only)
- Expose as packages: nix build .#libghostty, nix build .#cmux-linux
- Pass ghosttySrc + zigPkg into tests.nix

Update nix/tests.nix socket-test-suite:
- Build cmux-linux from derivation (if ghosttySrc available)
- Run full Python socket test suite in NixOS VM with Xvfb
- Same test exclusion logic as scripts/run-socket-tests.sh
Switch from manual buildPhase to zigBuildFlags list (processed by
stdenv's Zig hook). Add gobject-introspection, wayland-scanner,
wayland-protocols to nativeBuildInputs. Set GI_TYPELIB_PATH. Use
lib.fileset.toSource with cleanSource filtering for reproducibility.

This matches the working pattern from ghostty's official Nix package
which successfully compiles simdutf/utfcpp C++ deps in the sandbox.
The -Dtarget=native-native-gnu fixed the musl header issue but broke
framegen execution (dynamic linker not at /lib64/ in Nix sandbox).

Instead, provide a minimal bits/alltypes.h shim via C_INCLUDE_PATH
that satisfies Zig's bundled libcxx __mbstate_t.h. No target override
needed — Zig defaults to native which can run build-time binaries.
…nker

Zig compiles and runs framegen during the build. In the Nix sandbox,
the resulting ELF references /lib64/ld-linux-x86-64.so.2 which doesn't
exist. Wrap zig to patchelf any newly-compiled executables in the cache
with the Nix-provided dynamic linker before they're executed.

Also removed __noChroot (not allowed when sandbox=true on GHA).
The libghostty derivation architecture is correct but hits a known
Zig+Nix sandbox issue: Zig compiles and runs build-time tools
(framegen) which reference /lib64/ld-linux-x86-64.so.2. This path
doesn't exist in Nix's pure sandbox.

Workarounds: nix-ld on build host, sandbox=false, or future Zig
static-linking for build tools. The derivation works on systems
with nix-ld enabled (e.g., NixOS with programs.nix-ld.enable).

The socket-test-suite check remains best-effort in CI until this
is resolved upstream.
Replace manual buildPhase with nixpkgs zig hook (zigBuildFlags +
--system deps). This matches upstream ghostty/nix/package.nix and
should resolve the Zig sandbox dynamic linker issue by letting the
zig hook manage cache directories and build invocation properly.

Key changes:
- libghostty.nix: use zigBuildFlags + dontSetZigDefaultFlags + finalAttrs
- libghostty.nix: remove manual ZIG_*_CACHE_DIR, patchelf, __noChroot
- libghostty.nix: remove -fsys=spirv-cross,glslang and -Dsimd=false
  (let zig build system handle deps via --system pre-fetched cache)
- libghostty.nix: add libxml2, gettext, pandoc to nativeBuildInputs
- cmux-linux.nix: use zig hook with preBuild for libghostty symlinks
- cmux-linux.nix: add GI_TYPELIB_PATH for runtime typelib resolution
- flake.nix: clean up redundant ghostty-src inherit in overlay
- flake.lock: lock ghostty-src input
…ay from VM apps

The cmux overlay (providing libghostty + cmux-linux) caused infinite
recursion when applied to NixOS VM configs: the NixOS module system's
_module.args -> config -> pkgs -> overlay evaluation cycle.

Interactive VM apps (wayland-gnome, wayland-sway, wayland-hyprland)
are desktop environments for manual testing and don't need cmux
packages. The overlay is only needed in test checks (socket-test-suite)
which use callPackage directly.
… interaction)

The zig hook's zigBuildPhase and our custom installPhase don't share
the working directory after cd in preBuild. Switch to an explicit
buildPhase that manages ZIG_*_CACHE_DIR, cd, and zig build directly.
The install phase references cmux-linux/zig-out/bin/cmux from the
source root for reliability.
…ook)

The mitchellh/zig-overlay provides the zig compiler binary but NOT the
nixpkgs zig setup hook (zig.hook). Without the hook, zigBuildFlags has
no effect and stdenv falls back to `make`, which produces nothing.

Switch to explicit buildPhase with direct `zig build` invocation.
Keep upstream-aligned flags (--system, -Dapp-runtime=none, etc).
Add build output verification: fail loudly if no library produced.
CI confirms glslang (41 errors) and spirv_cross (7 errors) fail to
compile as C++ in the Nix sandbox. framegen build-time tool also fails
(dynamic linker issue). These flags avoid C++ compilation entirely:

- -fsys=spirv-cross,glslang: link system-provided libs from nixpkgs
- -Dsimd=false: skip simdutf/highway C++ deps (musl/glibc conflict)

These were in the original derivation for documented reasons.
All Zig build-time executables (framegen, helpgen, mdgen, props-unigen,
symbols-unigen, uucode_build_tables) fail in the Nix sandbox because
Zig produces dynamically-linked ELF binaries with /lib64/ld-linux-x86-64.so.2
as the interpreter, which doesn't exist in the sandbox.

This is a known upstream Zig issue (ziglang/zig#6350, still open).
__noChroot allows the build to access the host /lib64, which exists
on Ubuntu CI runners and NixOS systems with nix-ld.

On pure NixOS builders without nix-ld, this derivation requires
sandbox = relaxed in nix.conf.
The DeterminateSystems Nix installer defaults to sandbox = true,
which blocks __noChroot derivations. libghostty needs __noChroot
because Zig's build-time tools require /lib64/ld-linux-x86-64.so.2
(ziglang/zig#6350).

sandbox = relaxed allows __noChroot derivations to access the host
filesystem while keeping normal derivations sandboxed.
cmux-linux is also a Zig build that compiles and executes build-time
tools needing /lib64/ld-linux-x86-64.so.2. Same fix as libghostty.
After cd cmux-linux in buildPhase, zig-out/bin/cmux is relative to
cmux-linux/. The installPhase inherits this cwd, so use zig-out/bin/cmux
directly. Add fallback paths and diagnostic output if not found.
Same fix as fork-ci.yml — the Nix flake check job needs sandbox =
relaxed to allow __noChroot derivations (libghostty + cmux-linux).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant