{-# LANGUAGE CPP              #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}

-----------------------------------------------------------------------------
-- |
-- Module      :  Distribution.System
-- Copyright   :  Duncan Coutts 2007-2008
--
-- Maintainer  :  cabal-devel@haskell.org
-- Portability :  portable
--
-- Cabal often needs to do slightly different things on specific platforms. You
-- probably know about the 'System.Info.os' however using that is very
-- inconvenient because it is a string and different Haskell implementations
-- do not agree on using the same strings for the same platforms! (In
-- particular see the controversy over \"windows\" vs \"mingw32\"). So to make it
-- more consistent and easy to use we have an 'OS' enumeration.
--
module Distribution.System (
  -- * Operating System
  OS(..),
  buildOS,

  -- * Machine Architecture
  Arch(..),
  buildArch,

  -- * Platform is a pair of arch and OS
  Platform(..),
  buildPlatform,
  platformFromTriple,

  -- * Internal
  knownOSs,
  knownArches,

  -- * Classification
  ClassificationStrictness (..),
  classifyOS,
  classifyArch,
  ) where

import Prelude ()
import Distribution.Compat.Prelude hiding (Applicative(..))
import Control.Applicative (Applicative(..))

#if !MIN_VERSION_base(4,10,0)
import Control.Applicative (liftA2)
#endif

import qualified System.Info (os, arch)
import Distribution.Utils.Generic (lowercase)

import Distribution.Parsec
import Distribution.Pretty

import qualified Distribution.Compat.CharParsing as P
import qualified Text.PrettyPrint as Disp

-- | How strict to be when classifying strings into the 'OS' and 'Arch' enums.
--
-- The reason we have multiple ways to do the classification is because there
-- are two situations where we need to do it.
--
-- For parsing OS and arch names in .cabal files we really want everyone to be
-- referring to the same or arch by the same name. Variety is not a virtue
-- in this case. We don't mind about case though.
--
-- For the System.Info.os\/arch different Haskell implementations use different
-- names for the same or\/arch. Also they tend to distinguish versions of an
-- OS\/arch which we just don't care about.
--
-- The 'Compat' classification allows us to recognise aliases that are already
-- in common use but it allows us to distinguish them from the canonical name
-- which enables us to warn about such deprecated aliases.
--
data ClassificationStrictness = Permissive | Compat | Strict

-- ------------------------------------------------------------
-- * Operating System
-- ------------------------------------------------------------

-- | These are the known OS names: Linux, Windows, OSX
--  ,FreeBSD, OpenBSD, NetBSD, DragonFly
--  ,Solaris, AIX, HPUX, IRIX
--  ,HaLVM ,Hurd ,IOS, Android, Ghcjs, Wasi
--
-- The following aliases can also be used:,
--    * Windows aliases: mingw32, win32, cygwin32
--    * OSX alias: darwin
--    * Hurd alias: gnu
--    * FreeBSD alias: kfreebsdgnu
--    * Solaris alias: solaris2
--
data OS = Linux | Windows | OSX        -- tier 1 desktop OSs
        | FreeBSD | OpenBSD | NetBSD   -- other free Unix OSs
        | DragonFly
        | Solaris | AIX | HPUX | IRIX  -- ageing Unix OSs
        | HaLVM                        -- bare metal / VMs / hypervisors
        | Hurd                         -- GNU's microkernel
        | IOS  | Android               -- mobile OSs
        | Ghcjs
        | Wasi
        | OtherOS String
  deriving (OS -> OS -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: OS -> OS -> Bool
$c/= :: OS -> OS -> Bool
== :: OS -> OS -> Bool
$c== :: OS -> OS -> Bool
Eq, forall x. Rep OS x -> OS
forall x. OS -> Rep OS x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep OS x -> OS
$cfrom :: forall x. OS -> Rep OS x
Generic, Eq OS
OS -> OS -> Bool
OS -> OS -> Ordering
OS -> OS -> OS
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: OS -> OS -> OS
$cmin :: OS -> OS -> OS
max :: OS -> OS -> OS
$cmax :: OS -> OS -> OS
>= :: OS -> OS -> Bool
$c>= :: OS -> OS -> Bool
> :: OS -> OS -> Bool
$c> :: OS -> OS -> Bool
<= :: OS -> OS -> Bool
$c<= :: OS -> OS -> Bool
< :: OS -> OS -> Bool
$c< :: OS -> OS -> Bool
compare :: OS -> OS -> Ordering
$ccompare :: OS -> OS -> Ordering
Ord, Int -> OS -> ShowS
[OS] -> ShowS
OS -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [OS] -> ShowS
$cshowList :: [OS] -> ShowS
show :: OS -> String
$cshow :: OS -> String
showsPrec :: Int -> OS -> ShowS
$cshowsPrec :: Int -> OS -> ShowS
Show, ReadPrec [OS]
ReadPrec OS
Int -> ReadS OS
ReadS [OS]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [OS]
$creadListPrec :: ReadPrec [OS]
readPrec :: ReadPrec OS
$creadPrec :: ReadPrec OS
readList :: ReadS [OS]
$creadList :: ReadS [OS]
readsPrec :: Int -> ReadS OS
$creadsPrec :: Int -> ReadS OS
Read, Typeable, Typeable OS
OS -> DataType
OS -> Constr
(forall b. Data b => b -> b) -> OS -> OS
forall a.
Typeable a
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> OS -> u
forall u. (forall d. Data d => d -> u) -> OS -> [u]
forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> OS -> r
forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> OS -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> OS -> m OS
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> OS -> m OS
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c OS
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> OS -> c OS
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c OS)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c OS)
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> OS -> m OS
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> OS -> m OS
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> OS -> m OS
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> OS -> m OS
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> OS -> m OS
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> OS -> m OS
gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> OS -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> OS -> u
gmapQ :: forall u. (forall d. Data d => d -> u) -> OS -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> OS -> [u]
gmapQr :: forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> OS -> r
$cgmapQr :: forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> OS -> r
gmapQl :: forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> OS -> r
$cgmapQl :: forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> OS -> r
gmapT :: (forall b. Data b => b -> b) -> OS -> OS
$cgmapT :: (forall b. Data b => b -> b) -> OS -> OS
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c OS)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c OS)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c OS)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c OS)
dataTypeOf :: OS -> DataType
$cdataTypeOf :: OS -> DataType
toConstr :: OS -> Constr
$ctoConstr :: OS -> Constr
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c OS
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c OS
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> OS -> c OS
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> OS -> c OS
Data)

