Skip to content

Commit 0bd8ca6

Browse files
TeofilCmpickering
andcommitted
Support getting nonreinstallable units from GHC
cabal-install includes a hardcoded list of non-reinstallable packages. cabal-install will refuse to use a different version of these packages in a build plan unless the --allow-boot-library-installs flag is set. This list of packages is too pessimistic, and needlessly coupled to GHC. For instance, as of GHC-9.12, `base` and `template-haskell` can be "re-installed" without issue. This patch allows compilers to specify exactly which packages are wired-in and so should not be reinstalled. In the case of GHC-9.14+, this amounts to ghc-internal and ghc itself. If a compiler chooses to specify this information then it overrides the hardcoded non-reinstallable package list. Otherwise, it is still used for the sake of backwards compatibility. Note that this information comes in the form of unit-ids rather than package names. This patch extends the solver with constraints that force the use of a precise unit-id. The behaviour here is still somewhat pessimistic. In the future, we could further relax this restriction and only ban reinstalling these packafes when absolutely necessary, eg, only ban re-installing `ghc` if we are using plugins, etc. For the GHC change that added the interface to expose the unit-id of ghc-internal, see: https://gitlab.haskell.org/ghc/ghc/-/merge_requests/13297 Resolves #10087 Co-Authored-By: Matthew Pickering <matthewtpickering@gmail.com>
1 parent 01217ac commit 0bd8ca6

File tree

14 files changed

+74
-5
lines changed

14 files changed

+74
-5
lines changed

Cabal-syntax/src/Distribution/Compiler.hs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,10 @@ import Language.Haskell.Extension
5656
import Distribution.Version (Version, mkVersion', nullVersion)
5757

5858
import qualified Distribution.Compat.CharParsing as P
59+
import Distribution.Package (PackageName)
5960
import Distribution.Parsec (Parsec (..))
6061
import Distribution.Pretty (Pretty (..), prettyShow)
62+
import Distribution.Types.UnitId (UnitId)
6163
import qualified System.Info (compilerName, compilerVersion)
6264
import qualified Text.PrettyPrint as Disp
6365

@@ -213,6 +215,11 @@ data CompilerInfo = CompilerInfo
213215
-- ^ Supported language standards, if known.
214216
, compilerInfoExtensions :: Maybe [Extension]
215217
-- ^ Supported extensions, if known.
218+
, compilerInfoWiredInUnitIds :: Maybe [(PackageName, UnitId)]
219+
-- ^ 'UnitId's that the compiler doesn't support reinstalling.
220+
-- For instance, when using GHC plugins, one wants to use the
221+
-- exact same version of the `ghc` package as the one the
222+
-- compiler was linked against.
216223
}
217224
deriving (Generic, Show, Read)
218225

@@ -244,4 +251,4 @@ abiTagString (AbiTag tag) = tag
244251
-- compiler id's.
245252
unknownCompilerInfo :: CompilerId -> AbiTag -> CompilerInfo
246253
unknownCompilerInfo compilerId abiTag =
247-
CompilerInfo compilerId abiTag (Just []) Nothing Nothing
254+
CompilerInfo compilerId abiTag (Just []) Nothing Nothing Nothing

Cabal-tests/tests/UnitTests/Distribution/Simple/Program/GHC.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ tests = testGroup "Distribution.Simple.Program.GHC"
5454
, compilerLanguages = []
5555
, compilerExtensions = []
5656
, compilerProperties = Map.singleton "Support parallel --make" "YES"
57+
, compilerWiredInUnitIds = Nothing
5758
})
5859
(Platform X86_64 Linux)
5960
(mempty { ghcOptNumJobs = Flag (NumJobs (Just 4)) })

Cabal/src/Distribution/Simple/Compiler.hs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,9 @@ import Distribution.Pretty
9898
import Prelude ()
9999

100100
import Distribution.Compiler
101+
import Distribution.Package (PackageName)
101102
import Distribution.Simple.Utils
103+
import Distribution.Types.UnitId (UnitId)
102104
import Distribution.Utils.Path
103105
import Distribution.Version
104106

@@ -120,6 +122,11 @@ data Compiler = Compiler
120122
-- ^ Supported language standards.
121123
, compilerExtensions :: [(Extension, Maybe CompilerFlag)]
122124
-- ^ Supported extensions.
125+
, compilerWiredInUnitIds :: Maybe [(PackageName, UnitId)]
126+
-- ^ 'UnitId's that the compiler doesn't support reinstalling.
127+
-- For instance, when using GHC plugins, one wants to use the
128+
-- exact same version of the `ghc` package as the one the
129+
-- compiler was linked against.
123130
, compilerProperties :: Map String String
124131
-- ^ A key-value map for properties not covered by the above fields.
125132
}
@@ -178,6 +185,7 @@ compilerInfo c =
178185
(Just . compilerCompat $ c)
179186
(Just . map fst . compilerLanguages $ c)
180187
(Just . map fst . compilerExtensions $ c)
188+
(compilerWiredInUnitIds c)
181189

182190
-- ------------------------------------------------------------
183191

Cabal/src/Distribution/Simple/GHC.hs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,14 +247,25 @@ configure verbosity hcPath hcPkgPath conf0 = do
247247
compilerId :: CompilerId
248248
compilerId = CompilerId GHC ghcVersion
249249

