diff --git a/compiler/GHC/Driver/Session.hs b/compiler/GHC/Driver/Session.hs index b8eaf91f37b795dc17d4438e3b7dad76fed10fa0..c98ff74531de822f351b5d2b3e6ccbeee113ac29 100644 --- a/compiler/GHC/Driver/Session.hs +++ b/compiler/GHC/Driver/Session.hs @@ -3611,7 +3611,8 @@ compilerInfo dflags ("GHC Profiled", showBool hostIsProfiled), ("Debug on", showBool debugIsOn), ("LibDir", topDir dflags), - -- The path of the global package database used by GHC + -- This is always an absolute path, unlike "Relative Global Package DB" which is + -- in the settings file. ("Global Package DB", globalPackageDatabasePath dflags) ] where diff --git a/compiler/GHC/Settings/IO.hs b/compiler/GHC/Settings/IO.hs index 1807b8e7eeb12723ac27156196a03e4221ba9209..b48fca86e778069b493c0df26d9bdde3fec5ccf3 100644 --- a/compiler/GHC/Settings/IO.hs +++ b/compiler/GHC/Settings/IO.hs @@ -118,8 +118,14 @@ initSettings top_dir = do ldIsGnuLd <- getBooleanSetting "ld is GNU ld" arSupportsDashL <- getBooleanSetting "ar supports -L" - let globalpkgdb_path = installed "package.conf.d" - ghc_usage_msg_path = installed "ghc-usage.txt" + + -- The package database is either a relative path to the location of the settings file + -- OR an absolute path. + -- In case the path is absolute then top_dir </> abs_path == abs_path + -- the path is relative then top_dir </> rel_path == top_dir </> rel_path + globalpkgdb_path <- installed <$> getSetting "Relative Global Package DB" + + let ghc_usage_msg_path = installed "ghc-usage.txt" ghci_usage_msg_path = installed "ghci-usage.txt" -- For all systems, unlit, split, mangle are GHC utilities diff --git a/hadrian/bindist/Makefile b/hadrian/bindist/Makefile index 32f9952c8ca11205610608fcd88fdf085ad194e3..d58235464c80910231416130b29e426e1f73b620 100644 --- a/hadrian/bindist/Makefile +++ b/hadrian/bindist/Makefile @@ -141,6 +141,7 @@ lib/settings : config.mk @echo ',("Leading underscore", "$(LeadingUnderscore)")' >> $@ @echo ',("Use LibFFI", "$(UseLibffiForAdjustors)")' >> $@ @echo ',("RTS expects libdw", "$(GhcRtsWithLibdw)")' >> $@ + @echo ',("Relative Global Package DB", "package.conf.d")' >> $@ @echo "]" >> $@ # We need to install binaries relative to libraries. diff --git a/hadrian/src/Rules/Generate.hs b/hadrian/src/Rules/Generate.hs index 764d7b7990d87ff2aadccb07866126d6594d1311..3bcd1d8a6096babbaee829dc7d508234f228c8f4 100644 --- a/hadrian/src/Rules/Generate.hs +++ b/hadrian/src/Rules/Generate.hs @@ -422,6 +422,7 @@ generateSettings = do , ("Leading underscore", queryTarget (yesNo . tgtSymbolsHaveLeadingUnderscore)) , ("Use LibFFI", expr $ yesNo <$> useLibffiForAdjustors) , ("RTS expects libdw", yesNo <$> getFlag UseLibdw) + , ("Relative Global Package DB", return "package.conf.d" ) ] let showTuple (k, v) = "(" ++ show k ++ ", " ++ show v ++ ")" pure $ case settings of diff --git a/libraries/ghc-boot/GHC/Settings/Utils.hs b/libraries/ghc-boot/GHC/Settings/Utils.hs index 4ccbbf23b628eedfe1d123ba17d04dc0cf294c16..35706fbc9a6ae0e232eb90a75456d5dc142a010f 100644 --- a/libraries/ghc-boot/GHC/Settings/Utils.hs +++ b/libraries/ghc-boot/GHC/Settings/Utils.hs @@ -8,6 +8,7 @@ import qualified Data.Map as Map import GHC.BaseDir import GHC.Platform.ArchOS +import System.FilePath maybeRead :: Read a => String -> Maybe a maybeRead str = case reads str of @@ -42,6 +43,12 @@ getTargetArchOS settingsFile settings = ArchOS <$> readRawSetting settingsFile settings "target arch" <*> readRawSetting settingsFile settings "target os" +getGlobalPackageDb :: FilePath -> RawSettings -> Either String FilePath +getGlobalPackageDb settingsFile settings = do + rel_db <- getRawSetting settingsFile settings "Relative Global Package DB" + return (dropFileName settingsFile </> rel_db) + + getRawSetting :: FilePath -> RawSettings -> String -> Either String String diff --git a/utils/ghc-pkg/Main.hs b/utils/ghc-pkg/Main.hs index 236e73928cf9b91e76b51aeae401ad8055fd2e88..767fa69129f9f2126ad5849de44142382540f51b 100644 --- a/utils/ghc-pkg/Main.hs +++ b/utils/ghc-pkg/Main.hs @@ -28,7 +28,7 @@ import qualified GHC.Unit.Database as GhcPkg import GHC.Unit.Database hiding (mkMungePathUrl) import GHC.HandleEncoding import GHC.BaseDir (getBaseDir) -import GHC.Settings.Utils (getTargetArchOS, maybeReadFuzzy) +import GHC.Settings.Utils (getTargetArchOS, maybeReadFuzzy, getGlobalPackageDb, RawSettings) import GHC.Platform.Host (hostPlatformArchOS) import GHC.UniqueSubdir (uniqueSubdir) import qualified GHC.Data.ShortText as ST @@ -582,6 +582,21 @@ allPackagesInStack = concatMap packages stackUpTo :: FilePath -> PackageDBStack -> PackageDBStack stackUpTo to_modify = dropWhile ((/= to_modify) . location) +readFromSettingsFile :: FilePath + -> (FilePath -> RawSettings -> Either String b) + -> IO (Either String b) +readFromSettingsFile settingsFile f = do + settingsStr <- readFile settingsFile + pure $ do + mySettings <- case maybeReadFuzzy settingsStr of + Just s -> pure $ Map.fromList s + -- It's excusable to not have a settings file (for now at + -- least) but completely inexcusable to have a malformed one. + Nothing -> Left $ "Can't parse settings file " ++ show settingsFile + case f settingsFile mySettings of + Right archOS -> Right archOS + Left e -> Left e + getPkgDatabases :: Verbosity -> GhcPkg.DbOpenMode mode DbModifySelector -> Bool -- use the user db @@ -605,24 +620,38 @@ getPkgDatabases verbosity mode use_user use_cache expand_vars my_flags = do -- location is passed to the binary using the --global-package-db flag by the -- wrapper script. let err_msg = "missing --global-package-db option, location of global package database unknown\n" - global_conf <- + (top_dir, global_conf) <- case [ f | FlagGlobalConfig f <- my_flags ] of -- See Note [Base Dir] for more information on the base dir / top dir. [] -> do mb_dir <- getBaseDir case mb_dir of Nothing -> die err_msg Just dir -> do - r <- lookForPackageDBIn dir - case r of - Nothing -> die ("Can't find package database in " ++ dir) - Just path -> return path - fs -> return (last fs) - - -- The value of the $topdir variable used in some package descriptions - -- Note that the way we calculate this is slightly different to how it - -- is done in ghc itself. We rely on the convention that the global - -- package db lives in ghc's libdir. - top_dir <- absolutePath (takeDirectory global_conf) + -- Look for where it is given in the settings file, if marked there. + let settingsFile = dir </> "settings" + exists_settings_file <- doesFileExist settingsFile + erel_db <- + if exists_settings_file + then readFromSettingsFile settingsFile getGlobalPackageDb + else pure (Left ("Settings file doesn't exist: " ++ settingsFile)) + + case erel_db of + Right rel_db -> return (dir, dir </> rel_db) + -- If the version of GHC doesn't have this field or the settings file + -- doesn't exist for some reason, look in the libdir. + Left err -> do + r <- lookForPackageDBIn dir + case r of + Nothing -> die (unlines [err, ("Fallback: Can't find package database in " ++ dir)]) + Just path -> return (dir, path) + fs -> do + -- The value of the $topdir variable used in some package descriptions + -- Note that the way we calculate this is slightly different to how it + -- is done in ghc itself. We rely on the convention that the global + -- package db lives in ghc's libdir. + let pkg_db = last fs + top_dir <- absolutePath (takeDirectory pkg_db) + return (top_dir, pkg_db) let no_user_db = FlagNoUserDb `elem` my_flags @@ -641,16 +670,11 @@ getPkgDatabases verbosity mode use_user use_cache expand_vars my_flags = do warn $ "WARNING: settings file doesn't exist " ++ show settingsFile warn "cannot know target platform so guessing target == host (native compiler)." pure hostPlatformArchOS - True -> do - settingsStr <- readFile settingsFile - mySettings <- case maybeReadFuzzy settingsStr of - Just s -> pure $ Map.fromList s - -- It's excusable to not have a settings file (for now at - -- least) but completely inexcusable to have a malformed one. - Nothing -> die $ "Can't parse settings file " ++ show settingsFile - case getTargetArchOS settingsFile mySettings of - Right archOS -> pure archOS + True -> + readFromSettingsFile settingsFile getTargetArchOS >>= \case + Right v -> pure v Left e -> die e + let subdir = uniqueSubdir targetArchOS getFirstSuccess :: [IO a] -> IO (Maybe a)