git.iko.soy/typeable/stackage2nix
on master help sign in
Build Stackage packages from resolver (#33)
bbb8841Dmitry Bushev
.gitignore+1
@@ -1,2 +1,3 @@
1.stack-work
1.stack-work
2+Paths_stackage2nix.hs
2/*.nix
3/*.nix
src/Runner.hs+75−55
@@ -2,7 +2,7 @@ module Runner ( run ) where
2
2
3import Control.Lens
3import Control.Lens
4import Data.Foldable as F
4import Data.Foldable as F
5−import Data.Functor
5+import Data.List as L
6import Distribution.Nixpkgs.Haskell.FromStack
6import Distribution.Nixpkgs.Haskell.FromStack
7import Distribution.Nixpkgs.Haskell.FromStack.Package
7import Distribution.Nixpkgs.Haskell.FromStack.Package
8import Distribution.Nixpkgs.Haskell.Stack
8import Distribution.Nixpkgs.Haskell.Stack
@@ -18,8 +18,8 @@ import Runner.Cli
18import Stack.Config
18import Stack.Config
19import Stack.Types
19import Stack.Types
20import Stackage.Types
20import Stackage.Types
21−import System.IO (withFile, IOMode(..), hPutStrLn, hPrint)
21+import System.IO (withFile, IOMode(..), hPutStrLn)
22−import Text.PrettyPrint.HughesPJClass (render)
22+import Text.PrettyPrint.HughesPJClass (Doc, render)
23
23
24import qualified Data.Set as Set
24import qualified Data.Set as Set
25import qualified Data.Map as Map
25import qualified Data.Map as Map
@@ -29,60 +29,80 @@ import qualified LtsHaskell as LH
29run :: IO ()
29run :: IO ()
30run = do
30run = do
31 opts <- execParser pinfo
31 opts <- execParser pinfo
32− stackYaml <- envStackYaml >>= \case
32+ case opts ^. optConfigOrigin of
33− Just p -> putStrLn "Getting project config file from STACK_YAML environment" $> p
33+ -- Generate build derivation from stack.yaml file
34− Nothing -> pure $ opts ^. optStackYaml
34+ OriginStackYaml stackYaml -> do
35− stackConf <- either fail pure =<< readStackConfig stackYaml
35+ stackConf <- either fail pure =<< readStackConfig stackYaml
36− let buildPlanFile = LH.buildPlanFilePath (opts ^. optLtsHaskellRepo) (stackConf ^. scResolver)
36+ let buildPlanFile = LH.buildPlanFilePath (opts ^. optLtsHaskellRepo) (stackConf ^. scResolver)
37− buildPlan <- LH.loadBuildPlan buildPlanFile
37+ buildPlan <- LH.loadBuildPlan buildPlanFile
38− packageSetConfig <- LH.buildPackageSetConfig
38+ packageSetConfig <- LH.buildPackageSetConfig
39− (opts ^. optAllCabalHashesRepo)
39+ (opts ^. optAllCabalHashesRepo)
40− (opts ^. optNixpkgsRepository)
40+ (opts ^. optNixpkgsRepository)
41− buildPlan
41+ buildPlan
42− -- generate haskell packages override
43− let
42+ let
44− overrideConfig = mkOverrideConfig opts (siGhcVersion $ bpSystemInfo buildPlan)
43+ overrideConfig = mkOverrideConfig opts (siGhcVersion $ bpSystemInfo buildPlan)
45− stackPackagesConfig = mkStackPackagesConfig opts
44+ stackPackagesConfig = mkStackPackagesConfig opts
46− packages <- traverse (packageDerivation stackPackagesConfig (opts ^. optHackageDb))
45+ stackConfPackages <- traverse (packageDerivation stackPackagesConfig (opts ^. optHackageDb))
47− $ stackConf ^. scPackages
46+ $ stackConf ^. scPackages
48− let out = PP.overrideHaskellPackages overrideConfig packages
47+ let
49− withFile (opts ^. optOutDerivation) WriteMode $ \h -> do
50− hPutStrLn h ("# Generated by stackage2nix " ++ Text.display version ++ " from " ++ stackYaml ^. syFilePath)
51− hPrint h out
52− let
53− reachable = Set.map mkPackageName
48+ reachable = Set.map mkPackageName
54− $ F.foldr1 Set.union
49+ $ F.foldr1 Set.union
55− $ nodeDepends . mkNode <$> packages
50+ $ nodeDepends . mkNode <$> stackConfPackages
56− s2nLoader mHash pkgId =
51+ s2nLoader mHash pkgId =
57− if pkgName pkgId `Set.member` reachable
52+ if pkgName pkgId `Set.member` reachable
58− then packageLoader packageSetConfig Nothing pkgId
53+ then packageLoader packageSetConfig Nothing pkgId
59− else packageLoader packageSetConfig mHash pkgId
54+ else packageLoader packageSetConfig mHash pkgId
60− s2nPackageSetConfig = packageSetConfig { packageLoader = s2nLoader }
55+ s2nPackageSetConfig = packageSetConfig { packageLoader = s2nLoader }
61− s2nPackageConfig = PackageConfig
56+ s2nPackageConfig = PackageConfig
62− { enableCheck = opts ^. optDoCheckStackage
57+ { enableCheck = opts ^. optDoCheckStackage
63− , enableHaddock = opts ^. optDoHaddockStackage }
58+ , enableHaddock = opts ^. optDoHaddockStackage }
64− allNodes <- traverse (uncurry (buildNodeM s2nPackageSetConfig s2nPackageConfig))
59+ stackagePackages <- traverse (uncurry (buildNodeM s2nPackageSetConfig s2nPackageConfig))
65− $ Map.toList (bpPackages buildPlan)
60+ $ Map.toList (bpPackages buildPlan)
66
61
67− -- Find all reachable dependencies in stackage set to stick into
62+ -- Find all reachable dependencies in stackage set to stick into
68− -- stackage packages file. This is performed on the full stackage
63+ -- stackage packages file. This is performed on the full stackage
69− -- set rather than pruning stackage packages beforehand because
64+ -- set rather than pruning stackage packages beforehand because
70− -- stackage does not concern itself with build tools while cabal2nix
65+ -- stackage does not concern itself with build tools while cabal2nix
71− -- does: pruning only after generating full set of packages allows
66+ -- does: pruning only after generating full set of packages allows
72− -- us to make sure all those extra dependencies are explicitly
67+ -- us to make sure all those extra dependencies are explicitly
73− -- listed as well.
68+ -- listed as well.
74− let nodes = case opts ^. optOutPackagesClosure of
69+ let reachableStackagePackages = case opts ^. optOutPackagesClosure of
75− True -> flip reachableDependencies allNodes
70+ True -> flip reachableDependencies stackagePackages
76− -- Originally reachable nodes are root nodes
71+ -- Originally reachable nodes are root nodes
77− $ filter (\n -> mkPackageName (nodeName n) `Set.member` reachable) allNodes
72+ $ L.filter (\n -> mkPackageName (nodeName n) `Set.member` reachable) stackagePackages
78− False -> allNodes
73+ False -> stackagePackages
74+ writeOutFile buildPlanFile (opts ^. optOutStackagePackages)
75+ $ pPrintOutPackages (view nodeDerivation <$> reachableStackagePackages)
76+ writeOutFile buildPlanFile (opts ^. optOutStackageConfig)
77+ $ pPrintOutConfig (bpSystemInfo buildPlan) reachableStackagePackages
78+ writeOutFile (stackYaml ^. syFilePath) (opts ^. optOutDerivation)
79+ $ PP.overrideHaskellPackages overrideConfig stackConfPackages
79
80
81+ -- Generate Stackage packages from resolver
82+ OriginResolver stackResolver -> do
83+ let
84+ buildPlanFile = LH.buildPlanFilePath (opts ^. optLtsHaskellRepo) stackResolver
85+ packageConfig = PackageConfig
86+ { enableCheck = opts ^. optDoCheckStackage
87+ , enableHaddock = opts ^. optDoHaddockStackage }
88+ buildPlan <- LH.loadBuildPlan buildPlanFile
89+ packageSetConfig <- LH.buildPackageSetConfig
90+ (opts ^. optAllCabalHashesRepo)
91+ (opts ^. optNixpkgsRepository)
92+ buildPlan
93+ nodes <- traverse (uncurry (buildNodeM packageSetConfig packageConfig))
94+ $ Map.toList (bpPackages buildPlan)
95+
80− withFile (opts ^. optOutStackagePackages) WriteMode $ \h -> do
96+ writeOutFile buildPlanFile (opts ^. optOutStackagePackages)
81− hPutStrLn h ("# Generated by stackage2nix " ++ Text.display version ++ " from " ++ buildPlanFile)
82− hPutStrLn h $ render $ pPrintOutPackages (view nodeDerivation <$> nodes)
97+ $ pPrintOutPackages (view nodeDerivation <$> nodes)
83− withFile (opts ^. optOutStackageConfig) WriteMode $ \h -> do
98+ writeOutFile buildPlanFile (opts ^. optOutStackageConfig)
84− hPutStrLn h ("# Generated by stackage2nix " ++ Text.display version ++ " from " ++ buildPlanFile)
85− hPutStrLn h $ render $ pPrintOutConfig (bpSystemInfo buildPlan) nodes
99+ $ pPrintOutConfig (bpSystemInfo buildPlan) nodes
100+
101+writeOutFile :: Show source => source -> FilePath -> Doc -> IO ()
102+writeOutFile source filePath contents =
103+ withFile filePath WriteMode $ \h -> do
104+ hPutStrLn h ("# Generated by stackage2nix " ++ Text.display version ++ " from " ++ show source)
105+ hPutStrLn h $ render contents
86
106
87mkOverrideConfig :: Options -> Version -> OverrideConfig
107mkOverrideConfig :: Options -> Version -> OverrideConfig
88mkOverrideConfig opts ghcVersion = OverrideConfig
108mkOverrideConfig opts ghcVersion = OverrideConfig
src/Runner/Cli.hs+23−7
@@ -10,10 +10,20 @@ import Distribution.System as System
10import qualified Distribution.Text as Text
10import qualified Distribution.Text as Text
11import Options.Applicative as Opts
11import Options.Applicative as Opts
12import Paths_stackage2nix ( version )
12import Paths_stackage2nix ( version )
13+import Stack.Config
13import Stack.Types
14import Stack.Types
14import System.Environment
15import System.Environment
15import System.FilePath
16import System.FilePath
16
17
18+-- | Source that would be used to produce target derivation
19+data ConfigOrigin
20+ = OriginResolver StackResolver
21+ -- ^ Resolver to generate Stackage LTS
22+ | OriginStackYaml StackYaml
23+ -- ^ Stack config to generate build derivation
24+ deriving (Show)
25+
26+makePrisms ''ConfigOrigin
17
27
18data Options = Options
28data Options = Options
19 { _optAllCabalHashesRepo :: !FilePath
29 { _optAllCabalHashesRepo :: !FilePath
@@ -30,7 +40,7 @@ data Options = Options
30 , _optNixpkgsRepository :: !FilePath
40 , _optNixpkgsRepository :: !FilePath
31 , _optCompilerId :: !CompilerId
41 , _optCompilerId :: !CompilerId
32 , _optPlatform :: !Platform
42 , _optPlatform :: !Platform
33− , _optStackYamlArg :: !FilePath
43+ , _optConfigOrigin :: !ConfigOrigin
34 } deriving (Show)
44 } deriving (Show)
35
45
36makeLenses ''Options
46makeLenses ''Options
@@ -38,9 +48,6 @@ makeLenses ''Options
38envStackYaml :: IO (Maybe StackYaml)
48envStackYaml :: IO (Maybe StackYaml)
39envStackYaml = fmap mkStackYaml <$> lookupEnv "STACK_YAML"
49envStackYaml = fmap mkStackYaml <$> lookupEnv "STACK_YAML"
40
50
41−optStackYaml :: Getter Options StackYaml
42−optStackYaml = optStackYamlArg . to mkStackYaml
43−
44mkStackYaml :: FilePath -> StackYaml
51mkStackYaml :: FilePath -> StackYaml
45mkStackYaml p = case splitFileName p of
52mkStackYaml p = case splitFileName p of
46 (dir, "") -> StackYaml dir "stack.yaml"
53 (dir, "") -> StackYaml dir "stack.yaml"
@@ -64,7 +71,7 @@ options = Options
64 <*> nixpkgsRepository
71 <*> nixpkgsRepository
65 <*> compilerId
72 <*> compilerId
66 <*> platform
73 <*> platform
67− <*> stackYamlArg
74+ <*> configOrigin
68
75
69pinfo :: ParserInfo Options
76pinfo :: ParserInfo Options
70pinfo = info
77pinfo = info
@@ -143,11 +150,20 @@ doHaddockStackage = switch
143 ( long "do-haddock-stackage"
150 ( long "do-haddock-stackage"
144 <> help "enable haddock for Stackage packages" )
151 <> help "enable haddock for Stackage packages" )
145
152
153+resolver :: Parser StackResolver
154+resolver = StackResolver <$> option text
155+ ( long "resolver"
156+ <> help "stackage LTS resolver" )
157+
146−stackYamlArg :: Parser FilePath
158+stackYamlArg :: Parser StackYaml
147−stackYamlArg = Opts.argument str
159+stackYamlArg = mkStackYaml <$> Opts.argument str
148 ( metavar "STACK_YAML"
160 ( metavar "STACK_YAML"
149 <> help "path to stack.yaml file or directory" )
161 <> help "path to stack.yaml file or directory" )
150
162
163+configOrigin :: Parser ConfigOrigin
164+configOrigin = OriginResolver <$> resolver
165+ <|> OriginStackYaml <$> stackYamlArg
166+
151-- inherited from cabal2nix
167-- inherited from cabal2nix
152
168
153hackageDb :: Parser HackageDb
169hackageDb :: Parser HackageDb
src/Stack/Types.hs+1
@@ -10,6 +10,7 @@ import System.FilePath
10data StackYaml = StackYaml
10data StackYaml = StackYaml
11 { _syDirName :: !FilePath
11 { _syDirName :: !FilePath
12 , _syFileName :: !FilePath }
12 , _syFileName :: !FilePath }
13+ deriving (Ord, Eq, Show)
13
14
14makeLenses ''StackYaml
15makeLenses ''StackYaml
15
16