250+
projectUnitId :: Maybe String
251+
projectUnitId = Map.lookup "Project Unit Id" ghcInfoMap
252+
250253
-- The @AbiTag@ is the @Project Unit Id@ but with redundant information from the compiler version removed.
251254
-- For development versions of the compiler these look like:
252255
-- @Project Unit Id@: "ghc-9.13-inplace"
253256
-- @compilerId@: "ghc-9.13.20250413"
254257
-- So, we need to be careful to only strip the /common/ prefix.
255258
-- In this example, @AbiTag@ is "inplace".
256259
compilerAbiTag :: AbiTag
257-
compilerAbiTag = maybe NoAbiTag AbiTag (dropWhile (== '-') . stripCommonPrefix (prettyShow compilerId) <$> Map.lookup "Project Unit Id" ghcInfoMap)
260+
compilerAbiTag = maybe NoAbiTag AbiTag (dropWhile (== '-') . stripCommonPrefix (prettyShow compilerId) <$> projectUnitId)
261+
262+
wiredInUnitIds = do
263+
ghcInternalUnitId <- Map.lookup "ghc-internal Unit Id" ghcInfoMap
264+
ghcUnitId <- projectUnitId
265+
pure
266+
[ (mkPackageName "ghc", mkUnitId ghcUnitId)
267+
, (mkPackageName "ghc-internal", mkUnitId ghcInternalUnitId)
268+
]
258269

259270
let comp =
260271
Compiler
@@ -264,6 +275,7 @@ configure verbosity hcPath hcPkgPath conf0 = do
264275
, compilerLanguages = languages
265276
, compilerExtensions = extensions
266277
, compilerProperties = ghcInfoMap
278+
, compilerWiredInUnitIds = wiredInUnitIds
267279
}
268280
compPlatform = Internal.targetPlatform ghcInfo
269281
-- configure gcc and ld

Cabal/src/Distribution/Simple/GHCJS.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ configure verbosity hcPath hcPkgPath conf0 = do
203203
, compilerLanguages = languages
204204
, compilerExtensions = extensions
205205
, compilerProperties = ghcInfoMap
206+
, compilerWiredInUnitIds = Nothing
206207
}
207208
compPlatform = Internal.targetPlatform ghcjsInfo
208209
return (comp, compPlatform, progdb3)

Cabal/src/Distribution/Simple/UHC.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ configure verbosity hcPath _hcPkgPath progdb = do
7878
, compilerLanguages = uhcLanguages
7979
, compilerExtensions = uhcLanguageExtensions
8080
, compilerProperties = Map.empty
81+
, compilerWiredInUnitIds = Nothing
8182
}
8283
compPlatform = Nothing
8384
return (comp, compPlatform, progdb')

cabal-install-solver/src/Distribution/Solver/Modular/Message.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@ showFR _ UnknownPackage = " (unknown package)"
295295
showFR _ (GlobalConstraintVersion vr (ConstraintSourceProjectConfig pc)) = '\n' : (render . nest 6 $ docProjectConfigPathFailReason vr pc)
296296
showFR _ (GlobalConstraintVersion vr src) = " (" ++ constraintSource src ++ " requires " ++ prettyShow vr ++ ")"
297297
showFR _ (GlobalConstraintInstalled src) = " (" ++ constraintSource src ++ " requires installed instance)"
298+
showFR _ (GlobalConstraintInstalledSpecificUnitId unitId src) = " (" ++ constraintSource src ++ " requires installed instance with unit id " ++ prettyShow unitId ++ ")"
298299
showFR _ (GlobalConstraintSource src) = " (" ++ constraintSource src ++ " requires source instance)"
299300
showFR _ (GlobalConstraintFlag src) = " (" ++ constraintSource src ++ " requires opposite flag selection)"
300301
showFR _ ManualFlag = " (manual flag can only be changed explicitly)"

cabal-install-solver/src/Distribution/Solver/Modular/Package.hs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ module Distribution.Solver.Modular.Package
1010
, PN
1111
, QPV
1212
, instI
13+
, instUid
1314
, makeIndependent
1415
, primaryPP
1516
, setupPP
@@ -77,6 +78,10 @@ instI :: I -> Bool
7778
instI (I _ (Inst _)) = True
7879
instI _ = False
7980

81+
instUid :: UnitId -> I -> Bool
82+
instUid uid (I _ (Inst uid')) = uid == uid'
83+
instUid _ _ = False
84+
8085
-- | Is the package in the primary group of packages. This is used to
8186
-- determine (1) if we should try to establish stanza preferences
8287
-- for this goal, and (2) whether or not a user specified @--constraint@

cabal-install-solver/src/Distribution/Solver/Modular/Preference.hs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,9 @@ processPackageConstraintP qpn c i (LabeledPackageConstraint (PackageConstraint s
190190
go _ PackagePropertyInstalled
191191
| instI i = r
192192
| otherwise = Fail c (GlobalConstraintInstalled src)
193+
go _ (PackagePropertyInstalledSpecificUnitId unitId)
194+
| instUid unitId i = r
195+
| otherwise = Fail c (GlobalConstraintInstalledSpecificUnitId unitId src)
193196
go _ PackagePropertySource
194197
| not (instI i) = r
195198
| otherwise = Fail c (GlobalConstraintSource src)

cabal-install-solver/src/Distribution/Solver/Modular/Tree.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ data FailReason = UnsupportedExtension Extension
118118
| UnknownPackage
119119
| GlobalConstraintVersion VR ConstraintSource
120120
| GlobalConstraintInstalled ConstraintSource
121+
| GlobalConstraintInstalledSpecificUnitId UnitId ConstraintSource
121122
| GlobalConstraintSource ConstraintSource
122123
| GlobalConstraintFlag ConstraintSource
123124
| ManualFlag

0 commit comments

Comments
 (0)