git.iko.soy/typeable/cabal2nix
on v1.0 help sign in
typeable/cabal2nix/cabal2nix.hs
114 lines 4.6 kB history raw
1-- cabal2nix.hs
2--
3-- Copyright (c) 20011 Peter Simons <simons@cryp.to>
4-- See LICENSE file for licensing details.
6module Main ( main ) where
8import System.IO
9import System.Environment
10import Control.Exception
11import System.Exit
12import Distribution.PackageDescription.Parse
13import Distribution.Verbosity ( silent )
14import Distribution.PackageDescription
15import Distribution.Package
16import Distribution.License
17import Data.Version
18import Data.List
19import Control.Monad
20import Data.Char
22type PkgName = String
23type PkgVersion = [Int]
24type PkgSHA256 = String
25type PkgURL = String
26type PkgDescription = String
27type PkgLicense = License
28type PkgDependencies = [CondTree ConfVar [Dependency] ()]
29type PkgExtraLibs = [String]
31data Pkg = Pkg PkgName PkgVersion PkgSHA256 PkgURL PkgDescription PkgLicense PkgDependencies PkgExtraLibs
32 deriving (Show)
34toNixName :: String -> String
35toNixName name = f name
36 where
37 f [] = []
38 f ('-':c:cs) | c `notElem` "-" = toUpper c : f cs
39 f ('-':_) = error ("unexpected package name " ++ show name)
40 f (c:cs) = c : f cs
42toNix :: Pkg -> String
43toNix (Pkg name ver sha256 url desc lic deps libs) =
44 "{" ++ exprArgs ++"}:\n\n"
45 ++ "cabal.mkDerivation (self : {\n"
46 ++ " pname = " ++ show name ++ ";\n"
47 ++ " version = \"" ++ showVer ++ "\";\n"
48 ++ " sha256 = " ++ show sha256 ++ ";\n"
49 ++ " propagatedBuildInputs = [" ++ depList ++ "];\n"
50 ++ " meta = {\n"
51 ++ " homepage = \"" ++ url ++ "\";\n"
52 ++ " description = " ++ show desc ++ ";\n"
53 ++ " license = " ++ showLic lic ++ ";\n"
54 ++ " };\n"
55 ++ "})\n"
56 where
57 exprArgs = concat (intersperse "," ((if "cabal" `notElem` pkgDeps then ["cabal"] else []) ++ pkgDeps))
58 showVer = concat (intersperse "." (map show ver))
59 depList = concat (intersperse " " pkgDeps)
60 pkgDeps :: [String]
61 pkgDeps = map toNixName $
62 nub $ sort $ libs ++
63 [ n | dep <- deps, Dependency (PackageName n) _ <- condTreeConstraints dep
64 , n `notElem` ["base","containers"]
65 ]
66 showLic (GPL Nothing) = show "GPL"
67 showLic (GPL (Just (Version [2] []))) = "self.stdenv.lib.licenses.gpl2"
68 showLic (GPL (Just (Version [3] []))) = "self.stdenv.lib.licenses.gpl3"
69 showLic (LGPL Nothing) = show "LGPL"
70 showLic (LGPL (Just (Version [2,1] []))) = "self.stdenv.lib.licenses.lgpl21"
71 showLic (LGPL (Just (Version [3] []))) = "self.stdenv.lib.licenses.lgpl3"
72 showLic BSD3 = "self.stdenv.lib.licenses.bsd3"
73 showLic BSD4 = "self.stdenv.lib.licenses.bsd4"
74 showLic MIT = "self.stdenv.lib.licenses.mit"
75 showLic PublicDomain = "self.stdenv.lib.licenses.publicDomain"
76 showLic AllRightsReserved = "unknown"
77 showLic OtherLicense = "unknown"
78 showLic l = error $ "unknown license: " ++ show l
80readPackage :: FilePath -> String -> IO Pkg
81readPackage cabalFile sha256 = do
82 cabal <- readPackageDescription silent cabalFile
83 let pkg = packageDescription cabal
84 PackageName pkgname = pkgName (package pkg)
85 pkgver = versionBranch (pkgVersion (package pkg))
86 lic = license pkg
87 url = homepage pkg
88 desc = synopsis pkg
89 -- globalDeps = buildDepends pkg
90 libDeps = maybe [] (\x -> [x]) (condLibrary cabal)
91 exeDeps = [ tree | (_,tree) <- condExecutables cabal ]
92 libs = concat [ extraLibs (libBuildInfo (condTreeData x)) | x <- libDeps ]
93 libs' = concat [ extraLibs (buildInfo (condTreeData x)) | x <- exeDeps ]
94 return (Pkg pkgname pkgver sha256 url desc lic (map simplify libDeps ++ map simplify exeDeps) (libs++libs'))
95 where
97simplify :: CondTree ConfVar [Dependency] a -> CondTree ConfVar [Dependency] ()
98simplify (CondNode _ deps nodes) = CondNode () deps (map simp nodes)
99 where
100 simp (cond,tree,mtree) = (cond, simplify tree, maybe Nothing (Just . simplify) mtree)
102main :: IO ()
103main = bracket (return ()) (\() -> hFlush stdout >> hFlush stderr) $ \() -> do
104 args <- getArgs
106 when (length args /= 2) $ do
107 mapM_ (hPutStrLn stderr) [ "*** invalid command line syntax"
108 , "Usage: cabal2nix cabal-file sha256-hash"
109 ]
110 exitFailure
112 let cabalFile:sha256:[] = args
113 pkg <- readPackage cabalFile sha256
114 putStr (toNix pkg)