summaryrefslogtreecommitdiff
path: root/libraries/ghc-boot
diff options
context:
space:
mode:
authorSylvain Henry <sylvain@haskus.fr>2020-07-21 19:15:59 +0200
committerMarge Bot <ben+marge-bot@smart-cactus.org>2020-07-25 00:45:08 -0400
commit7721b923d53fb9eb93f80bb93b4c3bd976c05b4c (patch)
treeedc61b1ed9885e442c7327460052f10d1ca589fa /libraries/ghc-boot
parent73145d57f961c73b5853da7881d6a21e48e05909 (diff)
downloadhaskell-7721b923d53fb9eb93f80bb93b4c3bd976c05b4c.tar.gz
Move GHC.Platform into the compiler
Previously it was in ghc-boot so that ghc-pkg could use it. However it wasn't necessary because ghc-pkg only uses a subset of it: reading target arch and OS from the settings file. This is now done via GHC.Platform.ArchOS (was called PlatformMini before).
Diffstat (limited to 'libraries/ghc-boot')
-rw-r--r--libraries/ghc-boot/GHC/Platform.hs356
-rw-r--r--libraries/ghc-boot/GHC/Platform/ArchOS.hs152
-rw-r--r--libraries/ghc-boot/GHC/Settings/Platform.hs103
-rw-r--r--libraries/ghc-boot/GHC/Settings/Utils.hs57
-rw-r--r--libraries/ghc-boot/GHC/UniqueSubdir.hs14
-rw-r--r--libraries/ghc-boot/ghc-boot.cabal.in3
-rw-r--r--libraries/ghc-boot/ghc.mk15
7 files changed, 221 insertions, 479 deletions
diff --git a/libraries/ghc-boot/GHC/Platform.hs b/libraries/ghc-boot/GHC/Platform.hs
deleted file mode 100644
index 9191dda44f..0000000000
--- a/libraries/ghc-boot/GHC/Platform.hs
+++ /dev/null
@@ -1,356 +0,0 @@
-{-# LANGUAGE LambdaCase, ScopedTypeVariables #-}
-
--- | A description of the platform we're compiling for.
---
-module GHC.Platform
- ( PlatformMini(..)
- , PlatformWordSize(..)
- , PlatformConstants(..)
- , Platform(..)
- , platformArch
- , platformOS
- , Arch(..)
- , OS(..)
- , ArmISA(..)
- , ArmISAExt(..)
- , ArmABI(..)
- , PPC_64ABI(..)
- , ByteOrder(..)
- , target32Bit
- , isARM
- , osElfTarget
- , osMachOTarget
- , osSubsectionsViaSymbols
- , platformUsesFrameworks
- , platformWordSizeInBytes
- , platformWordSizeInBits
- , platformMinInt
- , platformMaxInt
- , platformMaxWord
- , platformInIntRange
- , platformInWordRange
- , PlatformMisc(..)
- , stringEncodeArch
- , stringEncodeOS
- , SseVersion (..)
- , BmiVersion (..)
- )
-where
-
-import Prelude -- See Note [Why do we import Prelude here?]
-import GHC.Read
-import GHC.ByteOrder (ByteOrder(..))
-import GHC.Platform.Constants
-import Data.Word
-import Data.Int
-
--- | Contains the bare-bones arch and os information. This isn't enough for
--- code gen, but useful for tasks where we can fall back upon the host
--- platform, as this is all we know about the host platform.
-data PlatformMini
- = PlatformMini
- { platformMini_arch :: Arch
- , platformMini_os :: OS
- }
- deriving (Read, Show, Eq)
-
--- | Contains enough information for the native code generator to emit
--- code for this platform.
-data Platform = Platform
- { platformMini :: !PlatformMini
- , platformWordSize :: !PlatformWordSize -- ^ Word size
- , platformByteOrder :: !ByteOrder -- ^ Byte order (endianness)
- , platformUnregisterised :: !Bool
- , platformHasGnuNonexecStack :: !Bool
- , platformHasIdentDirective :: !Bool
- , platformHasSubsectionsViaSymbols :: !Bool
- , platformIsCrossCompiling :: !Bool
- , platformLeadingUnderscore :: !Bool -- ^ Symbols need underscore prefix
- , platformTablesNextToCode :: !Bool
- -- ^ Determines whether we will be compiling info tables that reside just
- -- before the entry code, or with an indirection to the entry code. See
- -- TABLES_NEXT_TO_CODE in includes/rts/storage/InfoTables.h.
- , platformConstants :: !PlatformConstants
- -- ^ Constants such as structure offsets, type sizes, etc.
- }
- deriving (Read, Show, Eq)
-
-data PlatformWordSize
- = PW4 -- ^ A 32-bit platform
- | PW8 -- ^ A 64-bit platform
- deriving (Eq)
-
-instance Show PlatformWordSize where
- show PW4 = "4"
- show PW8 = "8"
-
-instance Read PlatformWordSize where
- readPrec = do
- i :: Int <- readPrec
- case i of
- 4 -> return PW4
- 8 -> return PW8
- other -> fail ("Invalid PlatformWordSize: " ++ show other)
-
-platformWordSizeInBytes :: Platform -> Int
-platformWordSizeInBytes p =
- case platformWordSize p of
- PW4 -> 4
- PW8 -> 8
-
-platformWordSizeInBits :: Platform -> Int
-platformWordSizeInBits p = platformWordSizeInBytes p * 8
-
--- | Legacy accessor
-platformArch :: Platform -> Arch
-platformArch = platformMini_arch . platformMini
-
--- | Legacy accessor
-platformOS :: Platform -> OS
-platformOS = platformMini_os . platformMini
-
--- | Architectures that the native code generator knows about.
--- TODO: It might be nice to extend these constructors with information
--- about what instruction set extensions an architecture might support.
---
-data Arch
- = ArchUnknown
- | ArchX86
- | ArchX86_64
- | ArchPPC
- | ArchPPC_64
- { ppc_64ABI :: PPC_64ABI
- }
- | ArchS390X
- | ArchSPARC
- | ArchSPARC64
- | ArchARM
- { armISA :: ArmISA
- , armISAExt :: [ArmISAExt]
- , armABI :: ArmABI
- }
- | ArchARM64
- | ArchAlpha
- | ArchMipseb
- | ArchMipsel
- | ArchJavaScript
- deriving (Read, Show, Eq)
-
--- Note [Platform Syntax]
--- ~~~~~~~~~~~~~~~~~~~~~~
--- There is a very loose encoding of platforms shared by many tools we are
--- encoding to here. GNU Config (http://git.savannah.gnu.org/cgit/config.git),
--- and LLVM's http://llvm.org/doxygen/classllvm_1_1Triple.html are perhaps the
--- most definitional parsers. The basic syntax is a list of '-'-separated
--- components. The Unix 'uname' command syntax is related but briefer.
---
--- Those two parsers are quite forgiving, and even the 'config.sub'
--- normalization is forgiving too. The "best" way to encode a platform is
--- therefore somewhat a matter of taste.
---
--- The 'stringEncode*' functions here convert each part of GHC's structured
--- notion of a platform into one dash-separated component.
-
--- | See Note [Platform Syntax].
-stringEncodeArch :: Arch -> String
-stringEncodeArch = \case
- ArchUnknown -> "unknown"
- ArchX86 -> "i386"
- ArchX86_64 -> "x86_64"
- ArchPPC -> "powerpc"
- ArchPPC_64 { ppc_64ABI = abi } -> case abi of
- ELF_V1 -> "powerpc64"
- ELF_V2 -> "powerpc64le"
- ArchS390X -> "s390x"
- ArchSPARC -> "sparc"
- ArchSPARC64 -> "sparc64"
- ArchARM { armISA = isa, armISAExt = _, armABI = _ } -> "arm" ++ vsuf
- where
- vsuf = case isa of
- ARMv5 -> "v5"
- ARMv6 -> "v6"
- ARMv7 -> "v7"
- ArchARM64 -> "aarch64"
- ArchAlpha -> "alpha"
- ArchMipseb -> "mipseb"
- ArchMipsel -> "mipsel"
- ArchJavaScript -> "js"
-
-isARM :: Arch -> Bool
-isARM (ArchARM {}) = True
-isARM ArchARM64 = True
-isARM _ = False
-
--- | Operating systems that the native code generator knows about.
--- Having OSUnknown should produce a sensible default, but no promises.
-data OS
- = OSUnknown
- | OSLinux
- | OSDarwin
- | OSSolaris2
- | OSMinGW32
- | OSFreeBSD
- | OSDragonFly
- | OSOpenBSD
- | OSNetBSD
- | OSKFreeBSD
- | OSHaiku
- | OSQNXNTO
- | OSAIX
- | OSHurd
- deriving (Read, Show, Eq)
-
--- | See Note [Platform Syntax].
-stringEncodeOS :: OS -> String
-stringEncodeOS = \case
- OSUnknown -> "unknown"
- OSLinux -> "linux"
- OSDarwin -> "darwin"
- OSSolaris2 -> "solaris2"
- OSMinGW32 -> "mingw32"
- OSFreeBSD -> "freebsd"
- OSDragonFly -> "dragonfly"
- OSOpenBSD -> "openbsd"
- OSNetBSD -> "netbsd"
- OSKFreeBSD -> "kfreebsdgnu"
- OSHaiku -> "haiku"
- OSQNXNTO -> "nto-qnx"
- OSAIX -> "aix"
- OSHurd -> "hurd"
-
--- | ARM Instruction Set Architecture, Extensions and ABI
---
-data ArmISA
- = ARMv5
- | ARMv6
- | ARMv7
- deriving (Read, Show, Eq)
-
-data ArmISAExt
- = VFPv2
- | VFPv3
- | VFPv3D16
- | NEON
- | IWMMX2
- deriving (Read, Show, Eq)
-
-data ArmABI
- = SOFT
- | SOFTFP
- | HARD
- deriving (Read, Show, Eq)
-
--- | PowerPC 64-bit ABI
---
-data PPC_64ABI
- = ELF_V1
- | ELF_V2
- deriving (Read, Show, Eq)
-
--- | This predicate tells us whether the platform is 32-bit.
-target32Bit :: Platform -> Bool
-target32Bit p =
- case platformWordSize p of
- PW4 -> True
- PW8 -> False
-
--- | This predicate tells us whether the OS supports ELF-like shared libraries.
-osElfTarget :: OS -> Bool
-osElfTarget OSLinux = True
-osElfTarget OSFreeBSD = True
-osElfTarget OSDragonFly = True
-osElfTarget OSOpenBSD = True
-osElfTarget OSNetBSD = True
-osElfTarget OSSolaris2 = True
-osElfTarget OSDarwin = False
-osElfTarget OSMinGW32 = False
-osElfTarget OSKFreeBSD = True
-osElfTarget OSHaiku = True
-osElfTarget OSQNXNTO = False
-osElfTarget OSAIX = False
-osElfTarget OSHurd = True
-osElfTarget OSUnknown = False
- -- Defaulting to False is safe; it means don't rely on any
- -- ELF-specific functionality. It is important to have a default for
- -- portability, otherwise we have to answer this question for every
- -- new platform we compile on (even unreg).
-
--- | This predicate tells us whether the OS support Mach-O shared libraries.
-osMachOTarget :: OS -> Bool
-osMachOTarget OSDarwin = True
-osMachOTarget _ = False
-
-osUsesFrameworks :: OS -> Bool
-osUsesFrameworks OSDarwin = True
-osUsesFrameworks _ = False
-
-platformUsesFrameworks :: Platform -> Bool
-platformUsesFrameworks = osUsesFrameworks . platformOS
-
-osSubsectionsViaSymbols :: OS -> Bool
-osSubsectionsViaSymbols OSDarwin = True
-osSubsectionsViaSymbols _ = False
-
--- | Platform-specific settings formerly hard-coded in Config.hs.
---
--- These should probably be all be triaged whether they can be computed from
--- other settings or belong in another another place (like 'Platform' above).
-data PlatformMisc = PlatformMisc
- { -- TODO Recalculate string from richer info?
- platformMisc_targetPlatformString :: String
- , platformMisc_ghcWithInterpreter :: Bool
- , platformMisc_ghcWithSMP :: Bool
- , platformMisc_ghcRTSWays :: String
- , platformMisc_libFFI :: Bool
- , platformMisc_ghcThreaded :: Bool
- , platformMisc_ghcDebugged :: Bool
- , platformMisc_ghcRtsWithLibdw :: Bool
- , platformMisc_llvmTarget :: String
- }
-
--- | Minimum representable Int value for the given platform
-platformMinInt :: Platform -> Integer
-platformMinInt p = case platformWordSize p of
- PW4 -> toInteger (minBound :: Int32)
- PW8 -> toInteger (minBound :: Int64)
-
--- | Maximum representable Int value for the given platform
-platformMaxInt :: Platform -> Integer
-platformMaxInt p = case platformWordSize p of
- PW4 -> toInteger (maxBound :: Int32)
- PW8 -> toInteger (maxBound :: Int64)
-
--- | Maximum representable Word value for the given platform
-platformMaxWord :: Platform -> Integer
-platformMaxWord p = case platformWordSize p of
- PW4 -> toInteger (maxBound :: Word32)
- PW8 -> toInteger (maxBound :: Word64)
-
--- | Test if the given Integer is representable with a platform Int
-platformInIntRange :: Platform -> Integer -> Bool
-platformInIntRange platform x = x >= platformMinInt platform && x <= platformMaxInt platform
-
--- | Test if the given Integer is representable with a platform Word
-platformInWordRange :: Platform -> Integer -> Bool
-platformInWordRange platform x = x >= 0 && x <= platformMaxWord platform
-
-
---------------------------------------------------
--- Instruction sets
---------------------------------------------------
-
--- | x86 SSE instructions
-data SseVersion
- = SSE1
- | SSE2
- | SSE3
- | SSE4
- | SSE42
- deriving (Eq, Ord)
-
--- | x86 BMI (bit manipulation) instructions
-data BmiVersion
- = BMI1
- | BMI2
- deriving (Eq, Ord)
-
diff --git a/libraries/ghc-boot/GHC/Platform/ArchOS.hs b/libraries/ghc-boot/GHC/Platform/ArchOS.hs
new file mode 100644
index 0000000000..bd3ef5f4cc
--- /dev/null
+++ b/libraries/ghc-boot/GHC/Platform/ArchOS.hs
@@ -0,0 +1,152 @@
+{-# LANGUAGE LambdaCase, ScopedTypeVariables #-}
+
+-- | Platform architecture and OS
+--
+-- We need it in ghc-boot because ghc-pkg needs it.
+module GHC.Platform.ArchOS
+ ( ArchOS(..)
+ , Arch(..)
+ , OS(..)
+ , ArmISA(..)
+ , ArmISAExt(..)
+ , ArmABI(..)
+ , PPC_64ABI(..)
+ , stringEncodeArch
+ , stringEncodeOS
+ )
+where
+
+import Prelude -- See Note [Why do we import Prelude here?]
+
+-- | Platform architecture and OS.
+data ArchOS
+ = ArchOS Arch OS
+ deriving (Read, Show, Eq)
+
+-- | Architectures
+--
+-- TODO: It might be nice to extend these constructors with information about
+-- what instruction set extensions an architecture might support.
+--
+data Arch
+ = ArchUnknown
+ | ArchX86
+ | ArchX86_64
+ | ArchPPC
+ | ArchPPC_64 PPC_64ABI
+ | ArchS390X
+ | ArchSPARC
+ | ArchSPARC64
+ | ArchARM ArmISA [ArmISAExt] ArmABI
+ | ArchARM64
+ | ArchAlpha
+ | ArchMipseb
+ | ArchMipsel
+ | ArchJavaScript
+ deriving (Read, Show, Eq)
+
+-- | ARM Instruction Set Architecture
+data ArmISA
+ = ARMv5
+ | ARMv6
+ | ARMv7
+ deriving (Read, Show, Eq)
+
+-- | ARM extensions
+data ArmISAExt
+ = VFPv2
+ | VFPv3
+ | VFPv3D16
+ | NEON
+ | IWMMX2
+ deriving (Read, Show, Eq)
+
+-- | ARM ABI
+data ArmABI
+ = SOFT
+ | SOFTFP
+ | HARD
+ deriving (Read, Show, Eq)
+
+-- | PowerPC 64-bit ABI
+data PPC_64ABI
+ = ELF_V1
+ | ELF_V2
+ deriving (Read, Show, Eq)
+
+-- | Operating systems.
+--
+-- Using OSUnknown to generate code should produce a sensible default, but no
+-- promises.
+data OS
+ = OSUnknown
+ | OSLinux
+ | OSDarwin
+ | OSSolaris2
+ | OSMinGW32
+ | OSFreeBSD
+ | OSDragonFly
+ | OSOpenBSD
+ | OSNetBSD
+ | OSKFreeBSD
+ | OSHaiku
+ | OSQNXNTO
+ | OSAIX
+ | OSHurd
+ deriving (Read, Show, Eq)
+
+
+-- Note [Platform Syntax]
+-- ~~~~~~~~~~~~~~~~~~~~~~
+--
+-- There is a very loose encoding of platforms shared by many tools we are
+-- encoding to here. GNU Config (http://git.savannah.gnu.org/cgit/config.git),
+-- and LLVM's http://llvm.org/doxygen/classllvm_1_1Triple.html are perhaps the
+-- most definitional parsers. The basic syntax is a list of '-'-separated
+-- components. The Unix 'uname' command syntax is related but briefer.
+--
+-- Those two parsers are quite forgiving, and even the 'config.sub'
+-- normalization is forgiving too. The "best" way to encode a platform is
+-- therefore somewhat a matter of taste.
+--
+-- The 'stringEncode*' functions here convert each part of GHC's structured
+-- notion of a platform into one dash-separated component.
+
+-- | See Note [Platform Syntax].
+stringEncodeArch :: Arch -> String
+stringEncodeArch = \case
+ ArchUnknown -> "unknown"
+ ArchX86 -> "i386"
+ ArchX86_64 -> "x86_64"
+ ArchPPC -> "powerpc"
+ ArchPPC_64 ELF_V1 -> "powerpc64"
+ ArchPPC_64 ELF_V2 -> "powerpc64le"
+ ArchS390X -> "s390x"
+ ArchSPARC -> "sparc"
+ ArchSPARC64 -> "sparc64"
+ ArchARM ARMv5 _ _ -> "armv5"
+ ArchARM ARMv6 _ _ -> "armv6"
+ ArchARM ARMv7 _ _ -> "armv7"
+ ArchARM64 -> "aarch64"
+ ArchAlpha -> "alpha"
+ ArchMipseb -> "mipseb"
+ ArchMipsel -> "mipsel"
+ ArchJavaScript -> "js"
+
+-- | See Note [Platform Syntax].
+stringEncodeOS :: OS -> String
+stringEncodeOS = \case
+ OSUnknown -> "unknown"
+ OSLinux -> "linux"
+ OSDarwin -> "darwin"
+ OSSolaris2 -> "solaris2"
+ OSMinGW32 -> "mingw32"
+ OSFreeBSD -> "freebsd"
+ OSDragonFly -> "dragonfly"
+ OSOpenBSD -> "openbsd"
+ OSNetBSD -> "netbsd"
+ OSKFreeBSD -> "kfreebsdgnu"
+ OSHaiku -> "haiku"
+ OSQNXNTO -> "nto-qnx"
+ OSAIX -> "aix"
+ OSHurd -> "hurd"
diff --git a/libraries/ghc-boot/GHC/Settings/Platform.hs b/libraries/ghc-boot/GHC/Settings/Platform.hs
deleted file mode 100644
index 95278da76e..0000000000
--- a/libraries/ghc-boot/GHC/Settings/Platform.hs
+++ /dev/null
@@ -1,103 +0,0 @@
--- 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.Platform where
-
-import Prelude -- See Note [Why do we import Prelude here?]
-
-import GHC.BaseDir
-import GHC.Platform
-import GHC.Settings.Utils
-
-import Data.Map (Map)
-import qualified Data.Map as Map
-
------------------------------------------------------------------------------
--- parts of settings file
-
-getTargetPlatform
- :: FilePath -- ^ Settings filepath (for error messages)
- -> RawSettings -- ^ Raw settings file contents
- -> PlatformConstants -- ^ Platform constants
- -> Either String Platform
-getTargetPlatform settingsFile mySettings constants = 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"
- targetWordBigEndian <- getBooleanSetting "target word big endian"
- targetLeadingUnderscore <- getBooleanSetting "Leading underscore"
- targetUnregisterised <- getBooleanSetting "Unregisterised"
- targetHasGnuNonexecStack <- getBooleanSetting "target has GNU nonexec stack"
- targetHasIdentDirective <- getBooleanSetting "target has .ident directive"
- targetHasSubsectionsViaSymbols <- getBooleanSetting "target has subsections via symbols"
- crossCompiling <- getBooleanSetting "cross compiling"
- tablesNextToCode <- getBooleanSetting "Tables next to code"
-
- pure $ Platform
- { platformMini = PlatformMini
- { platformMini_arch = targetArch
- , platformMini_os = targetOS
- }
- , platformWordSize = targetWordSize
- , platformByteOrder = if targetWordBigEndian then BigEndian else LittleEndian
- , platformUnregisterised = targetUnregisterised
- , platformHasGnuNonexecStack = targetHasGnuNonexecStack
- , platformHasIdentDirective = targetHasIdentDirective
- , platformHasSubsectionsViaSymbols = targetHasSubsectionsViaSymbols
- , platformIsCrossCompiling = crossCompiling
- , platformLeadingUnderscore = targetLeadingUnderscore
- , platformTablesNextToCode = tablesNextToCode
- , platformConstants = constants
- }
-
------------------------------------------------------------------------------
--- 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
diff --git a/libraries/ghc-boot/GHC/Settings/Utils.hs b/libraries/ghc-boot/GHC/Settings/Utils.hs
index 1f1cd67030..4ccbbf23b6 100644
--- a/libraries/ghc-boot/GHC/Settings/Utils.hs
+++ b/libraries/ghc-boot/GHC/Settings/Utils.hs
@@ -3,6 +3,11 @@ module GHC.Settings.Utils where
import Prelude -- See Note [Why do we import Prelude here?]
import Data.Char (isSpace)
+import Data.Map (Map)
+import qualified Data.Map as Map
+
+import GHC.BaseDir
+import GHC.Platform.ArchOS
maybeRead :: Read a => String -> Maybe a
maybeRead str = case reads str of
@@ -13,3 +18,55 @@ maybeReadFuzzy :: Read a => String -> Maybe a
maybeReadFuzzy str = case reads str of
[(x, s)] | all isSpace s -> Just x
_ -> Nothing
+
+
+-- 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 platform.
+--
+-- This module has just enough code to read key value pairs from the settings
+-- file, and read the target platform from those pairs.
+
+type RawSettings = Map String String
+
+-- | Read target Arch/OS from the settings
+getTargetArchOS
+ :: FilePath -- ^ Settings filepath (for error messages)
+ -> RawSettings -- ^ Raw settings file contents
+ -> Either String ArchOS
+getTargetArchOS settingsFile settings =
+ ArchOS <$> readRawSetting settingsFile settings "target arch"
+ <*> readRawSetting settingsFile settings "target os"
+
+
+getRawSetting
+ :: FilePath -> RawSettings -> String -> Either String String
+getRawSetting settingsFile settings key = case Map.lookup key settings of
+ Just xs -> Right xs
+ Nothing -> Left $ "No entry for " ++ show key ++ " in " ++ show settingsFile
+
+getRawFilePathSetting
+ :: FilePath -> FilePath -> RawSettings -> String -> Either String String
+getRawFilePathSetting top_dir settingsFile settings key =
+ expandTopDir top_dir <$> getRawSetting settingsFile settings key
+
+getRawBooleanSetting
+ :: FilePath -> RawSettings -> String -> Either String Bool
+getRawBooleanSetting settingsFile settings key = do
+ rawValue <- getRawSetting settingsFile settings key
+ case rawValue of
+ "YES" -> Right True
+ "NO" -> Right False
+ xs -> Left $ "Bad value for " ++ show key ++ ": " ++ show xs
+
+readRawSetting
+ :: (Show a, Read a) => FilePath -> RawSettings -> String -> Either String a
+readRawSetting settingsFile settings key = case Map.lookup key settings 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
diff --git a/libraries/ghc-boot/GHC/UniqueSubdir.hs b/libraries/ghc-boot/GHC/UniqueSubdir.hs
index b59fdc43ce..5ffaafefd8 100644
--- a/libraries/ghc-boot/GHC/UniqueSubdir.hs
+++ b/libraries/ghc-boot/GHC/UniqueSubdir.hs
@@ -6,19 +6,15 @@ import Prelude -- See Note [Why do we import Prelude here?]
import Data.List (intercalate)
-import GHC.Platform
+import GHC.Platform.ArchOS
import GHC.Version (cProjectVersion)
-- | A filepath like @x86_64-linux-7.6.3@ with the platform string to use when
-- constructing platform-version-dependent files that need to co-exist.
---
--- 'ghc-pkg' falls back on the host platform if the settings file is missing,
--- and so needs this since we don't have information about the host platform in
--- as much detail as 'Platform', so we use 'PlatformMini' instead.
-uniqueSubdir :: PlatformMini -> FilePath
-uniqueSubdir archOs = intercalate "-"
- [ stringEncodeArch $ platformMini_arch archOs
- , stringEncodeOS $ platformMini_os archOs
+uniqueSubdir :: ArchOS -> FilePath
+uniqueSubdir (ArchOS arch os) = intercalate "-"
+ [ stringEncodeArch arch
+ , stringEncodeOS os
, cProjectVersion
]
-- NB: This functionality is reimplemented in Cabal, so if you
diff --git a/libraries/ghc-boot/ghc-boot.cabal.in b/libraries/ghc-boot/ghc-boot.cabal.in
index aed65d8f0a..e320a5725f 100644
--- a/libraries/ghc-boot/ghc-boot.cabal.in
+++ b/libraries/ghc-boot/ghc-boot.cabal.in
@@ -43,10 +43,9 @@ Library
GHC.Serialized
GHC.ForeignSrcLang
GHC.HandleEncoding
- GHC.Platform
+ GHC.Platform.ArchOS
GHC.Platform.Host
GHC.Platform.Constants
- GHC.Settings.Platform
GHC.Settings.Utils
GHC.UniqueSubdir
GHC.Version
diff --git a/libraries/ghc-boot/ghc.mk b/libraries/ghc-boot/ghc.mk
index 9c5d695d8c..d183ccc501 100644
--- a/libraries/ghc-boot/ghc.mk
+++ b/libraries/ghc-boot/ghc.mk
@@ -42,17 +42,14 @@ libraries/ghc-boot/dist-install/build/GHC/Platform/Host.hs: mk/project.mk | $$(d
@echo >> $@
@echo 'import GHC.Platform' >> $@
@echo >> $@
- @echo 'cHostPlatformArch :: Arch' >> $@
- @echo 'cHostPlatformArch = $(HaskellHostArch)' >> $@
+ @echo 'hostPlatformArch :: Arch' >> $@
+ @echo 'hostPlatformArch = $(HaskellHostArch)' >> $@
@echo >> $@
- @echo 'cHostPlatformOS :: OS' >> $@
- @echo 'cHostPlatformOS = $(HaskellHostOs)' >> $@
+ @echo 'hostPlatformOS :: OS' >> $@
+ @echo 'hostPlatformOS = $(HaskellHostOs)' >> $@
@echo >> $@
- @echo 'cHostPlatformMini :: PlatformMini' >> $@
- @echo 'cHostPlatformMini = PlatformMini' >> $@
- @echo ' { platformMini_arch = cHostPlatformArch' >> $@
- @echo ' , platformMini_os = cHostPlatformOS' >> $@
- @echo ' }' >> $@
+ @echo 'hostPlatformArchOS :: ArchOS' >> $@
+ @echo 'hostPlatformArchOS = ArchOS hostPlatformArch hostPlatformOS' >> $@
@echo done.
libraries/ghc-boot/dist-boot/package-data.mk: \