Skip to content

Commit 29f4a95

Browse files
Try #1145:
2 parents f279cde + 98bb35e commit 29f4a95

File tree

1 file changed

+40
-20
lines changed

1 file changed

+40
-20
lines changed

builder/shell-for.nix

Lines changed: 40 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -25,39 +25,59 @@ let
2525

2626
selectedPackages = packages hsPkgs;
2727
additionalPackages = additional hsPkgs;
28-
selectedComponents = components hsPkgs;
28+
directlySelectedComponents = components hsPkgs;
2929

30-
# The configs of all the selected components
31-
selectedConfigs = map (c: c.config) selectedComponents
32-
++ lib.optionals packageSetupDeps (map (p: p.setup.config) selectedPackages);
33-
34-
name = if lib.length selectedPackages == 1
35-
then "ghc-shell-for-${(lib.head selectedPackages).identifier.name}"
36-
else "ghc-shell-for-packages";
37-
38-
# Given a `packages = [ a b ]` we construct a shell with the dependencies of `a` and `b`.
30+
# Given `directlySelectedComponents = [ a b ]`, we construct a shell that includes all of their dependencies
3931
#
40-
# But if `a` depends on `b`, we don't want to include `b`, because
32+
# But we want to exclude `a` if it is a transitive dependecy of `b`
33+
# because:
4134
# - cabal will end up ignoring that built version;
4235
# - The user has indicated that's what they're working on, so they probably don't want to have to build
4336
# it first (and it will change often).
44-
# Generally we never want to include any of (the components of) the selected packages as dependencies.
37+
# Generally we never want to include any of `directlySelectedComponents` as dependencies.
38+
#
39+
# We do this by defining a set of `selectedComponents`, where `x` is in `selectedComponents` if and only if:
40+
# - `x` is in `directlySelectedComponents`
41+
# - `x` is a transitive dependency of something in `directlySelectedComponents`
42+
# and `x` transitively depends on something in `directlySelectedComponents`
43+
# We use the dependencies of `selectedComponents` filtering out members of `selectedComponents`
4544
#
4645
# Furthermore, if `a` depends on `b`, `a` will include the library component of `b` in its `buildInputs`
4746
# (to make `propagatedBuildInputs` of `pkgconfig-depends` work). So we also need to filter those
4847
# (the pkgconfig depends of `b` will still be included in the
4948
# system shell's `buildInputs` via `b`'s own `buildInputs`).
50-
# We have to do this slightly differently because we will be looking at the actual components rather
51-
# than the packages.
5249

53-
# Given a list of `depends`, removes those which are components of packages which were selected as part of the shell.
50+
51+
# all packages that are indirectly depended on by `directlySelectedComponents`
52+
# including `directlySelectedComponents`
53+
transitiveDependenciesComponents =
54+
builtins.listToAttrs
55+
(builtins.map (x: lib.nameValuePair (x.name) x)
56+
(haskellLib.flatLibDepends {depends = directlySelectedComponents;}));
57+
58+
selectedComponentsBitmap =
59+
lib.mapAttrs
60+
(_: x: (builtins.any
61+
(dep: selectedComponentsBitmap."${(haskellLib.dependToLib dep).name}") x.config.depends))
62+
transitiveDependenciesComponents
63+
// builtins.listToAttrs (map (x: lib.nameValuePair x.name true) directlySelectedComponents); # base case
64+
65+
selectedComponents =
66+
lib.filter (x: selectedComponentsBitmap."${x.name}") (lib.attrValues transitiveDependenciesComponents);
67+
68+
# Given a list of `depends`, removes those which are selected components
5469
removeSelectedInputs =
55-
# All the components of the selected packages: we shouldn't add any of these as dependencies
56-
let selectedPackageComponents = map (x: x.name) selectedComponents;
57-
in lib.filter (input:
58-
!(builtins.elem ((haskellLib.dependToLib input).name or null) selectedPackageComponents));
70+
lib.filter (input: !(selectedComponentsBitmap."${((haskellLib.dependToLib input).name or null)}" or false));
71+
72+
# The configs of all the selected components
73+
selectedConfigs = map (c: c.config) selectedComponents
74+
++ lib.optionals packageSetupDeps (map (p: p.setup.config) selectedPackages);
75+
76+
name = if lib.length selectedPackages == 1
77+
then "ghc-shell-for-${(lib.head selectedPackages).identifier.name}"
78+
else "ghc-shell-for-packages";
5979

60-
# We need to remove any dependencies which are selected packages (see above).
80+
# We need to remove any dependencies which would bring in selected components (see above).
6181
packageInputs = removeSelectedInputs (lib.concatMap (cfg: cfg.depends) selectedConfigs)
6282
++ additionalPackages;
6383

0 commit comments

Comments
 (0)