Patching GHC for your project

I’m sharing here how you can apply a patch to GHC from within your project, so that next time I forget it, I can find it.

Of course you could fork nixpkgs and update patches = in the ghc derivation like this one but sometimes you want to patch only the GHC used in your project, not for all of nixpkgs (e.g. you don’t care about your patch applying to pandoc and thus rebuilding half of nixpkgs).

How to:

Use this (e.g. in your overlay or other nix configuration):

  haskellPackages = with pkgs.haskell.lib; pkgs.haskell.packages.ghc865.override (oldHaskellPackages: {

    # Override the ghc here:
    overrides = lib.composeExtensions (oldHaskellPackages.overrides or (_: _: {})) (self: super: {
      patches = (old.patches or []) ++ [
        (pkgs.fetchpatch {
          url = "https://gitlab.haskell.org/nh2/ghc/-/commit/766ae0129dadd677d5ab500c2af8d5d747761ac4.patch";
          name = "ghc-Add-RTS-disable-delayed-os-memory-return.patch";
          sha256 = "0p46g1315kgg8v4gv29cni9rm9b2nbjcpg0qaf5sr6yarwaq7k47";
        })
      ];
    });

    overrides = self: super: {
      # Haskell package overrides go in here
      cryptonite = overrideCabal super.cryptonite (old: {
        src = ...;
      });
    });
  });

The line

lib.composeExtensions (oldHaskellPackages.overrides or (_: _: {}))

is long and ugly, but it is currently the correct boilerplate way to ensure to not accidentally remove the effects of previous overlays, as is explained in https://github.com/NixOS/nixpkgs/issues/26561#issuecomment-397350884.

3 Likes

One thing that I haven’t figured out yet is how to use a patched GHC project for a single Haskell package only.

E.g. in the example above, I’m adding a flag to the RTS which needs a patched GHC only for linking the final executable (e.g. pandoc).

Is it possible to override the GHC e.g. only for that one link?

CC @peti

Hmm, I’m no longer sure this actually works correctly.

Doing nix-store -q --tree on the output, I now see that both the the original GHC and the patched GHC are added to the inputDrvs of the package:

+---/nix/store/1hndilaprvpk2x3hyiidhgvpj77nqa8b-myhaskellpackage-0.1.0.0.drv
    +---/nix/store/iszb9bc4wbl1xax6a1ppyy73aahdqi3n-stdenv-linux.drv [...]
    +---/nix/store/mnd8c37nk0q1b70wrv1i3w1sg69sw3ja-ghc-8.6.5.drv [...]
    ...
    +---/nix/store/s6k04mlqmyz5vrf91hk8bg066ndyyv7x-ghc-8.6.5.drv [...]

That also means both those GHCs are on PATH, and creates a problem for me in that in cabal inside nix-shell a different ghc is used than by nix-build. As a result, building my exe in nix-shell results in my patched GHC flag being available, and the executable built with nix-build errors with the flag being unknown.

1 Like

I’ve filed this as https://github.com/NixOS/nixpkgs/issues/101580