instance Binary OS
instance Structured OS
instance NFData OS where rnf :: OS -> ()
rnf = forall a. (Generic a, GNFData (Rep a)) => a -> ()
genericRnf

knownOSs :: [OS]
knownOSs :: [OS]
knownOSs = [OS
Linux, OS
Windows, OS
OSX
           ,OS
FreeBSD, OS
OpenBSD, OS
NetBSD, OS
DragonFly
           ,OS
Solaris, OS
AIX, OS
HPUX, OS
IRIX
           ,OS
HaLVM
           ,OS
Hurd
           ,OS
IOS, OS
Android
           ,OS
Ghcjs
           ,OS
Wasi]

osAliases :: ClassificationStrictness -> OS -> [String]
osAliases :: ClassificationStrictness -> OS -> [String]
osAliases ClassificationStrictness
Permissive OS
Windows = [String
"mingw32", String
"win32", String
"cygwin32"]
osAliases ClassificationStrictness
Compat     OS
Windows = [String
"mingw32", String
"win32"]
osAliases ClassificationStrictness
_          OS
OSX     = [String
"darwin"]
osAliases ClassificationStrictness
_          OS
Hurd    = [String
"gnu"]
osAliases ClassificationStrictness
Permissive OS
FreeBSD = [String
"kfreebsdgnu"]
osAliases ClassificationStrictness
Compat     OS
FreeBSD = [String
"kfreebsdgnu"]
osAliases ClassificationStrictness
Permissive OS
Solaris = [String
"solaris2"]
osAliases ClassificationStrictness
Compat     OS
Solaris = [String
"solaris2"]
osAliases ClassificationStrictness
Permissive OS
Android = [String
"linux-android", String
"linux-androideabi", String
"linux-androideabihf"]
osAliases ClassificationStrictness
Compat     OS
Android = [String
"linux-android"]
osAliases ClassificationStrictness
_          OS
_       = []

instance Pretty OS where
  pretty :: OS -> Doc
pretty (OtherOS String
name) = String -> Doc
Disp.text String
name
  pretty OS
