Home / Input Output / haskell.nix
Jun 11, 5-6 PM (0)
Jun 11, 6-7 PM (0)
Jun 11, 7-8 PM (0)
Jun 11, 8-9 PM (0)
Jun 11, 9-10 PM (0)
Jun 11, 10-11 PM (0)
Jun 11, 11-12 AM (0)
Jun 12, 12-1 AM (1)
Jun 12, 1-2 AM (0)
Jun 12, 2-3 AM (0)
Jun 12, 3-4 AM (0)
Jun 12, 4-5 AM (0)
Jun 12, 5-6 AM (0)
Jun 12, 6-7 AM (0)
Jun 12, 7-8 AM (0)
Jun 12, 8-9 AM (0)
Jun 12, 9-10 AM (0)
Jun 12, 10-11 AM (0)
Jun 12, 11-12 PM (0)
Jun 12, 12-1 PM (0)
Jun 12, 1-2 PM (0)
Jun 12, 2-3 PM (0)
Jun 12, 3-4 PM (1)
Jun 12, 4-5 PM (0)
Jun 12, 5-6 PM (0)
Jun 12, 6-7 PM (0)
Jun 12, 7-8 PM (0)
Jun 12, 8-9 PM (0)
Jun 12, 9-10 PM (0)
Jun 12, 10-11 PM (0)
Jun 12, 11-12 AM (0)
Jun 13, 12-1 AM (1)
Jun 13, 1-2 AM (0)
Jun 13, 2-3 AM (0)
Jun 13, 3-4 AM (0)
Jun 13, 4-5 AM (0)
Jun 13, 5-6 AM (0)
Jun 13, 6-7 AM (0)
Jun 13, 7-8 AM (0)
Jun 13, 8-9 AM (0)
Jun 13, 9-10 AM (0)
Jun 13, 10-11 AM (0)
Jun 13, 11-12 PM (0)
Jun 13, 12-1 PM (0)
Jun 13, 1-2 PM (0)
Jun 13, 2-3 PM (0)
Jun 13, 3-4 PM (0)
Jun 13, 4-5 PM (0)
Jun 13, 5-6 PM (0)
Jun 13, 6-7 PM (0)
Jun 13, 7-8 PM (0)
Jun 13, 8-9 PM (0)
Jun 13, 9-10 PM (0)
Jun 13, 10-11 PM (0)
Jun 13, 11-12 AM (0)
Jun 14, 12-1 AM (1)
Jun 14, 1-2 AM (0)
Jun 14, 2-3 AM (0)
Jun 14, 3-4 AM (0)
Jun 14, 4-5 AM (0)
Jun 14, 5-6 AM (0)
Jun 14, 6-7 AM (0)
Jun 14, 7-8 AM (0)
Jun 14, 8-9 AM (0)
Jun 14, 9-10 AM (0)
Jun 14, 10-11 AM (0)
Jun 14, 11-12 PM (0)
Jun 14, 12-1 PM (0)
Jun 14, 1-2 PM (0)
Jun 14, 2-3 PM (0)
Jun 14, 3-4 PM (0)
Jun 14, 4-5 PM (0)
Jun 14, 5-6 PM (0)
Jun 14, 6-7 PM (0)
Jun 14, 7-8 PM (0)
Jun 14, 8-9 PM (0)
Jun 14, 9-10 PM (0)
Jun 14, 10-11 PM (0)
Jun 14, 11-12 AM (0)
Jun 15, 12-1 AM (1)
Jun 15, 1-2 AM (1)
Jun 15, 2-3 AM (0)
Jun 15, 3-4 AM (0)
Jun 15, 4-5 AM (0)
Jun 15, 5-6 AM (0)
Jun 15, 6-7 AM (0)
Jun 15, 7-8 AM (0)
Jun 15, 8-9 AM (0)
Jun 15, 9-10 AM (0)
Jun 15, 10-11 AM (0)
Jun 15, 11-12 PM (0)
Jun 15, 12-1 PM (0)
Jun 15, 1-2 PM (0)
Jun 15, 2-3 PM (0)
Jun 15, 3-4 PM (0)
Jun 15, 4-5 PM (0)
Jun 15, 5-6 PM (0)
Jun 15, 6-7 PM (0)
Jun 15, 7-8 PM (0)
Jun 15, 8-9 PM (0)
Jun 15, 9-10 PM (0)
Jun 15, 10-11 PM (0)
Jun 15, 11-12 AM (0)
Jun 16, 12-1 AM (0)
Jun 16, 1-2 AM (0)
Jun 16, 2-3 AM (0)
Jun 16, 3-4 AM (0)
Jun 16, 4-5 AM (3)
Jun 16, 5-6 AM (0)
Jun 16, 6-7 AM (0)
Jun 16, 7-8 AM (0)
Jun 16, 8-9 AM (0)
Jun 16, 9-10 AM (1)
Jun 16, 10-11 AM (0)
Jun 16, 11-12 PM (0)
Jun 16, 12-1 PM (0)
Jun 16, 1-2 PM (0)
Jun 16, 2-3 PM (0)
Jun 16, 3-4 PM (0)
Jun 16, 4-5 PM (0)
Jun 16, 5-6 PM (0)
Jun 16, 6-7 PM (0)
Jun 16, 7-8 PM (0)
Jun 16, 8-9 PM (0)
Jun 16, 9-10 PM (0)
Jun 16, 10-11 PM (0)
Jun 16, 11-12 AM (0)
Jun 17, 12-1 AM (1)
Jun 17, 1-2 AM (1)
Jun 17, 2-3 AM (0)
Jun 17, 3-4 AM (0)
Jun 17, 4-5 AM (0)
Jun 17, 5-6 AM (0)
Jun 17, 6-7 AM (0)
Jun 17, 7-8 AM (2)
Jun 17, 8-9 AM (0)
Jun 17, 9-10 AM (0)
Jun 17, 10-11 AM (1)
Jun 17, 11-12 PM (0)
Jun 17, 12-1 PM (0)
Jun 17, 1-2 PM (0)
Jun 17, 2-3 PM (0)
Jun 17, 3-4 PM (0)
Jun 17, 4-5 PM (0)
Jun 17, 5-6 PM (0)
Jun 17, 6-7 PM (0)
Jun 17, 7-8 PM (0)
Jun 17, 8-9 PM (0)
Jun 17, 9-10 PM (0)
Jun 17, 10-11 PM (0)
Jun 17, 11-12 AM (0)
Jun 18, 12-1 AM (1)
Jun 18, 1-2 AM (0)
Jun 18, 2-3 AM (0)
Jun 18, 3-4 AM (0)
Jun 18, 4-5 AM (0)
Jun 18, 5-6 AM (1)
Jun 18, 6-7 AM (0)
Jun 18, 7-8 AM (0)
Jun 18, 8-9 AM (0)
Jun 18, 9-10 AM (0)
Jun 18, 10-11 AM (1)
Jun 18, 11-12 PM (0)
Jun 18, 12-1 PM (0)
Jun 18, 1-2 PM (0)
Jun 18, 2-3 PM (0)
Jun 18, 3-4 PM (0)
Jun 18, 4-5 PM (0)
Jun 18, 5-6 PM (0)
18 commits this week Jun 11, 2026 - Jun 18, 2026
builder: harden darwin-codesign-flush per review
Address review feedback on the signingUtils flush patch:

