Open Pitometsu opened 8 years ago
I'm not with familiar with nix things. Pinging @YPares.
This would have to use packages from https://raw.githubusercontent.com/NixOS/nixpkgs/master/pkgs/development/haskell-modules/hackage-packages.nix and be able to map name+version into nix names.
You can hack Stack to do this, but it's ugly, and it doesn't seem to work very well with Intero (though it seems to work fine for all things directly in Stack).
# stack.yaml
nix:
enable: true
shell-file: shell.nix
packages: []
resolver: ghc-8.0.1
packages:
- '.'
First, we tell Stack to use a ghc-xxx
resolver, because these come with no packages, and we can expect Nix to provide all the packages we need.
# default.nix
{ pkgs ? import <nixpkgs> {}
, haskellPackages ? pkgs.haskellPackages }:
let haskellOverrides = self: super:
{ # equivalent to extra-deps
# somePackage = self.callHackage "somePackage" "0.version.bump.0" {};
};
hp = haskellPackages.override { overrides = haskellOverrides; };
# cabal2nixResult should really be in nixpkgs somewhere, but I redefine it here
# Edit: For clarity, I'll explain.
# cabal2nixResult basically converts a `.cabal` file to a usable Nix expression at build time.
cabal2nixResult = src: pkgs.runCommand "cabal2nixResult" {
buildCommand = ''
cabal2nix file://"${src}" >"$out"
'';
buildInputs = [ pkgs.cabal2nix ];
# Support unicode characters in cabal files
${if !pkgs.stdenv.isDarwin then "LOCALE_ARCHIVE" else null} = "${pkgs.glibcLocales}/lib/locale/locale-archive";
${if !pkgs.stdenv.isDarwin then "LC_ALL" else null} = "en_US.UTF-8";
} "";
in hp.callPackage (cabal2nixResult ./.) {}
Here, we use Nix to build based on the .cabal
file, and setup a section for extra deps.
# shell.nix
{ pkgs ? import <nixpkgs> {}
, haskellPackages ? pkgs.haskellPackages }:
# ^ Note, we ignored the `ghc` argument stack provides
let overrideCabal = pkg: pkgs.haskell.lib.overrideCabal pkg ({ buildDepends ? [], ... }: {
buildDepends = buildDepends ++ [ pkgs.cabal-install ];
});
in (overrideCabal (import ./default.nix { inherit pkgs haskellPackages; })).env
Finally, this creates the shell that Stack needs to do its thing. Ordinarily, Stack gives shell.nix
a GHC that it's obligated to put on the path for Stack to use. But we've opted to instead use our own GHC. The GHC we use will include all the dependencies for our package. Once Stack enters the shell, it will use that GHC to compile everything.
It mostly works with Intero. For the most part, it works just fine. But it seems like there are edge cases that cause Intero to hang or fail. Template Haskell seems to be a major culprit of this. Haven't tried to track this down at all. But I think that if Stack had more official support for this goal, we might see some better behavior.
My suggestion would be to have some field under nix
in stack.yaml
that basically says "Nix is going to do all the Haskell dependencies work, so there's no need for a resolver or extra-deps or anything." Then Stack just enters the nix shell and figures out how to use the environment that Nix setup. May require a little specialized setup on the Nix side, but that would be ok.
For reference: Here's a repo where I lay out a skeleton for the above approach.
@ElvishJerricco how do you use that skeleton, do you run stack inside a nix-shell? Do you still have to set up individual .nix files for each repo?
(I'd love it if I could stack build --nix
and it would just use cachix for haskell libs instead of recompiling the entire kmettiverse, but without having to learn the dotnix language or clinix usage.)
It's a feature request.
Is it possible to use stack as a thin frontend to nix, and install even haskell dependencies from here?
It may have format like
or
Also, in this case
nix
should understandextra-dependencies
fromgit
.