on iko/ghcjs-patch-master help sign in
Merge pull request #12 from input-output-hk/builder-haddock

Dev environments

commit34511726b7b43a8a22f8026b4e9f9672e57b2cd6 authorRodney Lorrimar <dev@rodney.id.au> dateFri 1 Feb 2019, 20:11 (8 years ago) parent2491b395704909
23 files changed+731−42
.travis.yml+1−5 builder/comp-builder.nix+54−16 builder/default.nix+5−2 builder/with-package-wrapper.nix+77 doc/removing-with-package-wrapper.md+66 lib/default.nix+17−3 modules/component-driver.nix+9 modules/package.nix+27−9 test/cabal-22/default.nix−1 test/cabal-simple/cabal-simple.cabal+5 test/cabal-simple/cabal-simple.nix+11−2 test/cabal-simple/default.nix+7−2 test/cabal-simple/plan.nix+92 test/default.nix+9−2 test/tests.sh+46 test/unit.nix+54 test/with-packages/Point.hs+12 test/with-packages/Setup.hs+2 test/with-packages/TestWithPackages.hs+6 test/with-packages/default.nix+81 test/with-packages/plan.nix+99 test/with-packages/test-with-packages.cabal+15 test/with-packages/test-with-packages.nix+36
.travis.yml+1−5
@@ -19,8 +19,4 @@ before_script:
1919script:
2020- 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='
2121- cachix use nix-tools
22−- nix-build
23− -I nixpkgs=https://github.com/NixOS/nixpkgs-channels/archive/${CHANNEL}.tar.gz
24− test/default.nix
25− --cores 0
26− -j2
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
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 }:
22
33{ componentId
44, component
@@ -16,8 +16,9 @@
1616, preBuild ? null, postBuild ? null
1717, preCheck ? null, postCheck ? null
1818, preInstall ? null, postInstall ? null
19+, shellHook ? null
1920
20−, doCheck ? component.doCheck || componentId.ctype == "test"
21+, doCheck ? component.doCheck || haskellLib.isTest componentId
2122, doCrossCheck ? component.doCrossCheck || false
2223, dontPatchELF ? true
2324, dontStrip ? true
@@ -27,7 +28,9 @@
2728}:
2829
2930let
30− fullName = "${name}-${componentId.ctype}-${componentId.cname}";
31+ fullName = if haskellLib.isAll componentId
32+ then "${name}-all"
33+ else "${name}-${componentId.ctype}-${componentId.cname}";
3134
3235 flagsAndConfig = field: xs: lib.optionalString (xs != []) ''
3336 echo ${lib.concatStringsSep " " (map (x: "--${field}=${x}") xs)} >> $out/configure-flags
@@ -44,18 +47,30 @@ let
4447 in map ({val,...}: val) closure;
4548
4649 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
4851 echo "--dependency=${p}=$id" >> $out/configure-flags
4952 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
5154 echo "constraint: ${p} == $ver" >> $out/cabal.config
5255 echo "constraint: ${p} installed" >> $out/cabal.config
5356 fi
5457 '';
5558
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+
5665 configFiles = runCommand "${fullName}-config" { nativeBuildInputs = [ghc]; } (''
5766 mkdir -p $out
58− ${ghc.targetPrefix}ghc-pkg -v0 init $out/package.conf.d
67+
68+ # Calls ghc-pkg for the target platform
69+ target-pkg() {
70+ ${ghc.targetPrefix}ghc-pkg "$@"
71+ }
72+
73+ target-pkg init $out/package.conf.d
5974
6075 ${lib.concatStringsSep "\n" (lib.mapAttrsToList flagsAndConfig {
6176 "extra-lib-dirs" = map (p: "${lib.getLib p}/lib") component.libs;
@@ -67,11 +82,11 @@ let
6782 # Note: we need to use --global-package-db with ghc-pkg to prevent it
6883 # from looking into the implicit global package db when registering the package.
6984 ${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
7186 '') nonReinstallablePkgs}
7287
7388 ${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 -
7590 '') flatDepends}
7691
7792 # Note: we pass `clear` first to ensure that we never consult the implicit global package db.
@@ -79,6 +94,14 @@ let
7994
8095 echo ${lib.concatStringsSep " " (lib.mapAttrsToList (fname: val: "--flags=${lib.optionalString (!val) "-" + fname}") flags)} >> $out/configure-flags
8196
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+
82105 '' + lib.optionalString component.doExactConfig ''
83106 echo "--exact-configuration" >> $out/configure-flags
84107 echo "allow-newer: ${package.identifier.name}:*" >> $out/cabal.config
@@ -115,14 +138,14 @@ let
115138 sed -i "s,dynamic-library-dirs: .*,dynamic-library-dirs: $dynamicLinksDir," $f
116139 done
117140 '' + ''
118− ${ghc.targetPrefix}ghc-pkg -v0 --package-db $out/package.conf.d recache
141+ target-pkg --package-db $out/package.conf.d recache
119142 '' + ''
120− ${ghc.targetPrefix}ghc-pkg -v0 --package-db $out/package.conf.d check
143+ target-pkg --package-db $out/package.conf.d check
121144 '');
122145
123146 finalConfigureFlags = lib.concatStringsSep " " (
124147 [ "--prefix=$out"
125− "${componentId.ctype}:${componentId.cname}"
148+ "${haskellLib.componentTarget componentId}"
126149 "$(cat ${configFiles}/configure-flags)"
127150 # GHC
128151 "--with-ghc=${ghc.targetPrefix}ghc"
@@ -145,6 +168,16 @@ let
145168 ++ component.configureFlags
146169 );
147170
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+
148181in stdenv.mkDerivation ({
149182 name = fullName;
150183
@@ -154,6 +187,7 @@ in stdenv.mkDerivation ({
154187 inherit (package) identifier;
155188 config = component;
156189 inherit configFiles;
190+ env = shellWrappers;
157191 };
158192
159193 meta = {
@@ -167,6 +201,7 @@ in stdenv.mkDerivation ({
167201 };
168202
169203 CABAL_CONFIG = configFiles + /cabal.config;
204+ GHC_ENVIRONMENT = configFiles + /ghc-environment;
170205 LANG = "en_US.UTF-8"; # GHC needs the locale configured during the Haddock phase.
171206 LC_ALL = "en_US.UTF-8";
172207
@@ -179,9 +214,7 @@ in stdenv.mkDerivation ({
179214 nativeBuildInputs =
180215 [ghc]
181216 ++ lib.optional (component.pkgconfig != []) pkgconfig
182− ++ lib.concatMap (c: if c.isHaskell or false
183− then builtins.attrValues (c.components.exes or {})
184− else [c]) component.build-tools;
217+ ++ executableToolDepends;
185218
186219 SETUP_HS = setup + /bin/Setup;
187220
@@ -217,12 +250,12 @@ in stdenv.mkDerivation ({
217250 installPhase = ''
218251 runHook preInstall
219252 $SETUP_HS copy ${lib.concatStringsSep " " component.setupInstallFlags}
220− ${lib.optionalString (haskellLib.isLibrary componentId) ''
253+ ${lib.optionalString (haskellLib.isLibrary componentId || haskellLib.isAll componentId) ''
221254 $SETUP_HS register --gen-pkg-config=${name}.conf
222255 ${ghc.targetPrefix}ghc-pkg -v0 init $out/package.conf.d
223256 ${ghc.targetPrefix}ghc-pkg -v0 --package-db ${configFiles}/package.conf.d -f $out/package.conf.d register ${name}.conf
224257 ''}
225− ${lib.optionalString (componentId.ctype == "test") ''
258+ ${lib.optionalString (haskellLib.isTest componentId || haskellLib.isAll componentId) ''
226259 mkdir -p $out/${name}
227260 if [ -f "dist/build/${componentId.cname}/${componentId.cname}" ]; then
228261 cp dist/build/${componentId.cname}/${componentId.cname} $out/${name}/
@@ -233,6 +266,11 @@ in stdenv.mkDerivation ({
233266 ''}
234267 runHook postInstall
235268 '';
269+
270+ shellHook = ''
271+ export PATH="${shellWrappers}/bin:$PATH"
272+ ${toString shellHook}
273+ '';
236274}
237275# patches can (if they like) depend on the version and revision of the package.
238276// 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 }:
22
33{ flags
44, package
@@ -22,6 +22,8 @@
2222, preInstall
2323, postInstall
2424
25+, shellHook
26+
2527, ...
2628}@config:
2729
@@ -67,11 +69,12 @@ let
6769 '';
6870 };
6971
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; };
7173
7274 buildComp = componentId: component: comp-builder {
7375 inherit componentId component package name src flags setup cabalFile patches revision
7476 preUnpack postUnpack preConfigure postConfigure preBuild postBuild preCheck postCheck preInstall postInstall
77+ shellHook
7578 ;
7679 };
7780
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 @@
33with haskellLib;
44
55{
6+ # Within the package components, these are the attribute names of
7+ # nested attrsets.
68 subComponentTypes = [
79 "sublibs"
810 "foreignlibs"
@@ -66,13 +68,25 @@ with haskellLib;
6668 applyComponents = f: config:
6769 let
6870 comps = config.components;
69− libComp = lib.mapAttrs (cname: f {ctype="lib"; cname=config.package.identifier.name;}) (removeAttrs comps subComponentTypes);
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"; };
74+ libComp = lib.mapAttrs applyLibrary (removeAttrs comps (subComponentTypes ++ [ "all" ]));
7075 subComps = lib.mapAttrs
71− (ctype: lib.mapAttrs (cname: f {inherit cname; ctype=componentPrefix.${ctype};}))
76+ (ctype: lib.mapAttrs (applySubComp ctype))
7277 (builtins.intersectAttrs (lib.genAttrs subComponentTypes (_: null)) comps);
73− in subComps // libComp;
78+ allComp = { all = applyAllComp comps.all; };
79+ in subComps // libComp // allComp;
7480
7581 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}";
7690
7791 # Avoid pkgs.callPackage for now. It does a lot of nonsense with OOP
7892 # style programming that we should avoid until we know we want it.
modules/component-driver.nix+9
@@ -6,7 +6,16 @@ let
66 ghc = config.ghc.package;
77 buildGHC = buildModules.config.ghc.package;
88 inherit (config) nonReinstallablePkgs;
9+ inherit withPackage;
910 };
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+
1019in
1120
1221{
modules/package.nix+27−9
@@ -19,6 +19,8 @@ with lib;
1919with types;
2020
2121let
22+ haskellLib = let hl = import ../lib { inherit lib; haskellLib = hl; }; in hl;
23+
2224 # This is just like listOf, except that it filters out all null elements.
2325 listOfFilteringNulls = elemType: listOf elemType // {
2426 # Mostly copied from nixpkgs/lib/types.nix
@@ -97,11 +99,11 @@ in {
9799 };
98100
99101 components = let
100− componentType = check: submodule {
102+ componentType = defaults: submodule {
101103 options = {
102104 depends = mkOption {
103105 type = listOfFilteringNulls unspecified;
104− default = [];
106+ default = defaults.depends or [];
105107 };
106108 libs = mkOption {
107109 type = listOfFilteringNulls (nullOr package);
@@ -141,7 +143,7 @@ in {
141143 };
142144 doCheck = mkOption {
143145 type = bool;
144− default = check;
146+ default = defaults.doCheck or false;
145147 };
146148 doCrossCheck = mkOption {
147149 type = bool;
@@ -151,28 +153,40 @@ in {
151153 };
152154 in {
153155 library = mkOption {
154− type = componentType false;
156+ type = componentType {};
155157 };
156158 sublibs = mkOption {
157− type = attrsOf (componentType false);
159+ type = attrsOf (componentType {});
158160 default = {};
159161 };
160162 foreignlibs = mkOption {
161− type = attrsOf (componentType false);
163+ type = attrsOf (componentType {});
162164 default = {};
163165 };
164166 exes = mkOption {
165− type = attrsOf (componentType false);
167+ type = attrsOf (componentType {});
166168 default = {};
167169 };
168170 tests = mkOption {
169− type = attrsOf (componentType config.doCheck);
171+ type = attrsOf (componentType { inherit (config) doCheck; });
170172 default = {};
171173 };
172174 benchmarks = mkOption {
173− type = attrsOf (componentType false);
175+ type = attrsOf (componentType {});
174176 default = {};
175177 };
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+ };
176190 };
177191
178192 name = mkOption {
@@ -261,6 +275,10 @@ in {
261275 type = nullOr string;
262276 default = null;
263277 };
278+ shellHook = mkOption {
279+ type = nullOr string;
280+ default = null;
281+ };
264282 doCheck = mkOption {
265283 type = bool;
266284 default = false;
test/cabal-22/default.nix−1
@@ -31,7 +31,6 @@ in
3131 printf "checking whether executable runs... " >& 2
3232 "$exe"
3333
34− # fixme: linux-specific
3534 printf "checking that executable is dynamically linked to system libraries... " >& 2
3635 '' + pkgs.lib.optionalString pkgs.stdenv.isLinux ''
3736 ldd $exe | grep libpthread
test/cabal-simple/cabal-simple.cabal+5
@@ -19,6 +19,9 @@ library
1919 -- other-modules:
2020 -- other-extensions:
2121 build-depends: base >=4.11 && <4.12
22+ , extra
23+ , safe
24+ , aeson
2225 -- hs-source-dirs:
2326 default-language: Haskell2010
2427
@@ -27,5 +30,7 @@ executable cabal-simple
2730 -- other-modules:
2831 -- other-extensions:
2932 build-depends: base >=4.11 && <4.12
33+ , extra
34+ , optparse-applicative
3035 -- hs-source-dirs:
3136 default-language: Haskell2010
test/cabal-simple/cabal-simple.nix+11−2
@@ -25,11 +25,20 @@
2525 };
2626 components = {
2727 "library" = {
28− depends = [ (hsPkgs.base) ];
28+ depends = [
29+ (hsPkgs.base)
30+ (hsPkgs.extra)
31+ (hsPkgs.safe)
32+ (hsPkgs.aeson)
33+ ];
2934 };
3035 exes = {
3136 "cabal-simple" = {
32− depends = [ (hsPkgs.base) ];
37+ depends = [
38+ (hsPkgs.base)
39+ (hsPkgs.extra)
40+ (hsPkgs.optparse-applicative)
41+ ];
3342 };
3443 };
3544 };
test/cabal-simple/default.nix+7−2
@@ -33,18 +33,23 @@ in
3333 printf "checking whether executable runs... " >& 2
3434 $exe
3535
36− # fixme: linux-specific
3736 printf "checking that executable is dynamically linked to system libraries... " >& 2
3837 '' + pkgs.lib.optionalString pkgs.stdenv.isLinux ''
3938 ldd $exe | grep libpthread
4039 '' + pkgs.lib.optionalString pkgs.stdenv.isDarwin ''
4140 otool -L $exe |grep .dylib
4241 '' + ''
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+
4348 touch $out
4449 '';
4550
4651 meta.platforms = platforms.all;
47−} // { inherit (packages) cabal-simple; }
52+} // { inherit (packages) cabal-simple; inherit pkgSet; }
4853
4954## steps to generate local files
5055# 1. cabal-to-nix cabal-simple.cabal > cabal-simple.nix
test/cabal-simple/plan.nix+92
@@ -1,18 +1,110 @@
11hackage:
22 {
33 packages = {
4+ "binary".revision = hackage."binary"."0.8.5.1".revisions.default;
45 "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;
59 "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;
661 "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;
783 "integer-gmp".revision = hackage."integer-gmp"."1.0.2.0".revisions.default;
884 };
985 compiler = {
1086 version = "8.4.4";
1187 nix-name = "ghc844";
1288 packages = {
89+ "binary" = "0.8.5.1";
1390 "ghc-prim" = "0.5.2.0";
91+ "stm" = "2.4.5.1";
92+ "unix" = "2.7.2.2";
1493 "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";
15100 "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";
16108 "integer-gmp" = "1.0.2.0";
17109 };
18110 };
test/default.nix+9−2
@@ -6,16 +6,23 @@ let
66 # all packages from hackage as nix expressions
77 hackage = import (fetchFromGitHub { owner = "angerman";
88 repo = "hackage.nix";
9− rev = "66c28064da46525711722b75b4adb2ac878897d3";
10− sha256 = "12ffzzjgirwzha3ngxbniccgn19406iryxspq19kgi4kz9lz6bpr";
9+ rev = "5223a45e08b1b0d738fdd292b39e49f39f21536f";
10+ sha256 = "09r662kn2qs444fmqni9jamaxnrk9jrg6whqmxbwhfgd5vy3yynq";
1111 name = "hackage-exprs-source"; });
1212
1313 # The new Haskell infra applied to nix representation of Hackage
1414 haskell = import ../. hackage;
1515
16+ haskellLib = let hl = import ../lib { inherit lib; haskellLib = hl; }; in hl;
17+
1618in {
1719 cabal-simple = callPackage ./cabal-simple { inherit haskell; };
1820 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; };
1926}
2027
2128## 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+ }