- Drop `|| true` on the flush so a flush failure aborts the build rather
  than being silently swallowed (signing an unflushed binary risks the very
  invalid signature this works around).
- Assert the sed injection actually took effect (grep -qF) so the build fails
  loudly if upstream sign() drifts, instead of silently reintroducing the bug.

Also move the explanatory comments out of the installPhase shell string so
they are nix comments rather than baked into the generated script.
builder: fix intermittent invalid code signatures on aarch64-darwin
On aarch64-darwin, executables built by haskell.nix could ship an invalid
ad-hoc code signature, causing macOS to kill them at startup with SIGKILL
("Code Signature Invalid" / "Invalid Page") before any code runs. It is
intermittent: the same derivation builds a valid binary on one run and an
invalid one on the next, so it slips through CI and lands in the binary cache
(see haskell.nix#2018).

Root cause is a write->sign page-cache coherence race, not an ld64 or sigtool
bug. ld64 ad-hoc signs the executable during linking; for large Mach-Os the
bytes hashed for the signature can differ from what is finally on disk, so the
kernel rejects the signature at load time. The same applies to any signer run
inside the build. macOS `sync` is asynchronous and does not settle it; a real
flush to stable storage (F_FULLFSYNC) does.

Fix: add autoSignDarwinBinariesHook to the component and v2 cabal-slice
builders, with signingUtils patched so sign() F_FULLFSYNCs (+ F_NOCACHE drops
the stale mapping) the binary before reading it for signing. It then hashes
exactly the bytes that land on disk, producing a signature the kernel accepts.

The concrete buildPackages.darwin derivations are overridden directly rather
than via an overlay: `darwin` is a spliced package set, so overlay `//`
additions do not survive splicing, and overrideScope rebuilds far too much.

Verified on cardano-ledger's cardano-ledger-shelley:test:tests (a ~170 MB
binary that reproduced reliably): 6/6 invalid before, 6/6 valid after via the
v1 component builder, and 4/4 valid via the v2 cabal-slice builder
(builderVersion = 2, full 556-derivation tree). Confirmed the hook re-signs
and the binary runs in both.
Fixes for reinstallable lib:ghc build-tools, freetype pkg-config version, and wasm test filesystem access (#2522)
* useLocalGhcLib: expose genprimopcode/deriveConstants for reinstallable lib:ghc

When `build-tool-depends` is on, lib:ghc names `genprimopcode` and
`deriveConstants` as exe build-tools.  These live in the GHC source tree, not
on hackage, so cabal could only find them by chance on PATH.  Expose them
(alongside the `compiler/` subdir) as reinstallable source-repository-packages
from the GHC source, wired through inputMap, so cabal satisfies the goals
normally.

This removes the need for the `packages.ghc...build-tools = mkForce [alex
happy]` override, so drop it from configuration-nix.nix.

* cabal-pkg-config: report freetype's pkg-config (libtool) version

FreeType's freetype2.pc advertises a libtool/ABI version (e.g. 26.2.20) that
is deliberately decoupled from the release .version (e.g. 2.13.3), per
freetype's docs/VERSIONS.TXT.  `pkg-config --modversion freetype2` returns the
libtool number, so plan-to-nix must report the same value; otherwise the v2
slice's UnitId (which folds the resolved freetype2 version into
pkgHashPkgConfigDeps) forks, taking every transitive consumer
(gi-freetype2 -> gi-harfbuzz -> gi-pango -> gi-gdk3 -> gi-gtk3 -> ...) with it.