other          = String -> Doc
Disp.text (ShowS
lowercase (forall a. Show a => a -> String
show OS
other))

instance Parsec OS where
  parsec :: forall (m :: * -> *). CabalParsing m => m OS
parsec = ClassificationStrictness -> String -> OS
classifyOS ClassificationStrictness
Compat forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *). CabalParsing m => m String
parsecIdent



classifyOS :: ClassificationStrictness -> String -> OS
classifyOS :: ClassificationStrictness -> String -> OS
classifyOS ClassificationStrictness
strictness String
s =
  forall a. a -> Maybe a -> a
fromMaybe (String -> OS
OtherOS String
s) forall a b. (a -> b) -> a -> b
$ forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup (ShowS
lowercase String
s) [(String, OS)]
osMap
  where
    osMap :: [(String, OS)]
osMap = [ (String
name, OS
os)
            | OS
os <- [OS]
knownOSs
            , String
name <- forall a. Pretty a => a -> String
prettyShow OS
os forall a. a -> [a] -> [a]
: ClassificationStrictness -> OS -> [String]
osAliases ClassificationStrictness
strictness OS
os ]

buildOS :: OS
buildOS :: OS
buildOS = ClassificationStrictness -> String -> OS
classifyOS ClassificationStrictness
Permissive String
System.Info.os

-- ------------------------------------------------------------
-- * Machine Architecture
-- ------------------------------------------------------------

-- | These are the known Arches: I386, X86_64, PPC, PPC64, Sparc,
-- Arm, AArch64, Mips, SH, IA64, S390, S390X, Alpha, Hppa, Rs6000,
-- M68k, Vax, JavaScript and Wasm32.
--
-- The following aliases can also be used:
--    * PPC alias: powerpc
--    * PPC64 alias : powerpc64, powerpc64le
--    * Sparc aliases: sparc64, sun4
--    * Mips aliases: mipsel, mipseb
--    * Arm aliases: armeb, armel
--    * AArch64 aliases: arm64
--
data Arch = I386  | X86_64  | PPC  | PPC64 | Sparc
          | Arm   | AArch64 | Mips | SH
          | IA64  | S390    | S390X
          | Alpha | Hppa    | Rs6000
          | M68k  | Vax
          | JavaScript
          | Wasm32
          | OtherArch String
  deriving (Arch -> Arch -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Arch -> Arch -> Bool
$c/= :: Arch -> Arch -> Bool
== :: Arch -> Arch -> Bool
$c== :: Arch -> Arch -> Bool
Eq, forall x. Rep Arch x -> Arch
forall x. Arch -> Rep Arch x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Arch x -> Arch
$cfrom :: forall x. Arch -> Rep Arch x
Generic, Eq Arch
Arch -> Arch -> Bool
Arch -> Arch -> Ordering
Arch -> Arch -> Arch
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Arch -> Arch -> Arch
$cmin :: Arch -> Arch -> Arch
max :: Arch -> Arch -> Arch
$cmax :: Arch -> Arch -> Arch
>= :: Arch -> Arch -> Bool
$c>= :: Arch -> Arch -> Bool
> :: Arch -> Arch -> Bool
$c> :: Arch -> Arch -> Bool
<= :: Arch -> Arch -> Bool
$c<= :: Arch -> Arch -> Bool
< :: Arch -> Arch -> Bool
$c< :: Arch -> Arch -> Bool
compare :: Arch -> Arch -> Ordering
$ccompare :: Arch -> Arch -> Ordering
Ord, Int -> Arch -> ShowS
[Arch] -> ShowS
Arch -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Arch] -> ShowS
$cshowList :: [Arch] -> ShowS
show :: Arch -> String
$cshow :: Arch -> String
showsPrec :: Int -> Arch -> ShowS
$cshowsPrec :: Int -> Arch -> ShowS
Show, ReadPrec [Arch]
ReadPrec Arch
Int -> ReadS Arch
ReadS [Arch]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Arch]
$creadListPrec :: ReadPrec [Arch]
readPrec :: ReadPrec Arch
$creadPrec :: ReadPrec Arch
readList :: ReadS [Arch]
$creadList :: ReadS [Arch]
readsPrec :: Int -> ReadS Arch
$creadsPrec :: Int -> ReadS Arch
Read, Typeable, Typeable Arch
Arch -> DataType
Arch -> Constr
(forall b. Data b => b -> b) -> Arch -> Arch
forall a.
Typeable a
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> Arch -> u
forall u. (forall d. Data d => d -> u) -> Arch -> [u]
forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Arch -> r
forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Arch -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Arch -> m Arch
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Arch -> m Arch
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Arch
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Arch -> c Arch
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Arch)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Arch)
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Arch -> m Arch
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Arch -> m Arch
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Arch -> m Arch
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Arch -> m Arch
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Arch -> m Arch
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Arch -> m Arch
gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Arch -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Arch -> u
gmapQ :: forall u. (forall d. Data d => d -> u) -> Arch -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> Arch -> [u]
gmapQr :: forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Arch -> r
$cgmapQr :: forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Arch -> r
gmapQl :: forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Arch -> r
$cgmapQl :: forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Arch -> r
gmapT :: (forall b. Data b => b -> b) -> Arch -> Arch
$cgmapT :: (forall b. Data b => b -> b) -> Arch -> Arch
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Arch)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Arch)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Arch)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Arch)
dataTypeOf :: Arch -> DataType
$cdataTypeOf :: Arch -> DataType
toConstr :: Arch -> Constr
$ctoConstr :: Arch -> Constr
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Arch
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Arch
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Arch -> c Arch
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Arch -> c Arch
Data)

