Chris Stryczynski
Chris Stryczynski

Reputation: 33941

How can I enable Haskell profiling when using Nix's callCabal2nix

Currenty my default.nix looks like:

{
  sources ? import ./nix/sources.nix
, compiler ? "ghc865" } :
let
  niv = import sources.nixpkgs {
    overlays = [
      (_ : _ : { niv = import sources.niv {}; })
    ] ;
    config = {};
  };
  pkgs = niv.pkgs;
  myHaskellPackages = pkgs.haskell.packages.${compiler}.override {
    overrides = self: super: {
      mkDerivation = args: super.mkDerivation (args // {
        enableLibraryProfiling = true;
      });
    };
  };
in
(myHaskellPackages.callCabal2nix "moscoviumorange" (./.) {})

I'd like to enable Haskell profiling for my application and it's dependencies. For my application I can handle this with hpack with:

executables:
  moscoviumorange-p:
    ghc-options: -main-is Main -prof -fprof-auto
    source-dirs: src
    main: Main.hs

How do I do the same for the dependent libraries?

Upvotes: 4

Views: 774

Answers (1)

Chris Stryczynski
Chris Stryczynski

Reputation: 33941

This can be doing using callCabal2nixWithOptions:

...
(myHaskellPackages.callCabal2nixWithOptions "moscoviumorange" (./.) "--enable-profiling" {})

How I figured it out:

Using the nix repl I found the path to the function via:

nix-repl> pkgs.haskell.packages.ghc865.callCabal2nix  
«lambda @ /nix/store/54fafxcq7b6ac2hvs8qzp2bgqzgpiiga-nixos-19.09.1019.c5aabb0d603/nixos/pkgs/development/haskell-modules/make-package-set.nix:213:21»

I then checkout the the nixpkgs repo (making sure it's on the same commit as the one I reference in default.nix) and navigated to that file+line, which I found:

    # Creates a Haskell package from a source package by calling cabal2nix on the source.
    callCabal2nixWithOptions = name: src: extraCabal2nixOptions: args:
      let
        filter = path: type:
                   pkgs.lib.hasSuffix "${name}.cabal" path ||
                   baseNameOf path == "package.yaml";
        expr = self.haskellSrc2nix {
          inherit name extraCabal2nixOptions;
          src = if pkgs.lib.canCleanSource src
                  then pkgs.lib.cleanSourceWith { inherit src filter; }
                else src;
        };
      in overrideCabal (callPackageKeepDeriver expr args) (orig: {
           inherit src;
         });

    callCabal2nix = name: src: args: self.callCabal2nixWithOptions name src "" args;

Further narrowing down to haskellSrc2nix:

  haskellSrc2nix = { name, src, sha256 ? null, extraCabal2nixOptions ? "" }:
    let
      sha256Arg = if sha256 == null then "--sha256=" else ''--sha256="${sha256}"'';
    in pkgs.buildPackages.stdenv.mkDerivation {
      name = "cabal2nix-${name}";
      nativeBuildInputs = [ pkgs.buildPackages.cabal2nix ];
      preferLocalBuild = true;
      allowSubstitutes = false;
      phases = ["installPhase"];
      LANG = "en_US.UTF-8";
      LOCALE_ARCHIVE = pkgs.lib.optionalString (buildPlatform.libc == "glibc") "${buildPackages.glibcLocales}/lib/locale/locale-archive";
      installPhase = ''
        export HOME="$TMP"
        mkdir -p "$out"
        cabal2nix --compiler=${self.ghc.haskellCompilerName} --system=${hostPlatform.config} ${sha256Arg} "${src}" ${extraCabal2nixOptions} > "$out/default.nix"
      '';
  };

Aha! Doing a google for cabal2nix profiling - it seems to support an option with a command line argument.

https://github.com/NixOS/cabal2nix/blob/650d5300c6bb5632bbab6fcb2d939fb476e469c5/src/Cabal2nix.hs#L92

Upvotes: 4

Related Questions