git.iko.soy/typeable/cabal2nix
on master help sign in
Support all architectures and OSs that GHC and Cabal support

This replicates GHC's normalization logic so that Cabal's built in parsers can be used. This should ensure maximum compatibility with how the Cabal file will actually be evaluated during the build. Additionally, this adds support for passing in the full LLVM style platform triple/quadruple (e.g. x86_64-unknown-linux-gnu) instead of just the short Nix style (x86_64-linux). This will make it possible for the ABI to treated as part of the OS where applicable (e.g. linux-android). We can then change `make-package-set.nix` to use `hostPlatform.config` instead of `hostPlatform.system` to get the full information.

commit0bb88f0009710e013564f24c195fd037e766310e authorKen Micklas <ken.micklas@obsidian.systems> dateMon 19 Mar 2018, 14:52 (9 years ago) parent5b271ab
1 file changed+51−16
src/Cabal2nix.hs+51−16
src/Cabal2nix.hs+51−16
@@ -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