instance Binary Arch
instance Structured Arch
instance NFData Arch where rnf :: Arch -> ()
rnf = forall a. (Generic a, GNFData (Rep a)) => a -> ()
genericRnf

knownArches :: [Arch]
knownArches :: [Arch]
knownArches = [Arch
I386, Arch
X86_64, Arch
PPC, Arch
PPC64, Arch
Sparc
              ,Arch
Arm, Arch
AArch64, Arch
Mips, Arch
SH
              ,Arch
IA64, Arch
S390, Arch
S390X
              ,Arch
Alpha, Arch
Hppa, Arch
Rs6000
              ,Arch
M68k, Arch
Vax
              ,Arch
JavaScript
              ,Arch
Wasm32]

archAliases :: ClassificationStrictness -> Arch -> [String]
archAliases :: ClassificationStrictness -> Arch -> [String]
archAliases ClassificationStrictness
Strict Arch
_       = []
archAliases ClassificationStrictness
Compat Arch
_       = []
archAliases ClassificationStrictness
_      Arch
PPC     = [String
"powerpc"]
archAliases ClassificationStrictness
_      Arch
PPC64   = [String
"powerpc64", String
"powerpc64le"]
archAliases ClassificationStrictness
_      Arch
Sparc   = [String
"sparc64", String
"sun4"]
archAliases ClassificationStrictness
_      Arch
Mips    = [String
"mipsel", String
"mipseb"]
archAliases ClassificationStrictness
_      Arch
Arm     = [String
"armeb", String
"armel"]
archAliases ClassificationStrictness
_      Arch
AArch64 = [String
"arm64"]
archAliases ClassificationStrictness
_      Arch
_       = []

instance Pretty Arch where
  pretty :: Arch -> Doc
pretty (OtherArch String
name) = String -> Doc
Disp.text String
name
  pretty Arch
other            = String -> Doc
Disp.text (ShowS
lowercase (forall a. Show a => a -> String
show Arch
other))

instance Parsec Arch where
  parsec :: forall (m :: * -> *). CabalParsing m => m Arch
parsec = ClassificationStrictness -> String -> Arch
classifyArch ClassificationStrictness
Strict forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *). CabalParsing m => m String
parsecIdent

classifyArch :: ClassificationStrictness -> String -> Arch
classifyArch :: ClassificationStrictness -> String -> Arch
classifyArch ClassificationStrictness
strictness String
s =
  forall a. a -> Maybe a -> a
fromMaybe (String -> Arch
OtherArch String
s) forall a b. (a -> b) -> a -> b
$ forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup (ShowS
lowercase String
s) [(String, Arch)]
archMap
  where
    archMap :: [(String, Arch)]
archMap = [ (String
name, Arch
arch)
              | Arch
arch <- [Arch]
knownArches
              , String
name <- forall a. Pretty a => a -> String
prettyShow Arch
arch forall a. a -> [a] -> [a]
: ClassificationStrictness -> Arch -> [String]
archAliases ClassificationStrictness
strictness Arch
arch ]

