git.iko.soy/typeable/stackage2nix
on master help sign in
typeable/stackage2nix/src/LtsHaskell.hs
98 lines 4.1 kB history raw
1module LtsHaskell where
3import AllCabalHashes
4import Control.Lens
5import Control.Monad.Catch
6import Data.Maybe
7import Data.Text as T
8import Distribution.Text as Text (display)
9import Control.Monad
10import Distribution.Compiler (CompilerInfo(..), AbiTag(NoAbiTag), CompilerId(..), CompilerFlavor(GHC))
11import Distribution.System (Platform(..))
12import Distribution.Package (PackageName, PackageIdentifier(..), Dependency(..))
13import Distribution.Nixpkgs.Haskell.PackageSourceSpec as PackageSourceSpec
14import Distribution.Nixpkgs.Haskell.FromStack
15import Distribution.Nixpkgs.Haskell.Stack
16import Distribution.Nixpkgs.Fetch
17import Distribution.Nixpkgs.PackageMap (readNixpkgPackageMap, resolve)
18import Distribution.Version (Version, withinRange)
19import Language.Haskell.Extension (Language(Haskell98, Haskell2010))
20import Language.Nix
21import Stack.Config
22import Stackage.BuildPlan
23import Stackage.Types (SystemInfo(..))
24import System.FilePath as Path
26import qualified Distribution.Nixpkgs.Haskell.Hackage as DB
27import qualified Data.Yaml as Yaml
28import qualified Data.Map as Map
29import qualified Data.Set as Set
32loadBuildPlan :: FilePath -> IO BuildPlan
33loadBuildPlan = Yaml.decodeFileEither >=> \case
34 Left err -> fail $ "Failed to parse stackage build plan: " ++ show err
35 Right bp -> return bp
37getPackageFromRepo :: FilePath -> Maybe SHA1Hash -> PackageIdentifier -> IO Package
38getPackageFromRepo allCabalHashesPath mSha1Hash pkgId = do
39 (pkgDesc, _) <- case mSha1Hash of
40 Just sha1 ->
41 readPackageByHash allCabalHashesPath sha1
42 `catchAll` const (readPackageByName allCabalHashesPath pkgId)
43 Nothing -> readPackageByName allCabalHashesPath pkgId
44 meta <- readPackageMeta allCabalHashesPath pkgId
45 let
46 tarballSHA256 = fromMaybe
47 (error (display pkgId ++ ": meta data has no SHA256 hash for the tarball"))
48 (view (mHashes . at "SHA256") meta)
49 source = DerivationSource "url" ("mirror://hackage/" ++ display pkgId ++ ".tar.gz") "" tarballSHA256
50 return $ Package source False pkgDesc
52getPackageFromDb :: DB.HackageDB -> PackageIdentifier -> IO Package
53getPackageFromDb hackageDb pkgId =
54 getStackPackageFromDb hackageDb
55 $ StackPackage (PlIndex $ PackageIndex (T.pack $ Text.display pkgId) Nothing) True Nothing
57loadPackage :: DB.HackageDB -> FilePath -> Maybe SHA1Hash -> PackageIdentifier -> IO Package
58loadPackage hackageDb allCabalHashesPath mSha1Hash pkgId =
59 getPackageFromRepo allCabalHashesPath mSha1Hash pkgId
60 `catchIOError` const (getPackageFromDb hackageDb pkgId)
62ghcCompilerInfo :: Version -> CompilerInfo
63ghcCompilerInfo v = CompilerInfo
64 { compilerInfoId = CompilerId GHC v
65 , compilerInfoAbiTag = NoAbiTag
66 , compilerInfoCompat = Just []
67 , compilerInfoLanguages = Just [Haskell98, Haskell2010]
68 , compilerInfoExtensions = Nothing
69 }
71buildPlanContainsDependency :: Map.Map PackageName Version -> Dependency -> Bool
72buildPlanContainsDependency packageVersions (Dependency depName versionRange) =
73 maybe False (`withinRange` versionRange) $ Map.lookup depName packageVersions
75buildPackageSetConfig
76 :: DB.HackageDB
77 -> FilePath
78 -> FilePath
79 -> BuildPlan
80 -> IO PackageSetConfig
81buildPackageSetConfig hackageDb optAllCabalHashes optNixpkgsRepository buildPlan = do
82 nixpkgs <- readNixpkgPackageMap optNixpkgsRepository Nothing
83 let
84 systemInfo = bpSystemInfo buildPlan
85 packageVersions = fmap ppVersion (bpPackages buildPlan) `Map.union` siCorePackages systemInfo
86 return PackageSetConfig
87 { packageLoader = loadPackage hackageDb optAllCabalHashes
88 , targetPlatform = Platform (siArch systemInfo) (siOS systemInfo)
89 , targetCompiler = ghcCompilerInfo (siGhcVersion systemInfo)
90 , nixpkgsResolver = resolve (Map.map (Set.map (over path ("pkgs":))) nixpkgs)
91 , haskellResolver = buildPlanContainsDependency packageVersions }
93-- Path to Yaml build definition file in lts-haskell repository
94buildPlanFilePath :: FilePath -> StackResolver -> FilePath
95buildPlanFilePath ltsRepoDir resolver =
96 ltsRepoDir Path.</>
97 (resolver ^. to unStackResolver) Path.<.>
98 ".yaml"