git.iko.soy/typeable/cabal2nix
on master help sign in
hackage2nix: implement proper argument resolution
commit839fc12ff5791ac222a9ebc97f38faae9490442b authorPeter Simons <simons@cryp.to> dateMon 12 Jan 2015, 15:31 (12 years ago) parentcd89e0d
1 file changed+38−21
src/hackage2nix.hs+38−21
src/hackage2nix.hs+38−21
@@ -1,4 +1,4 @@
1−-- Run: cabal build -j hackage2nix && dist/build/hackage2nix/hackage2nix >hackage-packages.nix && mv hackage-packages.nix ~/.nix-defexpr/pkgs/development/haskell-modules/hackage-packages.nix && nix-env -qaP | tail -1
1+-- Run: cabal build -j hackage2nix && time dist/build/hackage2nix/hackage2nix >hackage-packages.nix && mv hackage-packages.nix ~/.nix-defexpr/pkgs/development/haskell-modules/hackage-packages.nix && nix-env -qaP | tail -1
22
33module Main ( main ) where
44
@@ -7,6 +7,7 @@ import Cabal2Nix.Generate ( cabal2nix' )
77import Cabal2Nix.Hackage ( readHashedHackage, Hackage )
88import Cabal2Nix.Package
99import Data.List
10+import Data.Function
1011import Control.Monad
1112import Control.Monad.Par.Combinator
1213import Control.Monad.Par.IO
@@ -19,7 +20,7 @@ import Data.Set ( Set )
1920import qualified Data.Set as Set
2021import Distribution.Compiler
2122import Distribution.NixOS.Derivation.Cabal
22−import Distribution.NixOS.PackageMap ( PackageMap, readNixpkgPackageMap )
23+import Distribution.NixOS.PackageMap
2324import Distribution.NixOS.PrettyPrinting hiding ( attr, (<>) )
2425import Distribution.Package
2526import Distribution.PackageDescription hiding ( buildDepends, extraLibs, buildTools )
@@ -104,26 +105,32 @@ generatePackageSet hackage nixpkgs = do
104105 -- TODO: Include list of broken dependencies in the generated output.
105106 descr = hackage Map.! name Map.! version
106107 (_, _, drv') = cabal2nix resolver descr
107− drv = drv' { src = srcSpec, editedCabalFile = if revision drv == 0 then "" else cabalFileHash }
108+ drv = drv' { src = srcSpec, editedCabalFile = if revision drv == 0 then "" else cabalFileHash
109+ , metaSection = (metaSection drv') { broken = not (Set.null missing) } -- Missing Haskell dependencies!
110+ }
108111
109112 missing :: Set String
110− missing = Set.fromList $
111− filter (not . isKnownNixpkgAttribute nixpkgs hackage) (extraLibs drv ++ pkgConfDeps drv ++ buildTools drv) ++
112− filter (flip Set.notMember knownAttributesSet) (buildDepends drv ++ testDepends drv)
113+ missing = Set.fromList $ filter (`Set.notMember` knownAttributesSet) (buildDepends drv ++ testDepends drv)
113114
114− missingOverrides :: Doc
115− missingOverrides | Set.null missing = empty
116− | otherwise = fcat [ text (' ':dep++" = null;") | dep <- Set.toAscList missing ] <> space
115+ buildInputs :: Map Attribute (Maybe Path)
116+ buildInputs = Map.unions
117+ [ Map.fromList [ (n, Nothing) | n <- Set.toList missing ]
118+ , Map.fromList [ (n, resolveNixpkgsAttribute nixpkgs n) | n <- Set.toAscList (Set.fromList (extraLibs drv ++ pkgConfDeps drv)) ]
119+ , Map.fromList [ (n, resolveNixpkgsOrHackageAttribute nixpkgs hackage n) | n <- Set.toAscList (Set.fromList (buildTools drv)) ]
120+ ]
117121
118− conflicts :: Set String
119− conflicts = Set.intersection knownAttributesSet (Set.fromList (extraLibs drv ++ pkgConfDeps drv))
122+ systemOverrides :: Doc
123+ systemOverrides = fsep (map (uncurry formatOverride) (Map.toAscList buildInputs))
120124
121− conflictOverrides :: Doc
122− conflictOverrides | Set.null conflicts = empty
123− | otherwise = text " inherit (pkgs) " <> hsep (map text (Set.toAscList conflicts)) <> text "; "
125+ formatOverride :: Attribute -> Maybe Path -> Doc
126+ formatOverride n Nothing = space <> text n <> text " = null;" -- missing attribute
127+ formatOverride n (Just []) -- Haskell package:
128+ | n == name = formatOverride n Nothing -- refers to a missing system library
129+ | otherwise = empty -- found by callPackage
130+ formatOverride n (Just p) = (text " inherit" <+> parens (text (intercalate "." p)) <+> text n) <> semi
124131
125132 overrides :: Doc
126− overrides = conflictOverrides $+$ missingOverrides
133+ overrides = systemOverrides
127134
128135 attr | Just v <- Map.lookup name generatedDefaultPackageSet, v == version = name
129136 | otherwise = name ++ '_' : [ if c == '.' then '_' else c | c <- display version ]
@@ -134,13 +141,23 @@ generatePackageSet hackage nixpkgs = do
134141 liftIO $ mapM_ (\pkg -> putStrLn pkg >> putStrLn "") pkgs
135142 liftIO $ putStrLn "}"
136143
137−isKnownNixpkgAttribute :: Nixpkgs -> Hackage -> String -> Bool
138−isKnownNixpkgAttribute nixpkgs hackage name
139− | Just _ <- Map.lookup name hackage = True
140− | otherwise = maybe False goodScope (Map.lookup name nixpkgs)
144+resolveNixpkgsOrHackageAttribute :: Nixpkgs -> Hackage -> Attribute -> Maybe Path
145+resolveNixpkgsOrHackageAttribute nixpkgs hackage name
146+ | p@(Just _) <- resolveNixpkgsAttribute nixpkgs name = p
147+ | Just _ <- Map.lookup name hackage = Just []
148+ | otherwise = Nothing
149+
150+resolveNixpkgsAttribute :: Nixpkgs -> Attribute -> Maybe Path
151+resolveNixpkgsAttribute nixpkgs name
152+ | Just paths <- Map.lookup name nixpkgs = getShortestPath (Set.toList (paths `Set.intersection` goodScopes))
153+ | otherwise = Nothing
141154 where
142− goodScope :: Set [String] -> Bool
143− goodScope = not . Set.null . Set.intersection (Set.fromList [[], ["xlibs"], ["gnome"]])
155+ goodScopes :: Set Path
156+ goodScopes = Set.fromList [[], ["xlibs"], ["gnome"], ["gnome3"], ["kde4"]]
157+
158+ getShortestPath :: [Path] -> Maybe Path
159+ getShortestPath [] = Nothing
160+ getShortestPath ps = Just ("pkgs" : minimumBy (on compare length) ps)
144161
145162-- These packages replace the latest respective version during dependency resolution.
146163defaultPackageOverrides :: [Constraint]