Add a `passthru.pc-version` table (the known release->libtool rows from
VERSIONS.TXT), falling back to .version with a warning for unknown releases.
This does not alter freetype's derivation, so it neither rebuilds nor forces a
build of freetype during planning.

* wasm: give test runner filesystem access; skip subprocess check on wasm

The wasm testWrapper ran `wasmtime <test>` with no `--dir`, so WASI granted the
module zero filesystem access and any test reading its data-files
(getDataFileName, under <pkg>-data/share/...) or a source-relative file failed
with a misleading "does not exist".  Preopen `/nix/store` and `.` so those
reads work.

The check-datadir test also exercises a build-tool-depends exe via readProcess,
which WASI cannot do (no process spawning -> "unsupported operation").  Guard
that check to non-wasm targets; the datadir and source-relative-file checks
still run under wasm.

* wasm: fix zlib cross-compilation

zlib doesn't cross-compile cleanly to wasm:

  * gzguts.h only `#include <errno.h>` when NO_STRERROR is unset, but
    gzread.c / gzwrite.c use errno / EAGAIN / EWOULDBLOCK unconditionally.
    zlib's configure probes strerror by compiling *and running* a test, which
    can't run when cross-compiling to wasm, so it defines NO_STRERROR (even
    though wasi-libc has strerror) and the gz* sources fail to compile with
    "use of undeclared identifier 'errno'".  Always include errno.h.

  * zlib sets NIX_LDFLAGS = "--undefined-version" whenever the linker is lld
    (to counter lld 16+'s --no-undefined-version default for its shared-lib
    version script).  wasm-ld is lld-based but rejects that flag, and we build
    static anyway, so drop it.

