Skip to content

Commit 40b8bf0

Browse files
committed
Build nonReinstallablePkgs from pre-existing packages in plan.json (input-output-hk#2207)
1 parent 20ce0f0 commit 40b8bf0

File tree

5 files changed

+78
-6
lines changed

5 files changed

+78
-6
lines changed

changelog.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,47 @@
11
This file contains a summary of changes to Haskell.nix and `nix-tools`
22
that will impact users.
33

4+
## Jun 5, 2024
5+
6+
Haskell.nix now respects the `pre-existing` packages selected
7+
by the cabal planner. The selection made by the planner
8+
is used to set `nonReinstallablePkgs`.
9+
10+
Instead setting `nonReinstallablePkgs` and `reinstallableLibGhc`
11+
haskell.nix projects should add `constraints` to the cabal project.
12+
13+
For instance to force the use of the `pre-exising` `text`
14+
package add:
15+
16+
```
17+
constraints: text installed
18+
```
19+
20+
To make sure `text` is reinstalled use:
21+
22+
```
23+
constraints: text source
24+
```
25+
26+
The `pre-existing` `ghc` will now be used by default as
27+
that is what `cabal` will choose (haskell.nix used to choose
28+
`reinstallableLibGhc=true` by default).
29+
30+
To allow cabal to choose reinstalling `ghc` add:
31+
32+
```
33+
allow-boot-library-installs: True
34+
```
35+
36+
To force cabal to choose reinstalling:
37+
38+
```
39+
constraints: ghc source
40+
allow-boot-library-installs: True
41+
```
42+
43+
It may also need `allow-newer: ghc:Cabal`
44+
445
## Mar 27, 2023
546

647
Haskell.nix will no longer parse the `cabal.project` file to

lib/default.nix

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,19 @@ in {
335335

336336
# Converts from a `compoent.depends` value to a library derivation.
337337
# In the case of sublibs the `depends` value should already be the derivation.
338-
dependToLib = d: d.components.library or d;
338+
dependToLib = d:
339+
# Do simplify this to `d.components.library or d`, as that
340+
# will not give a good error message if the `.library`
341+
# is missing (happens if the package is unplanned,
342+
# but has overrides).
343+
# It would be nice to put an `assert` here, but there is
344+
# currently no good way to get the name of the dependency
345+
# when it is not in the plan. The attribute path of
346+
# `d` in the `nix` error should include the name
347+
# eg. `packages.Cabal.components.library`.
348+
if d ? components
349+
then d.components.library
350+
else d;
339351

340352
projectOverlays = import ./project-overlays.nix {
341353
inherit lib haskellLib;

modules/component-driver.nix

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ let
1010
in
1111

1212
{
13+
# Packages in that are `pre-existing` in the cabal plan
14+
options.preExistingPkgs = lib.mkOption {
15+
type = lib.types.listOf lib.types.str;
16+
default = [];
17+
};
1318
# This has a slightly modified option type. We will *overwrite* any previous
1419
# setting of nonRelocatablePkgs, instead of merging them. Otherwise you
1520
# have no chance of removing packages retroactively. We might improve this
@@ -53,7 +58,11 @@ in
5358
#
5459
# without reinstallable-lib:ghc, this is significantly larger.
5560

56-
config.nonReinstallablePkgs =
61+
config.nonReinstallablePkgs = if config.preExistingPkgs != []
62+
then ["rts"] ++ config.preExistingPkgs
63+
++ lib.optionals (builtins.compareVersions config.compiler.version "8.11" < 0 && pkgs.stdenv.hostPlatform.isGhcjs) [
64+
"ghcjs-prim" "ghcjs-th"]
65+
else
5766
[ "rts" "ghc-prim" "integer-gmp" "integer-simple" "base"
5867
"array"
5968
"ghc-boot-th" "template-haskell"

nix-tools/nix-tools/plan2nix/Plan2Nix.hs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ plan2nix args Plan { packages, extras, components, compilerVersion, compilerPack
8585
-- called from the toplevel project directory.
8686
cwd <- getCurrentDirectory
8787
extrasNix <- fmap (mkNonRecSet . concat) . forM (Map.toList extras) $ \case
88-
(_name, Just (Package v flags (Just (LocalPath folder)) False)) ->
88+
(_name, Just (Package v flags (Just (LocalPath folder)) False _)) ->
8989
do cabalFiles <- findCabalFiles (argHpackUse args) folder
9090
forM cabalFiles $ \cabalFile ->
9191
let pkg = cabalFilePkgName cabalFile
@@ -95,7 +95,7 @@ plan2nix args Plan { packages, extras, components, compilerVersion, compilerPack
9595
in do createDirectoryIfMissing True (takeDirectory nixFile)
9696
writeDoc nixFile . prettyNix =<< cabal2nix True (argDetailLevel args) src cabalFile
9797
return $ fromString pkg $= mkPath False nix
98-
(_name, Just (Package v flags (Just (DVCS (Git url rev) subdirs)) False)) ->
98+
(_name, Just (Package v flags (Just (DVCS (Git url rev) subdirs)) False _)) ->
9999
fmap concat . forM subdirs $ \subdir ->
100100
do cacheHits <- liftIO $ cacheHits (argCacheFile args) url rev subdir
101101
case cacheHits of
@@ -109,11 +109,14 @@ plan2nix args Plan { packages, extras, components, compilerVersion, compilerPack
109109
return $ fromString pkg $= mkPath False nix
110110
_ -> return []
111111
let flags = concatMap (\case
112-
(name, Just (Package _v f _hasDescriptionOverride _)) -> flags2nix name f
112+
(name, Just (Package _v f _hasDescriptionOverride _ _)) -> flags2nix name f
113113
_ -> []) $ Map.toList extras
114114
-- Set the `planned` option for all components in the plan.
115115
planned = map (\name -> name <> ".planned" $=
116116
("lib" @. "mkOverride" @@ mkInt 900 @@ mkBool True)) $ Set.toList components
117+
preExisting = concatMap (\case
118+
(name, Just (Package _ _ _ _ True)) -> [mkStr name]
119+
_ -> []) $ Map.toList packages
117120

118121
return $ mkNonRecSet [
119122
"pkgs" $= ("hackage" ==> mkNonRecSet
@@ -126,7 +129,10 @@ plan2nix args Plan { packages, extras, components, compilerVersion, compilerPack
126129
])
127130
, "extras" $= ("hackage" ==> mkNonRecSet [ "packages" $= extrasNix ])
128131
, "modules" $= mkList [
129-
mkParamset [("lib", Nothing)] True ==> mkNonRecSet [ "packages" $= mkNonRecSet flags ]
132+
mkNonRecSet [
133+
"preExistingPkgs" $= mkList preExisting
134+
]
135+
, mkParamset [("lib", Nothing)] True ==> mkNonRecSet [ "packages" $= mkNonRecSet flags ]
130136
, mkParamset [("lib", Nothing)] True ==> mkNonRecSet [ "packages" $= mkNonRecSet planned ]
131137
]
132138
]
@@ -200,6 +206,7 @@ value2plan plan = Plan { packages, components, extras, compilerVersion, compiler
200206
. KeyMap.toList $ KeyMap.mapMaybe (^? _Bool) $ pkg ^. key "flags" . _Object
201207
, packageSrc = Nothing
202208
, packageHasDescriptionOverride = isJust (pkg ^? key "pkg-cabal-sha256")
209+
, packagePreExisting = False
203210
}
204211

205212
(_, "inplace") -> Just $ Package
@@ -208,6 +215,7 @@ value2plan plan = Plan { packages, components, extras, compilerVersion, compiler
208215
. KeyMap.toList $ KeyMap.mapMaybe (^? _Bool) $ pkg ^. key "flags" . _Object
209216
, packageSrc = Nothing
210217
, packageHasDescriptionOverride = isJust (pkg ^? key "pkg-cabal-sha256")
218+
, packagePreExisting = False
211219
}
212220
-- Until we figure out how to force Cabal to reconfigure just about any package
213221
-- this here might be needed, so that we get the pre-existing packages as well.
@@ -220,6 +228,7 @@ value2plan plan = Plan { packages, components, extras, compilerVersion, compiler
220228
, packageFlags = Map.empty
221229
, packageSrc = Nothing
222230
, packageHasDescriptionOverride = isJust (pkg ^? key "pkg-cabal-sha256") -- likely this is always false
231+
, packagePreExisting = True
223232
}
224233
_ -> Nothing
225234

nix-tools/nix-tools/plan2nix/Plan2Nix/Plan.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,5 @@ data Package = Package
4747
, packageFlags :: HashMap VarName Bool
4848
, packageSrc :: Maybe PkgSrc
4949
, packageHasDescriptionOverride :: Bool
50+
, packagePreExisting :: Bool
5051
} deriving (Show)

0 commit comments

Comments
 (0)