buildArch :: Arch
buildArch :: Arch
buildArch = ClassificationStrictness -> String -> Arch
classifyArch ClassificationStrictness
Permissive String
System.Info.arch

-- ------------------------------------------------------------
-- * Platform
-- ------------------------------------------------------------

data Platform = Platform Arch OS
  deriving (Platform -> Platform -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Platform -> Platform -> Bool
$c/= :: Platform -> Platform -> Bool
== :: Platform -> Platform -> Bool
$c== :: Platform -> Platform -> Bool
Eq, forall x. Rep Platform x -> Platform
forall x. Platform -> Rep Platform x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Platform x -> Platform
$cfrom :: forall x. Platform -> Rep Platform x
Generic, Eq Platform
Platform -> Platform -> Bool
Platform -> Platform -> Ordering
Platform -> Platform -> Platform
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Platform -> Platform -> Platform
$cmin :: Platform -> Platform -> Platform
max :: Platform -> Platform -> Platform
$cmax :: Platform -> Platform -> Platform
>= :: Platform -> Platform -> Bool
$c>= :: Platform -> Platform -> Bool
> :: Platform -> Platform -> Bool
$c> :: Platform -> Platform -> Bool
<= :: Platform -> Platform -> Bool
$c<= :: Platform -> Platform -> Bool
< :: Platform -> Platform -> Bool
$c< :: Platform -> Platform -> Bool
compare :: Platform -> Platform -> Ordering
$ccompare :: Platform -> Platform -> Ordering
Ord, Int -> Platform -> ShowS
[Platform] -> ShowS
Platform -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Platform] -> ShowS
$cshowList :: [Platform] -> ShowS
show :: Platform -> String
$cshow :: Platform -> String
showsPrec :: Int -> Platform -> ShowS
$cshowsPrec :: Int -> Platform -> ShowS
Show, ReadPrec [Platform]
ReadPrec Platform
Int -> ReadS Platform
ReadS [Platform]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Platform]
$creadListPrec :: ReadPrec [Platform]
readPrec :: ReadPrec Platform
$creadPrec :: ReadPrec Platform
readList :: ReadS [Platform]
$creadList :: ReadS [Platform]
readsPrec :: Int -> ReadS Platform
$creadsPrec :: Int -> ReadS Platform
Read, Typeable, Typeable Platform
Platform -> DataType
Platform -> Constr
(forall b. Data b => b -> b) -> Platform -> Platform
forall a.
Typeable a
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> Platform -> u
forall u. (forall d. Data d => d -> u) -> Platform -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Platform -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Platform -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Platform -> m Platform
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Platform -> m Platform
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Platform
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Platform -> c Platform
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Platform)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Platform)
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Platform -> m Platform
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Platform -> m Platform
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Platform -> m Platform
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Platform -> m Platform
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Platform -> m Platform
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Platform -> m Platform
gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Platform -> u
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Platform -> u
gmapQ :: forall u. (forall d. Data d => d -> u) -> Platform -> [u]
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> Platform -> [u]
gmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Platform -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> Platform -> r
gmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Platform -> r
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> Platform -> r
gmapT :: (forall b. Data b => b -> b) -> Platform -> Platform
$cgmapT :: (forall b. Data b => b -> b) -> Platform -> Platform
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Platform)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Platform)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Platform)
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c Platform)
dataTypeOf :: Platform -> DataType
$cdataTypeOf :: Platform -> DataType
toConstr :: Platform -> Constr
$ctoConstr :: Platform -> Constr
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Platform
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c Platform
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Platform -> c Platform
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Platform -> c Platform
Data)

instance Binary Platform
instance Structured Platform
instance NFData Platform where rnf :: Platform -> ()
rnf = forall a. (Generic a, GNFData (Rep a)) => a -> ()
genericRnf

instance Pretty Platform where
  pretty :: Platform -> Doc
pretty (Platform Arch
arch OS
os) = forall a. Pretty a => a -> Doc
pretty Arch
arch Doc -> Doc -> Doc
<<>> Char -> Doc
Disp.char Char
'-' Doc -> Doc -> Doc
<<>> forall a. Pretty a => a -> Doc
pretty OS
os

