on iko/ghcjs-patch-master help sign in
Merge pull request #12 from input-output-hk/builder-haddock
3451172Rodney Lorrimar
@@ -19,8 +19,4 @@ before_script:
19script:
19script:
20- nix-env -if https://github.com/cachix/cachix/tarball/master --extra-substituters https://cachix.cachix.org --trusted-public-keys 'cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= cachix.cachix.org-1:eWNHQldwUO7G2VkjpnjDbWwy4KQ/HNxht7H4SSoMckM='
20- nix-env -if https://github.com/cachix/cachix/tarball/master --extra-substituters https://cachix.cachix.org --trusted-public-keys 'cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY= cachix.cachix.org-1:eWNHQldwUO7G2VkjpnjDbWwy4KQ/HNxht7H4SSoMckM='
21- cachix use nix-tools
21- cachix use nix-tools
22−- nix-build
23− -I nixpkgs=https://github.com/NixOS/nixpkgs-channels/archive/${CHANNEL}.tar.gz
22+- NIX_PATH=nixpkgs=https://github.com/NixOS/nixpkgs-channels/archive/${CHANNEL}.tar.gz NIX_BUILD_ARGS="--cores 0 --max-jobs 2" ./test/tests.sh
24− test/default.nix
25− --cores 0
26− -j2
builder/comp-builder.nix+54−16
@@ -1,4 +1,4 @@
1−{ stdenv, buildPackages, ghc, lib, pkgconfig, writeText, runCommand, haskellLib, nonReinstallablePkgs }:
1+{ stdenv, buildPackages, ghc, lib, pkgconfig, writeText, runCommand, haskellLib, nonReinstallablePkgs, withPackage }:
2
2
3{ componentId
3{ componentId
4, component
4, component
@@ -16,8 +16,9 @@
16, preBuild ? null, postBuild ? null
16, preBuild ? null, postBuild ? null
17, preCheck ? null, postCheck ? null
17, preCheck ? null, postCheck ? null
18, preInstall ? null, postInstall ? null
18, preInstall ? null, postInstall ? null
19+, shellHook ? null
19
20
20−, doCheck ? component.doCheck || componentId.ctype == "test"
21+, doCheck ? component.doCheck || haskellLib.isTest componentId
21, doCrossCheck ? component.doCrossCheck || false
22, doCrossCheck ? component.doCrossCheck || false
22, dontPatchELF ? true
23, dontPatchELF ? true
23, dontStrip ? true
24, dontStrip ? true
@@ -27,7 +28,9 @@
27}:
28}:
28
29
29let
30let
31+ fullName = if haskellLib.isAll componentId
32+ then "${name}-all"
30− fullName = "${name}-${componentId.ctype}-${componentId.cname}";
33+ else "${name}-${componentId.ctype}-${componentId.cname}";
31
34
32 flagsAndConfig = field: xs: lib.optionalString (xs != []) ''
35 flagsAndConfig = field: xs: lib.optionalString (xs != []) ''
33 echo ${lib.concatStringsSep " " (map (x: "--${field}=${x}") xs)} >> $out/configure-flags
36 echo ${lib.concatStringsSep " " (map (x: "--${field}=${x}") xs)} >> $out/configure-flags
@@ -44,18 +47,30 @@ let
44 in map ({val,...}: val) closure;
47 in map ({val,...}: val) closure;
45
48
46 exactDep = pdbArg: p: ''
49 exactDep = pdbArg: p: ''
47− if id=$(${ghc.targetPrefix}ghc-pkg -v0 ${pdbArg} field ${p} id --simple-output); then
50+ if id=$(target-pkg ${pdbArg} field ${p} id --simple-output); then
48 echo "--dependency=${p}=$id" >> $out/configure-flags
51 echo "--dependency=${p}=$id" >> $out/configure-flags
49 fi
52 fi
50− if ver=$(${ghc.targetPrefix}ghc-pkg -v0 ${pdbArg} field ${p} version --simple-output); then
53+ if ver=$(target-pkg ${pdbArg} field ${p} version --simple-output); then
51 echo "constraint: ${p} == $ver" >> $out/cabal.config
54 echo "constraint: ${p} == $ver" >> $out/cabal.config
52 echo "constraint: ${p} installed" >> $out/cabal.config
55 echo "constraint: ${p} installed" >> $out/cabal.config
53 fi
56 fi
54 '';
57 '';
55
58
59+ envDep = pdbArg: p: ''
60+ if id=$(target-pkg ${pdbArg} field ${p} id --simple-output); then
61+ echo "package-id $id" >> $out/ghc-environment
62+ fi
63+ '';
64+
56 configFiles = runCommand "${fullName}-config" { nativeBuildInputs = [ghc]; } (''
65 configFiles = runCommand "${fullName}-config" { nativeBuildInputs = [ghc]; } (''
57 mkdir -p $out
66 mkdir -p $out
67+
68+ # Calls ghc-pkg for the target platform
69+ target-pkg() {
58− ${ghc.targetPrefix}ghc-pkg -v0 init $out/package.conf.d
70+ ${ghc.targetPrefix}ghc-pkg "$@"
71+ }
72+
73+ target-pkg init $out/package.conf.d
59
74
60 ${lib.concatStringsSep "\n" (lib.mapAttrsToList flagsAndConfig {
75 ${lib.concatStringsSep "\n" (lib.mapAttrsToList flagsAndConfig {
61 "extra-lib-dirs" = map (p: "${lib.getLib p}/lib") component.libs;
76 "extra-lib-dirs" = map (p: "${lib.getLib p}/lib") component.libs;
@@ -67,11 +82,11 @@ let
67 # Note: we need to use --global-package-db with ghc-pkg to prevent it
82 # Note: we need to use --global-package-db with ghc-pkg to prevent it
68 # from looking into the implicit global package db when registering the package.
83 # from looking into the implicit global package db when registering the package.
69 ${lib.concatMapStringsSep "\n" (p: ''
84 ${lib.concatMapStringsSep "\n" (p: ''
70− ${ghc.targetPrefix}ghc-pkg -v0 describe ${p} | ${ghc.targetPrefix}ghc-pkg -v0 --force --global-package-db $out/package.conf.d register - || true
85+ target-pkg describe ${p} | target-pkg --force --global-package-db $out/package.conf.d register - || true
71 '') nonReinstallablePkgs}
86 '') nonReinstallablePkgs}
72
87
73 ${lib.concatMapStringsSep "\n" (p: ''
88 ${lib.concatMapStringsSep "\n" (p: ''
74− ${ghc.targetPrefix}ghc-pkg -v0 --package-db ${p}/package.conf.d dump | ${ghc.targetPrefix}ghc-pkg -v0 --force --package-db $out/package.conf.d register -
89+ target-pkg --package-db ${p}/package.conf.d dump | target-pkg --force --package-db $out/package.conf.d register -
75 '') flatDepends}
90 '') flatDepends}
76
91
77 # Note: we pass `clear` first to ensure that we never consult the implicit global package db.
92 # Note: we pass `clear` first to ensure that we never consult the implicit global package db.
@@ -79,6 +94,14 @@ let
79
94
80 echo ${lib.concatStringsSep " " (lib.mapAttrsToList (fname: val: "--flags=${lib.optionalString (!val) "-" + fname}") flags)} >> $out/configure-flags
95 echo ${lib.concatStringsSep " " (lib.mapAttrsToList (fname: val: "--flags=${lib.optionalString (!val) "-" + fname}") flags)} >> $out/configure-flags
81
96
97+ # Provide a GHC environment file
98+ cat > $out/ghc-environment <<EOF
99+ clear-package-db
100+ package-db $out/package.conf.d
101+ EOF
102+ ${lib.concatMapStringsSep "\n" (p: envDep "--package-db ${p.components.library}/package.conf.d" p.identifier.name) component.depends}
103+ ${lib.concatMapStringsSep "\n" (envDep "") (lib.remove "ghc" nonReinstallablePkgs)}
104+
82 '' + lib.optionalString component.doExactConfig ''
105 '' + lib.optionalString component.doExactConfig ''
83 echo "--exact-configuration" >> $out/configure-flags
106 echo "--exact-configuration" >> $out/configure-flags
84 echo "allow-newer: ${package.identifier.name}:*" >> $out/cabal.config
107 echo "allow-newer: ${package.identifier.name}:*" >> $out/cabal.config
@@ -115,14 +138,14 @@ let
115 sed -i "s,dynamic-library-dirs: .*,dynamic-library-dirs: $dynamicLinksDir," $f
138 sed -i "s,dynamic-library-dirs: .*,dynamic-library-dirs: $dynamicLinksDir," $f
116 done
139 done
117 '' + ''
140 '' + ''
118− ${ghc.targetPrefix}ghc-pkg -v0 --package-db $out/package.conf.d recache
141+ target-pkg --package-db $out/package.conf.d recache
119 '' + ''
142 '' + ''
120− ${ghc.targetPrefix}ghc-pkg -v0 --package-db $out/package.conf.d check
143+ target-pkg --package-db $out/package.conf.d check
121 '');
144 '');
122
145
123 finalConfigureFlags = lib.concatStringsSep " " (
146 finalConfigureFlags = lib.concatStringsSep " " (
124 [ "--prefix=$out"
147 [ "--prefix=$out"
125− "${componentId.ctype}:${componentId.cname}"
148+ "${haskellLib.componentTarget componentId}"
126 "$(cat ${configFiles}/configure-flags)"
149 "$(cat ${configFiles}/configure-flags)"
127 # GHC
150 # GHC
128 "--with-ghc=${ghc.targetPrefix}ghc"
151 "--with-ghc=${ghc.targetPrefix}ghc"
@@ -145,6 +168,16 @@ let
145 ++ component.configureFlags
168 ++ component.configureFlags
146 );
169 );
147
170
171+ executableToolDepends = lib.concatMap (c: if c.isHaskell or false
172+ then builtins.attrValues (c.components.exes or {})
173+ else [c]) component.build-tools;
174+
175+ # Unfortunately, we need to wrap ghc commands for cabal builds to
176+ # work in the nix-shell. See ../doc/removing-with-package-wrapper.md.
177+ shellWrappers = withPackage {
178+ inherit package configFiles;
179+ };
180+
148in stdenv.mkDerivation ({
181in stdenv.mkDerivation ({
149 name = fullName;
182 name = fullName;
150
183
@@ -154,6 +187,7 @@ in stdenv.mkDerivation ({
154 inherit (package) identifier;
187 inherit (package) identifier;
155 config = component;
188 config = component;
156 inherit configFiles;
189 inherit configFiles;
190+ env = shellWrappers;
157 };
191 };
158
192
159 meta = {
193 meta = {
@@ -167,6 +201,7 @@ in stdenv.mkDerivation ({
167 };
201 };
168
202
169 CABAL_CONFIG = configFiles + /cabal.config;
203 CABAL_CONFIG = configFiles + /cabal.config;
204+ GHC_ENVIRONMENT = configFiles + /ghc-environment;
170 LANG = "en_US.UTF-8"; # GHC needs the locale configured during the Haddock phase.
205 LANG = "en_US.UTF-8"; # GHC needs the locale configured during the Haddock phase.
171 LC_ALL = "en_US.UTF-8";
206 LC_ALL = "en_US.UTF-8";
172
207
@@ -179,9 +214,7 @@ in stdenv.mkDerivation ({
179 nativeBuildInputs =
214 nativeBuildInputs =
180 [ghc]
215 [ghc]
181 ++ lib.optional (component.pkgconfig != []) pkgconfig
216 ++ lib.optional (component.pkgconfig != []) pkgconfig
182− ++ lib.concatMap (c: if c.isHaskell or false
217+ ++ executableToolDepends;
183− then builtins.attrValues (c.components.exes or {})
184− else [c]) component.build-tools;
185
218
186 SETUP_HS = setup + /bin/Setup;
219 SETUP_HS = setup + /bin/Setup;
187
220
@@ -217,12 +250,12 @@ in stdenv.mkDerivation ({
217 installPhase = ''
250 installPhase = ''
218 runHook preInstall
251 runHook preInstall
219 $SETUP_HS copy ${lib.concatStringsSep " " component.setupInstallFlags}
252 $SETUP_HS copy ${lib.concatStringsSep " " component.setupInstallFlags}
220− ${lib.optionalString (haskellLib.isLibrary componentId) ''
253+ ${lib.optionalString (haskellLib.isLibrary componentId || haskellLib.isAll componentId) ''
221 $SETUP_HS register --gen-pkg-config=${name}.conf
254 $SETUP_HS register --gen-pkg-config=${name}.conf
222 ${ghc.targetPrefix}ghc-pkg -v0 init $out/package.conf.d
255 ${ghc.targetPrefix}ghc-pkg -v0 init $out/package.conf.d
223 ${ghc.targetPrefix}ghc-pkg -v0 --package-db ${configFiles}/package.conf.d -f $out/package.conf.d register ${name}.conf
256 ${ghc.targetPrefix}ghc-pkg -v0 --package-db ${configFiles}/package.conf.d -f $out/package.conf.d register ${name}.conf
224 ''}
257 ''}
225− ${lib.optionalString (componentId.ctype == "test") ''
258+ ${lib.optionalString (haskellLib.isTest componentId || haskellLib.isAll componentId) ''
226 mkdir -p $out/${name}
259 mkdir -p $out/${name}
227 if [ -f "dist/build/${componentId.cname}/${componentId.cname}" ]; then
260 if [ -f "dist/build/${componentId.cname}/${componentId.cname}" ]; then
228 cp dist/build/${componentId.cname}/${componentId.cname} $out/${name}/
261 cp dist/build/${componentId.cname}/${componentId.cname} $out/${name}/
@@ -233,6 +266,11 @@ in stdenv.mkDerivation ({
233 ''}
266 ''}
234 runHook postInstall
267 runHook postInstall
235 '';
268 '';
269+
270+ shellHook = ''
271+ export PATH="${shellWrappers}/bin:$PATH"
272+ ${toString shellHook}
273+ '';
236}
274}
237# patches can (if they like) depend on the version and revision of the package.
275# patches can (if they like) depend on the version and revision of the package.
238// lib.optionalAttrs (patches != []) { patches = map (p: if builtins.isFunction p then p { inherit (package.identifier) version; inherit revision; } else p) patches; }
276// lib.optionalAttrs (patches != []) { patches = map (p: if builtins.isFunction p then p { inherit (package.identifier) version; inherit revision; } else p) patches; }
builder/default.nix+5−2
@@ -1,4 +1,4 @@
1−{ pkgs, buildPackages, stdenv, lib, haskellLib, ghc, buildGHC, fetchurl, writeText, runCommand, pkgconfig, nonReinstallablePkgs }:
1+{ pkgs, buildPackages, stdenv, lib, haskellLib, ghc, buildGHC, fetchurl, writeText, runCommand, pkgconfig, nonReinstallablePkgs, withPackage }:
2
2
3{ flags
3{ flags
4, package
4, package
@@ -22,6 +22,8 @@
22, preInstall
22, preInstall
23, postInstall
23, postInstall
24
24
25+, shellHook
26+
25, ...
27, ...
26}@config:
28}@config:
27
29
@@ -67,11 +69,12 @@ let
67 '';
69 '';
68 };
70 };
69
71
70− comp-builder = haskellLib.weakCallPackage pkgs ./comp-builder.nix { inherit ghc haskellLib nonReinstallablePkgs; };
72+ comp-builder = haskellLib.weakCallPackage pkgs ./comp-builder.nix { inherit ghc haskellLib nonReinstallablePkgs withPackage; };
71
73
72 buildComp = componentId: component: comp-builder {
74 buildComp = componentId: component: comp-builder {
73 inherit componentId component package name src flags setup cabalFile patches revision
75 inherit componentId component package name src flags setup cabalFile patches revision
74 preUnpack postUnpack preConfigure postConfigure preBuild postBuild preCheck postCheck preInstall postInstall
76 preUnpack postUnpack preConfigure postConfigure preBuild postBuild preCheck postCheck preInstall postInstall
77+ shellHook
75 ;
78 ;
76 };
79 };
77
80
builder/with-package-wrapper.nixnew file+77
@@ -0,0 +1,77 @@
1+# This is a simplified version of the ghcWithPackages wrapper in
2+# nixpkgs, adapted to work with the package database of a single
3+# component.
4+{ lib, stdenv, ghc, runCommand, lndir, makeWrapper
5+}:
6+
7+{ package
8+, configFiles
9+, postBuild ? ""
10+}:
11+
12+let
13+ isGhcjs = ghc.isGhcjs or false;
14+ ghcCommand' = if isGhcjs then "ghcjs" else "ghc";
15+ ghcCommand = "${ghc.targetPrefix}${ghcCommand'}";
16+ ghcCommandCaps= lib.toUpper ghcCommand';
17+ libDir = "$out/lib/${ghcCommand}-${ghc.version}";
18+ docDir = "$out/share/doc/ghc/html";
19+ packageCfgDir = "${libDir}/package.conf.d";
20+
21+in runCommand "${ghc.name}-with-${package.identifier.name}" {
22+ preferLocalBuild = true;
23+ passthru = {
24+ inherit (ghc) version meta;
25+ baseGhc = ghc;
26+ inherit package;
27+ };
28+} (
29+ ''
30+ . ${makeWrapper}/nix-support/setup-hook
31+
32+ # Start with a ghc...
33+ mkdir -p $out/bin
34+ ${lndir}/bin/lndir -silent ${ghc} $out
35+
36+ # ...and replace package database with the one from target package config.
37+ rm -rf ${libDir}
38+ mkdir -p ${libDir}
39+ ln -s ${configFiles}/package.conf.d ${packageCfgDir}
40+
41+ # Wrap compiler executables with correct env variables.
42+ # The NIX_ variables are used by the patched Paths_ghc module.
43+ # The GHC_ENVIRONMENT variable forces ghc to use the build
44+ # dependencies of the component.
45+
46+ for prg in ${ghcCommand} ${ghcCommand}i ${ghcCommand}-${ghc.version} ${ghcCommand}i-${ghc.version} runghc runhaskell; do
47+ if [[ -x "${ghc}/bin/$prg" ]]; then
48+ rm -f $out/bin/$prg
49+ makeWrapper ${ghc}/bin/$prg $out/bin/$prg \
50+ --set "NIX_${ghcCommandCaps}" "$out/bin/${ghcCommand}" \
51+ --set "NIX_${ghcCommandCaps}PKG" "$out/bin/${ghcCommand}-pkg" \
52+ --set "NIX_${ghcCommandCaps}_DOCDIR" "${docDir}" \
53+ --set "NIX_${ghcCommandCaps}_LIBDIR" "${libDir}" \
54+ --set "${ghcCommandCaps}_ENVIRONMENT" "${configFiles}/ghc-environment"
55+ fi
56+ done
57+
58+ # Point ghc-pkg to the package database of the component using the
59+ # GHC_PACKAGE_PATH variable.
60+
61+ for prg in ${ghcCommand}-pkg ${ghcCommand}-pkg-${ghc.version}; do
62+ if [[ -x "${ghc}/bin/$prg" ]]; then
63+ rm -f $out/bin/$prg
64+ makeWrapper ${ghc}/bin/$prg $out/bin/$prg \
65+ --set "${ghcCommandCaps}_PACKAGE_PATH" "${configFiles}/package.conf.d"
66+ fi
67+ done
68+
69+ # fixme: check if this is needed
70+ # haddock was referring to the base ghc, https://github.com/NixOS/nixpkgs/issues/36976
71+ if [[ -x "${ghc}/bin/haddock" ]]; then
72+ rm -f $out/bin/haddock
73+ makeWrapper ${ghc}/bin/haddock $out/bin/haddock \
74+ --set "NIX_${ghcCommandCaps}_LIBDIR" "${libDir}"
75+ fi
76+ ''
77+)
doc/removing-with-package-wrapper.mdnew file+66
@@ -0,0 +1,66 @@
1+# `ghcWithPackages` wrapper removal
2+
3+The current [Nixpkgs Haskell infrastructure][nixpkgs-haskell] and `haskell.nix` both
4+provide a `ghcWithPackages` derivation which contains shell script
5+wrappers that wrap `ghc` and `ghc-pkg`.
6+
7+In the Nixpkgs Haskell infrastructure, the wrapper scripts are used
8+for building Haskell packages. However, in `haskell.nix`, the wrappers
9+are only used for development environments.
10+
11+The wrapper scripts provide a `ghc` command that "knows" about the
12+package set and has all Haskell package dependencies available to it.
13+
14+We would like to remove the wrapper scripts, but it's currently not
15+possible to configure all build tools using environment variables
16+alone.
17+
18+## Plain `ghc`
19+
20+When using `ghc` or `ghci` by itself, the `GHC_ENVIRONMENT` variable
21+can point to a configuration file containing an exact package
22+set. This works quite well.
23+
24+## `ghc-pkg`
25+
26+The package tool `ghc-pkg` does not recognize `GHC_ENVIRONMENT`, but
27+does recognize a `GHC_PACKAGE_PATH` pointing to a `package.conf.d`.
28+
29+This works well. However, the `cabal` command will refuse to start if
30+`GHC_PACKAGE_PATH` is set.
31+
32+## `Setup.hs`
33+
34+When invoking `Setup.hs configure`, the package database is provided
35+with the `--package-db` argument and exact dependencies in the package
36+set can be provided as `--dependency` arguments.
37+
38+The `haskell.nix` component builder uses `Setup.hs` with these
39+command-line options to build Haskell packages.
40+
41+## `cabal new-build`
42+
43+Cabal-install will observe the `CABAL_CONFIG` environment variable,
44+which points to a cabal config file. This config file can provide a
45+`package-db` value, but it can't specify exact versions of packages.
46+
47+Cabal is designed to solve dependencies, not simply take the package
48+set which is given to it.
49+
50+Therefore, `cabal` does not use `GHC_ENVIRONMENT`, but instead creates
51+its own environment file. It will not accept `--dependency` arguments.
52+
53+As far as I know, the best way to force `cabal` to take a pre-computed
54+package set is to use a `new-freeze` file. However there is no
55+environment variable (or config file entry) which can specify a path
56+to a freeze file.
57+
58+Specifying a `package-db` path in the cabal config file is not enough
59+for it to successfully resolve dependencies.
60+
61+As mentioned before, `cabal` does not work when `GHC_PACKAGE_PATH` is
62+set. The best way to work around this is to wrap `ghc` and `ghc-pkg`
63+in shell scripts.
64+
65+
66+[nixpkgs-haskell]: https://nixos.org/nixpkgs/manual/#users-guide-to-the-haskell-infrastructure
lib/default.nix+17−3
@@ -3,6 +3,8 @@
3with haskellLib;
3with haskellLib;
4
4
5{
5{
6+ # Within the package components, these are the attribute names of
7+ # nested attrsets.
6 subComponentTypes = [
8 subComponentTypes = [
7 "sublibs"
9 "sublibs"
8 "foreignlibs"
10 "foreignlibs"
@@ -66,13 +68,25 @@ with haskellLib;
66 applyComponents = f: config:
68 applyComponents = f: config:
67 let
69 let
68 comps = config.components;
70 comps = config.components;
71+ applyLibrary = cname: f { cname = config.package.identifier.name; ctype = "lib"; };
72+ applySubComp = ctype: cname: f { inherit cname; ctype = componentPrefix.${ctype}; };
73+ applyAllComp = f { cname = config.package.identifier.name; ctype = "all"; };
69− libComp = lib.mapAttrs (cname: f {ctype="lib"; cname=config.package.identifier.name;}) (removeAttrs comps subComponentTypes);
74+ libComp = lib.mapAttrs applyLibrary (removeAttrs comps (subComponentTypes ++ [ "all" ]));
70 subComps = lib.mapAttrs
75 subComps = lib.mapAttrs
71− (ctype: lib.mapAttrs (cname: f {inherit cname; ctype=componentPrefix.${ctype};}))
76+ (ctype: lib.mapAttrs (applySubComp ctype))
72 (builtins.intersectAttrs (lib.genAttrs subComponentTypes (_: null)) comps);
77 (builtins.intersectAttrs (lib.genAttrs subComponentTypes (_: null)) comps);
78+ allComp = { all = applyAllComp comps.all; };
73− in subComps // libComp;
79+ in subComps // libComp // allComp;
74
80
75 isLibrary = componentId: componentId.ctype == "lib";
81 isLibrary = componentId: componentId.ctype == "lib";
82+ isAll = componentId: componentId.ctype == "all";
83+ isTest = componentId: componentId.ctype == "test";
84+
85+ # Format a componentId as it should appear as a target on the
86+ # command line of the setup script.
87+ componentTarget = componentId:
88+ if componentId.ctype == "all" then ""
89+ else "${componentId.ctype}:${componentId.cname}";
76
90
77 # Avoid pkgs.callPackage for now. It does a lot of nonsense with OOP
91 # Avoid pkgs.callPackage for now. It does a lot of nonsense with OOP
78 # style programming that we should avoid until we know we want it.
92 # style programming that we should avoid until we know we want it.
modules/component-driver.nix+9
@@ -6,7 +6,16 @@ let
6 ghc = config.ghc.package;
6 ghc = config.ghc.package;
7 buildGHC = buildModules.config.ghc.package;
7 buildGHC = buildModules.config.ghc.package;
8 inherit (config) nonReinstallablePkgs;
8 inherit (config) nonReinstallablePkgs;
9+ inherit withPackage;
9 };
10 };
11+
12+ withPackage = import ../builder/with-package-wrapper.nix {
13+ inherit lib;
14+ inherit (pkgs) stdenv runCommand makeWrapper;
15+ inherit (pkgs.xorg) lndir;
16+ ghc = config.ghc.package;
17+ };
18+
10in
19in
11
20
12{
21{
modules/package.nix+27−9
@@ -19,6 +19,8 @@ with lib;
19with types;
19with types;
20
20
21let
21let
22+ haskellLib = let hl = import ../lib { inherit lib; haskellLib = hl; }; in hl;
23+
22 # This is just like listOf, except that it filters out all null elements.
24 # This is just like listOf, except that it filters out all null elements.
23 listOfFilteringNulls = elemType: listOf elemType // {
25 listOfFilteringNulls = elemType: listOf elemType // {
24 # Mostly copied from nixpkgs/lib/types.nix
26 # Mostly copied from nixpkgs/lib/types.nix
@@ -97,11 +99,11 @@ in {
97 };
99 };
98
100
99 components = let
101 components = let
100− componentType = check: submodule {
102+ componentType = defaults: submodule {
101 options = {
103 options = {
102 depends = mkOption {
104 depends = mkOption {
103 type = listOfFilteringNulls unspecified;
105 type = listOfFilteringNulls unspecified;
104− default = [];
106+ default = defaults.depends or [];
105 };
107 };
106 libs = mkOption {
108 libs = mkOption {
107 type = listOfFilteringNulls (nullOr package);
109 type = listOfFilteringNulls (nullOr package);
@@ -141,7 +143,7 @@ in {
141 };
143 };
142 doCheck = mkOption {
144 doCheck = mkOption {
143 type = bool;
145 type = bool;
144− default = check;
146+ default = defaults.doCheck or false;
145 };
147 };
146 doCrossCheck = mkOption {
148 doCrossCheck = mkOption {
147 type = bool;
149 type = bool;
@@ -151,28 +153,40 @@ in {
151 };
153 };
152 in {
154 in {
153 library = mkOption {
155 library = mkOption {
154− type = componentType false;
156+ type = componentType {};
155 };
157 };
156 sublibs = mkOption {
158 sublibs = mkOption {
157− type = attrsOf (componentType false);
159+ type = attrsOf (componentType {});
158 default = {};
160 default = {};
159 };
161 };
160 foreignlibs = mkOption {
162 foreignlibs = mkOption {
161− type = attrsOf (componentType false);
163+ type = attrsOf (componentType {});
162 default = {};
164 default = {};
163 };
165 };
164 exes = mkOption {
166 exes = mkOption {
165− type = attrsOf (componentType false);
167+ type = attrsOf (componentType {});
166 default = {};
168 default = {};
167 };
169 };
168 tests = mkOption {
170 tests = mkOption {
169− type = attrsOf (componentType config.doCheck);
171+ type = attrsOf (componentType { inherit (config) doCheck; });
170 default = {};
172 default = {};
171 };
173 };
172 benchmarks = mkOption {
174 benchmarks = mkOption {
173− type = attrsOf (componentType false);
175+ type = attrsOf (componentType {});
174 default = {};
176 default = {};
175 };
177 };
178+ all = let
179+ subComponentsDepends = sub: concatLists
180+ (mapAttrsToList (_: c: c.depends or []) config.components.${sub} or {});
181+ default = {
182+ depends = config.components.library.depends ++
183+ concatMap subComponentsDepends haskellLib.subComponentTypes;
184+ };
185+ in mkOption {
186+ type = componentType default;
187+ inherit default;
188+ defaultText = "The merged dependencies of all other components";
189+ };
176 };
190 };
177
191
178 name = mkOption {
192 name = mkOption {
@@ -261,6 +275,10 @@ in {
261 type = nullOr string;
275 type = nullOr string;
262 default = null;
276 default = null;
263 };
277 };
278+ shellHook = mkOption {
279+ type = nullOr string;
280+ default = null;
281+ };
264 doCheck = mkOption {
282 doCheck = mkOption {
265 type = bool;
283 type = bool;
266 default = false;
284 default = false;
test/cabal-22/default.nix−1
@@ -31,7 +31,6 @@ in
31 printf "checking whether executable runs... " >& 2
31 printf "checking whether executable runs... " >& 2
32 "$exe"
32 "$exe"
33
33
34− # fixme: linux-specific
35 printf "checking that executable is dynamically linked to system libraries... " >& 2
34 printf "checking that executable is dynamically linked to system libraries... " >& 2
36 '' + pkgs.lib.optionalString pkgs.stdenv.isLinux ''
35 '' + pkgs.lib.optionalString pkgs.stdenv.isLinux ''
37 ldd $exe | grep libpthread
36 ldd $exe | grep libpthread
test/cabal-simple/cabal-simple.cabal+5
@@ -19,6 +19,9 @@ library
19 -- other-modules:
19 -- other-modules:
20 -- other-extensions:
20 -- other-extensions:
21 build-depends: base >=4.11 && <4.12
21 build-depends: base >=4.11 && <4.12
22+ , extra
23+ , safe
24+ , aeson
22 -- hs-source-dirs:
25 -- hs-source-dirs:
23 default-language: Haskell2010
26 default-language: Haskell2010
24
27
@@ -27,5 +30,7 @@ executable cabal-simple
27 -- other-modules:
30 -- other-modules:
28 -- other-extensions:
31 -- other-extensions:
29 build-depends: base >=4.11 && <4.12
32 build-depends: base >=4.11 && <4.12
33+ , extra
34+ , optparse-applicative
30 -- hs-source-dirs:
35 -- hs-source-dirs:
31 default-language: Haskell2010
36 default-language: Haskell2010
test/cabal-simple/cabal-simple.nix+11−2
@@ -25,11 +25,20 @@
25 };
25 };
26 components = {
26 components = {
27 "library" = {
27 "library" = {
28+ depends = [
28− depends = [ (hsPkgs.base) ];
29+ (hsPkgs.base)
30+ (hsPkgs.extra)
31+ (hsPkgs.safe)
32+ (hsPkgs.aeson)
33+ ];
29 };
34 };
30 exes = {
35 exes = {
31 "cabal-simple" = {
36 "cabal-simple" = {
37+ depends = [
32− depends = [ (hsPkgs.base) ];
38+ (hsPkgs.base)
39+ (hsPkgs.extra)
40+ (hsPkgs.optparse-applicative)
41+ ];
33 };
42 };
34 };
43 };
35 };
44 };
test/cabal-simple/default.nix+7−2
@@ -33,18 +33,23 @@ in
33 printf "checking whether executable runs... " >& 2
33 printf "checking whether executable runs... " >& 2
34 $exe
34 $exe
35
35
36− # fixme: linux-specific
37 printf "checking that executable is dynamically linked to system libraries... " >& 2
36 printf "checking that executable is dynamically linked to system libraries... " >& 2
38 '' + pkgs.lib.optionalString pkgs.stdenv.isLinux ''
37 '' + pkgs.lib.optionalString pkgs.stdenv.isLinux ''
39 ldd $exe | grep libpthread
38 ldd $exe | grep libpthread
40 '' + pkgs.lib.optionalString pkgs.stdenv.isDarwin ''
39 '' + pkgs.lib.optionalString pkgs.stdenv.isDarwin ''
41 otool -L $exe |grep .dylib
40 otool -L $exe |grep .dylib
42 '' + ''
41 '' + ''
42+
43+ printf "Checking that \"all\" component has the programs... " >& 2
44+ all_exe="${packages.cabal-simple.components.all}/bin/cabal-simple"
45+ test -f "$all_exe"
46+ echo "$all_exe" >& 2
47+
43 touch $out
48 touch $out
44 '';
49 '';
45
50
46 meta.platforms = platforms.all;
51 meta.platforms = platforms.all;
47−} // { inherit (packages) cabal-simple; }
52+} // { inherit (packages) cabal-simple; inherit pkgSet; }
48
53
49## steps to generate local files
54## steps to generate local files
50# 1. cabal-to-nix cabal-simple.cabal > cabal-simple.nix
55# 1. cabal-to-nix cabal-simple.cabal > cabal-simple.nix
test/cabal-simple/plan.nix+92
@@ -1,18 +1,110 @@
1hackage:
1hackage:
2 {
2 {
3 packages = {
3 packages = {
4+ "binary".revision = hackage."binary"."0.8.5.1".revisions.default;
4 "ghc-prim".revision = hackage."ghc-prim"."0.5.2.0".revisions.default;
5 "ghc-prim".revision = hackage."ghc-prim"."0.5.2.0".revisions.default;
6+ "extra".revision = hackage."extra"."1.6.14".revisions.default;
7+ "stm".revision = hackage."stm"."2.4.5.1".revisions.default;
8+ "unix".revision = hackage."unix"."2.7.2.2".revisions.default;
5 "rts".revision = hackage."rts"."1.0".revisions.default;
9 "rts".revision = hackage."rts"."1.0".revisions.default;
10+ "clock".revision = hackage."clock"."0.7.2".revisions.default;
11+ "clock".flags.llvm = false;
12+ "scientific".revision = hackage."scientific"."0.3.6.2".revisions.default;
13+ "scientific".flags.integer-simple = false;
14+ "scientific".flags.bytestring-builder = false;
15+ "deepseq".revision = hackage."deepseq"."1.4.3.0".revisions.default;
16+ "random".revision = hackage."random"."1.1".revisions.default;
17+ "uuid-types".revision = hackage."uuid-types"."1.0.3".revisions.default;
18+ "optparse-applicative".revision = hackage."optparse-applicative"."0.14.3.0".revisions.default;
19+ "dlist".revision = hackage."dlist"."0.8.0.5".revisions.default;
20+ "directory".revision = hackage."directory"."1.3.1.5".revisions.default;
21+ "transformers-compat".revision = hackage."transformers-compat"."0.6.2".revisions.default;
22+ "transformers-compat".flags.five = false;
23+ "transformers-compat".flags.generic-deriving = true;
24+ "transformers-compat".flags.two = false;
25+ "transformers-compat".flags.five-three = true;
26+ "transformers-compat".flags.mtl = true;
27+ "transformers-compat".flags.four = false;
28+ "transformers-compat".flags.three = false;
29+ "template-haskell".revision = hackage."template-haskell"."2.13.0.0".revisions.default;
30+ "vector".revision = hackage."vector"."0.12.0.2".revisions.default;
31+ "vector".flags.unsafechecks = false;
32+ "vector".flags.internalchecks = false;
33+ "vector".flags.wall = false;
34+ "vector".flags.boundschecks = true;
35+ "primitive".revision = hackage."primitive"."0.6.4.0".revisions.default;
36+ "time-locale-compat".revision = hackage."time-locale-compat"."0.1.1.5".revisions.default;
37+ "time-locale-compat".flags.old-locale = false;
38+ "safe".revision = hackage."safe"."0.3.17".revisions.default;
39+ "base-compat".revision = hackage."base-compat"."0.10.5".revisions.default;
40+ "ansi-terminal".revision = hackage."ansi-terminal"."0.8.2".revisions.default;
41+ "ansi-terminal".flags.example = false;
42+ "tagged".revision = hackage."tagged"."0.8.6".revisions.default;
43+ "tagged".flags.transformers = true;
44+ "tagged".flags.deepseq = true;
45+ "containers".revision = hackage."containers"."0.5.11.0".revisions.default;
46+ "integer-logarithms".revision = hackage."integer-logarithms"."1.0.2.2".revisions.default;
47+ "integer-logarithms".flags.check-bounds = false;
48+ "integer-logarithms".flags.integer-gmp = true;
49+ "bytestring".revision = hackage."bytestring"."0.10.8.2".revisions.default;
50+ "ansi-wl-pprint".revision = hackage."ansi-wl-pprint"."0.6.8.2".revisions.default;
51+ "ansi-wl-pprint".flags.example = false;
52+ "StateVar".revision = hackage."StateVar"."1.1.1.1".revisions.default;
53+ "contravariant".revision = hackage."contravariant"."1.5".revisions.default;
54+ "contravariant".flags.semigroups = true;
55+ "contravariant".flags.tagged = true;
56+ "contravariant".flags.statevar = true;
57+ "contravariant".flags.safe = false;
58+ "text".revision = hackage."text"."1.2.3.1".revisions.default;
59+ "unordered-containers".revision = hackage."unordered-containers"."0.2.9.0".revisions.default;
60+ "unordered-containers".flags.debug = false;
6 "base".revision = hackage."base"."4.11.1.0".revisions.default;
61 "base".revision = hackage."base"."4.11.1.0".revisions.default;
62+ "time".revision = hackage."time"."1.8.0.2".revisions.default;
63+ "transformers".revision = hackage."transformers"."0.5.5.0".revisions.default;
64+ "hashable".revision = hackage."hashable"."1.2.7.0".revisions.default;
65+ "hashable".flags.sse2 = true;
66+ "hashable".flags.integer-gmp = true;
67+ "hashable".flags.sse41 = false;
68+ "hashable".flags.examples = false;
69+ "attoparsec".revision = hackage."attoparsec"."0.13.2.2".revisions.default;
70+ "attoparsec".flags.developer = false;
71+ "colour".revision = hackage."colour"."2.3.4".revisions.default;
72+ "filepath".revision = hackage."filepath"."1.4.2".revisions.default;
73+ "process".revision = hackage."process"."1.6.3.0".revisions.default;
74+ "pretty".revision = hackage."pretty"."1.1.3.6".revisions.default;
75+ "aeson".revision = hackage."aeson"."1.4.2.0".revisions.default;
76+ "aeson".flags.cffi = false;
77+ "aeson".flags.fast = false;
78+ "aeson".flags.bytestring-builder = false;
79+ "aeson".flags.developer = false;
80+ "ghc-boot-th".revision = hackage."ghc-boot-th"."8.4.4".revisions.default;
81+ "th-abstraction".revision = hackage."th-abstraction"."0.2.10.0".revisions.default;
82+ "array".revision = hackage."array"."0.5.2.0".revisions.default;
7 "integer-gmp".revision = hackage."integer-gmp"."1.0.2.0".revisions.default;
83 "integer-gmp".revision = hackage."integer-gmp"."1.0.2.0".revisions.default;
8 };
84 };
9 compiler = {
85 compiler = {
10 version = "8.4.4";
86 version = "8.4.4";
11 nix-name = "ghc844";
87 nix-name = "ghc844";
12 packages = {
88 packages = {
89+ "binary" = "0.8.5.1";
13 "ghc-prim" = "0.5.2.0";
90 "ghc-prim" = "0.5.2.0";
91+ "stm" = "2.4.5.1";
92+ "unix" = "2.7.2.2";
14 "rts" = "1.0";
93 "rts" = "1.0";
94+ "deepseq" = "1.4.3.0";
95+ "directory" = "1.3.1.5";
96+ "template-haskell" = "2.13.0.0";
97+ "containers" = "0.5.11.0";
98+ "bytestring" = "0.10.8.2";
99+ "text" = "1.2.3.1";
15 "base" = "4.11.1.0";
100 "base" = "4.11.1.0";
101+ "time" = "1.8.0.2";
102+ "transformers" = "0.5.5.0";
103+ "filepath" = "1.4.2";
104+ "process" = "1.6.3.0";
105+ "pretty" = "1.1.3.6";
106+ "ghc-boot-th" = "8.4.4";
107+ "array" = "0.5.2.0";
16 "integer-gmp" = "1.0.2.0";
108 "integer-gmp" = "1.0.2.0";
17 };
109 };
18 };
110 };
test/default.nix+9−2
@@ -6,16 +6,23 @@ let
6 # all packages from hackage as nix expressions
6 # all packages from hackage as nix expressions
7 hackage = import (fetchFromGitHub { owner = "angerman";
7 hackage = import (fetchFromGitHub { owner = "angerman";
8 repo = "hackage.nix";
8 repo = "hackage.nix";
9− rev = "66c28064da46525711722b75b4adb2ac878897d3";
9+ rev = "5223a45e08b1b0d738fdd292b39e49f39f21536f";
10− sha256 = "12ffzzjgirwzha3ngxbniccgn19406iryxspq19kgi4kz9lz6bpr";
10+ sha256 = "09r662kn2qs444fmqni9jamaxnrk9jrg6whqmxbwhfgd5vy3yynq";
11 name = "hackage-exprs-source"; });
11 name = "hackage-exprs-source"; });
12
12
13 # The new Haskell infra applied to nix representation of Hackage
13 # The new Haskell infra applied to nix representation of Hackage
14 haskell = import ../. hackage;
14 haskell = import ../. hackage;
15
15
16+ haskellLib = let hl = import ../lib { inherit lib; haskellLib = hl; }; in hl;
17+
16in {
18in {
17 cabal-simple = callPackage ./cabal-simple { inherit haskell; };
19 cabal-simple = callPackage ./cabal-simple { inherit haskell; };
18 cabal-22 = callPackage ./cabal-22 { inherit haskell; };
20 cabal-22 = callPackage ./cabal-22 { inherit haskell; };
21+ with-packages = callPackage ./with-packages { inherit haskell; };
22+
23+ # Run unit tests with: nix-instantiate --eval --strict -A unit
24+ # An empty list means success.
25+ unit = callPackage ./unit.nix { inherit haskellLib; };
19}
26}
20
27
21## possible test cases
28## possible test cases
test/tests.shnew file+46
@@ -0,0 +1,46 @@
1+#! /usr/bin/env nix-shell
2+#! nix-shell -i bash -p bash jq nix
3+
4+set -euo pipefail
5+
6+NIX_BUILD_ARGS="${NIX_BUILD_ARGS:-}"
7+
8+cd $(dirname $0)
9+
10+printf "*** Running the nix-build tests...\n" >& 2
11+nix-build $NIX_BUILD_ARGS --no-out-link --keep-going ./default.nix
12+echo >& 2
13+
14+printf "*** Running the unit tests... " >& 2
15+res=$(nix-instantiate --eval --json --strict ./default.nix -A unit)
16+num_failed=$(jq length <<< "$res")
17+if [ $num_failed -eq 0 ]; then
18+ printf "PASSED\n" >& 2
19+else
20+ printf "$num_failed FAILED\n" >& 2
21+ jq . <<< "$res"
22+ exit 1
23+fi
24+
25+printf "*** Checking that a nix-shell works for runghc...\n" >& 2
26+nix-shell $NIX_BUILD_ARGS \
27+ --pure ./default.nix \
28+ -A with-packages.test-shell \
29+ --run 'runghc with-packages/Point.hs'
30+echo >& 2
31+
32+printf "*** Checking that a nix-shell works for cabal...\n" >& 2
33+nix-shell $NIX_BUILD_ARGS \
34+ --pure ./default.nix \
35+ -A with-packages.test-shell \
36+ --run 'echo CABAL_CONFIG=$CABAL_CONFIG && type -p ghc && cd with-packages && rm -rf dist-newstyle .ghc-environment* && cabal new-build'
37+echo >& 2
38+
39+printf "*** Checking that a nix-shell works for cabal (doExactConfig component)...\n" >& 2
40+nix-shell $NIX_BUILD_ARGS \
41+ --pure ./default.nix \
42+ -A with-packages.test-shell-dec \
43+ --run 'echo CABAL_CONFIG=$CABAL_CONFIG && echo GHC_ENVIRONMENT=$GHC_ENVIRONMENT && cd with-packages && rm -rf dist-newstyle .ghc-environment* && cabal new-build'
44+echo >& 2
45+
46+printf "\n*** Finished successfully\n" >& 2
test/unit.nixnew file+54
@@ -0,0 +1,54 @@
1+{ lib, haskellLib }:
2+
3+let
4+ emptyConfig = {
5+ components = {
6+ benchmarks = { };
7+ exes = { };
8+ foreignlibs = { };
9+ library = "library";
10+ sublibs = { };
11+ tests = { };
12+ all = "all";
13+ };
14+ package.identifier.name = "empty";
15+ };
16+
17+ componentsConfig = {
18+ components = {
19+ benchmarks = { bbb = "bbb"; };
20+ exes = { eee = "eee"; };
21+ foreignlibs = { fff = "fff"; };
22+ library = "library";
23+ sublibs = { };
24+ tests = { ttt = "ttt"; };
25+ all = "all";
26+ };
27+ package.identifier.name = "nnn";
28+ };
29+
30+in
31+lib.runTests {
32+ # identity function for applyComponents
33+ test-applyComponents-id = {
34+ expr = haskellLib.applyComponents (componentId: component: component) emptyConfig;
35+ expected = emptyConfig.components;
36+ };
37+
38+ # map a component to its component name and check these are correct
39+ test-applyComponents-library = {
40+ expr = haskellLib.applyComponents (componentId: component: componentId.cname) emptyConfig;
41+ expected = emptyConfig.components // { library = "empty"; all = "empty"; };
42+ };
43+
44+ test-applyComponents-components = {
45+ expr = haskellLib.applyComponents (componentId: component: component) componentsConfig;
46+ expected = componentsConfig.components;
47+ };
48+
49+ # testing that the tests work
50+ testId = {
51+ expr = lib.id 1;
52+ expected = 1;
53+ };
54+}
test/with-packages/Point.hsnew file+12
@@ -0,0 +1,12 @@
1+{-# LANGUAGE TemplateHaskell #-}
2+module Main where
3+
4+import Control.Lens
5+
6+data Point = Point { _x :: Double, _y :: Double }
7+makeLenses ''Point
8+
9+main :: IO ()
10+main = print (point^.x + point^.y)
11+ where
12+ point = Point { _x = 40.0, _y = 2.0 }
test/with-packages/Setup.hsnew file+2
@@ -0,0 +1,2 @@
1+import Distribution.Simple
2+main = defaultMain
test/with-packages/TestWithPackages.hsnew file+6
@@ -0,0 +1,6 @@
1+-- | Haddock test stuff
2+module TestWithPackages (hello) where
3+
4+-- | Standard hello text.
5+hello :: String
6+hello = "Hello, world!"
test/with-packages/default.nixnew file+81
@@ -0,0 +1,81 @@
1+{ pkgs
2+, haskell
3+, stdenv
4+}:
5+
6+with stdenv.lib;
7+
8+let
9+ pkgSet = haskell.mkPkgSet {
10+ inherit pkgs;
11+ # generated with:
12+ # cabal new-build
13+ # plan-to-nix dist-newstyle/cache/plan.json > plan.nix
14+ # cabal-to-nix test-with-packages.cabal > test-with-packages.nix
15+ pkg-def = import ./plan.nix;
16+ pkg-def-overlays = [
17+ { test-with-packages = ./test-with-packages.nix; }
18+ ];
19+ modules = [
20+ # overrides to fix the build
21+ {
22+ packages.transformers-compat.components.library.doExactConfig = true;
23+ }
24+
25+ # vary component config for tests
26+ {
27+ packages.test-with-packages.components = {
28+ all.doExactConfig = false; # the default
29+ library.doExactConfig = true; # not the default
30+ };
31+ }
32+ ];
33+ };
34+
35+ packages = pkgSet.config.hsPkgs;
36+
37+ # Add cabal as a buildInput for a haskell derivation. Useful for nix-shell.
38+ addCabalInstall = drv: drv.overrideAttrs (oldAttrs: {
39+ buildInputs = (oldAttrs.buildInputs or []) ++ [ pkgs.cabal-install ];
40+ });
41+
42+in
43+ stdenv.mkDerivation {
44+ name = "with-packages-test";
45+
46+ buildCommand = let
47+ package = packages.test-with-packages;
48+ inherit (package.components) library;
49+ in ''
50+ ########################################################################
51+ # test with-packages
52+
53+ printf "checking that the 'all' component works... " >& 2
54+ echo ${package.components.all} >& 2
55+
56+ printf "checking that the 'library' component works... " >& 2
57+ echo ${package.components.library} >& 2
58+
59+ printf "checking that the package env has the dependencies... " >& 2
60+ ${package.components.all.env}/bin/runghc ${./Point.hs}
61+ echo >& 2
62+
63+ printf "checking that components.library.env has the dependencies... " >& 2
64+ ${library.env}/bin/runghc ${./Point.hs}
65+ # echo >& 2
66+
67+ touch $out
68+ '';
69+
70+ meta.platforms = platforms.all;
71+} // {
72+ # Used for debugging with nix repl
73+ inherit packages pkgSet;
74+
75+ # Used for testing externally with nix-shell (../tests.sh).
76+ # This just adds cabal-install to the existing shells.
77+ test-shell = addCabalInstall packages.test-with-packages.components.all;
78+
79+ # A variant of test-shell with the component option doExactConfig enabled
80+ test-shell-dec = addCabalInstall packages.test-with-packages.components.library;
81+}
test/with-packages/plan.nixnew file+99
@@ -0,0 +1,99 @@
1+hackage:
2+ {
3+ packages = {
4+ "void".revision = hackage."void"."0.7.2".revisions.default;
5+ "semigroupoids".revision = hackage."semigroupoids"."5.2.2".revisions.default;
6+ "free".revision = hackage."free"."5.0.2".revisions.default;
7+ "exceptions".revision = hackage."exceptions"."0.10.0".revisions.default;
8+ "binary".revision = hackage."binary"."0.8.5.1".revisions.default;
9+ "ghc-prim".revision = hackage."ghc-prim"."0.5.2.0".revisions.default;
10+ "bifunctors".revision = hackage."bifunctors"."5.5.3".revisions.default;
11+ "stm".revision = hackage."stm"."2.4.5.1".revisions.default;
12+ "mtl".revision = hackage."mtl"."2.2.2".revisions.default;
13+ "rts".revision = hackage."rts"."1.0".revisions.default;
14+ "adjunctions".revision = hackage."adjunctions"."4.4".revisions.default;
15+ "invariant".revision = hackage."invariant"."0.5.1".revisions.default;
16+ "distributive".revision = hackage."distributive"."0.5.3".revisions.default;
17+ "parallel".revision = hackage."parallel"."3.2.2.0".revisions.default;
18+ "deepseq".revision = hackage."deepseq"."1.4.3.0".revisions.default;
19+ "semigroups".revision = hackage."semigroups"."0.18.5".revisions.default;
20+ "transformers-compat".revision = hackage."transformers-compat"."0.6.2".revisions.default;
21+ "template-haskell".revision = hackage."template-haskell"."2.13.0.0".revisions.default;
22+ "vector".revision = hackage."vector"."0.12.0.1".revisions.default;
23+ "call-stack".revision = hackage."call-stack"."0.1.0".revisions.default;
24+ "primitive".revision = hackage."primitive"."0.6.3.0".revisions.default;
25+ "profunctors".revision = hackage."profunctors"."5.2.2".revisions.default;
26+ "tagged".revision = hackage."tagged"."0.8.5".revisions.default;
27+ "lens".revision = hackage."lens"."4.16.1".revisions.default;
28+ "containers".revision = hackage."containers"."0.5.11.0".revisions.default;
29+ "reflection".revision = hackage."reflection"."2.1.4".revisions.default;
30+ "bytestring".revision = hackage."bytestring"."0.10.8.2".revisions.default;
31+ "StateVar".revision = hackage."StateVar"."1.1.1.1".revisions.default;
32+ "contravariant".revision = hackage."contravariant"."1.4.1".revisions.default;
33+ "text".revision = hackage."text"."1.2.3.1".revisions.default;
34+ "unordered-containers".revision = hackage."unordered-containers"."0.2.9.0".revisions.default;
35+ "base".revision = hackage."base"."4.11.1.0".revisions.default;
36+ "comonad".revision = hackage."comonad"."5.0.4".revisions.default;
37+ "transformers".revision = hackage."transformers"."0.5.5.0".revisions.default;
38+ "hashable".revision = hackage."hashable"."1.2.7.0".revisions.default;
39+ "transformers-base".revision = hackage."transformers-base"."0.4.5.2".revisions.default;
40+ "filepath".revision = hackage."filepath"."1.4.2".revisions.default;
41+ "kan-extensions".revision = hackage."kan-extensions"."5.2".revisions.default;
42+ "pretty".revision = hackage."pretty"."1.1.3.6".revisions.default;
43+ "ghc-boot-th".revision = hackage."ghc-boot-th"."8.4.4".revisions.default;
44+ "base-orphans".revision = hackage."base-orphans"."0.7".revisions.default;
45+ "th-abstraction".revision = hackage."th-abstraction"."0.2.8.0".revisions.default;
46+ "array".revision = hackage."array"."0.5.2.0".revisions.default;
47+ "integer-gmp".revision = hackage."integer-gmp"."1.0.2.0".revisions.default;
48+ };
49+ compiler = {
50+ version = "8.4.4";
51+ nix-name = "ghc844";
52+ packages = {
53+ "void" = "0.7.2";
54+ "semigroupoids" = "5.2.2";
55+ "free" = "5.0.2";
56+ "exceptions" = "0.10.0";
57+ "binary" = "0.8.5.1";
58+ "ghc-prim" = "0.5.2.0";
59+ "bifunctors" = "5.5.3";
60+ "stm" = "2.4.5.1";
61+ "mtl" = "2.2.2";
62+ "rts" = "1.0";
63+ "adjunctions" = "4.4";
64+ "invariant" = "0.5.1";
65+ "distributive" = "0.5.3";
66+ "parallel" = "3.2.2.0";
67+ "deepseq" = "1.4.3.0";
68+ "semigroups" = "0.18.5";
69+ "transformers-compat" = "0.6.2";
70+ "template-haskell" = "2.13.0.0";
71+ "vector" = "0.12.0.1";
72+ "call-stack" = "0.1.0";
73+ "primitive" = "0.6.3.0";
74+ "profunctors" = "5.2.2";
75+ "tagged" = "0.8.5";
76+ "lens" = "4.16.1";
77+ "containers" = "0.5.11.0";
78+ "reflection" = "2.1.4";
79+ "bytestring" = "0.10.8.2";
80+ "StateVar" = "1.1.1.1";
81+ "contravariant" = "1.4.1";
82+ "text" = "1.2.3.1";
83+ "unordered-containers" = "0.2.9.0";
84+ "base" = "4.11.1.0";
85+ "comonad" = "5.0.4";
86+ "transformers" = "0.5.5.0";
87+ "hashable" = "1.2.7.0";
88+ "transformers-base" = "0.4.5.2";
89+ "filepath" = "1.4.2";
90+ "kan-extensions" = "5.2";
91+ "pretty" = "1.1.3.6";
92+ "ghc-boot-th" = "8.4.4";
93+ "base-orphans" = "0.7";
94+ "th-abstraction" = "0.2.8.0";
95+ "array" = "0.5.2.0";
96+ "integer-gmp" = "1.0.2.0";
97+ };
98+ };
99+ }
test/with-packages/test-with-packages.cabalnew file+15
@@ -0,0 +1,15 @@
1+cabal-version: 2.2
2+name: test-with-packages
3+version: 0.1.0.0
4+license: NONE
5+author: Rodney Lorrimar
6+maintainer: rodney.lorrimar@iohk.io
7+
8+library
9+ exposed-modules: TestWithPackages
10+ -- other-modules:
11+ -- other-extensions:
12+ build-depends: base ^>=4.11.1.0
13+ , lens
14+ -- hs-source-dirs:
15+ default-language: Haskell2010
test/with-packages/test-with-packages.nixnew file+36
@@ -0,0 +1,36 @@
1+{ system
2+, compiler
3+, flags
4+, pkgs
5+, hsPkgs
6+, pkgconfPkgs
7+, ... }:
8+ {
9+ flags = {};
10+ package = {
11+ specVersion = "2.2";
12+ identifier = {
13+ name = "test-with-packages";
14+ version = "0.1.0.0";
15+ };
16+ license = "NONE";
17+ copyright = "";
18+ maintainer = "rodney.lorrimar@iohk.io";
19+ author = "Rodney Lorrimar";
20+ homepage = "";
21+ url = "";
22+ synopsis = "";
23+ description = "";
24+ buildType = "Simple";
25+ };
26+ components = {
27+ "library" = {
28+ depends = [
29+ (hsPkgs.base)
30+ (hsPkgs.lens)
31+ ];
32+ };
33+ };
34+ } // rec {
35+ src = pkgs.lib.mkDefault ./.;
36+ }