git.iko.soy/typeable/cabal2nix
on master help sign in
Support more fine-grained dependency information and start to re-factor the code to use lenses.
commit11e6088a4c6116c6784facbcf0e9e6f88fca6e90 authorPeter Simons <simons@cryp.to> dateMon 26 Jan 2015, 22:35 (12 years ago) parent3803048
9 files changed+467−337
src/Cabal2Nix/Generate.hs+105−53 src/Cabal2Nix/Normalize.hs+37−28 src/Cabal2Nix/PostProcess.hs+102−82 src/Distribution/Nixpkgs/Haskell.hs+119−85 src/Distribution/Nixpkgs/Meta.hs+23−26 src/Distribution/Nixpkgs/Util/PrettyPrinting.hs+13−1 src/cabal2nix.hs+37−38 src/hackage2nix.hs+25−18 test/spec.hs+6−6
src/Cabal2Nix/Generate.hs+105−53
@@ -1,22 +1,34 @@
1+{-# LANGUAGE RecordWildCards #-}
2+
13module Cabal2Nix.Generate ( cabal2nix, cabal2nix' ) where
24
35import Cabal2Nix.Flags
4−import Cabal2Nix.License
6+import Cabal2Nix.Name
57import Cabal2Nix.Normalize
68import Cabal2Nix.PostProcess
9+import Control.Lens
10+-- import Data.Set.Lens
11+-- import Control.Applicative
712import Data.Maybe
13+import qualified Data.Set as Set
14+import Data.Version
815import Distribution.Compiler
916import Distribution.Nixpkgs.Haskell
10−import qualified Distribution.Package as Cabal
17+import qualified Distribution.Nixpkgs.Haskell as Nix
18+import Cabal2Nix.License
19+import Distribution.Nixpkgs.Fetch
20+import qualified Distribution.Nixpkgs.Meta as Nix
21+import Distribution.Package
22+import Distribution.Version
23+import Distribution.PackageDescription
1124import qualified Distribution.PackageDescription as Cabal
1225import Distribution.PackageDescription.Configuration
1326import Distribution.System
14−import qualified Data.Set as Set
1527
16−cabal2nix :: Cabal.FlagAssignment -> Cabal.GenericPackageDescription -> Derivation
17−cabal2nix flags' cabal = drv { cabalFlags = flags }
28+cabal2nix :: FlagAssignment -> GenericPackageDescription -> Derivation
29+cabal2nix flags' cabal = normalize $ drv & cabalFlags .~ flags
1830 where drv = cabal2nix' descr
19− flags = normalizeCabalFlags (flags' ++ configureCabalFlags (Cabal.package (Cabal.packageDescription cabal)))
31+ flags = normalizeCabalFlags (flags' ++ configureCabalFlags (package (packageDescription cabal)))
2032 Right (descr, _) = finalizePackageDescription
2133 flags
2234 (const True)
@@ -25,52 +37,92 @@ cabal2nix flags' cabal = drv { cabalFlags = flags }
2537 []
2638 cabal
2739
28−cabal2nix' :: Cabal.PackageDescription -> Derivation
29−cabal2nix' tpkg = normalize $ postProcess $ normalize MkDerivation
30− { pname = let Cabal.PackageName x = Cabal.pkgName pkg in x
31− , version = Cabal.pkgVersion pkg
32− , revision = maybe 0 read (lookup "x-revision" xfields)
33− , src = error "cabal2nix left the src field undefined"
34− , isLibrary = isJust (Cabal.library tpkg)
35− , isExecutable = not (null (Cabal.executables tpkg))
36− , extraFunctionArgs = Set.empty
37− , buildDepends = Set.fromList $ map unDep deps
38− , testDepends = Set.fromList $ map unDep tstDeps ++ concatMap Cabal.extraLibs tests
39− , buildTools = Set.fromList $ map unDep tools
40− , extraLibs = Set.fromList libs
41− , pkgConfDeps = Set.fromList pcs
42− , configureFlags = Set.empty
43− , cabalFlags = configureCabalFlags pkg
44− , runHaddock = True
45− , jailbreak = False
46− , doCheck = True
47− , testTarget = ""
48− , hyperlinkSource = True
49− , enableSplitObjs = True
50− , phaseOverrides = ""
51− , editedCabalFile= if isJust (lookup "x-revision" xfields) then fromJust (lookup "x-cabal-file-hash" xfields) else ""
52− , metaSection = Meta
53− { homepage = Cabal.homepage tpkg
54− , description = Cabal.synopsis tpkg
55− , license = fromCabalLicense (Cabal.license tpkg)
56− , platforms = Set.empty
57− , hydraPlatforms = Set.empty
58− , maintainers = Set.empty
59− , broken = False
60− }
40+nullDerivation :: Derivation
41+nullDerivation = MkDerivation
42+ { _pkgid = error "undefined _pkgid"
43+ , _revision = error "undefined _revision"
44+ , _src = error "undefined _src"
45+ , _isLibrary = error "undefined _isLibrary"
46+ , _isExecutable = error "undefined _isExecutable"
47+ , _extraFunctionArgs = error "undefined _extraFunctionArgs"
48+ , _libraryDepends = error "undefined _libraryDepends"
49+ , _executableDepends = error "undefined _executableDepends"
50+ , _testDepends = error "undefined _testDepends"
51+ , _configureFlags = error "undefined _configureFlags"
52+ , _cabalFlags = error "undefined _cabalFlags"
53+ , _runHaddock = error "undefined _runHaddock"
54+ , _jailbreak = error "undefined _jailbreak"
55+ , _doCheck = error "undefined _doCheck"
56+ , _testTarget = error "undefined _testTarget"
57+ , _hyperlinkSource = error "undefined _hyperlinkSource"
58+ , _enableSplitObjs = error "undefined _enableSplitObjs"
59+ , _phaseOverrides = error "undefined _phaseOverrides"
60+ , _editedCabalFile = error "undefined _editedCabalFile"
61+ , _metaSection = error "undefined _metaSection"
6162 }
62− where
63− xfields = Cabal.customFieldsPD tpkg
64− pkg = Cabal.package tpkg
65− deps = Cabal.buildDepends tpkg
66− tests = map Cabal.testBuildInfo (Cabal.testSuites tpkg)
67− libDeps = map Cabal.libBuildInfo (maybeToList (Cabal.library tpkg))
68− exeDeps = map Cabal.buildInfo (Cabal.executables tpkg)
69− tstDeps = concatMap Cabal.buildTools tests ++ concatMap Cabal.pkgconfigDepends tests ++
70− concatMap Cabal.targetBuildDepends tests
71− tools = concatMap Cabal.buildTools (libDeps ++ exeDeps)
72− libs = concatMap Cabal.extraLibs (libDeps ++ exeDeps)
73− pcs = map unDep (concatMap Cabal.pkgconfigDepends (libDeps ++ exeDeps))
7463
75−unDep :: Cabal.Dependency -> String
76−unDep (Cabal.Dependency (Cabal.PackageName x) _) = x
64+cabal2nix' :: PackageDescription -> Derivation
65+cabal2nix' PackageDescription {..} = normalize $ postProcess $
66+ let
67+ xrev = maybe 0 read (lookup "x-revision" customFieldsPD)
68+ in
69+ nullDerivation
70+ & pkgid .~ package
71+ & revision .~ xrev
72+ & src .~ DerivationSource
73+ { derivKind = "url"
74+ , derivUrl = mempty
75+ , derivRevision = mempty
76+ , derivHash = mempty
77+ }
78+ & isLibrary .~ isJust library
79+ & isExecutable .~ not (null executables)
80+ & extraFunctionArgs .~ mempty
81+ & libraryDepends .~ maybe mempty (convertBuildInfo . libBuildInfo) library
82+ & executableDepends .~ mconcat (map (convertBuildInfo . buildInfo) executables)
83+ & testDepends .~ mconcat (map (convertBuildInfo . testBuildInfo) testSuites)
84+ & configureFlags .~ mempty
85+ & cabalFlags .~ configureCabalFlags package
86+ & runHaddock .~ True
87+ & jailbreak .~ False
88+ & doCheck .~ True
89+ & testTarget .~ mempty
90+ & hyperlinkSource .~ True
91+ & enableSplitObjs .~ True
92+ & phaseOverrides .~ mempty
93+ & editedCabalFile .~ (if xrev > 0 then fromJust (lookup "x-cabal-file-hash" customFieldsPD) else "")
94+ & metaSection .~ ( nullMeta
95+ & Nix.homepage .~ homepage
96+ & Nix.description .~ synopsis
97+ & Nix.license .~ fromCabalLicense license
98+ & Nix.platforms .~ mempty
99+ & Nix.hydraPlatforms .~ mempty
100+ & Nix.maintainers .~ mempty
101+ & Nix.broken .~ False
102+ )
103+
104+nullBuildInfo :: Nix.BuildInfo
105+nullBuildInfo = Nix.BuildInfo
106+ { _haskell = error "undefined _haskell"
107+ , _pkgconfig = error "undefined _pkgconfig"
108+ , _system = error "undefined _system"
109+ , _tool = error "undefined _tool"
110+ }
111+
112+nullMeta :: Nix.Meta
113+nullMeta = Nix.Meta
114+ { Nix._homepage = error "undefined Nix._homepage"
115+ , Nix._description = error "undefined Nix._description"
116+ , Nix._license = error "undefined Nix._license"
117+ , Nix._platforms = error "undefined Nix._platforms"
118+ , Nix._hydraPlatforms = error "undefined Nix._hydraPlatforms"
119+ , Nix._maintainers = error "undefined Nix._maintainers"
120+ , Nix._broken = error "undefined Nix._broken"
121+ }
122+
123+convertBuildInfo :: Cabal.BuildInfo -> Nix.BuildInfo
124+convertBuildInfo Cabal.BuildInfo {..} = nullBuildInfo
125+ & haskell .~ Set.fromList targetBuildDepends
126+ & system .~ Set.fromList [ Dependency (PackageName y) anyVersion | x <- extraLibs, y <- libNixName x, not (null y) ]
127+ & pkgconfig .~ Set.fromList [ Dependency (PackageName y) anyVersion | Dependency (PackageName x) _ <- pkgconfigDepends, y <- libNixName x, not (null y) ]
128+ & tool .~ Set.fromList [ Dependency (PackageName y) anyVersion | Dependency (PackageName x) _ <- buildTools, y <- buildToolNixName x, not (null y) ]
src/Cabal2Nix/Normalize.hs+37−28
@@ -1,42 +1,51 @@
1−{-# LANGUAGE RecordWildCards #-}
2−
3−module Cabal2Nix.Normalize ( normalize, normalizeList, normalizeSet, normalizeCabalFlags ) where
1+module Cabal2Nix.Normalize ( normalize, normalizeCabalFlags ) where
42
53import Cabal2Nix.CorePackages
64import Cabal2Nix.Name
7−import Data.Char
8−import Data.Set ( Set )
9−import qualified Data.Set as Set
5+import Control.Lens
106import Data.Function
117import Data.List
8+import Data.Set ( Set )
9+import qualified Data.Set as Set
1210import Distribution.Nixpkgs.Haskell
11+import Distribution.Nixpkgs.Meta
1312import Distribution.Nixpkgs.Util.Regex ( regsubmatch )
13+import Distribution.Package
1414import Distribution.PackageDescription ( FlagAssignment, FlagName(..) )
1515import Distribution.Simple.Utils ( lowercase )
16+import Distribution.Version
1617
1718normalize :: Derivation -> Derivation
18−normalize deriv@(MkDerivation {..}) = deriv
19− { buildDepends = normalizeNixNames (Set.delete pname buildDepends)
19+normalize drv = drv
20+ & over libraryDepends (normalizeBuildInfo (packageName drv))
21+ & over executableDepends (normalizeBuildInfo (packageName drv))
22+ & over testDepends (normalizeBuildInfo (packageName drv))
23+ & over metaSection normalizeMeta
24+ & over cabalFlags normalizeCabalFlags
25+
26+normalizeBuildInfo :: PackageName -> BuildInfo -> BuildInfo
27+normalizeBuildInfo pname bi = bi
28+ & haskell . contains (Dependency pname anyVersion) .~ False
29+ & tool %~ normalizeNixBuildTools . Set.filter (\(Dependency (PackageName n) _) -> n `notElem` coreBuildTools)
30+
31+ {-
32+ {
2033 , testDepends = normalizeNixNames (Set.delete pname testDepends)
21− , buildTools = normalizeNixBuildTools (Set.filter (`notElem` coreBuildTools) buildTools)
2234 , extraLibs = normalizeNixLibs extraLibs
2335 , pkgConfDeps = normalizeNixLibs pkgConfDeps
2436 , configureFlags = normalizeSet configureFlags
25− , cabalFlags = normalizeCabalFlags cabalFlags
26− , metaSection = normalizeMeta metaSection
2737 }
38+-}
2839
2940normalizeMeta :: Meta -> Meta
30−normalizeMeta meta@(Meta {..}) = meta
31− { description = normalizeDescription description
32− , maintainers = normalizeMaintainers maintainers
33− , platforms = normalizePlatforms platforms
34− }
41+normalizeMeta = over description normalizeSynopsis
42+ . over maintainers normalizeMaintainers
43+ . over platforms normalizePlatforms
3544
36−normalizeDescription :: String -> String
37−normalizeDescription desc
45+normalizeSynopsis :: String -> String
46+normalizeSynopsis desc
3847 | null desc = []
39− | last desc == '.' && length (filter ('.'==) desc) == 1 = normalizeDescription (init desc)
48+ | last desc == '.' && length (filter ('.'==) desc) == 1 = normalizeSynopsis (init desc)
4049 | otherwise = quote (unwords (words desc))
4150
4251quote :: String -> String
@@ -45,20 +54,20 @@ quote ('"':cs) = '\\' : '"' : quote cs
4554quote (c:cs) = c : quote cs
4655quote [] = []
4756
48−normalizeList :: [String] -> [String]
49−normalizeList = nub . sortBy (compare `on` map toLower) . filter (not . null)
50−
5157normalizeSet :: Set String -> Set String
5258normalizeSet = Set.filter (not . null)
5359
54−normalizeNixNames :: Set String -> Set String
55−normalizeNixNames = normalizeSet . Set.map toNixName
60+-- normalizeNixNames :: Set String -> Set String
61+-- normalizeNixNames = normalizeSet . Set.map toNixName
5662
57−normalizeNixLibs :: Set String -> Set String
58−normalizeNixLibs = normalizeSet . Set.fromList . concatMap libNixName . Set.toList
63+-- normalizeNixLibs :: Set String -> Set String
64+-- normalizeNixLibs = normalizeSet . Set.fromList . concatMap libNixName . Set.toList
5965
60−normalizeNixBuildTools :: Set String -> Set String
61−normalizeNixBuildTools = normalizeSet . Set.fromList . concatMap buildToolNixName . Set.toList
66+normalizeNixBuildTools :: Set Dependency -> Set Dependency
67+normalizeNixBuildTools = Set.fromList . concatMap buildToolNixName' . Set.toList
68+ where
69+ buildToolNixName' :: Dependency -> [Dependency]
70+ buildToolNixName' (Dependency (PackageName n) vr) = [ Dependency (PackageName n') vr | n' <- buildToolNixName n ]
6271
6372-- |Strip any kind of path prefix from maintainer names, filter duplicates, and
6473-- sort the resulting list alphabetically.
src/Cabal2Nix/PostProcess.hs+102−82
@@ -1,17 +1,113 @@
1−{-# LANGUAGE RecordWildCards #-}
2−
31module Cabal2Nix.PostProcess ( postProcess ) where
42
3+import Control.Lens
4+import Data.Maybe
55import qualified Data.Set as Set
66import Distribution.Nixpkgs.Haskell
7−import Distribution.Text ( display )
7+import Distribution.Package
8+import Distribution.Text
9+import Distribution.Version
810
911postProcess :: Derivation -> Derivation
10−postProcess = postProcess' . fixGtkBuilds
12+postProcess deriv = foldr ($) (fixGtkBuilds deriv) [ f | (Dependency n vr, f) <- hooks, packageName deriv == n, packageVersion deriv `withinRange` vr ]
1113
1214fixGtkBuilds :: Derivation -> Derivation
13−fixGtkBuilds deriv@(MkDerivation {..}) = deriv { pkgConfDeps = pkgConfDeps `Set.difference` buildDepends }
15+fixGtkBuilds drv = drv & dependencies . pkgconfig %~ (`Set.difference` buildDeps)
16+ where
17+ buildDeps = drv ^. dependencies . haskell
18+
19+hooks :: [(Dependency, Derivation -> Derivation)]
20+hooks = over (mapped._1) (\str -> fromMaybe (error ("invalid constraint: " ++ show str)) (simpleParse str))
21+ [ ("dns", set testTarget "spec") -- don't execute tests that try to access the network
22+ , ("bindings-GLFW", over (libraryDepends . system) (Set.union (Set.fromList [dep "libXext", dep "libXfixes"])))
23+ , ("cabal-install", set phaseOverrides cabalInstallPostInstall)
24+ , ("darcs", set phaseOverrides darcsInstallPostInstall)
25+ , ("git-annex", gitAnnexHook)
26+ , ("haddock", set phaseOverrides "preCheck = \"unset GHC_PACKAGE_PATH\";")
27+ , ("HFuse", set phaseOverrides hfusePreConfigure)
28+ , ("gf", set phaseOverrides gfPhaseOverrides . set doCheck False)
29+ , ("GlomeVec", set (libraryDepends . pkgconfig . contains (dep "llvm")) True)
30+ , ("gtk3", set (libraryDepends . pkgconfig . contains (dep "gtk3")) True)
31+ , ("jsaddle", set (dependencies . haskell . contains (dep "ghcjs-base")) False)
32+ , ("pango", set (libraryDepends . haskell . contains (dep "cairo")) True)
33+ , ("readline", over (libraryDepends . system) (Set.union (Set.fromList [dep "readline", dep "ncurses"])))
34+ , ("monad", set phaseOverrides xmonadPostInstall)
35+ , ("wxc", wxcHook)
36+ ]
37+
38+dep :: String -> Dependency
39+dep s = Dependency (PackageName s) anyVersion
40+
41+gitAnnexHook :: Derivation -> Derivation
42+gitAnnexHook = set phaseOverrides gitAnnexOverrides . over (executableDepends . system) (Set.union buildInputs)
43+ where
44+ gitAnnexOverrides = unlines
45+ [ "preConfigure = \"export HOME=$TEMPDIR\";"
46+ , "checkPhase = ''"
47+ , " cp dist/build/git-annex/git-annex git-annex"
48+ , " ./git-annex test"
49+ , "'';"
50+ ]
51+ buildInputs = Set.map dep $ Set.fromList ["git","rsync","gnupg","curl","wget","lsof","openssh","which","bup","perl"]
52+
53+hfusePreConfigure :: String
54+hfusePreConfigure = unlines
55+ [ "preConfigure = ''"
56+ , " sed -i -e \"s@ Extra-Lib-Dirs: /usr/local/lib@ Extra-Lib-Dirs: ${fuse}/lib@\" HFuse.cabal"
57+ , "'';"
58+ ]
59+
60+gfPhaseOverrides :: String
61+gfPhaseOverrides = unlines
62+ [ "postPatch = ''"
63+ , " sed -i \"s|\\\"-s\\\"|\\\"\\\"|\" ./Setup.hs"
64+ -- Disable silent compilation. Compiling takes long, it is best to see some
65+ -- output, otherwise it looks like the build step has stalled.
66+ , " sed -i \"s|numJobs (bf bi)++||\" ./Setup.hs"
67+ -- Parallel compilation fails. Disable it.
68+ , "'';"
69+ , "preBuild = ''export LD_LIBRARY_PATH=`pwd`/dist/build:$LD_LIBRARY_PATH'';"
70+ -- The build step itself, after having built the library, needs to be able
71+ -- to find the library it just built in order to compile grammar files.
72+ ]
73+
74+wxcHook :: Derivation -> Derivation
75+wxcHook drv = drv & libraryDepends . system %~ Set.union (Set.fromList [dep "wxGTK", dep "mesa", dep "libX11"])
76+ & phaseOverrides .~ wxcPostInstall (packageVersion drv)
77+ where
78+ wxcPostInstall :: Version -> String
79+ wxcPostInstall version = unlines
80+ [ "postInstall = ''"
81+ , " cp -v dist/build/libwxc.so." ++ display version ++ " $out/lib/libwxc.so"
82+ , "'';"
83+ ]
84+
85+cabalInstallPostInstall :: String
86+cabalInstallPostInstall = unlines
87+ [ "postInstall = ''"
88+ , " mkdir $out/etc"
89+ , " mv bash-completion $out/etc/bash_completion.d"
90+ , "'';"
91+ ]
92+
93+darcsInstallPostInstall :: String
94+darcsInstallPostInstall = unlines
95+ [ "postInstall = ''"
96+ , " mkdir -p $out/etc/bash_completion.d"
97+ , " mv contrib/darcs_completion $out/etc/bash_completion.d/darcs"
98+ , "'';"
99+ ]
100+
101+xmonadPostInstall :: String
102+xmonadPostInstall = unlines
103+ [ "postInstall = ''"
104+ , " shopt -s globstar"
105+ , " mkdir -p $out/share/man/man1"
106+ , " mv \"$out/\"**\"/man/\"*.1 $out/share/man/man1/"
107+ , "'';"
108+ ]
14109
110+{-
15111postProcess' :: Derivation -> Derivation
16112postProcess' deriv@(MkDerivation {..})
17113 | pname == "aeson" && version > Version [0,7] []
@@ -22,16 +118,11 @@ postProcess' deriv@(MkDerivation {..})
22118 | pname == "alex" && version >= Version [3,1] []
23119 = deriv { buildTools = Set.insert "perl" (Set.insert "happy" buildTools) }
24120 | pname == "apache-md5" = deriv { testDepends = Set.delete "crypto" testDepends }
25− | pname == "bindings-GLFW" = deriv { extraLibs = Set.insert "libXext" (Set.insert "libXfixes" extraLibs) }
26121 | pname == "bits-extras" = deriv { configureFlags = Set.insert "--ghc-option=-lgcc_s" configureFlags
27122 , extraLibs = Set.filter (/= "gcc_s") extraLibs
28123 }
29124 | pname == "Cabal" = deriv { phaseOverrides = "preCheck = \"unset GHC_PACKAGE_PATH; export HOME=$NIX_BUILD_TOP\";" }
30125 | pname == "cabal-bounds" = deriv { buildTools = Set.insert "cabal-install" buildTools }
31− | pname == "cabal-install" && version >= Version [0,14] []
32− = deriv { phaseOverrides = cabalInstallPostInstall }
33− | pname == "darcs" = deriv { phaseOverrides = darcsInstallPostInstall }
34− | pname == "dns" = deriv { testTarget = "spec" }
35126 | pname == "editline" = deriv { extraLibs = Set.insert "libedit" extraLibs }
36127 | pname == "epic" = deriv { extraLibs = Set.insert "gmp" (Set.insert "boehmgc" extraLibs)
37128 , buildTools = Set.insert "happy" buildTools
@@ -42,8 +133,6 @@ postProcess' deriv@(MkDerivation {..})
42133 , phaseOverrides = ghcParserPatchPhase }
43134 | pname == "ghc-paths" = deriv { phaseOverrides = ghcPathsPatches }
44135 | pname == "ghc-vis" = deriv { phaseOverrides = ghciPostInstall }
45− | pname == "git-annex" = deriv { phaseOverrides = gitAnnexOverrides
46− , buildTools = Set.fromList ["git","rsync","gnupg","curl","wget","lsof","openssh","which","bup","perl"] `Set.union` buildTools }
47136 | pname == "github-backup" = deriv { buildTools = Set.insert "git" buildTools }
48137 | pname == "gloss-raster" = deriv { extraLibs = Set.insert "llvm" extraLibs }
49138 | pname == "GLUT" = deriv { extraLibs = Set.fromList ["glut","libSM","libICE","libXmu","libXi","mesa"] `Set.union` extraLibs }
@@ -51,15 +140,10 @@ postProcess' deriv@(MkDerivation {..})
51140 | pname == "gtk2hs-buildtools"= deriv { buildDepends = Set.insert "hashtables" buildDepends }
52141 | pname == "haddock" && version < Version [2,14] []
53142 = deriv { buildTools = Set.insert "alex" (Set.insert "happy" buildTools) }
54− | pname == "gf" = deriv { phaseOverrides = gfPhaseOverrides
55− , doCheck = False }
56− | pname == "GlomeVec" = deriv { buildTools = Set.insert "llvm" buildTools }
57− | pname == "haddock" = deriv { phaseOverrides = haddockPreCheck }
58143 | pname == "happy" = deriv { buildTools = Set.insert "perl" buildTools }
59144 | pname == "haskeline" = deriv { buildDepends = Set.insert "utf8-string" buildDepends }
60145 | pname == "haskell-src" = deriv { buildTools = Set.insert "happy" buildTools }
61146 | pname == "haskell-src-meta" = deriv { buildDepends = Set.insert "uniplate" buildDepends }
62− | pname == "HFuse" = deriv { phaseOverrides = hfusePreConfigure }
63147 | pname == "hlibgit2" = deriv { buildTools = Set.insert "git" buildTools }
64148 | pname == "HList" = deriv { buildTools = Set.insert "diffutils" buildTools }
65149 | pname == "hmatrix" = deriv { extraLibs = Set.insert "liblapack" (Set.insert "blas" (Set.filter (/= "lapack") extraLibs)) }
@@ -87,7 +171,6 @@ postProcess' deriv@(MkDerivation {..})
87171 | pname == "pcap" = deriv { extraLibs = Set.insert "libpcap" extraLibs }
88172 | pname == "persistent" = deriv { extraLibs = Set.insert "sqlite3" extraLibs }
89173 | pname == "purescript" = deriv { buildTools = Set.insert "nodejs" buildTools }
90− | pname == "readline" = deriv { extraLibs = Set.insert "readline" (Set.insert "ncurses" extraLibs) }
91174 | pname == "repa-algorithms" = deriv { extraLibs = Set.insert "llvm" extraLibs }
92175 | pname == "repa-examples" = deriv { extraLibs = Set.insert "llvm" extraLibs }
93176 | pname == "saltine" = deriv { extraLibs = Set.map (\x -> if x == "sodium" then "libsodium" else x) extraLibs }
@@ -103,9 +186,6 @@ postProcess' deriv@(MkDerivation {..})
103186 | pname == "threadscope" = deriv { configureFlags = Set.insert "--ghc-options=-rtsopts" configureFlags }
104187 | pname == "thyme" = deriv { buildTools = Set.insert "cpphs" buildTools }
105188 | pname == "vacuum" = deriv { extraLibs = Set.insert "ghc-paths" extraLibs }
106− | pname == "wxc" = deriv { extraLibs = Set.fromList ["wxGTK","mesa","libX11"] `Set.union` extraLibs
107− , phaseOverrides = wxcPostInstall version
108− }
109189 | pname == "wxcore" = deriv { extraLibs = Set.fromList ["wxGTK","mesa","libX11"] `Set.union` extraLibs }
110190 | pname == "X11" && version >= Version [1,6] []
111191 = deriv { extraLibs = Set.fromList ["libXinerama","libXext","libXrender"] `Set.union` extraLibs }
@@ -119,7 +199,6 @@ postProcess' deriv@(MkDerivation {..})
119199
120200 | pname == "hnetcdf" = deriv { testDepends = Set.delete "netcdf" testDepends }
121201 | pname == "SDL2-ttf" = deriv { buildDepends = Set.delete "SDL2" buildDepends }
122− | pname == "jsaddle" = deriv { buildDepends = Set.delete "ghcjs-base" buildDepends, testDepends = Set.delete "ghcjs-base" testDepends }
123202 | pname == "hzk" = deriv { testDepends = Set.delete "zookeeper_mt" testDepends, buildTools = Set.insert "zookeeper_mt" buildTools }
124203 | pname == "z3" = deriv { phaseOverrides = "preBuild = stdenv.lib.optionalString stdenv.isDarwin \"export DYLD_LIBRARY_PATH=${z3}/lib\";" }
125204 | pname == "zip-archive" = deriv { testDepends = Set.delete "zip" testDepends, buildTools = Set.insert "zip" buildTools }
@@ -138,47 +217,6 @@ ghcModPostInstall pname version = unlines
138217 , "'';"
139218 ]
140219
141−wxcPostInstall :: Version -> String
142−wxcPostInstall version = unlines
143− [ "postInstall = ''"
144− , " cp -v dist/build/libwxc.so." ++ display version ++ " $out/lib/libwxc.so"
145− , "'';"
146− ]
147−
148−cabalInstallPostInstall :: String
149−cabalInstallPostInstall = unlines
150− [ "postInstall = ''"
151− , " mkdir $out/etc"
152− , " mv bash-completion $out/etc/bash_completion.d"
153− , "'';"
154− ]
155−
156−darcsInstallPostInstall :: String
157−darcsInstallPostInstall = unlines
158− [ "postInstall = ''"
159− , " mkdir -p $out/etc/bash_completion.d"
160− , " mv contrib/darcs_completion $out/etc/bash_completion.d/darcs"
161− , "'';"
162− ]
163−
164−xmonadPostInstall :: String
165−xmonadPostInstall = unlines
166− [ "postInstall = ''"
167− , " shopt -s globstar"
168− , " mkdir -p $out/share/man/man1"
169− , " mv \"$out/\"**\"/man/\"*.1 $out/share/man/man1/"
170− , "'';"
171− ]
172−
173−gitAnnexOverrides :: String
174−gitAnnexOverrides = unlines
175− [ "preConfigure = \"export HOME=$TEMPDIR\";"
176− , "checkPhase = ''"
177− , " cp dist/build/git-annex/git-annex git-annex"
178− , " ./git-annex test"
179− , "'';"
180− ]
181−
182220ghciPostInstall :: String
183221ghciPostInstall = unlines
184222 [ "postInstall = ''"
@@ -187,12 +225,6 @@ ghciPostInstall = unlines
187225 , "'';"
188226 ]
189227
190−hfusePreConfigure :: String
191−hfusePreConfigure = unlines
192− [ "preConfigure = ''"
193− , " sed -i -e \"s@ Extra-Lib-Dirs: /usr/local/lib@ Extra-Lib-Dirs: ${fuse}/lib@\" HFuse.cabal"
194− , "'';"
195− ]
196228
197229ghcPathsPatches :: String
198230ghcPathsPatches = "patches = [ ./ghc-paths-nix.patch ];"
@@ -244,16 +276,4 @@ ghcParserPatchPhase = unlines
244276 , "'';"
245277 ]
246278
247−gfPhaseOverrides :: String
248−gfPhaseOverrides = unlines
249− [ "postPatch = ''"
250− , " sed -i \"s|\\\"-s\\\"|\\\"\\\"|\" ./Setup.hs"
251− -- Disable silent compilation. Compiling takes long, it is best to see some
252− -- output, otherwise it looks like the build step has stalled.
253− , " sed -i \"s|numJobs (bf bi)++||\" ./Setup.hs"
254− -- Parallel compilation fails. Disable it.
255− , "'';"
256− , "preBuild = ''export LD_LIBRARY_PATH=`pwd`/dist/build:$LD_LIBRARY_PATH'';"
257− -- The build step itself, after having built the library, needs to be able
258− -- to find the library it just built in order to compile grammar files.
259− ]
279+-}
src/Distribution/Nixpkgs/Haskell.hs+119−85
@@ -1,22 +1,16 @@
1+{-# LANGUAGE TemplateHaskell #-}
12{-# LANGUAGE RecordWildCards, DeriveGeneric #-}
23{-# OPTIONS_GHC -fno-warn-orphans #-} -- for FlagName below
34
4−module Distribution.Nixpkgs.Haskell
5− ( Derivation(..)
6− , renderDerivation
7− , DerivationSource(..)
8− , module Distribution.Nixpkgs.Meta
9− , module Data.Version
10− )
11− where
5+module Distribution.Nixpkgs.Haskell where
126
137import Control.DeepSeq.Generics
14−import Data.Char
8+import Control.Lens
159import Data.Set ( Set )
1610import qualified Data.Set as Set
1711import Data.Function
1812import Data.List
19−import Data.Version
13+import Distribution.Version
2014import Distribution.Nixpkgs.Meta
2115import Distribution.Nixpkgs.Fetch
2216import Distribution.Nixpkgs.Util.PrettyPrinting
@@ -24,8 +18,19 @@ import Distribution.Package
2418import Distribution.PackageDescription ( FlagAssignment, FlagName(..) )
2519import GHC.Generics ( Generic )
2620
27−toAscList :: Set String -> [String]
28−toAscList = sortBy (compare `on` map toLower) . Set.toList
21+data BuildInfo = BuildInfo
22+ { _haskell :: Set Dependency
23+ , _pkgconfig :: Set Dependency
24+ , _system :: Set Dependency
25+ , _tool :: Set Dependency
26+ }
27+ deriving (Show, Eq, Generic)
28+
29+makeLenses ''BuildInfo
30+
31+instance Monoid BuildInfo where
32+ mempty = BuildInfo mempty mempty mempty mempty
33+ BuildInfo w1 x1 y1 z1 `mappend` BuildInfo w2 x2 y2 z2 = BuildInfo (w1 `mappend` w2) (x1 `mappend` x2) (y1 `mappend` y2) (z1 `mappend` z2)
2934
3035-- | A represtation of Nix expressions for building Haskell packages.
3136-- The data type correspond closely to the definition of
@@ -34,87 +39,116 @@ toAscList = sortBy (compare `on` map toLower) . Set.toList
3439-- Note that the "Text" instance definition provides pretty-printing,
3540-- but no parsing as of now!
3641data Derivation = MkDerivation
37− { pname :: String
38− , version :: Version
39− , revision :: Int
40− , src :: DerivationSource
41− , isLibrary :: Bool
42− , isExecutable :: Bool
43− , extraFunctionArgs :: Set String
44− , buildDepends :: Set String
45− , testDepends :: Set String
46− , buildTools :: Set String
47− , extraLibs :: Set String
48− , pkgConfDeps :: Set String
49− , configureFlags :: Set String
50− , cabalFlags :: FlagAssignment
51− , runHaddock :: Bool
52− , jailbreak :: Bool
53− , doCheck :: Bool
54− , testTarget :: String
55− , hyperlinkSource :: Bool
56− , enableSplitObjs :: Bool
57− , phaseOverrides :: String
58− , editedCabalFile :: String
59− , metaSection :: Meta
42+ { _pkgid :: PackageIdentifier
43+ , _revision :: Int
44+ , _src :: DerivationSource
45+ , _isLibrary :: Bool
46+ , _isExecutable :: Bool
47+ , _extraFunctionArgs :: Set String
48+ , _libraryDepends :: BuildInfo
49+ , _executableDepends :: BuildInfo
50+ , _testDepends :: BuildInfo
51+ , _configureFlags :: Set String
52+ , _cabalFlags :: FlagAssignment
53+ , _runHaddock :: Bool
54+ , _jailbreak :: Bool
55+ , _doCheck :: Bool
56+ , _testTarget :: String
57+ , _hyperlinkSource :: Bool
58+ , _enableSplitObjs :: Bool
59+ , _phaseOverrides :: String
60+ , _editedCabalFile :: String
61+ , _metaSection :: Meta
6062 }
61− deriving (Show, Eq, Ord, Generic)
63+ deriving (Show, Eq, Generic)
6264
63−instance Pretty Derivation where
64− pPrint = renderDerivation
65+makeLenses ''Derivation
66+
67+makeLensesFor [("_libraryDepends", "dependencies"), ("_executableDepends", "dependencies"), ("_testDepends", "dependencies")] ''Derivation
6568
6669instance Package Derivation where
67− packageId deriv = PackageIdentifier (PackageName (pname deriv)) (version deriv)
70+ packageId = _pkgid
71+
72+instance NFData BuildInfo where rnf = genericRnf
6873
6974instance NFData Derivation where rnf = genericRnf
7075
7176instance NFData FlagName where rnf = genericRnf
7277
73−renderDerivation :: Derivation -> Doc
74−renderDerivation (MkDerivation {..}) =
75− funargs (map text ("mkDerivation" : toAscList inputs)) $$ vcat
76− [ text "mkDerivation" <+> lbrace
77− , nest 2 $ vcat
78− [ attr "pname" $ string pname
79− , attr "version" $ doubleQuotes (disp version)
80− , onlyIf (revision > 0) $ attr "revision" $ doubleQuotes (int revision)
81− , sourceAttr src
82− , onlyIf (not (null editedCabalFile)) $ attr "editedCabalFile" $ string editedCabalFile
83− , boolattr "isLibrary" (not isLibrary || isExecutable) isLibrary
84− , boolattr "isExecutable" (not isLibrary || isExecutable) isExecutable
85− , listattr "buildDepends" empty (toAscList buildDepends)
86− , listattr "testDepends" empty (toAscList testDepends)
87− , listattr "buildTools" empty (toAscList buildTools)
88− , listattr "extraLibraries" empty (toAscList extraLibs)
89− , listattr "pkgconfigDepends" empty (toAscList pkgConfDeps)
90− , listattr "configureFlags" empty (map (show . show) renderedFlags)
91− , boolattr "enableSplitObjs" (not enableSplitObjs) enableSplitObjs
92− , boolattr "doHaddock" (not runHaddock) runHaddock
93− , boolattr "jailbreak" jailbreak jailbreak
94− , boolattr "doCheck" (not doCheck) doCheck
95− , onlyIf (not (null testTarget)) $ attr "testTarget" $ string testTarget
96− , boolattr "hyperlinkSource" (not hyperlinkSource) hyperlinkSource
97− , onlyIf (not (null phaseOverrides)) $ vcat ((map text . lines) phaseOverrides)
98− , pPrint metaSection
78+instance NFData VersionRange where rnf = genericRnf
79+
80+instance NFData Dependency where rnf = genericRnf
81+
82+instance Pretty Derivation where
83+ pPrint MkDerivation {..} = funargs (map text ("mkDerivation" : toAscList inputs)) $$ vcat
84+ [ text "mkDerivation" <+> lbrace
85+ , nest 2 $ vcat
86+ [ attr "pname" $ doubleQuotes $ disp (packageName _pkgid)
87+ , attr "version" $ doubleQuotes $ disp (packageVersion _pkgid)
88+ , sourceAttr _src
89+ , onlyIf (_revision > 0) $ attr "revision" $ doubleQuotes $ int _revision
90+ , onlyIf (not (null _editedCabalFile)) $ attr "editedCabalFile" $ string _editedCabalFile
91+ , listattr "configureFlags" empty (map (show . show) renderedFlags)
92+ , boolattr "isLibrary" (not _isLibrary || _isExecutable) _isLibrary
93+ , boolattr "isExecutable" (not _isLibrary || _isExecutable) _isExecutable
94+ , onlyIf (_libraryDepends /= mempty) $ pPrintBuildInfo "library" _libraryDepends
95+ , onlyIf (_executableDepends /= mempty) $ pPrintBuildInfo "executable" _executableDepends
96+ , onlyIf (_testDepends /= mempty) $ pPrintBuildInfo "test" _testDepends
97+ , boolattr "enableSplitObjs" (not _enableSplitObjs) _enableSplitObjs
98+ , boolattr "doHaddock" (not _runHaddock) _runHaddock
99+ , boolattr "jailbreak" _jailbreak _jailbreak
100+ , boolattr "doCheck" (not _doCheck) _doCheck
101+ , onlyIf (not (null _testTarget)) $ attr "testTarget" $ string _testTarget
102+ , boolattr "hyperlinkSource" (not _hyperlinkSource) _hyperlinkSource
103+ , onlyIf (not (null _phaseOverrides)) $ vcat ((map text . lines) _phaseOverrides)
104+ , pPrint _metaSection
105+ ]
106+ , rbrace
99107 ]
100− , rbrace
101− ]
102− where
103− inputs = Set.unions [ buildDepends, testDepends, buildTools, extraLibs, pkgConfDeps, extraFunctionArgs
104− , Set.fromList ["fetch" ++ derivKind src | derivKind src /= "" && not isHackagePackage]
105− ]
106− renderedFlags = [ text "-f" <> (if enable then empty else char '-') <> text f | (FlagName f, enable) <- cabalFlags ]
107− ++ map text (toAscList configureFlags)
108− isHackagePackage = "mirror://hackage/" `isPrefixOf` derivUrl src
109− sourceAttr (DerivationSource{..})
110− | isHackagePackage = attr "sha256" $ string derivHash
111− | derivKind /= "" = vcat
112− [ text "src" <+> equals <+> text ("fetch" ++ derivKind) <+> lbrace
113− , nest 2 $ vcat
114− [ attr "url" $ string derivUrl
115− , attr "sha256" $ string derivHash
116− , if derivRevision /= "" then attr "rev" (string derivRevision) else empty
108+ where
109+ inputs :: Set String
110+ inputs = Set.unions [ _extraFunctionArgs
111+ , Set.map unDep (_haskell _libraryDepends)
112+ , Set.map unDep (_haskell _executableDepends)
113+ , Set.map unDep (_haskell _testDepends)
114+ , Set.map unDep (_system _libraryDepends)
115+ , Set.map unDep (_system _executableDepends)
116+ , Set.map unDep (_system _testDepends)
117+ , Set.map unDep (_pkgconfig _libraryDepends)
118+ , Set.map unDep (_pkgconfig _executableDepends)
119+ , Set.map unDep (_pkgconfig _testDepends)
120+ , Set.map unDep (_tool _libraryDepends)
121+ , Set.map unDep (_tool _executableDepends)
122+ , Set.map unDep (_tool _testDepends)
123+ , Set.fromList ["fetch" ++ derivKind _src | derivKind _src /= "" && not isHackagePackage]
124+ ]
125+
126+ renderedFlags = [ text "-f" <> (if enable then empty else char '-') <> text f | (FlagName f, enable) <- _cabalFlags ]
127+ ++ map text (toAscList _configureFlags)
128+ isHackagePackage = "mirror://hackage/" `isPrefixOf` derivUrl _src
129+ sourceAttr (DerivationSource{..})
130+ | isHackagePackage = attr "sha256" $ string derivHash
131+ | derivKind /= "" = vcat
132+ [ text "src" <+> equals <+> text ("fetch" ++ derivKind) <+> lbrace
133+ , nest 2 $ vcat
134+ [ attr "url" $ string derivUrl
135+ , attr "sha256" $ string derivHash
136+ , if derivRevision /= "" then attr "rev" (string derivRevision) else empty
137+ ]
138+ , rbrace <> semi
117139 ]
118− , rbrace <> semi
119− ]
120− | otherwise = attr "src" $ text derivUrl
140+ | otherwise = attr "src" $ text derivUrl
141+
142+pPrintBuildInfo :: String -> BuildInfo -> Doc
143+pPrintBuildInfo prefix bi = vcat
144+ [ setattr (prefix++"HaskellDepends") (Set.map unDep (bi^.haskell))
145+ , setattr (prefix++"SystemDepends") (Set.map unDep (bi^.system))
146+ , setattr (prefix++"PkgconfigDepends") (Set.map unDep (bi^.pkgconfig))
147+ , setattr (prefix++"ToolDepends") (Set.map unDep (bi^.tool))
148+ ]
149+
150+unDep :: Dependency -> String
151+unDep (Dependency (PackageName x) _) = x
152+
153+instance Ord Dependency where
154+ compare = compare `on` unDep
src/Distribution/Nixpkgs/Meta.hs+23−26
@@ -1,3 +1,4 @@
1+{-# LANGUAGE TemplateHaskell #-}
12{-# LANGUAGE DeriveGeneric, RecordWildCards #-}
23{- |
34 A representation of the @meta@ section used in Nix expressions. A
@@ -5,13 +6,10 @@
56 of the Nixpkgs manual at <http://nixos.org/nixpkgs/docs.html>.
67 -}
78
8−module Distribution.Nixpkgs.Meta
9− ( Meta(..)
10− , module Distribution.Nixpkgs.License
11− )
12− where
9+module Distribution.Nixpkgs.Meta where
1310
1411import Control.DeepSeq.Generics
12+import Control.Lens
1513import Distribution.Nixpkgs.License
1614import Distribution.Nixpkgs.Util.PrettyPrinting
1715import GHC.Generics ( Generic )
@@ -39,33 +37,32 @@ import qualified Data.Set as Set
3937-- but no parsing as of now!
4038
4139data Meta = Meta
42− { homepage :: String -- ^ URL of the package homepage
43− , description :: String -- ^ short description of the package
44− , license :: License -- ^ licensing terms
45− , platforms :: Set String -- ^ list of supported platforms (from @pkgs\/lib\/platforms.nix@)
46− , hydraPlatforms :: Set String -- ^ list of platforms built by Hydra (from @pkgs\/lib\/platforms.nix@)
47− , maintainers :: Set String -- ^ list of maintainers from @pkgs\/lib\/maintainers.nix@
48− , broken :: Bool -- ^ set to @true@ if the build is known to fail
40+ { _homepage :: String -- ^ URL of the package homepage
41+ , _description :: String -- ^ short description of the package
42+ , _license :: License -- ^ licensing terms
43+ , _platforms :: Set String -- ^ list of supported platforms (from @pkgs\/lib\/platforms.nix@)
44+ , _hydraPlatforms :: Set String -- ^ list of platforms built by Hydra (from @pkgs\/lib\/platforms.nix@)
45+ , _maintainers :: Set String -- ^ list of maintainers from @pkgs\/lib\/maintainers.nix@
46+ , _broken :: Bool -- ^ set to @true@ if the build is known to fail
4947 }
5048 deriving (Show, Eq, Ord, Generic)
5149
52−instance Pretty Meta where
53− pPrint = renderMeta
50+makeLenses ''Meta
5451
5552instance NFData Meta where rnf = genericRnf
5653
57−renderMeta :: Meta -> Doc
58−renderMeta (Meta {..}) = vcat
59− [ onlyIf (not (null homepage)) $ attr "homepage" $ string homepage
60− , onlyIf (not (null description)) $ attr "description" $ string description
61− , attr "license" $ pPrint license
62− , onlyIf (not (Set.null platforms) && platforms /= Set.singleton "ghc.meta.platforms") $ sep
63− [ text "platforms" <+> equals, renderPlatformList (Set.toAscList platforms) ]
64− , onlyIf (not (Set.null hydraPlatforms)) $ sep
65− [ text "hydraPlatforms" <+> equals, renderPlatformList (Set.toAscList hydraPlatforms) ]
66− , listattr "maintainers" (text "with stdenv.lib.maintainers;") (Set.toAscList maintainers)
67− , boolattr "broken" broken broken
68− ]
54+instance Pretty Meta where
55+ pPrint Meta {..} = vcat
56+ [ onlyIf (not (null _homepage)) $ attr "homepage" $ string _homepage
57+ , onlyIf (not (null _description)) $ attr "description" $ string _description
58+ , attr "license" $ pPrint _license
59+ , onlyIf (not (Set.null _platforms) && _platforms /= Set.singleton "ghc.meta.platforms") $ sep
60+ [ text "platforms" <+> equals, renderPlatformList (Set.toAscList _platforms) ]
61+ , onlyIf (not (Set.null _hydraPlatforms)) $ sep
62+ [ text "hydraPlatforms" <+> equals, renderPlatformList (Set.toAscList _hydraPlatforms) ]
63+ , listattr "maintainers" (text "with stdenv.lib.maintainers;") (Set.toAscList _maintainers)
64+ , boolattr "broken" _broken _broken
65+ ]
6966
7067renderPlatformList :: [String] -> Doc
7168renderPlatformList plats =
src/Distribution/Nixpkgs/Util/PrettyPrinting.hs+13−1
@@ -2,6 +2,7 @@
22
33module Distribution.Nixpkgs.Util.PrettyPrinting
44 ( onlyIf
5+ , setattr, toAscList
56 , listattr
67 , boolattr
78 , attr
@@ -13,8 +14,13 @@ module Distribution.Nixpkgs.Util.PrettyPrinting
1314 )
1415 where
1516
16−import Text.PrettyPrint.HughesPJClass
17+import Data.Char
18+import Data.Function
19+import Data.List
20+import Data.Set ( Set )
21+import qualified Data.Set as Set
1722import Distribution.Text ( Text, disp )
23+import Text.PrettyPrint.HughesPJClass
1824
1925attr :: String -> Doc -> Doc
2026attr n v = text n <+> equals <+> v <> semi
@@ -32,6 +38,12 @@ listattr n prefix vs = onlyIf (not (null vs)) $
3238 rbrack <> semi
3339 ]
3440
41+setattr :: String -> Set String -> Doc
42+setattr name set = listattr name empty (toAscList set)
43+
44+toAscList :: Set String -> [String]
45+toAscList = sortBy (compare `on` map toLower) . Set.toList
46+
3547bool :: Bool -> Doc
3648bool True = text "true"
3749bool False = text "false"
src/cabal2nix.hs+37−38
@@ -1,3 +1,5 @@
1+{-# LANGUAGE RecordWildCards #-}
2+
13module Main ( main ) where
24
35import Cabal2Nix.Generate ( cabal2nix )
@@ -5,10 +7,12 @@ import Cabal2Nix.Normalize ( normalize )
57import Cabal2Nix.Package
68import Cabal2Nix.Version
79import Control.Exception ( bracket )
10+import Control.Lens
811import Data.Maybe ( fromMaybe )
912import qualified Data.Set as Set
1013import Distribution.Nixpkgs.Fetch
11−import Distribution.Nixpkgs.Haskell hiding ( version )
14+import Distribution.Nixpkgs.Haskell
15+import Distribution.Nixpkgs.Meta
1216import Distribution.Nixpkgs.Util.PrettyPrinting hiding ( (<>) )
1317import Distribution.PackageDescription ( FlagName(..), FlagAssignment )
1418import Distribution.Simple.Utils ( lowercase )
@@ -76,49 +80,44 @@ pinfo = info
7680
7781main :: IO ()
7882main = bracket (return ()) (\() -> hFlush stdout >> hFlush stderr) $ \() -> do
79− cfg <- execParser pinfo
80−
81− pkg <- getPackage (optHackageDb cfg) $ Source (optUrl cfg) (fromMaybe "" (optRevision cfg)) (maybe UnknownHash Guess (optSha256 cfg))
83+ Options {..} <- execParser pinfo
8284
83− let flags = readFlagList (optFlags cfg)
85+ pkg <- getPackage optHackageDb $ Source optUrl (fromMaybe "" optRevision) (maybe UnknownHash Guess optSha256)
8486
85− deriv = (cabal2nix flags $ pkgCabal pkg) { src = pkgSource pkg
86− , runHaddock = optHaddock cfg
87− , jailbreak = optJailbreak cfg
88− , hyperlinkSource = optHyperlinkSource cfg
89− }
90− deriv' = deriv { metaSection = (metaSection deriv)
91− { maintainers = Set.fromList (optMaintainer cfg)
92− , platforms = Set.fromList (optPlatform cfg)
93− }
94− , doCheck = doCheck deriv && optDoCheck cfg
95− , extraFunctionArgs = Set.insert "stdenv" (extraFunctionArgs deriv)
96− }
87+ let flags = readFlagList optFlags
9788
98− deriv'' :: Doc
99− deriv'' = pPrint (normalize deriv')
89+ deriv :: Derivation
90+ deriv = cabal2nix flags (pkgCabal pkg)
91+ & src .~ pkgSource pkg
92+ & runHaddock .~ optHaddock
93+ & jailbreak .~ optJailbreak
94+ & hyperlinkSource .~ optHyperlinkSource
95+ & metaSection.maintainers .~ Set.fromList optMaintainer
96+ & metaSection.platforms .~ Set.fromList optPlatform
97+ & doCheck &&~ optDoCheck
98+ & extraFunctionArgs . contains "stdenv" .~ True
10099
101− shell :: Doc -> Doc
102− shell expr = vcat
103− [ text "{ nixpkgs ? import <nixpkgs> {}, compiler ? \"ghc7101\" }:"
104− , text ""
105− , text "let"
106− , text ""
107− , text " inherit (nixpkgs) pkgs;"
108− , text ""
109− , hcat [ text " f = ", expr, semi ]
110− , text ""
111− , text " drv = pkgs.haskell.packages.${compiler}.callPackage f {};"
112− , text ""
113− , text "in"
114− , text ""
115− , text " if pkgs.lib.inNixShell then drv.env else drv"
116− ]
100+ deriv' :: Doc
101+ deriv' = pPrint (normalize deriv)
117102
118− deriv''' | optNixShellOutput cfg = shell deriv''
119− | otherwise = deriv''
103+ shell :: Doc
104+ shell = vcat
105+ [ text "{ nixpkgs ? import <nixpkgs> {}, compiler ? \"ghc7101\" }:"
106+ , text ""
107+ , text "let"
108+ , text ""
109+ , text " inherit (nixpkgs) pkgs;"
110+ , text ""
111+ , hcat [ text " f = ", deriv', semi ]
112+ , text ""
113+ , text " drv = pkgs.haskell.packages.${compiler}.callPackage f {};"
114+ , text ""
115+ , text "in"
116+ , text ""
117+ , text " if pkgs.lib.inNixShell then drv.env else drv"
118+ ]
120119
121− print deriv'''
120+ print (if optNixShellOutput then shell else deriv')
122121
123122readFlagList :: [String] -> FlagAssignment
124123readFlagList = map tagWithValue
src/hackage2nix.hs+25−18
@@ -29,6 +29,7 @@ import Cabal2Nix.Generate ( cabal2nix' )
2929import Cabal2Nix.Hackage ( readHashedHackage, Hackage )
3030import Cabal2Nix.Package
3131import Data.List
32+import Control.Lens
3233import Data.Function
3334import Control.Monad
3435import Control.Monad.Par.Combinator
@@ -43,6 +44,7 @@ import qualified Data.Set as Set
4344import Distribution.Compiler
4445import Distribution.Nixpkgs.Fetch
4546import Distribution.Nixpkgs.Haskell
47+import Distribution.Nixpkgs.Meta
4648import Distribution.Nixpkgs.PackageMap
4749import Distribution.Nixpkgs.Util.PrettyPrinting hiding ( attr, (<>) )
4850import Distribution.Package
@@ -158,29 +160,27 @@ generatePackageSet config hackage nixpkgs = do
158160 pkgs <- flip parMapM (Map.toAscList db) $ \(name, vs) -> do
159161 defs <- forM (Set.toAscList vs) $ \pkgversion -> do
160162 srcSpec <- liftIO $ sourceFromHackage UnknownHash (name ++ "-" ++ display pkgversion)
161− let Just cabalFileHash = lookup "x-cabal-file-hash" (customFieldsPD (packageDescription descr))
162−
163− -- TODO: Include list of broken dependencies in the generated output.
163+ let -- TODO: Include list of broken dependencies in the generated output.
164164 descr = hackage Map.! name Map.! pkgversion
165165 (missingDeps, _, drv') = cabal2nix resolver descr
166− drv = drv' { src = srcSpec, editedCabalFile = if revision drv == 0 then "" else cabalFileHash
167− , metaSection = (metaSection drv') { broken = not (Set.null missing) -- Missing Haskell dependencies!
168− , hydraPlatforms = if PackageName name `Set.member` brokenPackages config
169− then Set.singleton "stdenv.lib.platforms.none"
170− else hydraPlatforms (metaSection drv')
171− }
172− , jailbreak = not (null missingDeps) -- Dependency constraints aren't fulfilled
173− && name /= "jailbreak-cabal" -- Recursion: see "recursion".
174− }
166+
167+ haskellDependencies :: Set String
168+ haskellDependencies = Set.map unDep $ mconcat [ drv'^.x.haskell | x <- [libraryDepends,executableDepends,testDepends] ]
169+
170+ systemDependencies :: Set String
171+ systemDependencies = Set.map unDep $ mconcat [ drv'^.x.y | x <- [libraryDepends,executableDepends,testDepends], y <- [system,pkgconfig] ]
172+
173+ haskellOrSystemDependencies :: Set String
174+ haskellOrSystemDependencies = Set.map unDep $ mconcat [ drv'^.x.tool | x <- [libraryDepends,executableDepends,testDepends] ]
175175
176176 missing :: Set String
177− missing = Set.filter (`Set.notMember` knownAttributesSet) (buildDepends drv `Set.union` testDepends drv)
177+ missing = Set.filter (`Set.notMember` knownAttributesSet) haskellDependencies
178178
179179 buildInputs :: Map Attribute (Maybe Path)
180180 buildInputs = Map.unions
181181 [ Map.fromList [ (n, Nothing) | n <- Set.toList missing ]
182− , Map.fromList [ (n, resolveNixpkgsAttribute nixpkgs n) | n <- Set.toAscList (extraLibs drv `Set.union` pkgConfDeps drv) ]
183− , Map.fromList [ (n, resolveNixpkgsOrHackageAttribute nixpkgs hackage n) | n <- Set.toAscList (buildTools drv) ]
182+ , Map.fromList [ (n, resolveNixpkgsAttribute nixpkgs n) | n <- Set.toAscList systemDependencies ]
183+ , Map.fromList [ (n, resolveHackageThenNixpkgsAttribute nixpkgs hackage n) | n <- Set.toAscList haskellOrSystemDependencies ]
184184 ]
185185
186186 systemOverrides :: Doc
@@ -199,16 +199,23 @@ generatePackageSet config hackage nixpkgs = do
199199 attr | Just v <- Map.lookup name generatedDefaultPackageSet, v == pkgversion = name
200200 | otherwise = name ++ '_' : [ if c == '.' then '_' else c | c <- display pkgversion ]
201201
202+ drv = drv' & src .~ srcSpec
203+ & jailbreak .~ (not (null missingDeps) && (name /= "jailbreak-cabal")) -- Dependency constraints aren't fulfilled
204+ & metaSection . broken .~ not (Set.null missing) -- Missing Haskell dependencies!
205+ & metaSection.hydraPlatforms .~ (if PackageName name `Set.member` brokenPackages config
206+ then Set.singleton "stdenv.lib.platforms.none"
207+ else drv'^.metaSection.hydraPlatforms)
208+
202209 return $ nest 2 $ hang (string attr <+> equals <+> text "callPackage") 2 (parens (pPrint drv)) <+> (braces overrides <> semi)
203210 return (intercalate "\n\n" (map render defs))
204211
205212 liftIO $ mapM_ (\pkg -> putStrLn pkg >> putStrLn "") pkgs
206213 liftIO $ putStrLn "}"
207214
208−resolveNixpkgsOrHackageAttribute :: Nixpkgs -> Hackage -> Attribute -> Maybe Path
209−resolveNixpkgsOrHackageAttribute nixpkgs hackage name
210− | p@(Just _) <- resolveNixpkgsAttribute nixpkgs name = p
215+resolveHackageThenNixpkgsAttribute :: Nixpkgs -> Hackage -> Attribute -> Maybe Path
216+resolveHackageThenNixpkgsAttribute nixpkgs hackage name
211217 | Just _ <- Map.lookup name hackage = Just []
218+ | p@(Just _) <- resolveNixpkgsAttribute nixpkgs name = p
212219 | otherwise = Nothing
213220
214221resolveNixpkgsAttribute :: Nixpkgs -> Attribute -> Maybe Path
test/spec.hs+6−6
@@ -14,12 +14,12 @@ main = do
1414 it "License" $ mapM_ hitsBottom [Known undefined, Unknown (Just undefined)]
1515 it "Meta" $ do let meta = Meta "" "" (Unknown Nothing) empty empty empty False
1616 mapM_ hitsBottom
17− [ meta { homepage = undefined }
18− , meta { description = undefined }
19− , meta { license = undefined }
20− , meta { platforms = undefined }
21− , meta { maintainers = undefined }
22− , meta { broken = undefined }
17+ [ meta { _homepage = undefined }
18+ , meta { _description = undefined }
19+ , meta { _license = undefined }
20+ , meta { _platforms = undefined }
21+ , meta { _maintainers = undefined }
22+ , meta { _broken = undefined }
2323 ]
2424
2525hitsBottom :: NFData a => a -> Expectation