Paul Parker
Paul Parker

Reputation: 1313

How to get use `callCabal2nix` to supply package list to 'ghcWithPackages'?

I have a list of ~46 dependencies.

I produce a shell using among other things a call to:

server = pkgs.haskellPackages.callCabal2nix "server" ./server.cabal { };

within an override of pkgs.haskellPackages that goes into pkgs.myHaskellPackages.

The shell works fine. However, I have another nix for building a docker and this requires a build input that comes from:

ghc = pkgs.myHaskellPackages.ghcWithPackages (p: [ longlistofdependencies ]);

How do I specify the long list of dependencies without having to write them out manually, defeating the purpose of using callCabal2nix in the first place.

let                                                                                                                                                                                                                                           
  bootstrap = import <nixpkgs> { };                                                                                                                                                                                                           
                                                                                                                                                                                                                                              
  nixpkgs = builtins.fromJSON (builtins.readFile ./nixpkgs-unstable.json);                                                                                                                                                                    
                                                                                                                                                                                                                                              
  src = bootstrap.fetchFromGitHub {                                                                                                                                                                                                           
    owner = "NixOS";                                                                                                                                                                                                                          
    repo  = "nixpkgs";                                                                                                                                                                                                                        
    inherit (nixpkgs) rev sha256;                                                                                                                                                                                                             
  };                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                              
  config = {                                                                                                                                                                                                                                  
    allowBroken = true;                                                                                                                                                                                                                       
                                                                                                                                                                                                                                              
    packageOverrides = pkgs: rec {                                                                                                                                                                                                            
      servantSrc = pkgs.fetchFromGitHub {                                                                                                                                                                                                     
        owner = "haskell-servant";                                                                                                                                                                                                            
        repo = "servant";                                                                                                                                                                                                                     
        rev = "73c87bc2bc0685649f2337b06ab4fdc66c4ce1dd";                                                                                                                                                                                     
        sha256 = "0sw4mrncmfna30cyxrvinc1krqhfxn5dcc1ggzqfy39s0yl9q98r";                                                                                                                                                                      
        #sha256 = "0000000000000000000000000000000000000000000000000000";                                                                                                                                                                     
      } + "/servant";                                                                                                                                                                                                                         
                                                                                                                                                                                                                                              
      myHaskellPackages = pkgs.haskellPackages.override {                                                                                                                                                                                     
        overrides = haskellPackagesNew: haskellPackagesOld: rec {                                                                                                                                                                             
          server =                                                                                                                                                                                                                            
            haskellPackagesNew.callCabal2nix "server" ./server.cabal { };                                                                                                                                                                     
                                                                                                                                                                                                                                              
          servant =                                                                                                                                                                                                                           
            haskellPackagesNew.callCabal2nix "servant" servantSrc {};                                                                                                                                                                         

          # several other overridden packages                                                                                                                                                                                                                                    
        };
      };
    };
  };

  pkgs = import src { inherit config; };

  devShell = pkgs.myHaskellPackages.shellFor {
    packages = p: [
      p.server 
    ];
    buildInputs = with pkgs.haskellPackages; [
      hlint
      brittany
      haskell-language-server
    ];
  };

  # Every time a dependency changes in the cabal file, this has to be edited as well.
  ghc = pkgs.myHaskellPackages.ghcWithPackages (p: [
    p.aeson p.aeson-qq p.base p.blaze-html p.bytestring p.cache p.containers
    p.contravariant-extras p.criterion p.either p.hashable p.hasql
    p.hasql-migration p.hasql-pool p.hasql-th p.hasql-transaction p.hspec
    p.http-client p.http-conduit p.http-types p.immortal-queue p.lens p.linear
    p.monad-logger p.mtl p.pqueue p.pretty-simple p.QuickCheck p.raw-strings-qq
    p.servant-blaze p.servant-docs p.servant-server
    p.string-interpolate p.text p.text-format p.time p.tuple p.unordered-containers
    p.utf8-string p.vector p.vector-split p.wai p.wai-cors p.warp p.xlsx p.yaml
  ]);

in {
  inherit devShell;
  inherit ghc;
  inherit pkgs;
}

The ghc output is used in docker.nix as a build input:

let 
    inherit (import ./pinned-nixpkgs.nix) ghc pkgs;

    pricing-server =
        pkgs.stdenv.mkDerivation {
            name = "my-server";
            pname = "my-server";
            version = "1.1.0";
            src = ./.;

            buildPhase = ''
              ghc -O2 --make -outputdir ./tmp2 Main.hs
            '';

            installPhase = ''
              mkdir -p $out/bin
              cp Main $out/bin
              cp -r ./sql $out/bin
            '';

            buildInputs = [ ghc ];
        };
in
dockerTools.buildImage {
    # irrelevant to the question.
}

Upvotes: 3

Views: 1492

Answers (1)

Robert Hensing
Robert Hensing

Reputation: 7369

A possible solution is pkgs.myHaskellPackages.server.getBuildInputs.haskellBuildInputs, or pkgs.myHaskellPackages.server.getCabalDeps.libraryHaskellDepends.

You can explore these attributes, or any expression, with nix repl. You may have to expose some values from your let bindings though. In this case I just browsed through haskellPackages.warp in nix repl <nixpkgs>.

I also noticed you use rec in an overlay. This will work for you until it doesn't. I'd recommend to remove rec to avoid accessing attributes in a third way and use the more standard haskellPackagesNew.servant instead.

Upvotes: 3

Related Questions