[Git][ghc/ghc][wip/26661] hadrian: Remove old package.conf files when generating new ones
Zubin pushed to branch wip/26661 at Glasgow Haskell Compiler / GHC Commits: 4c75a5df by Zubin Duggal at 2026-06-10T16:53:58+05:30 hadrian: Remove old package.conf files when generating new ones Old package.conf files might exists with different hashes, causing issues like #26661 Fixes #26661 - - - - - 1 changed file: - hadrian/src/Hadrian/Haskell/Cabal/Parse.hs Changes: ===================================== hadrian/src/Hadrian/Haskell/Cabal/Parse.hs ===================================== @@ -15,6 +15,8 @@ module Hadrian.Haskell.Cabal.Parse ( ) where import Data.Bifunctor +import Data.Char (isDigit) +import Data.IORef import Data.List.Extra import Development.Shake import qualified Distribution.Compat.Graph as Graph @@ -394,35 +396,54 @@ registerPackage rs context = do -- Note: the @cPath@ is ignored. The path that's used is the 'buildDir' path -- from the local build info @lbi@. lbi <- liftIO $ C.getPersistBuildConfig Nothing (C.makeSymbolicPath cPath) - liftIO $ register db_path pid pd lbi + -- This runs `ghc --abi-hash`, so do it before acquiring the package + -- database resource below. + installedPkgInfo <- liftIO $ generateRegistrationInfo pd lbi + + let pkg_name = pkgName (package context) + -- Matches "<name>.conf" and "<name>-<version>[-<hash>].conf", but + -- not packages `pkg_name` merely prefixes: versions start with a + -- digit, package name components don't (for "ghc", + -- "ghc-9.15.1-abcd.conf" matches but "ghc-boot-9.15.1.conf" doesn't). + isPkgConf f = case stripPrefix (pkg_name ++ "-") (takeBaseName f) of + Just (c:_) -> isDigit c + _ -> takeBaseName f == pkg_name + + -- Unlike `ghc-pkg update/register` (used to populate the inplace and + -- stage0 databases), writing the .conf file directly doesn't remove + -- units this package was previously registered under. Stale .conf files + -- from earlier builds (with a different unit-id hash or version) make + -- this package's modules ambiguous (#26661), so delete them before + -- writing the new .conf file. + -- + -- Mutating the database needs exclusive access: a concurrent ghc-pkg + -- crashes if a .conf file it has seen disappears before it reads it. + -- See the comment about the package-db resource in `packageRules`. + withResources rs $ liftIO $ do + confs <- getDirectoryFilesIO db_path ["*.conf"] + let stale = [ f | f <- confs, isPkgConf f, takeBaseName f /= pid ] + unless (null stale) $ removeFiles db_path stale + writeUTF8File (db_path > pid <.> "conf") + (CP.showInstalledPackageInfo installedPkgInfo) -- Then after the register, which just writes the .conf file, do the recache step. buildWithResources rs $ target context (GhcPkg Recache (stage context)) [] [] -- This is copied and simplified from Cabal, because we want to install the package -- into a different package database to the one it was configured against. -register :: FilePath - -> String -- ^ Package Identifier - -> C.PackageDescription - -> LocalBuildInfo - -> IO () -register pkg_db pid pd lbi - = withLibLBI pd lbi $ \lib clbi -> do - - when reloc $ error "register does not support reloc" - installedPkgInfo <- generateRegistrationInfo pd lbi lib clbi - writeRegistrationFile installedPkgInfo - - where - regFile = pkg_db > pid <.> "conf" - reloc = relocatable lbi - - generateRegistrationInfo pkg lbi lib clbi = do - abi_hash <- C.mkAbiHash <$> GHC.libAbiHash C.silent pkg lbi lib clbi - return (C.absoluteInstalledPackageInfo pkg abi_hash lib lbi clbi) - - writeRegistrationFile installedPkgInfo = do - writeUTF8File regFile (CP.showInstalledPackageInfo installedPkgInfo) +generateRegistrationInfo :: C.PackageDescription + -> LocalBuildInfo + -> IO Installed.InstalledPackageInfo +generateRegistrationInfo pd lbi = do + when (relocatable lbi) $ error "register does not support reloc" + ref <- newIORef Nothing + withLibLBI pd lbi $ \lib clbi -> do + abi_hash <- C.mkAbiHash <$> GHC.libAbiHash C.silent pd lbi lib clbi + writeIORef ref (Just (C.absoluteInstalledPackageInfo pd abi_hash lib lbi clbi)) + mipi <- readIORef ref + case mipi of + Just ipi -> return ipi + Nothing -> error "generateRegistrationInfo: package has no library" -- | Build autogenerated files @autogen/cabal_macros.h@ and @autogen/Paths_*.hs@. View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/4c75a5df2a2a1b38b9f601ba00d9c056... -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/4c75a5df2a2a1b38b9f601ba00d9c056... You're receiving this email because of your account on gitlab.haskell.org.
participants (1)
-
Zubin (@wz1000)