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-...`.
This commit is contained in:
Hamish Mackenzie 2021-01-08 23:11:16 +13:00 committed by GitHub
parent f848b47dde
commit 2b7d93baf6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 108 additions and 80 deletions

View File

@ -325,31 +325,43 @@ let
${lib.optionalString (haskellLib.isLibrary componentId) ''
$SETUP_HS register --gen-pkg-config=${name}.conf
${ghc.targetPrefix}ghc-pkg -v0 init $out/package.conf.d
if [ -d "${name}.conf" ]; then
for pkg in ${name}.conf/*; do
${ghc.targetPrefix}ghc-pkg -v0 --package-db ${configFiles}/${configFiles.packageCfgDir} -f $out/package.conf.d register "$pkg"
done
elif [ -e "${name}.conf" ]; then
${ghc.targetPrefix}ghc-pkg -v0 --package-db ${configFiles}/${configFiles.packageCfgDir} -f $out/package.conf.d register ${name}.conf
fi
${ghc.targetPrefix}ghc-pkg -v0 --package-db ${configFiles}/${configFiles.packageCfgDir} -f $out/package.conf.d register ${name}.conf
mkdir -p $out/exactDep
touch $out/exactDep/configure-flags
touch $out/exactDep/cabal.config
touch $out/envDep
if id=$(${target-pkg-and-db} field ${package.identifier.name} id --simple-output); then
echo "--dependency=${package.identifier.name}=$id" >> $out/exactDep/configure-flags
echo "package-id $id" >> $out/envDep
elif id=$(${target-pkg-and-db} field "z-${package.identifier.name}-z-*" id --simple-output); then
name=$(${target-pkg-and-db} field "z-${package.identifier.name}-z-*" name --simple-output)
# so we are dealing with a sublib. As we build sublibs separately, the above
# query should be safe.
echo "--dependency=''${name#z-${package.identifier.name}-z-}=$id" >> $out/exactDep/configure-flags
else
echo 'ERROR: ${package.identifier.name} id could not be found with ${target-pkg-and-db}'
exit 0
fi
${ # The main library in a package has the same name as the package
if package.identifier.name == componentId.cname
then ''
if id=$(${target-pkg-and-db} field ${package.identifier.name} id --simple-output); then
echo "--dependency=${package.identifier.name}=$id" >> $out/exactDep/configure-flags
echo "package-id $id" >> $out/envDep
else
echo 'ERROR: ${package.identifier.name} id could not be found with ${target-pkg-and-db}'
exit 0
fi
''
else
# If the component name is not the package name this must be a sublib.
# As we build sublibs separately, the following query should be safe.
(''
if id=$(${target-pkg-and-db} field "z-${package.identifier.name}-z-*" id --simple-output); then
name=$(${target-pkg-and-db} field "z-${package.identifier.name}-z-*" name --simple-output)
echo "--dependency=''${name#z-${package.identifier.name}-z-}=$id" >> $out/exactDep/configure-flags
''
# Allow `package-name:sublib-name` to work in `build-depends`
# by adding the same `--dependency` again, but with the package
# name added.
+ ''
echo "--dependency=${package.identifier.name}:''${name#z-${package.identifier.name}-z-}=$id" >> $out/exactDep/configure-flags
else
echo 'ERROR: ${package.identifier.name} id could not be found with ${target-pkg-and-db}'
exit 0
fi
'')
}
if ver=$(${target-pkg-and-db} field ${package.identifier.name} version --simple-output); then
echo "constraint: ${package.identifier.name} == $ver" >> $out/exactDep/cabal.config
echo "constraint: ${package.identifier.name} installed" >> $out/exactDep/cabal.config
@ -372,21 +384,23 @@ let
'')
# In case `setup copy` did not create this
+ (lib.optionalString enableSeparateDataOutput "mkdir -p $data")
+ (lib.optionalString (stdenv.hostPlatform.isWindows && (haskellLib.mayHaveExecutable componentId)) ''
+ (lib.optionalString (stdenv.hostPlatform.isWindows && (haskellLib.mayHaveExecutable componentId)) (''
echo "Symlink libffi and gmp .dlls ..."
for p in ${lib.concatStringsSep " " [ libffi gmp ]}; do
find "$p" -iname '*.dll' -exec ln -s {} $out/bin \;
done
''
# symlink all .dlls into the local directory.
# we ask ghc-pkg for *all* dynamic-library-dirs and then iterate over the unique set
# to symlink over dlls as needed.
+ ''
echo "Symlink library dependencies..."
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
if [ -d "$libdir" ]; then
find "$libdir" -iname '*.dll' -exec ln -s {} $out/bin \;
fi
done
'')
''))
+ (lib.optionalString doCoverage ''
mkdir -p $out/share
cp -r dist/hpc $out/share

View File

@ -1,4 +1,4 @@
{ pkgs, buildPackages, stdenv, lib, haskellLib, ghc, fetchurl, pkgconfig, nonReinstallablePkgs, hsPkgs, compiler }:
{ pkgs, buildPackages, stdenv, lib, haskellLib, ghc, compiler-nix-name, fetchurl, pkgconfig, nonReinstallablePkgs, hsPkgs, compiler }:
let
# Builds a single component of a package.
@ -75,7 +75,7 @@ in {
# Build a Haskell package from its config.
# TODO: this pkgs is the adjusted pkgs, but pkgs.pkgs is unadjusted
build-package = haskellLib.weakCallPackage pkgs ./hspkg-builder.nix {
inherit haskellLib ghc comp-builder setup-builder;
inherit haskellLib ghc compiler-nix-name comp-builder setup-builder;
};
inherit shellFor makeConfigFiles;

View File

@ -1,4 +1,4 @@
{ pkgs, buildPackages, stdenv, lib, haskellLib, ghc, fetchurl, runCommand, comp-builder, setup-builder }:
{ pkgs, buildPackages, stdenv, lib, haskellLib, ghc, compiler-nix-name, fetchurl, runCommand, comp-builder, setup-builder }:
config:
{ flags
@ -34,10 +34,27 @@ let
import Distribution.Simple
main = defaultMain
'';
# Get the Cabal lib used to build `cabal-install`.
# To avoid infinite recursion we have to leave this out for packages
# needed to build `cabal-install`.
# We always do this for ghcjs as the patched version of Cabal is needed.
cabalLibDepends = lib.optional (
stdenv.hostPlatform.isGhcjs || (
builtins.elem compiler-nix-name["ghc865" "ghc884"]
&&
!builtins.elem package.identifier.name
["nix-tools" "alex" "happy" "hscolour" "Cabal" "bytestring" "aeson" "time"
"filepath" "base-compat-batteries" "base-compat" "unix" "directory" "transformers"
"containers" "binary" "mtl" "text" "process" "parsec"]
)
)
buildPackages.haskell-nix.cabal-install-unchecked.${compiler-nix-name}.project.hsPkgs.Cabal.components.library;
defaultSetup = setup-builder {
name = "${ghc.targetPrefix}default-Setup";
component = {
depends = config.setup-depends;
depends = config.setup-depends ++ cabalLibDepends;
libs = [];
frameworks = [];
doExactConfig = false;

View File

@ -15,6 +15,7 @@
, withHoogle ? true
, exactDeps ? false
, tools ? {}
, packageSetupDeps ? true
, ... } @ args:
let
@ -26,7 +27,8 @@ let
selectedComponents = components hsPkgs;
# The configs of all the selected components
selectedConfigs = map (c: c.config) selectedComponents ++ map (p: p.setup.config) selectedPackages;
selectedConfigs = map (c: c.config) selectedComponents
++ lib.optionals packageSetupDeps (map (p: p.setup.config) selectedPackages);
name = if lib.length selectedPackages == 1
then "ghc-shell-for-${(lib.head selectedPackages).identifier.name}"

View File

@ -3,6 +3,7 @@ let
builder = haskellLib.weakCallPackage pkgs ../builder {
inherit haskellLib;
ghc = config.ghc.package;
compiler-nix-name = config.compiler.nix-name;
inherit (config) nonReinstallablePkgs hsPkgs compiler;
};

View File

@ -2,59 +2,34 @@ final: prev:
{
haskell-nix = prev.haskell-nix // ({
defaultModules = prev.haskell-nix.defaultModules ++ final.lib.optional final.stdenv.hostPlatform.isGhcjs (
({ pkgs, buildModules, config, lib, ... }:
let
# Cabal project to build cabal for use in default setups
cabal-project = final.buildPackages.haskell-nix.hackage-project {
name = "cabal-install";
version = "3.2.0.0";
compiler-nix-name = config.compiler.nix-name;
modules = [{
packages.Cabal.patches = [
./patches/Cabal/Cabal-3.0.0.0-drop-pkg-db-check.diff
./patches/Cabal/Cabal-3.0.0.0-no-final-checks.diff
];
nonReinstallablePkgs = [ "array" "base" "binary" "bytestring" "containers" "deepseq"
"directory" "filepath" "ghc" "ghc-boot" "ghc-boot-th" "ghc-compact"
"ghc-heap" "ghc-prim" "ghci" "haskeline" "hpc" "integer-gmp"
"libiserv" "mtl" "parsec" "pretty" "process" "rts" "stm"
"template-haskell" "terminfo" "text" "time" "transformers" "unix"
"xhtml"
];
}
];
};
in {
# Override Cabal used for default setup
setup-depends = [ cabal-project.hsPkgs.Cabal ];
# Allow Cabal to be reinstalled so that custom setups will use a Cabal
# built with packages.Cabal.patches
nonReinstallablePkgs =
[ "rts" "ghc-heap" "ghc-prim" "integer-gmp" "integer-simple" "base"
"deepseq" "array" "ghc-boot-th" "pretty" "template-haskell"
"ghcjs-prim" "ghcjs-th"
]
++ lib.optionals (!config.reinstallableLibGhc) [
"ghc-boot"
"ghc" "Win32" "array" "binary" "bytestring" "containers"
"directory" "filepath" "ghc-boot" "ghc-compact" "ghc-prim"
"hpc"
"mtl" "parsec" "process" "text" "time" "transformers"
"unix" "xhtml" "terminfo"
];
# Include patches for custom setups
packages.Cabal.patches = [
./patches/Cabal/Cabal-3.0.0.0-drop-pkg-db-check.diff
./patches/Cabal/Cabal-3.0.0.0-no-final-checks.diff
({ pkgs, buildModules, config, lib, ... }: {
# Allow Cabal to be reinstalled so that custom setups will use a Cabal
# built with packages.Cabal.patches
nonReinstallablePkgs =
[ "rts" "ghc-heap" "ghc-prim" "integer-gmp" "integer-simple" "base"
"deepseq" "array" "ghc-boot-th" "pretty" "template-haskell"
"ghcjs-prim" "ghcjs-th"
]
++ lib.optionals (!config.reinstallableLibGhc) [
"ghc-boot"
"ghc" "Win32" "array" "binary" "bytestring" "containers"
"directory" "filepath" "ghc-boot" "ghc-compact" "ghc-prim"
"hpc"
"mtl" "parsec" "process" "text" "time" "transformers"
"unix" "xhtml" "terminfo"
];
testWrapper = [((final.writeScriptBin "node-wrapper" ''
set -euo pipefail
exe=$1
shift
${final.buildPackages.nodejs}/bin/node $exe $@
'') + "/bin/node-wrapper")];
}
)
# Include patches for custom setups
packages.Cabal.patches = [
./patches/Cabal/Cabal-3.0.0.0-drop-pkg-db-check.diff
./patches/Cabal/Cabal-3.0.0.0-no-final-checks.diff
];
testWrapper = [((final.writeScriptBin "node-wrapper" ''
set -euo pipefail
exe=$1
shift
${final.buildPackages.nodejs}/bin/node $exe $@
'') + "/bin/node-wrapper")];
})
);
});
}

View File

@ -22,6 +22,11 @@ in { haskell-nix = prev.haskell-nix // {
# Version of of cabal-install in hackage is broken for GHC 8.10.1
(lib.optionalAttrs (version == "3.2.0.0") {
packages.cabal-install.src = final.haskell-nix.sources.cabal-32 + "/cabal-install";
# Include patches needed for ghcjs
packages.Cabal.patches = [
./patches/Cabal/Cabal-3.0.0.0-drop-pkg-db-check.diff
./patches/Cabal/Cabal-3.0.0.0-no-final-checks.diff
];
})
];
};

View File

@ -1,4 +1,4 @@
cabal-version: 2.2
cabal-version: 3.0
-- Initial package description 'cabal-simple.cabal' generated by 'cabal
-- init'. For further documentation, see
-- http://haskell.org/cabal/users-guide/
@ -35,6 +35,7 @@ executable cabal-sublib
-- other-extensions:
build-depends: base
, cabal-sublib
, cabal-sublib:slib
, extra
, optparse-applicative
-- hs-source-dirs:

View File

@ -10,6 +10,13 @@ let
# haddock: No input file(s)
packages.cabal-sublib.doHaddock = false;
}
# TODO fix plan-to-nix so this is not needed.
# This is a manual work around for `plan-to-nix` not
# handling `build-depends: cabal-sublib:slib` correctly
({config, ...}: {
packages.cabal-sublib.components.exes.cabal-sublib.depends = [
config.hsPkgs.cabal-sublib.components.sublibs.slib ];
})
];
# The ./pkgs.nix works for linux & darwin, but not for windows
@ -55,7 +62,7 @@ in recurseIntoAttrs {
passthru = {
# Used for debugging with nix repl
inherit packages;
inherit packages project;
};
};
}

View File

@ -24,6 +24,8 @@ let
# they use a nix-shell --pure. Normally you would BYO cabal-install.
tools = { cabal = "3.2.0.0"; };
exactDeps = true;
# Avoid duplicate package issues when runghc looks for packages
packageSetupDeps = false;
};
envPkga = pkgSet.config.hsPkgs.shellFor {
@ -33,6 +35,8 @@ let
# they use a nix-shell --pure. Normally you would BYO cabal-install.
tools = { cabal = "3.2.0.0"; };
exactDeps = true;
# Avoid duplicate package issues when runghc looks for packages
packageSetupDeps = false;
};
envDefault = pkgSet.config.hsPkgs.shellFor {
@ -42,6 +46,8 @@ let
# This adds cabal-install to the shell, which helps tests because
# they use a nix-shell --pure. Normally you would BYO cabal-install.
tools = { cabal = "3.2.0.0"; };
# Avoid duplicate package issues when runghc looks for packages
packageSetupDeps = false;
};
in recurseIntoAttrs {