summaryrefslogtreecommitdiff
path: root/libraries/ghc-boot
diff options
context:
space:
mode:
authorJohn Ericson <John.Ericson@Obsidian.Systems>2019-05-31 19:33:33 -0400
committerMarge Bot <ben+marge-bot@smart-cactus.org>2019-06-19 22:16:16 -0400
commitd406a16ac22e6ad02da0d2c75212614eda09d2cb (patch)
tree21490fb5f60bb5fe5d8e540e4f95b0c49a58fb17 /libraries/ghc-boot
parenta298b96e624155e1860ff009951cb21be43b99d4 (diff)
downloadhaskell-d406a16ac22e6ad02da0d2c75212614eda09d2cb.tar.gz
ghc-pkg needs settings file to un-hardcode target platform
This matches GHC itself getting the target platform from there.
Diffstat (limited to 'libraries/ghc-boot')
-rw-r--r--libraries/ghc-boot/GHC/BaseDir.hs18
-rw-r--r--libraries/ghc-boot/GHC/Settings.hs104
-rw-r--r--libraries/ghc-boot/ghc-boot.cabal.in2
3 files changed, 123 insertions, 1 deletions
diff --git a/libraries/ghc-boot/GHC/BaseDir.hs b/libraries/ghc-boot/GHC/BaseDir.hs
index cc83355144..196ab2eb72 100644
--- a/libraries/ghc-boot/GHC/BaseDir.hs
+++ b/libraries/ghc-boot/GHC/BaseDir.hs
@@ -14,8 +14,9 @@
-- and so needs the top dir location to do that too.
module GHC.BaseDir where
-import Prelude -- See note [Why do we import Prelude here?]
+import Prelude -- See Note [Why do we import Prelude here?]
+import Data.List
import System.FilePath
-- Windows
@@ -26,6 +27,21 @@ import System.Environment (getExecutablePath)
import System.Environment (getExecutablePath)
#endif
+-- | Expand occurrences of the @$topdir@ interpolation in a string.
+expandTopDir :: FilePath -> String -> String
+expandTopDir = expandPathVar "topdir"
+
+-- | @expandPathVar var value str@
+--
+-- replaces occurences of variable @$var@ with @value@ in str.
+expandPathVar :: String -> FilePath -> String -> String
+expandPathVar var value str
+ | Just str' <- stripPrefix ('$':var) str
+ , null str' || isPathSeparator (head str')
+ = value ++ expandPathVar var value str'
+expandPathVar var value (x:xs) = x : expandPathVar var value xs
+expandPathVar _ _ [] = []
+
-- | Calculate the location of the base dir
getBaseDir :: IO (Maybe String)
#if defined(mingw32_HOST_OS)
diff --git a/libraries/ghc-boot/GHC/Settings.hs b/libraries/ghc-boot/GHC/Settings.hs
new file mode 100644
index 0000000000..fc9f95a586
--- /dev/null
+++ b/libraries/ghc-boot/GHC/Settings.hs
@@ -0,0 +1,104 @@
+-- Note [Settings file]
+-- ~~~~~~~~~~~~~~~~~~~~
+--
+-- GHC has a file, `${top_dir}/settings`, which is the main source of run-time
+-- configuration. ghc-pkg needs just a little bit of it: the target platform CPU
+-- arch and OS. It uses that to figure out what subdirectory of `~/.ghc` is
+-- associated with the current version/target.
+--
+-- This module has just enough code to read key value pairs from the settings
+-- file, and read the target platform from those pairs.
+--
+-- The "0" suffix is because the caller will partially apply it, and that will
+-- in turn be used a few more times.
+module GHC.Settings where
+
+import Prelude -- See Note [Why do we import Prelude here?]
+
+import GHC.BaseDir
+import GHC.Platform
+
+import Data.Char (isSpace)
+import Data.Map (Map)
+import qualified Data.Map as Map
+
+-----------------------------------------------------------------------------
+-- parts of settings file
+
+getTargetPlatform
+ :: FilePath -> RawSettings -> Either String Platform
+getTargetPlatform settingsFile mySettings = do
+ let
+ getBooleanSetting = getBooleanSetting0 settingsFile mySettings
+ readSetting :: (Show a, Read a) => String -> Either String a
+ readSetting = readSetting0 settingsFile mySettings
+
+ targetArch <- readSetting "target arch"
+ targetOS <- readSetting "target os"
+ targetWordSize <- readSetting "target word size"
+ targetUnregisterised <- getBooleanSetting "Unregisterised"
+ targetHasGnuNonexecStack <- readSetting "target has GNU nonexec stack"
+ targetHasIdentDirective <- readSetting "target has .ident directive"
+ targetHasSubsectionsViaSymbols <- readSetting "target has subsections via symbols"
+ crossCompiling <- getBooleanSetting "cross compiling"
+
+ pure $ Platform
+ { platformArch = targetArch
+ , platformOS = targetOS
+ , platformWordSize = targetWordSize
+ , platformUnregisterised = targetUnregisterised
+ , platformHasGnuNonexecStack = targetHasGnuNonexecStack
+ , platformHasIdentDirective = targetHasIdentDirective
+ , platformHasSubsectionsViaSymbols = targetHasSubsectionsViaSymbols
+ , platformIsCrossCompiling = crossCompiling
+ }
+
+-----------------------------------------------------------------------------
+-- settings file helpers
+
+type RawSettings = Map String String
+
+-- | See Note [Settings file] for "0" suffix
+getSetting0
+ :: FilePath -> RawSettings -> String -> Either String String
+getSetting0 settingsFile mySettings key = case Map.lookup key mySettings of
+ Just xs -> Right xs
+ Nothing -> Left $ "No entry for " ++ show key ++ " in " ++ show settingsFile
+
+-- | See Note [Settings file] for "0" suffix
+getFilePathSetting0
+ :: FilePath -> FilePath -> RawSettings -> String -> Either String String
+getFilePathSetting0 top_dir settingsFile mySettings key =
+ expandTopDir top_dir <$> getSetting0 settingsFile mySettings key
+
+-- | See Note [Settings file] for "0" suffix
+getBooleanSetting0
+ :: FilePath -> RawSettings -> String -> Either String Bool
+getBooleanSetting0 settingsFile mySettings key = do
+ rawValue <- getSetting0 settingsFile mySettings key
+ case rawValue of
+ "YES" -> Right True
+ "NO" -> Right False
+ xs -> Left $ "Bad value for " ++ show key ++ ": " ++ show xs
+
+-- | See Note [Settings file] for "0" suffix
+readSetting0
+ :: (Show a, Read a) => FilePath -> RawSettings -> String -> Either String a
+readSetting0 settingsFile mySettings key = case Map.lookup key mySettings of
+ Just xs -> case maybeRead xs of
+ Just v -> Right v
+ Nothing -> Left $ "Failed to read " ++ show key ++ " value " ++ show xs
+ Nothing -> Left $ "No entry for " ++ show key ++ " in " ++ show settingsFile
+
+-----------------------------------------------------------------------------
+-- read helpers
+
+maybeRead :: Read a => String -> Maybe a
+maybeRead str = case reads str of
+ [(x, "")] -> Just x
+ _ -> Nothing
+
+maybeReadFuzzy :: Read a => String -> Maybe a
+maybeReadFuzzy str = case reads str of
+ [(x, s)] | all isSpace s -> Just x
+ _ -> Nothing
diff --git a/libraries/ghc-boot/ghc-boot.cabal.in b/libraries/ghc-boot/ghc-boot.cabal.in
index 15721b1489..650f7518dc 100644
--- a/libraries/ghc-boot/ghc-boot.cabal.in
+++ b/libraries/ghc-boot/ghc-boot.cabal.in
@@ -44,10 +44,12 @@ Library
GHC.ForeignSrcLang
GHC.HandleEncoding
GHC.Platform
+ GHC.Settings
build-depends: base >= 4.7 && < 4.14,
binary == 0.8.*,
bytestring == 0.10.*,
+ containers >= 0.5 && < 0.7,
directory >= 1.2 && < 1.4,
filepath >= 1.3 && < 1.5,
ghc-boot-th == @ProjectVersionMunged@