@@ -1,5 +1,6 @@
1−{-# LANGUAGE RecordWildCards #-}
1+{-# LANGUAGE LambdaCase #-}
22{-# LANGUAGE OverloadedStrings #-}
3+{-# LANGUAGE RecordWildCards #-}
34
45module Cabal2nix
56 ( main, cabal2nix, cabal2nix', cabal2nixWithDB
@@ -9,7 +10,9 @@ module Cabal2nix
910import Control.Exception ( bracket )
1011import Control.Lens
1112import Control.Monad ( when )
12−import Data.Maybe ( fromMaybe, isJust )
13+import Data.List
14+import Data.List.Split
15+import Data.Maybe ( fromMaybe, isJust, listToMaybe )
1316import Data.Monoid ( (<>) )
1417import qualified Data.Set as Set
1518import Data.String
@@ -81,7 +84,7 @@ options = Options
8184 <*> switch (long "shell" <> help "generate output suitable for nix-shell")
8285 <*> many (strOption $ short 'f' <> long "flag" <> help "Cabal flag (may be specified multiple times)")
8386 <*> option (readP parse) (long "compiler" <> help "compiler to use when evaluating the Cabal file" <> value buildCompilerId <> showDefaultWith display)
84− <*> option (readP parsePlatform) (long "system" <> help "target system to use when evaluating the Cabal file" <> value buildPlatform <> showDefaultWith display)
87+ <*> option (maybeReader parsePlatform) (long "system" <> help "host system (in either short Nix format or full LLVM style) to use when evaluating the Cabal file" <> value buildPlatform <> showDefaultWith display)
8588 <*> optional (strOption $ long "subpath" <> metavar "PATH" <> help "Path to Cabal file's directory relative to the URI (default is root directory)")
8689 <*> optional (option utcTimeReader (long "hackage-snapshot" <> help "hackage snapshot time, ISO format"))
8790 <*> strArgument (metavar "URI")
@@ -99,19 +102,51 @@ readP p = eitherReader $ \s -> case [ r' | (r',"") <- P.readP_to_S p s ] of
99102 (r:_) -> Right r
100103 _ -> Left ("invalid value " ++ show s)
101104
102−parsePlatform :: P.ReadP r Platform
103−parsePlatform = do arch <- P.choice [ P.string "i686" >> return I386
104− , P.string "x86_64" >> return X86_64
105− , P.string "armv7l" >> return Arm
106− , P.string "armv6l" >> return Arm
107− -- Not yet supported yet, see Cabal #5221
108− --, P.string "aarch64" >> return AArch64
109− , P.string "mipsel" >> return Mips
110− ]
111− _ <- P.char '-'
112− os <- P.choice [ P.string "linux" >> return Linux, P.string "darwin" >> return OSX
113− , P.string "windows" >> return Windows]
114− return (Platform arch os)
105+-- | Replicate the normalization performed by GHC_CONVERT_CPU in GHC's aclocal.m4
106+-- since the output of that is what Cabal parses.
107+ghcConvertArch :: String -> String
108+ghcConvertArch arch = case arch of
109+ "i486" -> "i386"
110+ "i586" -> "i386"
111+ "i686" -> "i386"
112+ "amd64" -> "x86_64"
113+ _ -> fromMaybe arch $ listToMaybe
114+ [prefix | prefix <- archPrefixes, prefix `isPrefixOf` arch]
115+ where archPrefixes =
116+ [ "aarch64", "alpha", "arm", "hppa1_1", "hppa", "m68k", "mipseb"
117+ , "mipsel", "mips", "powerpc64le", "powerpc64", "powerpc", "s390x"
118+ , "sparc64", "sparc"
119+ ]
120+
121+-- | Replicate the normalization performed by GHC_CONVERT_OS in GHC's aclocal.m4
122+-- since the output of that is what Cabal parses.
123+ghcConvertOS :: String -> String
124+ghcConvertOS os = case os of
125+ "watchos" -> "ios"
126+ "tvos" -> "ios"
127+ "linux-android" -> "linux-android"
128+ _ | "linux-" `isPrefixOf` os -> "linux"
129+ _ -> fromMaybe os $ listToMaybe
130+ [prefix | prefix <- osPrefixes, prefix `isPrefixOf` os]
131+ where osPrefixes =
132+ [ "gnu", "openbsd", "aix", "darwin", "solaris2", "freebsd", "nto-qnx"]
133+
134+parseArch :: String -> Arch
135+parseArch = classifyArch Permissive . ghcConvertArch
136+
137+parseOS :: String -> OS
138+parseOS = classifyOS Permissive . ghcConvertOS
139+
140+parsePlatform :: String -> Maybe Platform
141+parsePlatform = parsePlatformParts . splitOn "-"
142+
143+parsePlatformParts :: [String] -> Maybe Platform
144+parsePlatformParts = \case
145+ [arch, os] ->
146+ Just $ Platform (parseArch arch) (parseOS os)
147+ (arch : _ : osParts) ->
148+ Just $ Platform (parseArch arch) $ parseOS $ intercalate "-" osParts
149+ _ -> Nothing
115150
116151pinfo :: ParserInfo Options
117152pinfo = info