* wasm: disable check-datadir v2 check (data-files unreachable under WASI)

The v2 check stages data-files as absolute /nix/store symlinks and points Cabal
at them via the <pkg>_datadir env var.  wasmtime neither forwards host env vars
to the wasm guest nor follows absolute symlinks (no CLI option for either), so
check-datadir.run-v2 cannot pass on wasm.  Gate run-v2 on a non-wasm host so
the wasi32 job isn't a permanent failure, and document why in both the test and
the wasm test wrapper.  (v1 run still runs on wasm: its data-files are real
files in a -data output.)

* check-datadir: disable on Windows and Android

The test runs the built test binary, which spawns a build-tool-depends exe
(readProcess) and reads its data-files / a source-relative file.  That can't be
reproduced when the binary runs under an emulator: Windows (wine) and Android
can't reliably spawn the build-tool.  Disable the whole test there
(meta.disabled), alongside the existing wasm run-v2 skip.

* pkgconf-pc-version: don't force a freetype cross build on wasm/musl/android

Adding a pc-version to freetype (overlays/cabal-pkg-config.nix) pulled freetype
into this test's scope on every target, but its build stack (zlib / libpng /
brotli / …) doesn't cross-compile to wasm, musl or android, so the test started
failing there.  freetype's .pc Version: is platform-independent, so gate it like
systemd — verify it on glibc / darwin / windows and drop it (leaving the test
disabled via the existing checks==[] guard) on the others.
pkgconf-pc-version: don't force a freetype cross build on wasm/musl/android
Adding a pc-version to freetype (overlays/cabal-pkg-config.nix) pulled freetype
into this test's scope on every target, but its build stack (zlib / libpng /
brotli / …) doesn't cross-compile to wasm, musl or android, so the test started
failing there.  freetype's .pc Version: is platform-independent, so gate it like
systemd — verify it on glibc / darwin / windows and drop it (leaving the test
disabled via the existing checks==[] guard) on the others.
check-datadir: disable on Windows and Android
The test runs the built test binary, which spawns a build-tool-depends exe
(readProcess) and reads its data-files / a source-relative file.  That can't be
reproduced when the binary runs under an emulator: Windows (wine) and Android
can't reliably spawn the build-tool.  Disable the whole test there
(meta.disabled), alongside the existing wasm run-v2 skip.
wasm: disable check-datadir v2 check (data-files unreachable under WASI)
The v2 check stages data-files as absolute /nix/store symlinks and points Cabal
at them via the <pkg>_datadir env var.  wasmtime neither forwards host env vars
to the wasm guest nor follows absolute symlinks (no CLI option for either), so
check-datadir.run-v2 cannot pass on wasm.  Gate run-v2 on a non-wasm host so
the wasi32 job isn't a permanent failure, and document why in both the test and
the wasm test wrapper.  (v1 run still runs on wasm: its data-files are real
files in a -data output.)
wasm: fix zlib cross-compilation
zlib doesn't cross-compile cleanly to wasm:

  * gzguts.h only `#include <errno.h>` when NO_STRERROR is unset, but
    gzread.c / gzwrite.c use errno / EAGAIN / EWOULDBLOCK unconditionally.
    zlib's configure probes strerror by compiling *and running* a test, which
    can't run when cross-compiling to wasm, so it defines NO_STRERROR (even
    though wasi-libc has strerror) and the gz* sources fail to compile with
    "use of undeclared identifier 'errno'".  Always include errno.h.

  * zlib sets NIX_LDFLAGS = "--undefined-version" whenever the linker is lld
    (to counter lld 16+'s --no-undefined-version default for its shared-lib
    version script).  wasm-ld is lld-based but rejects that flag, and we build
    static anyway, so drop it.
wasm: give test runner filesystem access; skip subprocess check on wasm
The wasm testWrapper ran `wasmtime <test>` with no `--dir`, so WASI granted the
module zero filesystem access and any test reading its data-files
(getDataFileName, under <pkg>-data/share/...) or a source-relative file failed
with a misleading "does not exist".  Preopen `/nix/store` and `.` so those
reads work.