instance Parsec Platform where
    -- TODO: there are ambiguous platforms like: `arch-word-os`
    -- which could be parsed as
    --   * Platform "arch-word" "os"
    --   * Platform "arch" "word-os"
    -- We could support that preferring variants 'OtherOS' or 'OtherArch'
    --
    -- For now we split into arch and os parts on the first dash.
    parsec :: forall (m :: * -> *). CabalParsing m => m Platform
parsec = do
        Arch
arch <- m Arch
parsecDashlessArch
        Char
_ <- forall (m :: * -> *). CharParsing m => Char -> m Char
P.char Char
'-'
        OS
os <- forall a (m :: * -> *). (Parsec a, CabalParsing m) => m a
parsec
        forall (m :: * -> *) a. Monad m => a -> m a
return (Arch -> OS -> Platform
Platform Arch
arch OS
os)
      where
        parsecDashlessArch :: m Arch
parsecDashlessArch = ClassificationStrictness -> String -> Arch
classifyArch ClassificationStrictness
Strict forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m String
dashlessIdent

        dashlessIdent :: m String
dashlessIdent = forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 (:) m Char
firstChar m String
rest
          where
            firstChar :: m Char
firstChar = forall (m :: * -> *). CharParsing m => (Char -> Bool) -> m Char
P.satisfy Char -> Bool
isAlpha
            rest :: m String
rest = forall (m :: * -> *). CharParsing m => (Char -> Bool) -> m String
P.munch (\Char
c -> Char -> Bool
isAlphaNum Char
c Bool -> Bool -> Bool
|| Char
c forall a. Eq a => a -> a -> Bool
== Char
'_')

-- | The platform Cabal was compiled on. In most cases,
-- @LocalBuildInfo.hostPlatform@ should be used instead (the platform we're
-- targeting).
buildPlatform :: Platform
buildPlatform :: Platform
buildPlatform = Arch -> OS -> Platform
Platform Arch
buildArch OS
buildOS

-- Utils:

parsecIdent :: CabalParsing m => m String
parsecIdent :: forall (m :: * -> *). CabalParsing m => m String
parsecIdent = (:) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m Char
firstChar forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> m String
rest
  where
    firstChar :: m Char
firstChar = forall (m :: * -> *). CharParsing m => (Char -> Bool) -> m Char
P.satisfy Char -> Bool
isAlpha
    rest :: m String
rest      = forall (m :: * -> *). CharParsing m => (Char -> Bool) -> m String
P.munch (\Char
c -> Char -> Bool
isAlphaNum Char
c Bool -> Bool -> Bool
|| Char
c forall a. Eq a => a -> a -> Bool
== Char
'_' Bool -> Bool -> Bool
|| Char
c forall a. Eq a => a -> a -> Bool
== Char
'-')

platformFromTriple :: String -> Maybe Platform
platformFromTriple :: String -> Maybe Platform
platformFromTriple String
triple =
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (forall a b. a -> b -> a
const forall a. Maybe a
Nothing) forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall a. ParsecParser a -> String -> Either String a
explicitEitherParsec ParsecParser Platform
parseTriple String
triple
  where parseWord :: ParsecParser String
parseWord = forall (m :: * -> *). CharParsing m => (Char -> Bool) -> m String
P.munch1 (\Char
c -> Char -> Bool
isAlphaNum Char
c Bool -> Bool -> Bool
|| Char
c forall a. Eq a => a -> a -> Bool
== Char
'_')
        parseTriple :: ParsecParser Platform
parseTriple = do
          Arch
arch <- forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (ClassificationStrictness -> String -> Arch
classifyArch ClassificationStrictness
Permissive) ParsecParser String
parseWord
          Char
_ <- forall (m :: * -> *). CharParsing m => Char -> m Char
P.char Char
'-'
          String
_ <- ParsecParser String
parseWord -- Skip vendor
          Char
_ <- forall (m :: * -> *). CharParsing m => Char -> m Char
P.char Char
'-'
          OS
os <- forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (ClassificationStrictness -> String -> OS
classifyOS ClassificationStrictness
Permissive) forall (m :: * -> *). CabalParsing m => m String
parsecIdent -- OS may have hyphens, like
                                               -- 'nto-qnx'
          forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Arch -> OS -> Platform
Platform Arch
arch OS
os