git.iko.soy/typeable/cabal2nix
on master help sign in
Determine the list of available Nixpkgs dynamically at run-time.
commitbfaaacdd0c17a7c3f4205a4122515b95a8c3df2d authorPeter Simons <simons@cryp.to> dateThu 25 Dec 2014, 13:44 (12 years ago) parent43e80d6
5 files changed+60−296
cabal2nix.cabal+3−1 release.nix+1−1 src/Distribution/NixOS/PackageMap.hs+38 src/hackage2nix.hs+16−293 test/doc-test.hs+2−1
cabal2nix.cabal+3−1
@@ -102,6 +102,7 @@ Executable hackage4nix
102102 Distribution.NixOS.Derivation.License
103103 Distribution.NixOS.Derivation.Meta
104104 Distribution.NixOS.PrettyPrinting
105+ Distribution.NixOS.PackageMap
105106 Distribution.NixOS.Regex
106107
107108Executable hackage2nix
@@ -109,7 +110,8 @@ Executable hackage2nix
109110 hs-source-dirs: src
110111 Build-Depends: base >= 3 && < 5, regex-posix, pretty, Cabal >= 1.18,
111112 filepath, directory, process, hackage-db >= 1.11, transformers, deepseq,
112− containers, mtl, monad-par, monad-par-extras, bytestring, SHA
113+ containers, mtl, monad-par, monad-par-extras, bytestring, SHA, aeson,
114+ split, utf8-string
113115 Ghc-Options: -Wall -threaded -rtsopts -with-rtsopts=-N
114116 Extensions: PatternGuards, RecordWildCards, CPP
115117 other-modules: Cabal2Nix.CorePackages
release.nix+1−1
@@ -26,7 +26,7 @@ in
2626 isExecutable = true;
2727 buildDepends = with haskellPackages; [
2828 Cabal deepseq filepath hackageDb monadPar monadParExtras mtl
29− regexPosix transformers SHA
29+ regexPosix transformers SHA aeson split utf8String
3030 ];
3131 testDepends = with haskellPackages; [ doctest ];
3232 doCheck = nativeCabal;
src/Distribution/NixOS/PackageMap.hsnew file+38
@@ -0,0 +1,38 @@
1+module Distribution.NixOS.PackageMap where
2+
3+import qualified Data.Aeson as JSON
4+import Data.List.Split
5+import qualified Data.Map as Map
6+import Data.Map.Strict ( Map )
7+import Data.Set ( Set )
8+import qualified Data.Set as Set
9+import qualified Data.String.UTF8 as UTF8 ( fromString, toRep )
10+import System.Process
11+
12+type Attribute = String
13+type Path = [Attribute]
14+
15+readNixpkgAttributeSet :: IO (Set Attribute)
16+readNixpkgAttributeSet = do
17+ buf <- readProcess "nix-env" ["-qaP", "--json"] ""
18+ let pkgmap :: Either String (Map Attribute JSON.Object)
19+ pkgmap = JSON.eitherDecodeStrict (UTF8.toRep (UTF8.fromString buf))
20+ either fail (return . Map.keysSet) pkgmap
21+
22+parsePackage :: Attribute -> (Attribute, Path)
23+parsePackage "" = error "empty string is not a valid package name"
24+parsePackage x = (last xs, init xs) where xs = splitOn "." x
25+
26+type PackageMap = Map Attribute (Set Path)
27+
28+attributeSet2PackageMap :: Set Attribute -> PackageMap
29+attributeSet2PackageMap pkgset = foldr (uncurry insertAttribute) Map.empty pkglist
30+ where
31+ pkglist :: [(Attribute, Path)]
32+ pkglist = Set.toList (Set.map parsePackage pkgset)
33+
34+ insertAttribute :: Attribute -> Path -> PackageMap -> PackageMap
35+ insertAttribute attr = Map.insertWith Set.union attr . Set.singleton
36+
37+readNixpkgPackageMap :: IO PackageMap
38+readNixpkgPackageMap = fmap attributeSet2PackageMap readNixpkgAttributeSet
src/hackage2nix.hs+16−293
@@ -17,17 +17,21 @@ import Data.Set ( Set )
1717import qualified Data.Set as Set
1818import Distribution.NixOS.Derivation.Cabal
1919import Distribution.NixOS.PrettyPrinting hiding ( (<>) )
20+import Distribution.NixOS.PackageMap ( PackageMap, readNixpkgPackageMap )
2021import Distribution.PackageDescription hiding ( buildDepends, extraLibs, buildTools )
2122import Distribution.Text
2223
2324main :: IO ()
24−main = readHashedHackage >>= runParIO . generatePackageSet
25+main = do
26+ hackage <- readHashedHackage
27+ nixpkgs <- readNixpkgPackageMap
28+ runParIO (generatePackageSet hackage nixpkgs)
2529
2630nixAttr :: String -> Version -> String
2731nixAttr name _ = name -- ++ "_" ++ [ if c == '.' then '_' else c | c <- display ver ]
2832
29−generatePackageSet :: Hackage -> ParIO ()
30−generatePackageSet db = do
33+generatePackageSet :: Hackage -> PackageMap -> ParIO ()
34+generatePackageSet db nixpkgs = do
3135 pkgs <- parMapM generatePackage (Map.toList db)
3236 liftIO $ putStrLn "/* hackage-packages.nix is an auto-generated file -- DO NOT EDIT! */"
3337 liftIO $ putStrLn ""
@@ -50,7 +54,7 @@ generatePackageSet db = do
5054 | otherwise = text " inherit (pkgs) " <> hsep (map text (Set.toAscList conflicts)) <> text "; "
5155
5256 missing :: Set String
53− missing = Set.union (Set.intersection missingSystemLibraries (Set.fromList (extraLibs drv ++ pkgConfDeps drv ++ buildTools drv)))
57+ missing = Set.union (Set.fromList (filter (not . isKnownNixpkgAttribute nixpkgs db) (extraLibs drv ++ pkgConfDeps drv ++ buildTools drv)))
5458 (selectMissingHackageNames (Set.fromList (buildDepends drv ++ testDepends drv)))
5559
5660 missingOverrides :: Doc
@@ -80,292 +84,11 @@ generatePackage (name, versions) = do
8084 drv = drv' { editedCabalFile = if revision drv' == 0 then "" else cabalFileHash }
8185 return (name, latestVersion, drv)
8286
83−-- TODO: We should obtain the list of valid attributes in Nixpkgs at
84−-- runtime instead of hard-coding a list of invalid attributes here.
85−--
86−-- TODO: This list is way overspecified; there are many packages in here
87−-- that are referred to in the buildDepends or testDepends section, i.e.
88−-- packages that we expect to be available from Hackage (but that
89−-- aren't).
90−
91−missingSystemLibraries :: Set String
92−missingSystemLibraries = Set.fromList
93− [ "accelerate-llvm"
94− , "accelerate-llvm-multidev"
95− , "accelerate-llvm-native"
96− , "accelerate-llvm-ptx"
97− , "advapi32"
98− , "Advapi32"
99− , "aether"
100− , "alut"
101− , "antlr3c"
102− , "appindicator"
103− , "appindicator3"
104− , "applicative"
105− , "apr-1"
106− , "apr-util-1"
107− , "arbb_dev"
108− , "b2"
109− , "bfd"
110− , "blkid"
111− , "bluetooth"
112− , "camwire_1394"
113− , "canlib"
114− , "casadi_control"
115− , "casadi_core"
116− , "casadi_ipopt_interface"
117− , "casadi_snopt_interface"
118− , "cblas"
119− , "CEGUIBase"
120− , "CEGUIOgreRenderer"
121− , "cgen-hs"
122− , "clntsh"
123− , "cmph"
124− , "codec2"
125− , "comctl32"
126− , "comdlg32"
127− , "com_err"
128− , "crypto"
129− , "csfml-audio"
130− , "csfml-graphics"
131− , "csfml-network"
132− , "csfml-system"
133− , "csfml-window"
134− , "csound64"
135− , "cudd"
136− , "curses"
137− , "cusparse"
138− , "cwiid"
139− , "d3d9"
140− , "d3dx9"
141− , "dbxml"
142− , "dc1394"
143− , "dc1394_control"
144− , "debian-mirror"
145− , "dns_sd"
146− , "doublefann"
147− , "dsound"
148− , "dttools"
149− , "easy-data"
150− , "EGL"
151− , "eibclient"
152− , "eng"
153− , "epd"
154− , "eskit"
155− , "esound"
156− , "ev"
157− , "event"
158− , "f77blas"
159− , "fann"
160− , "fftw3"
161− , "fftw3f"
162− , "fltk"
163− , "fltk_images"
164− , "fmodex"
165− , "fmodex64"
166− , "freenect_sync"
167− , "friso"
168− , "ftd2xx"
169− , "g"
170− , "gcc_s"
171− , "gcrypt"
172− , "gdi32"
173− , "gdk_x11"
174− , "gecodeint"
175− , "gecodekernel"
176− , "gecodesearch"
177− , "gecodeset"
178− , "gecodesupport"
179− , "GeoIP"
180− , "ghcjs-base"
181− , "GLESv2"
182− , "gnome_keyring"
183− , "gnome-vfs"
184− , "gnome_vfs_module"
185− , "gnomeVfsModule"
186− , "gomp"
187− , "GraphicsMagick"
188− , "grgen"
189− , "groonga"
190− , "gstreamer-audio"
191− , "gstreamer-base"
192− , "gstreamer-controller"
193− , "gstreamer-dataprotocol"
194− , "gstreamer-net"
195− , "gstreamer-plugins-base"
196− , "gtkC"
197− , "gtksourceview"
198− , "gtk_x11"
199− , "haste-lib"
200− , "hasteLib"
201− , "help"
202− , "hg3dcegui040"
203− , "hg3denet040"
204− , "hg3dogre040"
205− , "hg3dsdl2040"
206− , "hg3dsfml040"
207− , "HGamer3DCAudio015"
208− , "HGamer3DOIS015"
209− , "hsql-oracle"
210− , "hsql-sqlite"
211− , "HTam"
212− , "hyperestraier"
213− , "hyperleveldb"
214− , "ImageMagick"
215− , "Imlib2"
216− , "imm32"
217− , "instance-control"
218− , "integer"
219− , "integer-simple"
220− , "intel_aes"
221− , "Judy"
222− , "jvm"
223− , "K8055D"
224− , "kernel32"
225− , "kics"
226− , "language-css-attoparsec"
227− , "lapack"
228− , "lapacke"
229− , "lber"
230− , "lbfgsb"
231− , "ldap"
232− , "leksah-dummy"
233− , "leksah-main"
234− , "leksah-plugin-pane"
235− , "LEXER"
236− , "libaosd"
237− , "libavcodec"
238− , "libavformat"
239− , "libavutil"
240− , "libc"
241− , "libdpkg"
242− , "libglade"
243− , "libkmod"
244− , "libnm-glib"
245− , "librrd"
246− , "libsoup_gnome"
247− , "libswscale"
248− , "libudev"
249− , "libxfconf-0"
250− , "libxine"
251− , "llvm-config"
252− , "MagickCore"
253− , "MagickWand"
254− , "mozembed"
255− , "mpdec"
256− , "mpi"
257− , "msimg32"
258− , "mx"
259− , "mysqlclient"
260− , "mysqlConfig"
261− , "netsnmp"
262− , "newrelic-collector-client"
263− , "newrelic-common"
264− , "newrelic-transaction"
265− , "nm-glib"
266− , "notify"
267− , "nsl"
268− , "nvidia_x11"
269− , "nvvm"
270− , "objc"
271− , "odbc"
272− , "ogg"
273− , "OGRE"
274− , "OgreMain"
275− , "OgrePaging"
276− , "OgreProperty"
277− , "OgreRTShaderSystem"
278− , "OgreTerrain"
279− , "OIS"
280− , "ole32"
281− , "oleaut32"
282− , "opcodes"
283− , "opencc"
284− , "opencv_calib3d"
285− , "opencv_contrib"
286− , "opencv_core"
287− , "opencv_features2d"
288− , "opencv_flann"
289− , "opencv_gpu"
290− , "opencv_highgui"
291− , "opencv_imgproc"
292− , "opencv_legacy"
293− , "opencv_ml"
294− , "opencv_objdetect"
295− , "opencv_video"
296− , "OpenNI2"
297− , "ovr"
298− , "papi"
299− , "pfs"
300− , "pHash"
301− , "plplotd-gnome2"
302− , "popplerGlib"
303− , "qdbm"
304− , "Qt5Core"
305− , "Qt5Gui"
306− , "Qt5Qml"
307− , "Qt5Quick"
308− , "Qt5Widgets"
309− , "QtCore"
310− , "QtWebKit"
311− , "QuadProgpp"
312− , "quickcheck-lio-instances"
313− , "rados"
314− , "raptor"
315− , "raw1394"
316− , "rdkafka"
317− , "resolv"
318− , "riak-bump"
319− , "rocksdb"
320− , "rt"
321− , "scsynth"
322− , "SDL2_ttf"
323− , "sedna"
324− , "sfml-network"
325− , "sfml-system"
326− , "sfml-window"
327− , "shell32"
328− , "shfolder"
329− , "sipc"
330− , "sixense"
331− , "sixense_x64"
332− , "sqlplus"
333− , "ssh2"
334− , "stats-web"
335− , "string-templates"
336− , "swipl"
337− , "Synt"
338− , "systemd-daemon"
339− , "systemGraphviz"
340− , "tag_c"
341− , "taglib_c"
342− , "terralib4c"
343− , "theora"
344− , "tiff"
345− , "translib"
346− , "UniqueLogicNP"
347− , "user32"
348− , "util"
349− , "virt"
350− , "wayland-client"
351− , "wayland-cursor"
352− , "wayland-egl"
353− , "wayland-server"
354− , "winmm"
355− , "winspool"
356− , "wmflite"
357− , "ws2_32"
358− , "www-minus"
359− , "xau"
360− , "Xdamage"
361− , "xenctrl"
362− , "xerces-c"
363− , "Xfixes"
364− , "Xinerama"
365− , "xmmsclient"
366− , "xmmsclient-glib"
367− , "xqilla"
368− , "zephyr"
369− , "zeromq"
370− , "zookeeper_mt"
371− ]
87+isKnownNixpkgAttribute :: PackageMap -> Hackage -> String -> Bool
88+isKnownNixpkgAttribute nixpkgs hackage name
89+ | '.' `elem` name = True
90+ | Just _ <- Map.lookup name hackage = True
91+ | otherwise = maybe False goodScope (Map.lookup name nixpkgs)
92+ where
93+ goodScope :: Set [String] -> Bool
94+ goodScope = not . Set.null . Set.intersection (Set.fromList [[], ["xlibs"], ["gnome"]])
test/doc-test.hs+2−1
@@ -17,11 +17,11 @@ import Test.DocTest
1717main :: IO ()
1818main = do
1919 let libs = [ "dist/build/autogen/Paths_cabal2nix.hs"
20− , "src/Cabal2Nix/License.hs"
2120 , "src/Cabal2Nix/CorePackages.hs"
2221 , "src/Cabal2Nix/Flags.hs"
2322 , "src/Cabal2Nix/Generate.hs"
2423 , "src/Cabal2Nix/Hackage.hs"
24+ , "src/Cabal2Nix/License.hs"
2525 , "src/Cabal2Nix/Name.hs"
2626 , "src/Cabal2Nix/Normalize.hs"
2727 , "src/Cabal2Nix/Package.hs"
@@ -31,6 +31,7 @@ main = do
3131 , "src/Distribution/NixOS/Derivation/License.hs"
3232 , "src/Distribution/NixOS/Derivation/Meta.hs"
3333 , "src/Distribution/NixOS/Fetch.hs"
34+ , "src/Distribution/NixOS/PackageMap.hs"
3435 , "src/Distribution/NixOS/PrettyPrinting.hs"
3536 , "src/Distribution/NixOS/Regex.hs"
3637 ]