Skip to content

Commit 7446d04

Browse files
authored
Merge pull request #47 from input-output-hk/rvl/hackage-stackage
Provide hackage and stackage from haskell.nix
2 parents 2520ce0 + 7ff3d1a commit 7446d04

29 files changed

+568
-60
lines changed

README.org

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,34 @@
1-
* haskell.nix
1+
* Alternative Haskell Infrastructure for Nixpkgs
22

3-
This repository contains the runtime system for [[https://github.com/input-output-hk/nix-tools][nix-tools]].
4-
Please see [[https://github.com/input-output-hk/nix-tools][nix-tools]] for more details.
3+
[[https://travis-ci.org/input-output-hk/haskell.nix][https://travis-ci.org/input-output-hk/haskell.nix.svg?branch=master]]
4+
5+
=haskell.nix= is an experimental new builder for Haskell packages.
6+
7+
It works by automatically translating your Cabal or Stack project and
8+
its dependencies into Nix code. Most of your dependencies are already
9+
translated, so you generally won't have too much generated code.
10+
11+
For full documentation, see https://input-output-hk.github.io/haskell.nix
12+
13+
** Quickstart
14+
15+
This will download and build =nix-tools=.
16+
17+
#+begin_src sh
18+
nix build -f https://github.com/input-output-hk/haskell.nix/archive/master.tar.gz nix-tools -o nt
19+
./nt/bin/cabal-to-nix --help
20+
#+end_src
21+
22+
** Related repos
23+
24+
The =haskell.nix= repository contains the runtime system for building
25+
Haskell packages in Nix. It depends on other repos, which are:
26+
27+
- [[https://github.com/input-output-hk/nix-tools][nix-tools]] — provides the programs for generating Nix expressions from
28+
Haskell projects.
29+
30+
- [[https://github.com/input-output-hk/hackage.nix][hackage.nix]] — the latest contents of the [[https://hackage.haskell.org/][Hackage]] databases,
31+
converted to Nix expressions.
32+
33+
- [[https://github.com/input-output-hk/stackage.nix][stackage.nix]] — all of the [[https://www.stackage.org/][Stackage]] snapshots, converted to Nix
34+
expressions.

default.nix

Lines changed: 75 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
{ pkgs ? import <nixpkgs> {}
2+
}:
3+
14
let
25
# pkg-def's may reference boot packages, but those
36
# are not guaranteed to be available on hackage, as
@@ -13,19 +16,83 @@ let
1316
then filterAttrs (k: _: !(builtins.elem k boot-pkgs)) v
1417
else v)
1518
(pkg-def hackage);
16-
in
17-
hackage: let haskell = rec {
19+
1820
# ghc hackage patches.
1921
# these are patches that turn hackage packages into the same as the ones
2022
# ghc ships with the supposedly same version. See GHC Track Issue: 16199
2123
ghcHackagePatches = import ./patches;
2224

23-
compat = import ./compat.nix;
25+
compat = import ./lib/compat.nix;
26+
27+
# Utility function for downloading a pinned git repo, that can be
28+
# overridden with NIX_PATH.
29+
fetchExternal = import ./lib/fetch-external.nix;
30+
31+
# All packages from Hackage as Nix expressions
32+
hackage = import (fetchExternal {
33+
name = "hackage-exprs-source";
34+
specJSON = ./hackage-src.json;
35+
override = "hackage";
36+
});
37+
38+
# The set of all Stackage snapshots
39+
stackage = import (fetchExternal {
40+
name = "stackage-snapshot-source";
41+
specJSON = ./stackage-src.json;
42+
override = "stackage";
43+
});
44+
45+
packages = self: ({
46+
# Utility functions for working with the component builder.
47+
haskellLib = let hl = import ./lib { inherit (pkgs) lib; haskellLib = hl; }; in hl;
2448

25-
mkPkgSet
26-
= { pkgs, pkg-def, pkg-def-overlays ? [], modules ? [] }@args:
27-
import ./package-set.nix (args // { inherit hackage; pkg-def = strip-pkg-def pkgs pkg-def; });
49+
# Create a Haskell package set based on a cabal build plan (plan-to-nix)
50+
# and Nix expressions representing cabal packages (cabal-to-nix).
51+
mkPkgSet =
52+
{ pkg-def # Base package set. Either from stackage (via stack-to-nix) or from a cabal projects plan file (via plan-to-nix)
53+
, pkg-def-overlays ? [] # Additional packages to augment the Base package set `pkg-def` with.
54+
, modules ? []
55+
}@args:
2856

29-
mkNewPkgSet = args: builtins.trace "DEPRECATED: use mkPkgSet instead of mkNewPkgSet" (mkPkgSet args);
57+
import ./package-set.nix (args // {
58+
inherit hackage pkgs;
59+
pkg-def = strip-pkg-def pkgs pkg-def;
60+
});
3061

31-
}; in haskell
62+
# Create a Haskell package set based on a Stack configuration.
63+
mkStackPkgSet =
64+
{ stack-pkgs # Path to the output of stack-to-nix
65+
, pkg-def-overlays ? []
66+
, modules ? []
67+
}@args:
68+
69+
let
70+
# The Stackage release referenced in the stack config
71+
pkg-def = stackage.${stack-pkgs.resolver};
72+
# The compiler referenced in the stack config
73+
compiler = (stack-pkgs.overlay hackage).compiler or (pkg-def hackage).compiler;
74+
in self.mkPkgSet {
75+
inherit pkg-def;
76+
pkg-def-overlays = [ stack-pkgs.overlay ] ++ pkg-def-overlays;
77+
modules = [ ghcHackagePatches.${compiler.nix-name} ] ++ modules;
78+
};
79+
80+
# Programs for generating Nix expressions from Cabal and Stack
81+
# files.
82+
nix-tools = self.callPackage ./nix-tools {
83+
inherit fetchExternal;
84+
};
85+
86+
# Snapshots of Hackage and Stackage, converted to Nix expressions,
87+
# regularly updated.
88+
inherit hackage stackage;
89+
90+
# Scripts for keeping Hackage and Stackage up to date.
91+
maintainer-scripts = {
92+
update-hackage = self.callPackage ./scripts/update-hackage.nix {};
93+
update-stackage = self.callPackage ./scripts/update-stackage.nix {};
94+
};
95+
});
96+
97+
in
98+
pkgs.lib.makeScope pkgs.newScope packages

doc/maintainer-scripts.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Updating Hackage and Stackage Nix expressions
2+
3+
The [`hackage.nix`](https://github.com/input-output-hk/hackage.nix)
4+
and [`stackage.nix`](https://github.com/input-output-hk/stackage.nix)
5+
repos and corresponding files `hackage-src.json` and
6+
`stackage-src.json` will be regularly and automatically updated using
7+
scripts in this repo.
8+
9+
To run the updater scripts manually, use:
10+
11+
nix-build -A maintainer-scripts.update-hackage -o update-hackage.sh
12+
./update-hackage.sh
13+
14+
nix-build -A maintainer-scripts.update-stackage -o update-stackage.sh
15+
./update-stackage.sh
16+
17+
The scripts will clone the repo, generate the latest data, then
18+
attempt to push back to the repo and update the source JSON file.

hackage-src.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"url": "https://github.com/input-output-hk/hackage.nix",
3+
"rev": "3180384b563ec7c7b46bca86b3ace0f32d04cde8",
4+
"date": "2019-02-05T17:32:14+08:00",
5+
"sha256": "19ndkn8pivli9plwq0wnx1cj126l89yk7jw9a0dj51ic3b2qhlb2",
6+
"fetchSubmodules": false
7+
}
File renamed without changes.

lib/fetch-external.nix

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Provides a function for fetching a GitHub repo from a JSON spec,
2+
# overridable with the given entry on the NIX_PATH.
3+
4+
let
5+
overrideWith = import ./override-with.nix;
6+
in
7+
{ name, specJSON, override }:
8+
let
9+
spec = builtins.fromJSON (builtins.readFile specJSON);
10+
in
11+
overrideWith override
12+
(builtins.fetchTarball {
13+
inherit name;
14+
url = "${spec.url}/archive/${spec.rev}.tar.gz";
15+
inherit (spec) sha256;
16+
})

lib/override-with.nix

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# overrideWith - Allow the user to override the given default path
2+
# with a NIX_PATH entry.
3+
override: default:
4+
let
5+
try = builtins.tryEval (builtins.findFile builtins.nixPath override);
6+
in if try.success then
7+
builtins.trace "using search host <${override}>" try.value
8+
else
9+
default

nix-tools/default.nix

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{ symlinkJoin, fetchExternal, mkPkgSet }:
2+
3+
let
4+
src = fetchExternal {
5+
name = "nix-tools-src";
6+
specJSON = ./nix-tools-src.json;
7+
override = "nix-tools";
8+
};
9+
10+
hsPkgs = import (src + "/pkgs.nix") { inherit mkPkgSet; };
11+
in
12+
symlinkJoin {
13+
name = "nix-tools";
14+
paths = builtins.attrValues hsPkgs.nix-tools.components.exes;
15+
}

nix-tools/nix-tools-src.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"url": "https://github.com/input-output-hk/nix-tools",
3+
"rev": "232e4fde7f942ef234b649144016d5da0f7e2745",
4+
"date": "2019-02-11T12:59:38+08:00",
5+
"sha256": "1nrm9vcq443isk09z1fmlp8zxnw9p3cx95zbda29s5mky17ky2c0",
6+
"fetchSubmodules": false
7+
}

scripts/update-external.nix

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{ stdenv, writeScript, glibc, coreutils, git, nix-tools, cabal-install, nix-prefetch-git }:
2+
3+
{ name, script }:
4+
5+
with stdenv.lib;
6+
7+
writeScript "update-${name}-nix.sh" ''
8+
#!${stdenv.shell}
9+
10+
set -euo pipefail
11+
12+
export PATH="${makeBinPath [ coreutils glibc git nix-tools cabal-install nix-prefetch-git ]}"
13+
14+
${script}
15+
16+
git add .
17+
git commit --allow-empty -m "Automatic update for $(date)"
18+
19+
rev=$(git rev-parse HEAD)
20+
21+
git push
22+
23+
cd ..
24+
25+
nix-prefetch-git https://github.com/input-output-hk/${name}.nix.git --rev "$rev" | tee ${name}-src.json
26+
''

scripts/update-hackage.nix

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{ stdenv, writeScript, coreutils, glibc, git, nix-tools, cabal-install, nix-prefetch-git }@args:
2+
3+
import ./update-external.nix args {
4+
name = "hackage";
5+
script = ''
6+
# Make sure the hackage index is recent.
7+
cabal new-update
8+
9+
# Clone or update the Hackage Nix expressions repo.
10+
if [ -d hackage.nix ]; then
11+
cd hackage.nix
12+
git pull --ff-only
13+
cd ..
14+
else
15+
git clone [email protected]:input-output-hk/hackage.nix.git
16+
fi
17+
18+
echo "Running hackage-to-nix..."
19+
20+
hackage-to-nix hackage.nix
21+
22+
cd hackage.nix
23+
'';
24+
}

scripts/update-stackage.nix

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
{ stdenv, writeScript, coreutils, glibc, git, nix-tools, cabal-install, nix-prefetch-git }@args:
2+
3+
import ./update-external.nix args {
4+
name = "stackage";
5+
script = ''
6+
# Clone or update the main Stackage Nix expressions repo.
7+
# The upstream LTS and Nightly package sets are in submodules, which
8+
# should also be updated.
9+
if [ -d stackage.nix ]; then
10+
cd stackage.nix
11+
git pull --ff-only
12+
git submodule update --init
13+
git submodule foreach git pull origin master
14+
else
15+
git clone [email protected]:input-output-hk/stackage.nix.git
16+
cd stackage.nix
17+
git submodule update --init
18+
fi
19+
20+
echo "Running lts-to-nix for all snapshots..."
21+
22+
# update them all in parallel...
23+
N=$(getconf _NPROCESSORS_ONLN)
24+
for lts in {lts-haskell,stackage-nightly}/*.yaml
25+
do
26+
lts-to-nix $lts > $(basename ''${lts%.yaml}.nix) &
27+
while [[ $(jobs -r -p | wc -l) -gt $N ]]; do
28+
# can't use `wait -n` on older bash versions.
29+
# e.g. what ships with macOS High Sierra
30+
sleep 1;
31+
done
32+
done
33+
wait
34+
35+
# update nightlies
36+
echo "{" > nightlies.nix;
37+
for a in nightly-*.nix; do echo " \"''${a%%.nix}\" = import ./$a;" >> nightlies.nix; done;
38+
echo "}" >> nightlies.nix
39+
# update lts
40+
echo "{" > ltss.nix;
41+
for a in lts-*.nix; do echo " \"''${a%%.nix}\" = import ./$a;" >> ltss.nix; done;
42+
echo "}" >> ltss.nix
43+
'';
44+
}

stackage-src.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"url": "https://github.com/input-output-hk/stackage.nix",
3+
"rev": "2615a4e6b1651215ee400e62fcdcb195062a3d35",
4+
"date": "2019-02-05T17:41:44+08:00",
5+
"sha256": "08c8lb8x047hndwm1cb2zxixnjmrswfp5y18xp1v79cjqlva0qj6",
6+
"fetchSubmodules": false
7+
}

test/builder-haddock/default.nix

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
1-
{ pkgs
2-
, haskell
3-
, stdenv
4-
}:
1+
{ mkPkgSet, stdenv }:
52

63
with stdenv.lib;
74

85
let
9-
pkgSet = haskell.mkPkgSet {
10-
inherit pkgs;
6+
pkgSet = mkPkgSet {
117
# generated with:
128
# cabal new-build
139
# plan-to-nix dist-newstyle/cache/plan.json > plan.nix

test/cabal-22/default.nix

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
1-
{ pkgs
2-
, haskell
3-
, stdenv
4-
}:
1+
{ stdenv, mkPkgSet }:
52

63
with stdenv.lib;
74

85
let
9-
pkgSet = haskell.mkPkgSet {
10-
inherit pkgs;
6+
pkgSet = mkPkgSet {
117
pkg-def = import ./plan.nix;
128
pkg-def-overlays = [
139
{ project = ./project.nix; }
@@ -32,23 +28,23 @@ in
3228
"$exe"
3329
3430
printf "checking that executable is dynamically linked to system libraries... " >& 2
35-
'' + pkgs.lib.optionalString pkgs.stdenv.isLinux ''
31+
'' + optionalString stdenv.isLinux ''
3632
ldd $exe | grep libpthread
37-
'' + pkgs.lib.optionalString pkgs.stdenv.isDarwin ''
33+
'' + optionalString stdenv.isDarwin ''
3834
otool -L $exe | grep "libSystem.B"
3935
'' + ''
4036
# fixme: posix-specific
4137
printf "checking that dynamic library is produced... " >& 2
42-
'' + pkgs.lib.optionalString pkgs.stdenv.isLinux ''
38+
'' + optionalString stdenv.isLinux ''
4339
sofile=$(find "${packages.project.components.library}" | grep -e '\.so$')
44-
'' + pkgs.lib.optionalString pkgs.stdenv.isDarwin ''
40+
'' + optionalString stdenv.isDarwin ''
4541
sofile=$(find "${packages.project.components.library}" | grep -e '\.dylib$')
4642
'' + ''
4743
echo "$sofile"
4844
printf "checking that dynamic library is dynamically linked to prim... " >& 2
49-
'' + pkgs.lib.optionalString pkgs.stdenv.isLinux ''
45+
'' + optionalString stdenv.isLinux ''
5046
ldd $sofile | grep libHSghc-prim
51-
'' + pkgs.lib.optionalString pkgs.stdenv.isDarwin ''
47+
'' + optionalString stdenv.isDarwin ''
5248
otool -L $sofile | grep libHSghc-prim
5349
'' + ''
5450
touch $out

0 commit comments

Comments
 (0)