git.iko.soy/typeable/cabal2nix
on v1.2 help sign in
typeable/cabal2nix/cabal2nix.hs
114 lines 4.7 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 [] = error "toNixName: empty string is not a valid argument"
36toNixName name = f ((toLower (head name)) : tail name)
37 where
38 f [] = []
39 f ('-':c:cs) | c `notElem` "-" = toUpper c : f cs
40 f ('-':_) = error ("unexpected package name " ++ show name)
41 f (c:cs) = c : f cs
43toNix :: Pkg -> String
44toNix (Pkg name ver sha256 url desc lic deps libs) =
45 "{" ++ exprArgs ++"}:\n\n"
46 ++ "cabal.mkDerivation (self : {\n"
47 ++ " pname = " ++ show name ++ ";\n"
48 ++ " version = \"" ++ showVer ++ "\";\n"
49 ++ " sha256 = " ++ show sha256 ++ ";\n"
50 ++ " propagatedBuildInputs = [" ++ depList ++ "];\n"
51 ++ " meta = {\n"
52 ++ " homepage = \"" ++ url ++ "\";\n"
53 ++ " description = " ++ show desc ++ ";\n"
54 ++ " license = " ++ showLic lic ++ ";\n"
55 ++ " };\n"
56 ++ "})\n"
57 where
58 exprArgs = concat (intersperse "," ("cabal":pkgDeps))
59 showVer = concat (intersperse "." (map show ver))
60 depList = concat (intersperse " " pkgDeps)
61 pkgDeps :: [String]
62 pkgDeps = filter (/="cabal") $ nub $ sort $ map toNixName $
63 libs ++ [ 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)