on iko/ghcjs-patch-master help sign in
Allow package-name:sublib-name in build-depends (#963)

With cabal 3 it should be possible to reference a sublib in the `build-depends` of a `.cabal` file using `package-name:sublib-name` The `cabal-sublib` test is updated to include the new type syntax and a fix is included for the component builder. We will need to update `plan-to-nix` in `nix-tools` as well. For now the work around is to use a module to add the sublib to `depends` (see `test/cabal-sublib/default.nix`). Without this fix the `cabal-sublib:slib` was not found by `setup configure` because only `--dependency=slib=cabal-sublib-...` was passed. The fix is to also pass `--dependency=cabal-sublib:slib=cabal-sublib-...`.

commit2b7d93baf6eda8fc59a65330b60b67f9c6685286 authorHamish Mackenzie <Hamish.Mackenzie@iohk.io> dateFri 8 Jan 2021, 23:11 (6 years ago) parentf848b47
10 files changed+108−80
builder/comp-builder.nix+35−21 builder/default.nix+2−2 builder/hspkg-builder.nix+19−2 builder/shell-for.nix+3−1 modules/component-driver.nix+1 overlays/ghcjs.nix+27−52 overlays/hackage-quirks.nix+5 test/cabal-sublib/cabal-sublib.cabal+2−1 test/cabal-sublib/default.nix+8−1 test/shell-for/default.nix+6
builder/comp-builder.nix+35−21
@@ -325,31 +325,43 @@ let
325325 ${lib.optionalString (haskellLib.isLibrary componentId) ''
326326 $SETUP_HS register --gen-pkg-config=${name}.conf
327327 ${ghc.targetPrefix}ghc-pkg -v0 init $out/package.conf.d
328− if [ -d "${name}.conf" ]; then
329− for pkg in ${name}.conf/*; do
330− ${ghc.targetPrefix}ghc-pkg -v0 --package-db ${configFiles}/${configFiles.packageCfgDir} -f $out/package.conf.d register "$pkg"
331− done
332− elif [ -e "${name}.conf" ]; then
333− ${ghc.targetPrefix}ghc-pkg -v0 --package-db ${configFiles}/${configFiles.packageCfgDir} -f $out/package.conf.d register ${name}.conf
334− fi
328+ ${ghc.targetPrefix}ghc-pkg -v0 --package-db ${configFiles}/${configFiles.packageCfgDir} -f $out/package.conf.d register ${name}.conf
335329
336330 mkdir -p $out/exactDep
337331 touch $out/exactDep/configure-flags
338332 touch $out/exactDep/cabal.config
339333 touch $out/envDep
340334
341− if id=$(${target-pkg-and-db} field ${package.identifier.name} id --simple-output); then
342− echo "--dependency=${package.identifier.name}=$id" >> $out/exactDep/configure-flags
343− echo "package-id $id" >> $out/envDep
344− elif id=$(${target-pkg-and-db} field "z-${package.identifier.name}-z-*" id --simple-output); then
345− name=$(${target-pkg-and-db} field "z-${package.identifier.name}-z-*" name --simple-output)
346− # so we are dealing with a sublib. As we build sublibs separately, the above
347− # query should be safe.
348− echo "--dependency=''${name#z-${package.identifier.name}-z-}=$id" >> $out/exactDep/configure-flags
349− else
350− echo 'ERROR: ${package.identifier.name} id could not be found with ${target-pkg-and-db}'
351− exit 0
352− fi
335+ ${ # The main library in a package has the same name as the package
336+ if package.identifier.name == componentId.cname
337+ then ''
338+ if id=$(${target-pkg-and-db} field ${package.identifier.name} id --simple-output); then
339+ echo "--dependency=${package.identifier.name}=$id" >> $out/exactDep/configure-flags
340+ echo "package-id $id" >> $out/envDep
341+ else
342+ echo 'ERROR: ${package.identifier.name} id could not be found with ${target-pkg-and-db}'
343+ exit 0
344+ fi
345+ ''
346+ else
347+ # If the component name is not the package name this must be a sublib.
348+ # As we build sublibs separately, the following query should be safe.
349+ (''
350+ if id=$(${target-pkg-and-db} field "z-${package.identifier.name}-z-*" id --simple-output); then
351+ name=$(${target-pkg-and-db} field "z-${package.identifier.name}-z-*" name --simple-output)
352+ echo "--dependency=''${name#z-${package.identifier.name}-z-}=$id" >> $out/exactDep/configure-flags
353+ ''
354+ # Allow `package-name:sublib-name` to work in `build-depends`
355+ # by adding the same `--dependency` again, but with the package
356+ # name added.
357+ + ''
358+ echo "--dependency=${package.identifier.name}:''${name#z-${package.identifier.name}-z-}=$id" >> $out/exactDep/configure-flags
359+ else
360+ echo 'ERROR: ${package.identifier.name} id could not be found with ${target-pkg-and-db}'
361+ exit 0
362+ fi
363+ '')
364+ }
353365 if ver=$(${target-pkg-and-db} field ${package.identifier.name} version --simple-output); then
354366 echo "constraint: ${package.identifier.name} == $ver" >> $out/exactDep/cabal.config
355367 echo "constraint: ${package.identifier.name} installed" >> $out/exactDep/cabal.config
@@ -372,21 +384,23 @@ let
372384 '')
373385 # In case `setup copy` did not create this
374386 + (lib.optionalString enableSeparateDataOutput "mkdir -p $data")
375− + (lib.optionalString (stdenv.hostPlatform.isWindows && (haskellLib.mayHaveExecutable componentId)) ''
387+ + (lib.optionalString (stdenv.hostPlatform.isWindows && (haskellLib.mayHaveExecutable componentId)) (''
376388 echo "Symlink libffi and gmp .dlls ..."
377389 for p in ${lib.concatStringsSep " " [ libffi gmp ]}; do
378390 find "$p" -iname '*.dll' -exec ln -s {} $out/bin \;
379391 done
392+ ''
380393 # symlink all .dlls into the local directory.
381394 # we ask ghc-pkg for *all* dynamic-library-dirs and then iterate over the unique set
382395 # to symlink over dlls as needed.
396+ + ''
383397 echo "Symlink library dependencies..."
384398 for libdir in $(x86_64-pc-mingw32-ghc-pkg --package-db=$packageConfDir field "*" dynamic-library-dirs --simple-output|xargs|sed 's/ /\n/g'|sort -u); do
385399 if [ -d "$libdir" ]; then
386400 find "$libdir" -iname '*.dll' -exec ln -s {} $out/bin \;
387401 fi
388402 done
389− '')
403+ ''))
390404 + (lib.optionalString doCoverage ''
391405 mkdir -p $out/share
392406 cp -r dist/hpc $out/share
builder/default.nix+2−2
@@ -1,4 +1,4 @@
1−{ pkgs, buildPackages, stdenv, lib, haskellLib, ghc, fetchurl, pkgconfig, nonReinstallablePkgs, hsPkgs, compiler }:
1+{ pkgs, buildPackages, stdenv, lib, haskellLib, ghc, compiler-nix-name, fetchurl, pkgconfig, nonReinstallablePkgs, hsPkgs, compiler }:
22
33let
44 # Builds a single component of a package.
@@ -75,7 +75,7 @@ in {
7575 # Build a Haskell package from its config.
7676 # TODO: this pkgs is the adjusted pkgs, but pkgs.pkgs is unadjusted
7777 build-package = haskellLib.weakCallPackage pkgs ./hspkg-builder.nix {
78− inherit haskellLib ghc comp-builder setup-builder;
78+ inherit haskellLib ghc compiler-nix-name comp-builder setup-builder;
7979 };
8080
8181 inherit shellFor makeConfigFiles;
builder/hspkg-builder.nix+19−2
@@ -1,4 +1,4 @@
1−{ pkgs, buildPackages, stdenv, lib, haskellLib, ghc, fetchurl, runCommand, comp-builder, setup-builder }:
1+{ pkgs, buildPackages, stdenv, lib, haskellLib, ghc, compiler-nix-name, fetchurl, runCommand, comp-builder, setup-builder }:
22
33config:
44{ flags
@@ -34,10 +34,27 @@ let
3434 import Distribution.Simple
3535 main = defaultMain
3636 '';
37+
38+ # Get the Cabal lib used to build `cabal-install`.
39+ # To avoid infinite recursion we have to leave this out for packages
40+ # needed to build `cabal-install`.
41+ # We always do this for ghcjs as the patched version of Cabal is needed.
42+ cabalLibDepends = lib.optional (
43+ stdenv.hostPlatform.isGhcjs || (
44+ builtins.elem compiler-nix-name["ghc865" "ghc884"]
45+ &&
46+ !builtins.elem package.identifier.name
47+ ["nix-tools" "alex" "happy" "hscolour" "Cabal" "bytestring" "aeson" "time"
48+ "filepath" "base-compat-batteries" "base-compat" "unix" "directory" "transformers"
49+ "containers" "binary" "mtl" "text" "process" "parsec"]
50+ )
51+ )
52+ buildPackages.haskell-nix.cabal-install-unchecked.${compiler-nix-name}.project.hsPkgs.Cabal.components.library;
53+
3754 defaultSetup = setup-builder {
3855 name = "${ghc.targetPrefix}default-Setup";
3956 component = {
40− depends = config.setup-depends;
57+ depends = config.setup-depends ++ cabalLibDepends;
4158 libs = [];
4259 frameworks = [];
4360 doExactConfig = false;
builder/shell-for.nix+3−1
@@ -15,6 +15,7 @@
1515, withHoogle ? true
1616, exactDeps ? false
1717, tools ? {}
18+, packageSetupDeps ? true
1819, ... } @ args:
1920
2021let
@@ -26,7 +27,8 @@ let
2627 selectedComponents = components hsPkgs;
2728
2829 # The configs of all the selected components
29− selectedConfigs = map (c: c.config) selectedComponents ++ map (p: p.setup.config) selectedPackages;
30+ selectedConfigs = map (c: c.config) selectedComponents
31+ ++ lib.optionals packageSetupDeps (map (p: p.setup.config) selectedPackages);
3032
3133 name = if lib.length selectedPackages == 1
3234 then "ghc-shell-for-${(lib.head selectedPackages).identifier.name}"
modules/component-driver.nix+1
@@ -3,6 +3,7 @@ let
33 builder = haskellLib.weakCallPackage pkgs ../builder {
44 inherit haskellLib;
55 ghc = config.ghc.package;
6+ compiler-nix-name = config.compiler.nix-name;
67 inherit (config) nonReinstallablePkgs hsPkgs compiler;
78 };
89
overlays/ghcjs.nix+27−52
@@ -2,59 +2,34 @@ final: prev:
22{
33 haskell-nix = prev.haskell-nix // ({
44 defaultModules = prev.haskell-nix.defaultModules ++ final.lib.optional final.stdenv.hostPlatform.isGhcjs (
5− ({ pkgs, buildModules, config, lib, ... }:
6− let
7− # Cabal project to build cabal for use in default setups
8− cabal-project = final.buildPackages.haskell-nix.hackage-project {
9− name = "cabal-install";
10− version = "3.2.0.0";
11− compiler-nix-name = config.compiler.nix-name;
12− modules = [{
13− packages.Cabal.patches = [
14− ./patches/Cabal/Cabal-3.0.0.0-drop-pkg-db-check.diff
15− ./patches/Cabal/Cabal-3.0.0.0-no-final-checks.diff
16− ];
17− nonReinstallablePkgs = [ "array" "base" "binary" "bytestring" "containers" "deepseq"
18− "directory" "filepath" "ghc" "ghc-boot" "ghc-boot-th" "ghc-compact"
19− "ghc-heap" "ghc-prim" "ghci" "haskeline" "hpc" "integer-gmp"
20− "libiserv" "mtl" "parsec" "pretty" "process" "rts" "stm"
21− "template-haskell" "terminfo" "text" "time" "transformers" "unix"
22− "xhtml"
23− ];
24− }
25− ];
26− };
27− in {
28− # Override Cabal used for default setup
29− setup-depends = [ cabal-project.hsPkgs.Cabal ];
30− # Allow Cabal to be reinstalled so that custom setups will use a Cabal
31− # built with packages.Cabal.patches
32− nonReinstallablePkgs =
33− [ "rts" "ghc-heap" "ghc-prim" "integer-gmp" "integer-simple" "base"
34− "deepseq" "array" "ghc-boot-th" "pretty" "template-haskell"
35− "ghcjs-prim" "ghcjs-th"
36− ]
37− ++ lib.optionals (!config.reinstallableLibGhc) [
38− "ghc-boot"
39− "ghc" "Win32" "array" "binary" "bytestring" "containers"
40− "directory" "filepath" "ghc-boot" "ghc-compact" "ghc-prim"
41− "hpc"
42− "mtl" "parsec" "process" "text" "time" "transformers"
43− "unix" "xhtml" "terminfo"
44− ];
45− # Include patches for custom setups
46− packages.Cabal.patches = [
47− ./patches/Cabal/Cabal-3.0.0.0-drop-pkg-db-check.diff
48− ./patches/Cabal/Cabal-3.0.0.0-no-final-checks.diff
5+ ({ pkgs, buildModules, config, lib, ... }: {
6+ # Allow Cabal to be reinstalled so that custom setups will use a Cabal
7+ # built with packages.Cabal.patches
8+ nonReinstallablePkgs =
9+ [ "rts" "ghc-heap" "ghc-prim" "integer-gmp" "integer-simple" "base"
10+ "deepseq" "array" "ghc-boot-th" "pretty" "template-haskell"
11+ "ghcjs-prim" "ghcjs-th"
12+ ]
13+ ++ lib.optionals (!config.reinstallableLibGhc) [
14+ "ghc-boot"
15+ "ghc" "Win32" "array" "binary" "bytestring" "containers"
16+ "directory" "filepath" "ghc-boot" "ghc-compact" "ghc-prim"
17+ "hpc"
18+ "mtl" "parsec" "process" "text" "time" "transformers"
19+ "unix" "xhtml" "terminfo"
4920 ];
50− testWrapper = [((final.writeScriptBin "node-wrapper" ''
51− set -euo pipefail
52− exe=$1
53− shift
54− ${final.buildPackages.nodejs}/bin/node $exe $@
55− '') + "/bin/node-wrapper")];
56− }
57− )
21+ # Include patches for custom setups
22+ packages.Cabal.patches = [
23+ ./patches/Cabal/Cabal-3.0.0.0-drop-pkg-db-check.diff
24+ ./patches/Cabal/Cabal-3.0.0.0-no-final-checks.diff
25+ ];
26+ testWrapper = [((final.writeScriptBin "node-wrapper" ''
27+ set -euo pipefail
28+ exe=$1
29+ shift
30+ ${final.buildPackages.nodejs}/bin/node $exe $@
31+ '') + "/bin/node-wrapper")];
32+ })
5833 );
5934 });
6035}
overlays/hackage-quirks.nix+5
@@ -22,6 +22,11 @@ in { haskell-nix = prev.haskell-nix // {
2222 # Version of of cabal-install in hackage is broken for GHC 8.10.1
2323 (lib.optionalAttrs (version == "3.2.0.0") {
2424 packages.cabal-install.src = final.haskell-nix.sources.cabal-32 + "/cabal-install";
25+ # Include patches needed for ghcjs
26+ packages.Cabal.patches = [
27+ ./patches/Cabal/Cabal-3.0.0.0-drop-pkg-db-check.diff
28+ ./patches/Cabal/Cabal-3.0.0.0-no-final-checks.diff
29+ ];
2530 })
2631 ];
2732 };
test/cabal-sublib/cabal-sublib.cabal+2−1
@@ -1,4 +1,4 @@
1−cabal-version: 2.2
1+cabal-version: 3.0
22-- Initial package description 'cabal-simple.cabal' generated by 'cabal
33-- init'. For further documentation, see
44-- http://haskell.org/cabal/users-guide/
@@ -35,6 +35,7 @@ executable cabal-sublib
3535 -- other-extensions:
3636 build-depends: base
3737 , cabal-sublib
38+ , cabal-sublib:slib
3839 , extra
3940 , optparse-applicative
4041 -- hs-source-dirs:
test/cabal-sublib/default.nix+8−1
@@ -10,6 +10,13 @@ let
1010 # haddock: No input file(s)
1111 packages.cabal-sublib.doHaddock = false;
1212 }
13+ # TODO fix plan-to-nix so this is not needed.
14+ # This is a manual work around for `plan-to-nix` not
15+ # handling `build-depends: cabal-sublib:slib` correctly
16+ ({config, ...}: {
17+ packages.cabal-sublib.components.exes.cabal-sublib.depends = [
18+ config.hsPkgs.cabal-sublib.components.sublibs.slib ];
19+ })
1320 ];
1421
1522 # The ./pkgs.nix works for linux & darwin, but not for windows
@@ -55,7 +62,7 @@ in recurseIntoAttrs {
5562
5663 passthru = {
5764 # Used for debugging with nix repl
58− inherit packages;
65+ inherit packages project;
5966 };
6067 };
6168}
test/shell-for/default.nix+6
@@ -24,6 +24,8 @@ let
2424 # they use a nix-shell --pure. Normally you would BYO cabal-install.
2525 tools = { cabal = "3.2.0.0"; };
2626 exactDeps = true;
27+ # Avoid duplicate package issues when runghc looks for packages
28+ packageSetupDeps = false;
2729 };
2830
2931 envPkga = pkgSet.config.hsPkgs.shellFor {
@@ -33,6 +35,8 @@ let
3335 # they use a nix-shell --pure. Normally you would BYO cabal-install.
3436 tools = { cabal = "3.2.0.0"; };
3537 exactDeps = true;
38+ # Avoid duplicate package issues when runghc looks for packages
39+ packageSetupDeps = false;
3640 };
3741
3842 envDefault = pkgSet.config.hsPkgs.shellFor {
@@ -42,6 +46,8 @@ let
4246 # This adds cabal-install to the shell, which helps tests because
4347 # they use a nix-shell --pure. Normally you would BYO cabal-install.
4448 tools = { cabal = "3.2.0.0"; };
49+ # Avoid duplicate package issues when runghc looks for packages
50+ packageSetupDeps = false;
4551 };
4652
4753in recurseIntoAttrs {