The check-datadir test also exercises a build-tool-depends exe via readProcess,
which WASI cannot do (no process spawning -> "unsupported operation").  Guard
that check to non-wasm targets; the datadir and source-relative-file checks
still run under wasm.
cabal-pkg-config: report freetype's pkg-config (libtool) version
FreeType's freetype2.pc advertises a libtool/ABI version (e.g. 26.2.20) that
is deliberately decoupled from the release .version (e.g. 2.13.3), per
freetype's docs/VERSIONS.TXT.  `pkg-config --modversion freetype2` returns the
libtool number, so plan-to-nix must report the same value; otherwise the v2
slice's UnitId (which folds the resolved freetype2 version into
pkgHashPkgConfigDeps) forks, taking every transitive consumer
(gi-freetype2 -> gi-harfbuzz -> gi-pango -> gi-gdk3 -> gi-gtk3 -> ...) with it.

Add a `passthru.pc-version` table (the known release->libtool rows from
VERSIONS.TXT), falling back to .version with a warning for unknown releases.
This does not alter freetype's derivation, so it neither rebuilds nor forces a
build of freetype during planning.
useLocalGhcLib: expose genprimopcode/deriveConstants for reinstallable lib:ghc
When `build-tool-depends` is on, lib:ghc names `genprimopcode` and
`deriveConstants` as exe build-tools.  These live in the GHC source tree, not
on hackage, so cabal could only find them by chance on PATH.  Expose them
(alongside the `compiler/` subdir) as reinstallable source-repository-packages
from the GHC source, wired through inputMap, so cabal satisfies the goals
normally.

This removes the need for the `packages.ghc...build-tools = mkForce [alex
happy]` override, so drop it from configuration-nix.nix.
v2 check: reproduce the cabal v2-test environment for test checks
builderVersion = 2 runs a test's installed binary directly (not via
`cabal v2-test`) in an empty dir with only runtime libs on PATH, so tests
that rely on the environment cabal normally provides failed.  Bring the v2
`check` (lib/check.nix) in line with v1 / cabal v2-test:

- Set each installed package's `<pkg>_datadir` (the env var Cabal's
  `Paths_<pkg>` consults) to the `share` dir the slice stages under
  `$out/store/ghc-*/<unit>/share`, so `getDataFileName` finds `data-files`
  (the compiled-in datadir is an ephemeral build-time cabal dir).

- Put the component's `build-tool-depends` (`executableToolDepends`,
  including same-package exes a test spawns) on PATH, so e.g. a test that
  spawns its package's exe no longer fails with `spawnProcess: ... does not
  exist`.

- Run the test from a writable copy of the package source subdir
  (`passthru.srcSubDirPath`), so tests reading source-relative files
  (golden files / fixtures) find them — mirroring v1's unpack + cd.

All three happen before `preCheck` so a project's own `preCheck` can still
override them.  Exes are unaffected (they install to the store with a
correct, persistent datadir).

Adds the `check-datadir` test: a library package shipping a data-file, a
source-relative file, and a build-tool exe, with a test-suite that reads /
spawns all three — run under both builderVersion 1 and 2.
ghc: keep -std=... out of the settings "C compiler command" field
When GHC's configure is regenerated here via autoreconfHook using a host
autoconf >= 2.72, AC_PROG_CC probes for and appends the newest C standard
flag the compiler accepts (e.g. -std=gnu23 with clang 21) to $CC. GHC then
bakes $CC verbatim into the "C compiler command" / "C++ compiler command" /
"Haskell CPP command" settings fields. On aarch64-darwin with nixpkgs
nixos-26.05 (autoconf 2.73, clang 21) GHC therefore tries to exec a binary
literally named "cc -std=gnu23" and fails at configurePhase of the first
package it compiles:

  ghc-9.8.4: could not execute: /nix/store/...-clang-wrapper-21.1.8/bin/cc -std=gnu23

nixpkgs' own GHC is unaffected because it ships GHC's pre-generated configure
(no autoreconf), so the std flag never lands in the command field.

Move the std flag out of each command field into its matching flags field in
postInstall, mirroring the existing Windows dllwrap/windres settings fixup.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>