Skip to content

Commit 329548e

Browse files
committed
Use unit id for package key
1 parent 1bf543c commit 329548e

File tree

3 files changed

+165
-30
lines changed

3 files changed

+165
-30
lines changed

lib/call-cabal-project-to-nix.nix

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
{ pkgs, runCommand, cacert, index-state-hashes, haskellLib }:
22
{ name ? src.name or null # optional name for better error messages
33
, src
4-
, materialized-dir ? ../materialized
54
, compiler-nix-name # The name of the ghc compiler to use eg. "ghc884"
65
, index-state ? null # Hackage index-state, eg. "2019-10-10T00:00:00Z"
76
, index-sha256 ? null # The hash of the truncated hackage index-state
@@ -538,11 +537,11 @@ let
538537
'';
539538
};
540539

541-
plan-nix = materialize ({
540+
plan-json = materialize ({
542541
inherit materialized;
543542
sha256 = plan-sha256;
544543
sha256Arg = "plan-sha256";
545-
this = "project.plan-nix" + (if name != null then " for ${name}" else "");
544+
this = "project.plan-json" + (if name != null then " for ${name}" else "");
546545
} // pkgs.lib.optionalAttrs (checkMaterialization != null) {
547546
inherit checkMaterialization;
548547
}) (evalPackages.runCommand (nameAndSuffix "plan-to-nix-pkgs") {
@@ -564,7 +563,6 @@ let
564563
# These two output will be present if in cabal configure failed.
565564
# They are used to provide passthru.json and passthru.freeze that
566565
# check first for cabal configure failure.
567-
"json" # The `plan.json` file generated by cabal and used for `plan-to-nix` input
568566
"freeze" # The `cabal.project.freeze` file created by `cabal v2-freeze`
569567
];
570568
} ''
@@ -619,7 +617,7 @@ let
619617
export SSL_CERT_FILE=${cacert}/etc/ssl/certs/ca-bundle.crt
620618
export GIT_SSL_CAINFO=${cacert}/etc/ssl/certs/ca-bundle.crt
621619
622-
CABAL_DIR=${
620+
export CABAL_DIR=${
623621
# This creates `.cabal` directory that is as it would have
624622
# been at the time `cached-index-state`. We may include
625623
# some packages that will be excluded by `index-state-max`
@@ -630,7 +628,9 @@ let
630628
index-state = cached-index-state;
631629
sha256 = index-sha256-found;
632630
}
633-
} make-install-plan ${
631+
}
632+
633+
make-install-plan ${
634634
# Setting the desired `index-state` here in case it is not
635635
# in the cabal.project file. This will further restrict the
636636
# packages used by the solver (cached-index-state >= index-state-max).
@@ -676,29 +676,28 @@ let
676676
# proper relative paths.
677677
(cd $out${subDir'} && plan-to-nix --full ${if ignorePackageYaml then "--ignore-package-yaml" else ""} --plan-json $tmp${subDir'}/dist-newstyle/cache/plan.json -o .)
678678
679+
substituteInPlace $tmp${subDir'}/dist-newstyle/cache/plan.json --replace "$out" ""
680+
substituteInPlace $tmp${subDir'}/dist-newstyle/cache/plan.json --replace "$CABAL_DIR" ""
681+
679682
# Replace the /nix/store paths to minimal git repos with indexes (that will work with materialization).
680683
${fixedProject.replaceLocations}
681684
682-
# Make the plan.json file available in case we need to debug plan-to-nix
683-
cp $tmp${subDir'}/dist-newstyle/cache/plan.json $json
684-
685685
# Remove the non nix files ".project" ".cabal" "package.yaml" files
686686
# as they should not be in the output hash (they may change slightly
687687
# without affecting the nix).
688688
find $out \( -type f -or -type l \) ! -name '*.nix' -delete
689689
690+
# Make the plan.json file available in case we need to debug plan-to-nix
691+
cp $tmp${subDir'}/dist-newstyle/cache/plan.json $out
692+
690693
# Make the revised cabal files available (after the delete step avove)
691694
echo "Moving cabal files from $tmp${subDir'}/dist-newstyle/cabal-files to $out${subDir'}/cabal-files"
692695
mv $tmp${subDir'}/dist-newstyle/cabal-files $out${subDir'}/cabal-files
693696
694697
# Remove empty dirs
695698
find $out -type d -empty -delete
696-
697-
# move pkgs.nix to default.nix ensure we can just nix `import` the result.
698-
mv $out${subDir'}/pkgs.nix $out${subDir'}/default.nix
699699
'');
700700
in {
701-
projectNix = plan-nix;
702-
inherit index-state-max src;
701+
inherit plan-json index-state-max src;
703702
inherit (fixedProject) sourceRepos extra-hackages;
704703
}

overlays/default.nix

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ let
4848
static-nix-tools-for-default-setup = static-nix-tools' ../nix-tools-static-for-default-setup.nix;
4949

5050
# Version of nix-tools built with a pinned version of haskell.nix.
51-
pinned-nix-tools-lib = (import (final.haskell-nix.sources.flake-compat) {
51+
pinned-nix-tools-lib = (import final.haskell-nix.sources.flake-compat {
5252
pkgs = final;
5353
inherit (final) system;
5454
src = ../nix-tools;
@@ -63,7 +63,7 @@ let
6363
prev.haskell-nix // {
6464
inherit (nix-tools-pkgs) nix-tools nix-tools-set;
6565
# either nix-tools from its overlay or from the tarball.
66-
nix-tools-unchecked = static-nix-tools// {
66+
nix-tools-unchecked = static-nix-tools // {
6767
exes = static-nix-tools.exes // {
6868
inherit (static-nix-tools-for-default-setup.exes) default-setup default-setup-ghcjs;
6969
};

overlays/haskell.nix

Lines changed: 150 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -151,17 +151,8 @@ final: prev: {
151151
pkg-def = excludeBootPackages compiler-nix-name plan-pkgs.pkgs;
152152
patchesModule = ghcHackagePatches.${compiler-nix-name'} or {};
153153
package.compiler-nix-name.version = (compilerSelection final.buildPackages).${compiler-nix-name'}.version;
154-
plan.compiler-nix-name.version = (compilerSelection final.buildPackages).${(plan-pkgs.pkgs hackage).compiler.nix-name}.version;
155154
withMsg = final.lib.assertMsg;
156155
in
157-
# Check that the GHC version of the selected compiler matches the one of the plan
158-
assert (withMsg
159-
(package.compiler-nix-name.version
160-
== plan.compiler-nix-name.version)
161-
''
162-
The compiler versions for the package (${package.compiler-nix-name.version}) and the plan (${plan.compiler-nix-name.version}) don't match.
163-
Make sure you didn't forget to update plan-sha256.''
164-
);
165156
mkPkgSet {
166157
inherit pkg-def;
167158
pkg-def-extras = [ plan-pkgs.extras
@@ -653,11 +644,156 @@ final: prev: {
653644
{ config, options, ... }:
654645
let
655646
inherit (config) compiler-nix-name compilerSelection evalPackages;
656-
647+
selectedCompiler = (compilerSelection final.buildPackages).${compiler-nix-name};
648+
649+
plan-json = builtins.fromJSON (builtins.readFile (callProjectResults.plan-json + "/plan.json"));
650+
by-id = final.lib.listToAttrs (map (x: { name = x.id; value = x; }) plan-json.install-plan);
651+
to-key = p: if p.type == "pre-existing"
652+
then p.pkg-name
653+
else p.id;
654+
getComponents = cabal2nixComponents: hsPkgs: p:
655+
let
656+
components = p.components or { ${p.component-name} = { inherit (p) depends exe-depends; }; };
657+
lookupDependency = hsPkgs: d:
658+
if by-id.${d}.component-name or "lib" == "lib"
659+
then hsPkgs.${to-key by-id.${d}}
660+
else hsPkgs.${to-key by-id.${d}}.components.sublibs.${final.lib.removePrefix "lib:" by-id.${d}.component-name};
661+
lookupExeDependency = d:
662+
hsPkgs.pkgsBuildBuild.${to-key by-id.${d}}.components.exes.${final.lib.removePrefix "exe:" by-id.${d}.component-name};
663+
componentsWithPrefix = collectionName: prefix:
664+
final.lib.listToAttrs (final.lib.concatLists (final.lib.mapAttrsToList (n: c:
665+
final.lib.optional (final.lib.hasPrefix "${prefix}:" n) (
666+
let
667+
name = final.lib.removePrefix "${prefix}:" n;
668+
value = (if cabal2nixComponents == null then {} else cabal2nixComponents.${collectionName}.${name}) // {
669+
buildable = true;
670+
depends = map (lookupDependency hsPkgs) c.depends;
671+
build-tools = map lookupExeDependency c.exe-depends;
672+
};
673+
in { inherit name value; }
674+
)) components));
675+
in
676+
final.lib.mapAttrs componentsWithPrefix haskellLib.componentPrefix
677+
// final.lib.optionalAttrs (components ? lib) {
678+
library = (if cabal2nixComponents == null then {} else cabal2nixComponents.library) // {
679+
buildable = true;
680+
depends = map (lookupDependency hsPkgs) components.lib.depends;
681+
build-tools = map lookupExeDependency components.lib.exe-depends;
682+
};
683+
};
657684
callProjectResults = callCabalProjectToNix config;
658-
plan-pkgs = importAndFilterProject {
659-
inherit (callProjectResults) projectNix sourceRepos src;
660-
};
685+
plan-pkgs = if !builtins.pathExists (callProjectResults.plan-json + "/plan.json")
686+
then
687+
# TODO remove this once all the materialized files are updated
688+
importAndFilterProject {
689+
projectNix = callProjectResults.plan-json;
690+
inherit (callProjectResults) sourceRepos src;
691+
}
692+
else {
693+
pkgs = (hackage: {
694+
packages = final.lib.listToAttrs (
695+
final.lib.concatMap (p:
696+
final.lib.optional (p.type == "pre-existing" || (p.type == "configured" && (p.style == "global" || p.style == "inplace") )) {
697+
name = to-key p;
698+
value.revision =
699+
{hsPkgs, ...}@args:
700+
let cabal2nix = (if builtins.pathExists (callProjectResults.plan-json + "/cabal-files/${p.pkg-name}.nix")
701+
then import (callProjectResults.plan-json + "/cabal-files/${p.pkg-name}.nix")
702+
else (((hackage.${p.pkg-name}).${p.pkg-version}).revisions).default) (args // { hsPkgs = {}; });
703+
in cabal2nix // {
704+
flags = p.flags;
705+
components = getComponents cabal2nix.components hsPkgs p;
706+
package = cabal2nix.package // {
707+
setup-depends = map (lookupDependency hsPkgs.pkgsBuildBuild) (p.setup.depends or []);
708+
# TODO = map lookupExeDependency (p.setup.exe-depends or []);
709+
};
710+
};
711+
}) plan-json.install-plan);
712+
compiler = {
713+
inherit (selectedCompiler) version;
714+
};
715+
});
716+
extras = (hackage: {
717+
packages = final.lib.listToAttrs (
718+
final.lib.concatMap (p:
719+
final.lib.optional (p.type == "configured" && p.style == "local") {
720+
name = to-key p;
721+
value =
722+
{hsPkgs, ...}@args:
723+
let cabal2nix = import (callProjectResults.plan-json + "/.plan.nix/${p.pkg-name}.nix") (args // { hsPkgs = {}; });
724+
in builtins.removeAttrs cabal2nix ["src"] // {
725+
flags = p.flags;
726+
components = getComponents cabal2nix.components hsPkgs p;
727+
package = cabal2nix.package // {
728+
setup-depends = map (lookupDependency hsPkgs.pkgsBuildBuild) (p.setup.depends or []);
729+
# TODO = map lookupExeDependency (p.setup.exe-depends or []);
730+
};
731+
};
732+
}) plan-json.install-plan);
733+
});
734+
modules = [{
735+
preExistingPkgs =
736+
final.lib.concatMap (p:
737+
final.lib.optional (p.type == "pre-existing") p.pkg-name) plan-json.install-plan;
738+
}
739+
({lib, ...}: {
740+
packages = final.lib.listToAttrs (map (p:
741+
let components =
742+
if p ? component-name
743+
then { ${p.component-name} = { inherit (p) depends exe-depends; }; }
744+
else p.components or {};
745+
in {
746+
name = to-key p;
747+
value.components = final.lib.mapAttrs (type: x:
748+
if type == "library"
749+
then { planned = lib.mkOverride 900 true; }
750+
else
751+
final.lib.mapAttrs (_: _: {
752+
planned = lib.mkOverride 900 true;
753+
}) x
754+
) (getComponents null hsPkgs p);
755+
}) plan-json.install-plan);
756+
})
757+
({config, ...}: {
758+
hsPkgs = builtins.removeAttrs (builtins.mapAttrs (packageName: packageTargets:
759+
let
760+
byVersion = builtins.groupBy (x: x.pkg-version) packageTargets;
761+
versions = builtins.attrNames byVersion;
762+
in if builtins.length versions != 1
763+
then throw "Multiple versions for ${packageName} ${builtins.toJSON versions}"
764+
else let
765+
components = builtins.listToAttrs (map (x: { name = x.component-name; value = x.available; }) packageTargets);
766+
lookupComponent = collectionName: name: available:
767+
let attrPath =
768+
if collectionName == ""
769+
then "${packageName}.components.library"
770+
else "${packageName}.components.${collectionName}.${name}";
771+
in if builtins.length available != 1
772+
then throw "Multiple avaialble targets for ${attrPath}"
773+
else if builtins.isString (builtins.head available)
774+
then throw "${builtins.head available} looking for ${attrPath}"
775+
else if collectionName == ""
776+
then config.hsPkgs.${(builtins.head available).id}.components.library
777+
else config.hsPkgs.${(builtins.head available).id}.components.${collectionName}.${name};
778+
componentsWithPrefix = collectionName: prefix:
779+
final.lib.listToAttrs (final.lib.concatLists (final.lib.mapAttrsToList (n: available:
780+
final.lib.optional (final.lib.hasPrefix "${prefix}:" n) (
781+
let
782+
name = final.lib.removePrefix "${prefix}:" n;
783+
value = lookupComponent collectionName name available;
784+
in { inherit name value; }
785+
)) components));
786+
in {
787+
components =
788+
final.lib.mapAttrs componentsWithPrefix haskellLib.componentPrefix
789+
// final.lib.optionalAttrs (components ? lib) {
790+
library = lookupComponent "" "" components.lib;
791+
};
792+
})
793+
(builtins.groupBy (x: x.pkg-name) plan-json.targets)) config.preExistingPkgs;
794+
})
795+
];
796+
};
661797
buildProject = if final.stdenv.hostPlatform != final.stdenv.buildPlatform
662798
then final.pkgsBuildBuild.haskell-nix.cabalProject' projectModule
663799
else project;
@@ -682,7 +818,7 @@ final: prev: {
682818
else if config.ghc != null
683819
then config.ghc
684820
else
685-
final.lib.mkDefault (config.compilerSelection final.buildPackages).${compiler-nix-name};
821+
final.lib.mkDefault selectedCompiler;
686822
compiler.nix-name = final.lib.mkForce config.compiler-nix-name;
687823
evalPackages = final.lib.mkDefault evalPackages;
688824
} ];

0 commit comments

Comments
 (0)