Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC
Commits:
-
6b3044a0
by David Eichmann at 2026-05-30T11:58:48-04:00
-
f4e04210
by Matthew Pickering at 2026-05-30T11:59:34-04:00
-
2224e4eb
by Simon Jakobi at 2026-06-02T00:13:09-04:00
-
13652abf
by David Eichmann at 2026-06-02T00:13:10-04:00
20 changed files:
- + changelog.d/hadrian-system-cxx-std-lib-25303
- compiler/GHC/CmmToAsm/BlockLayout.hs
- compiler/GHC/Driver/Backpack.hs
- compiler/GHC/Driver/Session/Units.hs
- compiler/GHC/HsToCore/Usage.hs
- compiler/GHC/Linker/Unit.hs
- compiler/GHC/Rename/Pat.hs
- compiler/GHC/Unit/Info.hs
- compiler/GHC/Unit/State.hs
- compiler/GHC/Utils/Misc.hs
- ghc/GHCi/UI.hs
- hadrian/src/Builder.hs
- hadrian/src/Hadrian/Haskell/Cabal/Parse.hs
- hadrian/src/Hadrian/Haskell/Cabal/Type.hs
- hadrian/src/Hadrian/Utilities.hs
- hadrian/src/Main.hs
- hadrian/src/Rules/Generate.hs
- hadrian/src/Rules/Register.hs
- rts/sm/BlockAlloc.c
- rts/sm/MBlock.c
Changes:
| 1 | +section: packaging
|
|
| 2 | +synopsis: Fix Hadrian rules for system-cxx-std-lib package dependency
|
|
| 3 | +issues: #25303
|
|
| 4 | +mrs: !16013
|
|
| 5 | +description: {
|
|
| 6 | + Hadrian's handling of the `system-cxx-std-lib` virtual package has been
|
|
| 7 | + fixed and made more uniform.
|
|
| 8 | + |
|
| 9 | + Previously, `text` had an ad-hoc rule outside of `configurePackage` to
|
|
| 10 | + declare a dependency on `system-cxx-std-lib`, the dependency was not
|
|
| 11 | + discovered from cabal files, and the package database was not recached after
|
|
| 12 | + the `.conf` file was generated.
|
|
| 13 | + |
|
| 14 | + The dependency is now read from cabal files via a new
|
|
| 15 | + `dependsOnSystemCxxStdLib` field in `PackageData`, and the `.conf` file
|
|
| 16 | + is needed inside `configurePackage` alongside all other package
|
|
| 17 | + dependencies, consistent with how every other package is handled.
|
|
| 18 | + |
|
| 19 | + `shakeVersion` has been bumped to ensure existing build databases are
|
|
| 20 | + invalidated when upgrading, preventing binary deserialisation errors due to
|
|
| 21 | + the changed `PackageData` type.
|
|
| 22 | +} |
| ... | ... | @@ -36,6 +36,7 @@ import GHC.Utils.Outputable |
| 36 | 36 | import GHC.Utils.Panic
|
| 37 | 37 | import GHC.Utils.Misc
|
| 38 | 38 | |
| 39 | +import Data.Containers.ListUtils (nubOrd)
|
|
| 39 | 40 | import Data.List (sortOn, sortBy, nub)
|
| 40 | 41 | import Data.List.NonEmpty (nonEmpty)
|
| 41 | 42 | import qualified Data.List.NonEmpty as NE
|
| ... | ... | @@ -426,7 +427,7 @@ combineNeighbourhood edges chains |
| 426 | 427 | applyEdges :: [CfgEdge] -> FrontierMap -> FrontierMap -> Set.Set (BlockId, BlockId)
|
| 427 | 428 | -> ([BlockChain], Set.Set (BlockId,BlockId))
|
| 428 | 429 | applyEdges [] chainEnds _chainFronts combined =
|
| 429 | - (ordNub $ map snd $ mapElems chainEnds, combined)
|
|
| 430 | + (nubOrd $ map snd $ mapElems chainEnds, combined)
|
|
| 430 | 431 | applyEdges ((CfgEdge from to _w):edges) chainEnds chainFronts combined
|
| 431 | 432 | | Just (c1_e,c1) <- mapLookup from chainEnds
|
| 432 | 433 | , Just (c2_f,c2) <- mapLookup to chainFronts
|
| ... | ... | @@ -76,6 +76,7 @@ import GHC.Data.FastString |
| 76 | 76 | import qualified GHC.Data.EnumSet as EnumSet
|
| 77 | 77 | import qualified GHC.Data.ShortText as ST
|
| 78 | 78 | |
| 79 | +import Data.Containers.ListUtils (nubOrd)
|
|
| 79 | 80 | import Data.List ( partition )
|
| 80 | 81 | import System.Exit
|
| 81 | 82 | import Control.Monad
|
| ... | ... | @@ -763,14 +764,14 @@ hsunitModuleGraph do_link unit = do |
| 763 | 764 | let inodes = instantiationNodes (homeUnitId $ hsc_home_unit hsc_env) (hsc_units hsc_env)
|
| 764 | 765 | -- TODO: Backpack mode does not properly support ExternalPackage nodes yet
|
| 765 | 766 | -- Module nodes do not get given package dependencies (see hsModuleToModSummary).
|
| 766 | - let pkg_nodes = ordNub $ map (\(_, iud) -> UnitNode [] (instUnitInstanceOf iud)) inodes
|
|
| 767 | + let pkg_nodes = nubOrd $ map (\(_, iud) -> UnitNode [] (instUnitInstanceOf iud)) inodes
|
|
| 767 | 768 | let graph_nodes = nodes ++ req_nodes ++ (map (uncurry InstantiationNode) $ inodes) ++ pkg_nodes
|
| 768 | 769 | key_nodes = map mkNodeKey graph_nodes
|
| 769 | 770 | all_nodes = graph_nodes ++ [LinkNode key_nodes (homeUnitId $ hsc_home_unit hsc_env) | do_link]
|
| 770 | 771 | -- This error message is not very good but .bkp mode is just for testing so
|
| 771 | 772 | -- better to be direct rather than pretty.
|
| 772 | 773 | when
|
| 773 | - (length key_nodes /= length (ordNub key_nodes))
|
|
| 774 | + (length key_nodes /= length (nubOrd key_nodes))
|
|
| 774 | 775 | (pprPanic "Duplicate nodes keys in backpack file" (ppr key_nodes))
|
| 775 | 776 | |
| 776 | 777 | -- 3. Return the kaboodle
|
| ... | ... | @@ -25,7 +25,6 @@ import qualified GHC.Unit.State as State |
| 25 | 25 | import GHC.Types.SrcLoc
|
| 26 | 26 | import GHC.Types.SourceError
|
| 27 | 27 | |
| 28 | -import GHC.Utils.Misc
|
|
| 29 | 28 | import GHC.Utils.Panic
|
| 30 | 29 | import GHC.Utils.Outputable as Outputable
|
| 31 | 30 | import GHC.Utils.Monad ( liftIO, mapMaybeM )
|
| ... | ... | @@ -35,6 +34,7 @@ import System.IO |
| 35 | 34 | import System.Exit
|
| 36 | 35 | import System.FilePath
|
| 37 | 36 | import Control.Monad
|
| 37 | +import Data.Containers.ListUtils (nubOrdOn)
|
|
| 38 | 38 | import Data.List ( partition, (\\) )
|
| 39 | 39 | import qualified Data.Set as Set
|
| 40 | 40 | import GHC.Prelude
|
| ... | ... | @@ -204,7 +204,7 @@ checkDuplicateUnits dflags flags = |
| 204 | 204 | |
| 205 | 205 | where
|
| 206 | 206 | uids = map (second homeUnitId_) flags
|
| 207 | - deduplicated_uids = ordNubOn snd uids
|
|
| 207 | + deduplicated_uids = nubOrdOn snd uids
|
|
| 208 | 208 | duplicate_ids = Set.fromList (map snd uids \\ map snd deduplicated_uids)
|
| 209 | 209 | |
| 210 | 210 | duplicate_flags = filter (flip Set.member duplicate_ids . snd) uids
|
| ... | ... | @@ -32,6 +32,7 @@ import GHC.Unit.Module.Deps |
| 32 | 32 | import GHC.Data.Maybe
|
| 33 | 33 | import GHC.Data.FastString
|
| 34 | 34 | |
| 35 | +import Data.Containers.ListUtils (nubOrdOn)
|
|
| 35 | 36 | import Data.List (sortBy)
|
| 36 | 37 | import Data.Map (Map)
|
| 37 | 38 | import qualified Data.Map as Map
|
| ... | ... | @@ -180,7 +181,7 @@ the TH splice. |
| 180 | 181 | -- modules and direct object files for pkg dependencies
|
| 181 | 182 | mkObjectUsage :: Plugins -> FinderCache -> [LinkableUsage] -> PkgsLoaded -> IO [Usage]
|
| 182 | 183 | mkObjectUsage plugins fc th_links_needed th_pkgs_needed = do
|
| 183 | - let ls = ordNubOn linkableModule (th_links_needed ++ plugins_links_needed)
|
|
| 184 | + let ls = nubOrdOn linkableModule (th_links_needed ++ plugins_links_needed)
|
|
| 184 | 185 | ds = concatMap loaded_pkg_hs_objs $ eltsUDFM (plusUDFM th_pkgs_needed plugin_pkgs_needed) -- TODO possibly record loaded_pkg_non_hs_objs as well
|
| 185 | 186 | (plugins_links_needed, plugin_pkgs_needed) = loadedPluginDeps plugins
|
| 186 | 187 | concat <$> sequence (map linkableToUsage ls ++ map librarySpecToUsage ds)
|
| ... | ... | @@ -25,6 +25,7 @@ import qualified GHC.Data.ShortText as ST |
| 25 | 25 | import GHC.Settings
|
| 26 | 26 | |
| 27 | 27 | import Control.Monad
|
| 28 | +import Data.Containers.ListUtils (nubOrd)
|
|
| 28 | 29 | import Data.List (nub)
|
| 29 | 30 | import Data.Semigroup ( Semigroup(..) )
|
| 30 | 31 | import System.Directory
|
| ... | ... | @@ -95,7 +96,7 @@ collectArchives namever ways pc = |
| 95 | 96 | filterM doesFileExist [ searchPath </> ("lib" ++ lib ++ ".a")
|
| 96 | 97 | | searchPath <- searchPaths
|
| 97 | 98 | , lib <- libs ]
|
| 98 | - where searchPaths = ordNub . filter notNull . libraryDirsForWay ways $ pc
|
|
| 99 | + where searchPaths = nubOrd . filter notNull . libraryDirsForWay ways $ pc
|
|
| 99 | 100 | libs = unitHsLibs namever ways pc ++ (map ST.unpack . unitExtDepLibsStaticSys $ pc)
|
| 100 | 101 | |
| 101 | 102 | getLibs :: GhcNameVersion -> Ways -> UnitEnv -> [UnitId] -> IO [(String,String)]
|
| ... | ... | @@ -79,6 +79,7 @@ import GHC.Core.TyCon ( isKindName ) |
| 79 | 79 | import qualified GHC.LanguageExtensions as LangExt
|
| 80 | 80 | |
| 81 | 81 | import Control.Monad ( when, ap, guard, unless )
|
| 82 | +import Data.Containers.ListUtils (nubOrdOn)
|
|
| 82 | 83 | import Data.Foldable
|
| 83 | 84 | import Data.Function ( on )
|
| 84 | 85 | import Data.Functor.Identity ( Identity (..) )
|
| ... | ... | @@ -667,7 +668,7 @@ rnPatAndThen mk (OrPat _ pats) |
| 667 | 668 | ; pats' <- rnLPatsAndThen mk pats
|
| 668 | 669 | ; let bndrs = collectPatsBinders CollVarTyVarBinders (NE.toList pats')
|
| 669 | 670 | ; liftCps $ setSrcSpan loc $ checkErr (null bndrs) $
|
| 670 | - TcRnOrPatBindsVariables (NE.fromList (ordNubOn getOccName bndrs))
|
|
| 671 | + TcRnOrPatBindsVariables (NE.fromList (nubOrdOn getOccName bndrs))
|
|
| 671 | 672 | ; return (OrPat noExtField pats') }
|
| 672 | 673 | |
| 673 | 674 | rnPatAndThen mk (SumPat _ pat alt arity)
|
| ... | ... | @@ -49,6 +49,7 @@ import GHC.Unit.Database |
| 49 | 49 | |
| 50 | 50 | import GHC.Settings
|
| 51 | 51 | |
| 52 | +import Data.Containers.ListUtils (nubOrd)
|
|
| 52 | 53 | import Data.Version
|
| 53 | 54 | import Data.Bifunctor
|
| 54 | 55 | import Data.List (isPrefixOf, stripPrefix)
|
| ... | ... | @@ -185,7 +186,7 @@ mkUnitPprInfo ufs i = UnitPprInfo |
| 185 | 186 | |
| 186 | 187 | -- | Find all the include directories in the given units
|
| 187 | 188 | collectIncludeDirs :: [UnitInfo] -> [FilePath]
|
| 188 | -collectIncludeDirs ps = map ST.unpack $ ordNub (filter (not . ST.null) (concatMap unitIncludeDirs ps))
|
|
| 189 | +collectIncludeDirs ps = map ST.unpack $ nubOrd (filter (not . ST.null) (concatMap unitIncludeDirs ps))
|
|
| 189 | 190 | |
| 190 | 191 | -- | Find all the C-compiler options in the given units
|
| 191 | 192 | collectExtraCcOpts :: [UnitInfo] -> [String]
|
| ... | ... | @@ -193,7 +194,7 @@ collectExtraCcOpts ps = map ST.unpack (concatMap unitCcOptions ps) |
| 193 | 194 | |
| 194 | 195 | -- | Find all the library directories in the given units for the given ways
|
| 195 | 196 | collectLibraryDirs :: Ways -> [UnitInfo] -> [FilePath]
|
| 196 | -collectLibraryDirs ws = ordNub . filter notNull . concatMap (libraryDirsForWay ws)
|
|
| 197 | +collectLibraryDirs ws = nubOrd . filter notNull . concatMap (libraryDirsForWay ws)
|
|
| 197 | 198 | |
| 198 | 199 | -- | Find all the frameworks in the given units
|
| 199 | 200 | collectFrameworks :: [UnitInfo] -> [String]
|
| ... | ... | @@ -201,7 +202,7 @@ collectFrameworks ps = map ST.unpack (concatMap unitExtDepFrameworks ps) |
| 201 | 202 | |
| 202 | 203 | -- | Find all the package framework paths in these and the preload packages
|
| 203 | 204 | collectFrameworksDirs :: [UnitInfo] -> [String]
|
| 204 | -collectFrameworksDirs ps = map ST.unpack (ordNub (filter (not . ST.null) (concatMap unitExtDepFrameworkDirs ps)))
|
|
| 205 | +collectFrameworksDirs ps = map ST.unpack (nubOrd (filter (not . ST.null) (concatMap unitExtDepFrameworkDirs ps)))
|
|
| 205 | 206 | |
| 206 | 207 | -- | Either the 'unitLibraryDirs' or 'unitLibraryDynDirs' as appropriate for the way.
|
| 207 | 208 | libraryDirsForWay :: Ways -> UnitInfo -> [String]
|
| ... | ... | @@ -112,6 +112,7 @@ import GHC.Utils.Exception |
| 112 | 112 | import System.Directory
|
| 113 | 113 | import System.FilePath as FilePath
|
| 114 | 114 | import Control.Monad
|
| 115 | +import Data.Containers.ListUtils (nubOrd)
|
|
| 115 | 116 | import Data.Graph (stronglyConnComp, SCC(..))
|
| 116 | 117 | import Data.Char ( toUpper )
|
| 117 | 118 | import Data.List ( intersperse, partition, sortBy, sortOn, sort )
|
| ... | ... | @@ -1705,7 +1706,7 @@ mkUnitState logger cfg = do |
| 1705 | 1706 | basicLinkedUnits = fmap (RealUnit . Definite)
|
| 1706 | 1707 | $ filter (flip elemUniqMap pkg_db)
|
| 1707 | 1708 | $ unitConfigAutoLink cfg
|
| 1708 | - preload3 = ordNub $ (basicLinkedUnits ++ preload1)
|
|
| 1709 | + preload3 = nubOrd $ (basicLinkedUnits ++ preload1)
|
|
| 1709 | 1710 | |
| 1710 | 1711 | -- Close the preload packages with their dependencies
|
| 1711 | 1712 | dep_preload <- mayThrowUnitErr
|
| ... | ... | @@ -59,7 +59,7 @@ module GHC.Utils.Misc ( |
| 59 | 59 | replaceAt, dropTail, capitalise,
|
| 60 | 60 | |
| 61 | 61 | -- * Sorting
|
| 62 | - sortWith, minWith, nubSort, ordNub, ordNubOn,
|
|
| 62 | + sortWith, minWith, nubSort,
|
|
| 63 | 63 | |
| 64 | 64 | -- * Comparisons
|
| 65 | 65 | isEqual,
|
| ... | ... | @@ -570,23 +570,6 @@ minWith get_key xs = assert (not (null xs) ) |
| 570 | 570 | nubSort :: Ord a => [a] -> [a]
|
| 571 | 571 | nubSort = Set.toAscList . Set.fromList
|
| 572 | 572 | |
| 573 | --- | Remove duplicates but keep elements in order.
|
|
| 574 | --- O(n * log n)
|
|
| 575 | -ordNub :: Ord a => [a] -> [a]
|
|
| 576 | -ordNub xs = ordNubOn id xs
|
|
| 577 | - |
|
| 578 | --- | Remove duplicates but keep elements in order.
|
|
| 579 | --- O(n * log n)
|
|
| 580 | -ordNubOn :: Ord b => (a -> b) -> [a] -> [a]
|
|
| 581 | -ordNubOn f xs
|
|
| 582 | - = go Set.empty xs
|
|
| 583 | - where
|
|
| 584 | - go _ [] = []
|
|
| 585 | - go s (x:xs)
|
|
| 586 | - | Set.member (f x) s = go s xs
|
|
| 587 | - | otherwise = x : go (Set.insert (f x) s) xs
|
|
| 588 | - |
|
| 589 | - |
|
| 590 | 573 | {-
|
| 591 | 574 | ************************************************************************
|
| 592 | 575 | * *
|
| ... | ... | @@ -128,6 +128,7 @@ import Control.Monad.Trans.Except |
| 128 | 128 | import Data.Array
|
| 129 | 129 | import qualified Data.ByteString.Char8 as BS
|
| 130 | 130 | import Data.Char
|
| 131 | +import Data.Containers.ListUtils (nubOrd)
|
|
| 131 | 132 | import Data.Function
|
| 132 | 133 | import qualified Data.Foldable as Foldable
|
| 133 | 134 | import Data.IORef ( IORef, modifyIORef, newIORef, readIORef, writeIORef )
|
| ... | ... | @@ -786,7 +787,7 @@ installInteractiveHomeUnits dflags = do |
| 786 | 787 | -- This is mostly for a clear separation of concerns,
|
| 787 | 788 | -- to indicate we only care about unit dependencies from package dbs.
|
| 788 | 789 | & filter (not . selectHptFlag (HUG.allUnits $ hsc_HUG hsc_env))
|
| 789 | - & ordNub
|
|
| 790 | + & nubOrd
|
|
| 790 | 791 | else
|
| 791 | 792 | packageFlags dflags0
|
| 792 | 793 | |
| ... | ... | @@ -871,7 +872,7 @@ installInteractiveHomeUnits dflags = do |
| 871 | 872 | prefix =
|
| 872 | 873 | longestCommonPrefix stacks
|
| 873 | 874 | in
|
| 874 | - prefix ++ ordNub (concatMap (List.drop (length prefix)) stacks)
|
|
| 875 | + prefix ++ nubOrd (concatMap (List.drop (length prefix)) stacks)
|
|
| 875 | 876 | |
| 876 | 877 | reportError :: GhciMonad m => GhciCommandMessage -> m ()
|
| 877 | 878 | reportError err = do
|
| ... | ... | @@ -1249,7 +1250,7 @@ generatePromptFunctionFromString promptS modules_names line = |
| 1249 | 1250 | processString ('%':'s':xs) =
|
| 1250 | 1251 | liftM2 (<>) (return modules_list) (processString xs)
|
| 1251 | 1252 | where
|
| 1252 | - modules_list = hsep . map text . ordNub $ modules_names
|
|
| 1253 | + modules_list = hsep . map text . nubOrd $ modules_names
|
|
| 1253 | 1254 | processString ('%':'l':xs) =
|
| 1254 | 1255 | liftM2 (<>) (return $ ppr line) (processString xs)
|
| 1255 | 1256 | processString ('%':'d':xs) =
|
| ... | ... | @@ -39,7 +39,6 @@ import Packages |
| 39 | 39 | import GHC.IO.Encoding (getFileSystemEncoding)
|
| 40 | 40 | import qualified Data.ByteString as BS
|
| 41 | 41 | import qualified GHC.Foreign as GHC
|
| 42 | -import GHC.ResponseFile
|
|
| 43 | 42 | |
| 44 | 43 | import GHC.Toolchain (Target(..))
|
| 45 | 44 | import qualified GHC.Toolchain as Toolchain
|
| ... | ... | @@ -346,7 +345,15 @@ instance H.Builder Builder where |
| 346 | 345 | |
| 347 | 346 | Haddock BuildPackage -> runHaddock path buildArgs buildInputs
|
| 348 | 347 | |
| 349 | - Ghc _ _ -> runGhcWithResponse path buildArgs buildInputs buildOptions
|
|
| 348 | + Ghc _ _ ->
|
|
| 349 | + -- Use a response file for ghc invocations to avoid issues with command line
|
|
| 350 | + -- size limit on Windows (#26637).
|
|
| 351 | + -- NB: we can't put the buildArgs in a response file, because some flags require
|
|
| 352 | + -- empty arguments (such as the -dep-suffix flag), but that isn't supported
|
|
| 353 | + -- yet due to #26560.
|
|
| 354 | + withResponseFileOnWindows
|
|
| 355 | + (\buildInputs' -> cmd [path] buildArgs buildInputs' buildOptions)
|
|
| 356 | + buildInputs
|
|
| 350 | 357 | |
| 351 | 358 | HsCpp -> captureStdout
|
| 352 | 359 | |
| ... | ... | @@ -380,29 +387,15 @@ instance H.Builder Builder where |
| 380 | 387 | |
| 381 | 388 | _ -> cmd' [path] buildArgs buildOptions
|
| 382 | 389 | |
| 383 | --- | Invoke @haddock@ given a path to it and a list of arguments. The arguments
|
|
| 384 | --- are passed in a response file.
|
|
| 390 | +-- | Invoke @haddock@ given a path to it and a list of arguments. On Windows,
|
|
| 391 | +-- the input file arguments are passed as a response file.
|
|
| 385 | 392 | runHaddock :: FilePath -- ^ path to @haddock@
|
| 386 | 393 | -> [String]
|
| 387 | 394 | -> [FilePath] -- ^ input file paths
|
| 388 | 395 | -> Action ()
|
| 389 | -runHaddock haddockPath flagArgs fileInputs = withResponseFile $ \tmp -> do
|
|
| 390 | - writeFile' tmp $ escapeArgs fileInputs
|
|
| 391 | - cmd [haddockPath] flagArgs ('@' : tmp)
|
|
| 392 | - |
|
| 393 | --- | Use a response file for ghc invocations to avoid issues with command line
|
|
| 394 | --- size limit on Windows (#26637).
|
|
| 395 | -runGhcWithResponse :: FilePath -- ^ Path to ghc
|
|
| 396 | - -> [String] -- ^ Arguments passed on the command line
|
|
| 397 | - -> [FilePath] -- ^ Input file paths (passed via response file)
|
|
| 398 | - -> [CmdOption]
|
|
| 399 | - -> Action ()
|
|
| 400 | -runGhcWithResponse ghcPath buildArgs buildInputs buildOptions = withResponseFile $ \tmp -> do
|
|
| 401 | - -- We can't put the buildArgs in a response file, because some flags require
|
|
| 402 | - -- empty arguments (such as the -dep-suffix flag), but that isn't supported
|
|
| 403 | - -- yet due to #26560.
|
|
| 404 | - writeFile' tmp (escapeArgs buildInputs)
|
|
| 405 | - cmd [ghcPath] buildArgs ('@' : tmp) buildOptions
|
|
| 396 | +runHaddock haddockPath flagArgs fileInputs = withResponseFileOnWindows
|
|
| 397 | + (cmd [haddockPath] flagArgs)
|
|
| 398 | + fileInputs
|
|
| 406 | 399 | |
| 407 | 400 | -- TODO: Some builders are required only on certain platforms. For example,
|
| 408 | 401 | -- 'Objdump' is only required on OpenBSD and AIX. Add support for platform
|
| ... | ... | @@ -81,10 +81,11 @@ parsePackageData pkg = do |
| 81 | 81 | sorted = sort [ C.unPackageName p | C.Dependency p _ _ <- allDeps ]
|
| 82 | 82 | deps = nubOrd sorted \\ [name]
|
| 83 | 83 | depPkgs = mapMaybe findPackageByName deps
|
| 84 | + cxxStdLib = elem "system-cxx-std-lib" deps
|
|
| 84 | 85 | return $ PackageData name version
|
| 85 | 86 | (C.fromShortText (C.synopsis pd))
|
| 86 | 87 | (C.fromShortText (C.description pd))
|
| 87 | - depPkgs gpd
|
|
| 88 | + depPkgs cxxStdLib gpd
|
|
| 88 | 89 | where
|
| 89 | 90 | -- Collect an overapproximation of dependencies by ignoring conditionals
|
| 90 | 91 | collectDeps :: Maybe (C.CondTree v [C.Dependency] a) -> [C.Dependency]
|
| ... | ... | @@ -138,7 +139,9 @@ configurePackage :: Context -> Action () |
| 138 | 139 | configurePackage context@Context {..} = do
|
| 139 | 140 | putProgressInfo $ "| Configure package " ++ quote (pkgName package)
|
| 140 | 141 | gpd <- pkgGenericDescription package
|
| 141 | - depPkgs <- packageDependencies <$> readPackageData package
|
|
| 142 | + pd <- readPackageData package
|
|
| 143 | + let depPkgs = packageDependencies pd
|
|
| 144 | + needSystemCxxStdLib = dependsOnSystemCxxStdLib pd
|
|
| 142 | 145 | |
| 143 | 146 | -- Stage packages are those we have in this stage.
|
| 144 | 147 | stagePkgs <- stagePackages stage
|
| ... | ... | @@ -157,7 +160,12 @@ configurePackage context@Context {..} = do |
| 157 | 160 | -- We'll need those packages in our package database.
|
| 158 | 161 | deps <- sequence [ pkgConfFile (context { package = pkg, iplace = forceBaseAfterGhcInternal pkg })
|
| 159 | 162 | | pkg <- depPkgs, pkg `elem` stagePkgs ]
|
| 160 | - need $ extraPreConfigureDeps ++ deps
|
|
| 163 | + -- system-cxx-std-lib is magic.. it doesn't have a cabal file or source code, so we have
|
|
| 164 | + -- to treat it specially as `pkgConfFile` uses `readPackageData` to compute the version.
|
|
| 165 | + systemCxxStdLib <- sequence [ systemCxxStdLibConfPath (PackageDbLoc stage iplace) | needSystemCxxStdLib ]
|
|
| 166 | + need $ extraPreConfigureDeps
|
|
| 167 | + ++ deps
|
|
| 168 | + ++ systemCxxStdLib
|
|
| 161 | 169 | |
| 162 | 170 | -- Figure out what hooks we need.
|
| 163 | 171 | let configureFile = replaceFileName (pkgCabalFile package) "configure"
|
| ... | ... | @@ -30,6 +30,7 @@ data PackageData = PackageData |
| 30 | 30 | , synopsis :: String
|
| 31 | 31 | , description :: String
|
| 32 | 32 | , packageDependencies :: [Package]
|
| 33 | + , dependsOnSystemCxxStdLib :: Bool
|
|
| 33 | 34 | , genericPackageDescription :: GenericPackageDescription
|
| 34 | 35 | } deriving (Eq, Generic, Show)
|
| 35 | 36 |
| ... | ... | @@ -14,7 +14,7 @@ module Hadrian.Utilities ( |
| 14 | 14 | |
| 15 | 15 | -- * Paths
|
| 16 | 16 | BuildRoot (..), buildRoot, buildRootRules, isGeneratedSource,
|
| 17 | - KeepResponseFiles (..), keepResponseFiles, withResponseFile,
|
|
| 17 | + KeepResponseFiles (..), keepResponseFiles, withResponseFile, withResponseFileOnWindows,
|
|
| 18 | 18 | |
| 19 | 19 | -- * File system operations
|
| 20 | 20 | copyFile, copyFileUntracked, createFileLink, fixFile,
|
| ... | ... | @@ -48,8 +48,11 @@ import Data.Typeable (TypeRep, typeOf) |
| 48 | 48 | import Development.Shake hiding (Normal)
|
| 49 | 49 | import Development.Shake.Classes
|
| 50 | 50 | import Development.Shake.FilePath
|
| 51 | +import GHC.ResponseFile (escapeArgs)
|
|
| 51 | 52 | import System.Environment (lookupEnv)
|
| 53 | +import System.Info.Extra (isWindows)
|
|
| 52 | 54 | import System.IO (hClose, openTempFile)
|
| 55 | +import System.IO.Error (isPermissionError)
|
|
| 53 | 56 | |
| 54 | 57 | import qualified Data.ByteString as BS
|
| 55 | 58 | import qualified Control.Exception.Base as IO
|
| ... | ... | @@ -57,8 +60,7 @@ import qualified Data.HashMap.Strict as Map |
| 57 | 60 | import qualified System.Directory.Extra as IO
|
| 58 | 61 | import qualified System.Info.Extra as IO
|
| 59 | 62 | import qualified System.IO as IO
|
| 60 | -import System.IO.Error (isPermissionError)
|
|
| 61 | -import qualified System.FilePath.Posix as Posix
|
|
| 63 | +import qualified System.FilePath.Posix as Posix
|
|
| 62 | 64 | |
| 63 | 65 | -- | Extract a value from a singleton list, or terminate with an error message
|
| 64 | 66 | -- if the list does not contain exactly one value.
|
| ... | ... | @@ -328,6 +330,21 @@ keepResponseFiles = do |
| 328 | 330 | KeepResponseFiles keep <- userSetting (KeepResponseFiles False)
|
| 329 | 331 | return keep
|
| 330 | 332 | |
| 333 | +-- | Run an action either with command arguments direcly or by, on Windows,
|
|
| 334 | +-- placing those arguments into a response file escaped with @GHC.ResponseFile.escapeArgs@.
|
|
| 335 | +--
|
|
| 336 | +-- With @--keep-response-files@, the file is left on disk (if used)
|
|
| 337 | +withResponseFileOnWindows ::
|
|
| 338 | + ([String] -> Action a) -- ^ Action to perform given arguments (of the form @["\@reponseFilePath"]@ on Windows)
|
|
| 339 | + -> [String] -- ^ Command arguments
|
|
| 340 | + -> Action a
|
|
| 341 | +withResponseFileOnWindows action commandArgs = do
|
|
| 342 | + if isWindows
|
|
| 343 | + then withResponseFile $ \tmp -> do
|
|
| 344 | + writeFile' tmp (escapeArgs commandArgs)
|
|
| 345 | + action ['@' : tmp]
|
|
| 346 | + else action commandArgs
|
|
| 347 | + |
|
| 331 | 348 | -- | Run an action with a response file path.
|
| 332 | 349 | --
|
| 333 | 350 | -- With @--keep-response-files@, the file is left on disk.
|
| ... | ... | @@ -63,7 +63,13 @@ main = do |
| 63 | 63 | shakeColor <- shouldUseColor
|
| 64 | 64 | let options :: ShakeOptions
|
| 65 | 65 | options = shakeOptions
|
| 66 | - { shakeChange = ChangeModtimeAndDigest
|
|
| 66 | + { -- Bump shakeVersion whenever a type stored in the Shake oracle
|
|
| 67 | + -- changes its Binary representation (e.g. fields added/removed
|
|
| 68 | + -- from PackageData or other oracle value types). This forces
|
|
| 69 | + -- Shake to wipe the stale database instead of crashing on
|
|
| 70 | + -- deserialisation.
|
|
| 71 | + shakeVersion = "2"
|
|
| 72 | + , shakeChange = ChangeModtimeAndDigest
|
|
| 67 | 73 | , shakeFiles = buildRoot -/- Base.shakeFilesDir
|
| 68 | 74 | , shakeProgress = Progress.hadrianProgress cwd
|
| 69 | 75 | , shakeRebuild = rebuild
|
| ... | ... | @@ -242,9 +242,6 @@ copyRules = do |
| 242 | 242 | prefix -/- "html/**" <~ return "utils/haddock/haddock-api/resources"
|
| 243 | 243 | prefix -/- "latex/**" <~ return "utils/haddock/haddock-api/resources"
|
| 244 | 244 | |
| 245 | - forM_ [Inplace, Final] $ \iplace ->
|
|
| 246 | - root -/- relativePackageDbPath (PackageDbLoc stage iplace) -/- systemCxxStdLibConf %> \file -> do
|
|
| 247 | - copyFile ("mk" -/- "system-cxx-std-lib-1.0.conf") file
|
|
| 248 | 245 | |
| 249 | 246 | generateRules :: Rules ()
|
| 250 | 247 | generateRules = do
|
| ... | ... | @@ -6,7 +6,6 @@ module Rules.Register ( |
| 6 | 6 | |
| 7 | 7 | import Base
|
| 8 | 8 | import Context
|
| 9 | -import Flavour
|
|
| 10 | 9 | import Oracles.Setting
|
| 11 | 10 | import Hadrian.BuildPath
|
| 12 | 11 | import Hadrian.Expression
|
| ... | ... | @@ -48,14 +47,6 @@ configurePackageRules = do |
| 48 | 47 | isGmp <- (== "gmp") <$> interpretInContext ctx getBignumBackend
|
| 49 | 48 | when isGmp $
|
| 50 | 49 | need [buildP -/- "include/ghc-gmp.h"]
|
| 51 | - when (pkg == text) $ do
|
|
| 52 | - simdutf <- textWithSIMDUTF <$> flavour
|
|
| 53 | - when simdutf $ do
|
|
| 54 | - -- This is required, otherwise you get Error: hadrian:
|
|
| 55 | - -- Encountered missing or private dependencies:
|
|
| 56 | - -- system-cxx-std-lib ==1.0
|
|
| 57 | - cxxStdLib <- systemCxxStdLibConfPath $ PackageDbLoc stage Inplace
|
|
| 58 | - need [cxxStdLib]
|
|
| 59 | 50 | Cabal.configurePackage ctx
|
| 60 | 51 | |
| 61 | 52 | root -/- "**/autogen/cabal_macros.h" %> \out -> do
|
| ... | ... | @@ -105,6 +96,12 @@ registerPackageRules rs stage iplace = do |
| 105 | 96 | target (Context stage compiler vanilla iplace) (GhcPkg Recache stage) [] []
|
| 106 | 97 | writeFileLines stamp []
|
| 107 | 98 | |
| 99 | + -- Special rule for registering system-cxx-std-lib
|
|
| 100 | + root -/- relativePackageDbPath (PackageDbLoc stage iplace) -/- systemCxxStdLibConf %> \file -> do
|
|
| 101 | + copyFile ("mk" -/- "system-cxx-std-lib-1.0.conf") file
|
|
| 102 | + buildWithResources rs $
|
|
| 103 | + target (Context stage compiler vanilla iplace) (GhcPkg Recache stage) [] []
|
|
| 104 | + |
|
| 108 | 105 | -- Register a package.
|
| 109 | 106 | root -/- relativePackageDbPath (PackageDbLoc stage iplace) -/- "*.conf" %> \conf -> do
|
| 110 | 107 | historyDisable
|
| ... | ... | @@ -549,6 +549,8 @@ allocGroupOnNode (uint32_t node, W_ n) |
| 549 | 549 | ln++;
|
| 550 | 550 | }
|
| 551 | 551 | |
| 552 | + // If no free blocks exist then allocate a new megablock and keep just a
|
|
| 553 | + // chunk of it.
|
|
| 552 | 554 | if (ln == NUM_FREE_LISTS) {
|
| 553 | 555 | #if 0 /* useful for debugging fragmentation */
|
| 554 | 556 | if ((W_)mblocks_allocated * BLOCKS_PER_MBLOCK * BLOCK_SIZE_W
|
| ... | ... | @@ -1020,6 +1022,9 @@ freeGroup(bdescr *p) |
| 1020 | 1022 | }
|
| 1021 | 1023 | |
| 1022 | 1024 | // coalesce backwards
|
| 1025 | + // Note that p is not a megablock/megagroup, so there are still live blocks on
|
|
| 1026 | + // this megablock. Hence we can't coalesce backwards past the first block
|
|
| 1027 | + // descriptor of this megablock.
|
|
| 1023 | 1028 | if (p != FIRST_BDESCR(MBLOCK_ROUND_DOWN(p)))
|
| 1024 | 1029 | {
|
| 1025 | 1030 | bdescr *prev;
|
| ... | ... | @@ -95,6 +95,10 @@ typedef struct free_list { |
| 95 | 95 | } free_list;
|
| 96 | 96 | |
| 97 | 97 | static free_list *free_list_head;
|
| 98 | + |
|
| 99 | +// The address in `mblock_address_space` just after the highest MBlock. This
|
|
| 100 | +// will be the address of the next new MBlock committed when the free list is
|
|
| 101 | +// empty.
|
|
| 98 | 102 | static W_ mblock_high_watermark;
|
| 99 | 103 | /*
|
| 100 | 104 | * it is quite important that these are in the same cache line as they
|
| ... | ... | @@ -103,22 +107,47 @@ static W_ mblock_high_watermark; |
| 103 | 107 | */
|
| 104 | 108 | struct mblock_address_range mblock_address_space = { 0, 0, {} };
|
| 105 | 109 | |
| 110 | +// Search for the first committed MBlock at or after startingAt.
|
|
| 111 | +//
|
|
| 112 | +// start_iter [in/out]: The free_list or a subset of it. Must contain all
|
|
| 113 | +// entries for MBlocks at or after startingAt. On return this is set to the
|
|
| 114 | +// free_list entry just after the returned MBlock. If no MBlock was found, This
|
|
| 115 | +// is set to NULL (the search will have reached the end of the free list).
|
|
| 116 | +//
|
|
| 117 | +// startingAt [in]: address from which to start searching. This must be to the
|
|
| 118 | +// start of an MBlock.
|
|
| 119 | +//
|
|
| 120 | +// return: The address of the committed MBlock. NULL if no committed MBLock was
|
|
| 121 | +// found.
|
|
| 122 | +//
|
|
| 106 | 123 | static void *getAllocatedMBlock(free_list **start_iter, W_ startingAt)
|
| 107 | 124 | {
|
| 125 | + // We simultaneously traverse the free list and the mblock_address_space.
|
|
| 108 | 126 | free_list *iter;
|
| 109 | 127 | W_ p = startingAt;
|
| 110 | 128 | |
| 111 | 129 | for (iter = *start_iter; iter != NULL; iter = iter->next)
|
| 112 | 130 | {
|
| 131 | + // The current free MBlock, `iter`, is past the current MBlock, `p`.
|
|
| 132 | + // This means that `p` is committed (if it was free, then we would have
|
|
| 133 | + // found it on the free list). Stop searching.
|
|
| 113 | 134 | if (p < iter->address)
|
| 114 | 135 | break;
|
| 115 | 136 | |
| 137 | + // Note that if `p > iter->address`, then we don't bump `p`. This just
|
|
| 138 | + // means we are skipping entries in the free list that correspond to
|
|
| 139 | + // MBlocks before `startingAt`.
|
|
| 116 | 140 | if (p == iter->address)
|
| 141 | + // Move to the next MBlock. The MBlock may be committed,
|
|
| 142 | + // uncommitted, or even past mblock_high_watermark.
|
|
| 117 | 143 | p += iter->size;
|
| 118 | 144 | }
|
| 119 | 145 | |
| 146 | + // Output current free list entry.
|
|
| 120 | 147 | *start_iter = iter;
|
| 121 | 148 | |
| 149 | + // If we reached mblock_high_watermark, then we didn't find any committed
|
|
| 150 | + // MBlocks.
|
|
| 122 | 151 | if (p >= mblock_high_watermark)
|
| 123 | 152 | return NULL;
|
| 124 | 153 | |
| ... | ... | @@ -152,6 +181,11 @@ void * getNextMBlock(void **state STG_UNUSED, void *mblock) |
| 152 | 181 | return getAllocatedMBlock(casted_state, (W_)mblock + MBLOCK_SIZE);
|
| 153 | 182 | }
|
| 154 | 183 | |
| 184 | +// Used to implement getCommittedMBlocks. Search the free list for n contiguous
|
|
| 185 | +// free MBlocks, and commit those MBlocks, updating the free_list. Returns the
|
|
| 186 | +// address of the start of those MBlocks. Returns NULL if no n contiguous
|
|
| 187 | +// MBlocks were found in the free list. Unlike getFreshMBlocks, this doesn't
|
|
| 188 | +// attempt to allocate new MBlocks past mblock_high_watermark.
|
|
| 155 | 189 | static void *getReusableMBlocks(uint32_t n)
|
| 156 | 190 | {
|
| 157 | 191 | struct free_list *iter;
|
| ... | ... | @@ -163,7 +197,10 @@ static void *getReusableMBlocks(uint32_t n) |
| 163 | 197 | if (iter->size < size)
|
| 164 | 198 | continue;
|
| 165 | 199 | |
| 200 | + // We've found a large enough group of MBlocks.
|
|
| 166 | 201 | addr = (void*)iter->address;
|
| 202 | + |
|
| 203 | + // Update the free list.
|
|
| 167 | 204 | iter->address += size;
|
| 168 | 205 | iter->size -= size;
|
| 169 | 206 | if (iter->size == 0) {
|
| ... | ... | @@ -190,6 +227,9 @@ static void *getReusableMBlocks(uint32_t n) |
| 190 | 227 | return NULL;
|
| 191 | 228 | }
|
| 192 | 229 | |
| 230 | +// Used to implement getCommittedMBlocks. Commit n new MBlocks starting at
|
|
| 231 | +// mblock_high_watermark. May exit with an out of memory error if we've passed
|
|
| 232 | +// mblock_address_space.end (this is unlikely).
|
|
| 193 | 233 | static void *getFreshMBlocks(uint32_t n)
|
| 194 | 234 | {
|
| 195 | 235 | W_ size = MBLOCK_SIZE * (W_)n;
|
| ... | ... | @@ -207,6 +247,8 @@ static void *getFreshMBlocks(uint32_t n) |
| 207 | 247 | return addr;
|
| 208 | 248 | }
|
| 209 | 249 | |
| 250 | +// Commit n new MBlocks. Tries to reuse freed MBlocks, else commits new
|
|
| 251 | +// MBlock(s) at mblock_high_watermark.
|
|
| 210 | 252 | static void *getCommittedMBlocks(uint32_t n)
|
| 211 | 253 | {
|
| 212 | 254 | void *p;
|
| ... | ... | @@ -220,6 +262,11 @@ static void *getCommittedMBlocks(uint32_t n) |
| 220 | 262 | return p;
|
| 221 | 263 | }
|
| 222 | 264 | |
| 265 | +// Decommit n contiguous MBlocks starting at the given address.
|
|
| 266 | +//
|
|
| 267 | +// addr [in]: address of the start of the n MBlocks (in mblock_address_space).
|
|
| 268 | +//
|
|
| 269 | +// n [in]: number of contiguous MBlocks to decommit.
|
|
| 223 | 270 | static void decommitMBlocks(char *addr, uint32_t n)
|
| 224 | 271 | {
|
| 225 | 272 | struct free_list *iter, *prev;
|
| ... | ... | @@ -228,17 +275,24 @@ static void decommitMBlocks(char *addr, uint32_t n) |
| 228 | 275 | |
| 229 | 276 | osDecommitMemory(addr, size);
|
| 230 | 277 | |
| 278 | + // Update the free list.
|
|
| 231 | 279 | prev = NULL;
|
| 232 | 280 | for (iter = free_list_head; iter != NULL; iter = iter->next)
|
| 233 | 281 | {
|
| 234 | 282 | prev = iter;
|
| 235 | 283 | |
| 284 | + // iter is still entirely behind and not contiguous with the MBlocks so
|
|
| 285 | + // continue traversing free_list.
|
|
| 236 | 286 | if (iter->address + iter->size < address)
|
| 237 | 287 | continue;
|
| 238 | 288 | |
| 289 | + // The MBlocks are after and contiguous to iter. Simply modify the
|
|
| 290 | + // current entry to include n more MBlocks and possibly coalesce.
|
|
| 239 | 291 | if (iter->address + iter->size == address) {
|
| 240 | 292 | iter->size += size;
|
| 241 | 293 | |
| 294 | + // If the current free_list entry now reaches mblock_high_watermark,
|
|
| 295 | + // remove the entry and decrement mblock_high_watermark.
|
|
| 242 | 296 | if (address + size == mblock_high_watermark) {
|
| 243 | 297 | mblock_high_watermark -= iter->size;
|
| 244 | 298 | if (iter->prev) {
|
| ... | ... | @@ -251,6 +305,8 @@ static void decommitMBlocks(char *addr, uint32_t n) |
| 251 | 305 | return;
|
| 252 | 306 | }
|
| 253 | 307 | |
| 308 | + // If the current free_list entry now reaches the next free_list
|
|
| 309 | + // entry, coalesce them.
|
|
| 254 | 310 | if (iter->next &&
|
| 255 | 311 | iter->next->address == iter->address + iter->size) {
|
| 256 | 312 | struct free_list *next;
|
| ... | ... | @@ -269,6 +325,8 @@ static void decommitMBlocks(char *addr, uint32_t n) |
| 269 | 325 | stgFree(next);
|
| 270 | 326 | }
|
| 271 | 327 | return;
|
| 328 | + |
|
| 329 | + // The MBlocks are before and contiguous to iter.
|
|
| 272 | 330 | } else if (address + size == iter->address) {
|
| 273 | 331 | iter->address = address;
|
| 274 | 332 | iter->size += size;
|
| ... | ... | @@ -280,6 +338,9 @@ static void decommitMBlocks(char *addr, uint32_t n) |
| 280 | 338 | ASSERT(iter->prev->address + iter->prev->size < iter->address);
|
| 281 | 339 | }
|
| 282 | 340 | return;
|
| 341 | + |
|
| 342 | + // The MBlocks are before and not contiguous to iter. Insert a new entry
|
|
| 343 | + // just before iter.
|
|
| 283 | 344 | } else {
|
| 284 | 345 | struct free_list *new_iter;
|
| 285 | 346 | |
| ... | ... | @@ -311,6 +372,7 @@ static void decommitMBlocks(char *addr, uint32_t n) |
| 311 | 372 | if (address + size == mblock_high_watermark) {
|
| 312 | 373 | mblock_high_watermark -= size;
|
| 313 | 374 | } else {
|
| 375 | + // Add a new entry to the end of the free list.
|
|
| 314 | 376 | struct free_list *new_iter;
|
| 315 | 377 | |
| 316 | 378 | new_iter = stgMallocBytes(sizeof(struct free_list), "freeMBlocks");
|