Skip to content

Commit a1921f5

Browse files
authored
Fix "bash: Argument list too long" (input-output-hk#1937)
This change avoids duplicates in propagatedBuildInputs it uses `checkUnique` to enforce uniqueness at the top level and `uniqueWithName` fix places where duplicates might arise. For instance: * `packageInputs` in `shell-for.nix` gave rise to duplicates when the shell was for building more than one component (and they shared dependencies). * `libDeps` in `make-config-files.nix` would include duplicates if a `build-dependency` was repeated in a `.cabal` files (Cabal 3.8.1.0 includes two references to `process`). It should also remove duplicate `framework` `lib` and `pkgconfig-depends`. Fixes input-output-hk#1933
1 parent 0540d74 commit a1921f5

File tree

5 files changed

+38
-26
lines changed

5 files changed

+38
-26
lines changed

builder/comp-builder.nix

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -376,21 +376,21 @@ let
376376
mainProgram = exeName;
377377
};
378378

379-
propagatedBuildInputs =
380-
frameworks # Frameworks will be needed at link time
379+
propagatedBuildInputs = haskellLib.checkUnique "${ghc.targetPrefix}${fullName} propagatedBuildInputs" (
380+
haskellLib.uniqueWithName frameworks # Frameworks will be needed at link time
381381
# Not sure why pkgconfig needs to be propagatedBuildInputs but
382382
# for gi-gtk-hs it seems to help.
383-
++ map pkgs.lib.getDev (builtins.concatLists pkgconfig)
383+
++ haskellLib.uniqueWithName (map pkgs.lib.getDev (builtins.concatLists pkgconfig))
384384
# These only need to be propagated for library components (otherwise they
385385
# will be in `buildInputs`)
386-
++ lib.optionals (haskellLib.isLibrary componentId) configFiles.libDeps
386+
++ lib.optionals (haskellLib.isLibrary componentId) configFiles.libDeps # libDeps is already deduplicated
387387
++ lib.optionals (stdenv.hostPlatform.isWindows)
388-
(lib.flatten component.libs);
388+
(haskellLib.uniqueWithName (lib.flatten component.libs)));
389389

390-
buildInputs =
391-
lib.optionals (!haskellLib.isLibrary componentId) configFiles.libDeps
390+
buildInputs = haskellLib.checkUnique "${ghc.targetPrefix}${fullName} buildInputs" (
391+
lib.optionals (!haskellLib.isLibrary componentId) configFiles.libDeps # libDeps is already deduplicated
392392
++ lib.optionals (!stdenv.hostPlatform.isWindows)
393-
(lib.flatten component.libs);
393+
(haskellLib.uniqueWithName (lib.flatten component.libs)));
394394

395395
nativeBuildInputs =
396396
[ghc buildPackages.removeReferencesTo]

builder/haddock-builder.nix

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,11 @@ let
7272
outputs = ["out" "configFiles" "ghc"]
7373
++ lib.optional doHaddock' "doc";
7474

75-
propagatedBuildInputs =
76-
builtins.concatLists pkgconfig
77-
++ configFiles.libDeps;
75+
propagatedBuildInputs = haskellLib.checkUnique "${fullName} propagatedBuildInputs" (
76+
haskellLib.uniqueWithName (map lib.getDev (builtins.concatLists pkgconfig))
77+
++ configFiles.libDeps); # libDeps is already deduplicated
7878

79-
buildInputs = component.libs;
79+
buildInputs = haskellLib.uniqueWithName (lib.flatten component.libs);
8080

8181
nativeBuildInputs =
8282
[ ghc buildPackages.removeReferencesTo ]

builder/make-config-files.nix

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,12 @@ let
5151
libDir = ghc.libDir or "lib/${ghcCommand}-${ghc.version}";
5252
packageCfgDir = "${libDir}/package.conf.d";
5353

54-
libDeps = map chooseDrv (
55-
(if enableDWARF then (x: map (p: p.dwarf or p) x) else x: x)
56-
((if needsProfiling then (x: map (p: p.profiled or p) x) else x: x)
57-
(map haskellLib.dependToLib component.depends))
54+
libDeps = haskellLib.uniqueWithName (
55+
map chooseDrv (
56+
(if enableDWARF then (x: map (p: p.dwarf or p) x) else x: x)
57+
((if needsProfiling then (x: map (p: p.profiled or p) x) else x: x)
58+
(map haskellLib.dependToLib component.depends))
59+
)
5860
);
5961
script = ''
6062
${target-pkg} init $configFiles/${packageCfgDir}

builder/shell-for.nix

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,9 @@ let
8888
name = if (mkDrvArgs.name or null) == null then identifierName else mkDrvArgs.name;
8989

9090
# We need to remove any dependencies which would bring in selected components (see above).
91-
packageInputs = removeSelectedInputs (lib.concatMap (cfg: cfg.depends) selectedConfigs)
92-
++ additionalPackages;
91+
packageInputs = haskellLib.uniqueWithName
92+
(removeSelectedInputs (haskellLib.uniqueWithName (lib.concatMap (cfg: cfg.depends) selectedConfigs))
93+
++ additionalPackages);
9394

9495
# Add the system libraries and build tools of the selected haskell packages to the shell.
9596
# We need to remove any inputs which are selected components (see above).
@@ -98,17 +99,11 @@ let
9899
#
99100
# Also, we take care to keep duplicates out of the list, otherwise we may see
100101
# "Argument list too long" errors from bash when entering a shell.
101-
#
102-
# Version of `lib.unique` that should be fast if the name attributes are unique
103-
uniqueWithName = list:
104-
lib.concatMap lib.unique (
105-
builtins.attrValues (
106-
builtins.groupBy (x: if __typeOf x == "set" then x.name or "noname" else "notset") list));
107102
allSystemInputs = lib.concatMap (c: c.buildInputs ++ c.propagatedBuildInputs) selectedComponents;
108-
systemInputs = removeSelectedInputs (uniqueWithName allSystemInputs);
103+
systemInputs = removeSelectedInputs (haskellLib.uniqueWithName allSystemInputs);
109104

110105
nativeBuildInputs = removeSelectedInputs
111-
(uniqueWithName (lib.concatMap (c: c.executableToolDepends)
106+
(haskellLib.uniqueWithName (lib.concatMap (c: c.executableToolDepends)
112107
# When not using `exactDeps` cabal may try to build arbitrary dependencies
113108
# so in this case we need to provide the build tools for all of `hsPkgs`.
114109
# In some cases those tools may be unwanted or broken so the `allToolDeps`

lib/default.nix

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,4 +588,19 @@ in {
588588

589589
# How to run ldd when checking for static linking
590590
lddForTests = "${pkgs.pkgsBuildBuild.glibc.bin}/bin/ldd";
591+
592+
# Version of `lib.unique` that should be fast if the name attributes are unique
593+
uniqueWithName = list:
594+
lib.concatMap lib.unique (
595+
builtins.attrValues (
596+
builtins.groupBy (x: if __typeOf x == "set" then x.name or "noname" else "notset") list));
597+
598+
# Assert that each item in the list is unique
599+
checkUnique = msg: x:
600+
if __length x == __length (uniqueWithName x)
601+
then x
602+
else builtins.throw "Duplicate items found in ${msg} ${
603+
__toJSON (__attrNames (lib.filterAttrs (_: v: __length v > 1) (
604+
builtins.groupBy (x: if __typeOf x == "set" then x.name or "noname" else "notset") x)))
605+
}";
591606
}

0 commit comments

Comments
 (0)