module Distribution.ArchLinux.CabalTranslation (
preprocessCabal,
cabal2pkg,
oldCabal2Arch,
install_hook_name
) where
import Distribution.Package
import Distribution.PackageDescription
import Distribution.PackageDescription.Configuration
import Distribution.License
import Distribution.Version
import Distribution.Compiler
import Distribution.System
import Distribution.ArchLinux.PkgBuild
import Distribution.Text
import Data.Char
import Data.List
import qualified Data.Map as M
import Data.Maybe
import Data.Monoid
import System.FilePath
import Debug.Trace
preprocessCabal :: GenericPackageDescription -> Maybe PackageDescription
preprocessCabal cabalsrc =
case finalizePackageDescription
[]
(const True)
(Platform X86_64 buildOS)
(CompilerId GHC (Version [6,10,3] []))
corePackages
cabalsrc
of
Left deps -> trace ("Unresolved dependencies: " ++show deps) Nothing
Right (pkg,_) -> Just pkg { buildDepends = removeCoreFrom (buildDepends pkg) }
removeCoreFrom :: [Dependency] -> [Dependency]
removeCoreFrom [] = []
removeCoreFrom (x@(Dependency n vr):xs) =
case find (\(Dependency k _) -> n == k) corePackages of
Just (Dependency _ (ThisVersion v'))
| withinRange v' vr -> removeCoreFrom xs
Just (Dependency (PackageName "base") _)
-> removeCoreFrom xs
Just (Dependency _ AnyVersion) -> removeCoreFrom xs
_ -> x : removeCoreFrom xs
corePackages :: [Dependency]
corePackages =
[
Dependency (PackageName "base") (ThisVersion (Version [4,1,0,0] []))
,Dependency (PackageName "dph-base") (AnyVersion)
,Dependency (PackageName "dph-par" ) (AnyVersion)
,Dependency (PackageName "dph-prim-interface") (AnyVersion)
,Dependency (PackageName "dph-prim-par" ) (AnyVersion)
,Dependency (PackageName "dph-prim-seq" ) (AnyVersion)
,Dependency (PackageName "dph-seq" ) (AnyVersion)
,Dependency (PackageName "ghc") (AnyVersion)
,Dependency (PackageName "ghc-prim") (AnyVersion)
,Dependency (PackageName "integer") (AnyVersion)
,Dependency (PackageName "integer-gmp") (AnyVersion)
,Dependency (PackageName "ghc-binary") (AnyVersion)
]
cabal2pkg :: PackageDescription -> (PkgBuild, Maybe String)
cabal2pkg cabal
=
(emptyPkgBuild
{ arch_pkgname = archName
, arch_pkgver = vers
, arch_url = "http://hackage.haskell.org/package/"++display name
, arch_pkgdesc = case synopsis cabal of
[] -> take 80 (description cabal)
s -> s
, arch_license =
ArchList . return $
case license cabal of
x@GPL {} -> x
x@LGPL {} -> x
l -> UnknownLicense ("custom:"++ show l)
, arch_makedepends = if not hasLibrary
then my_makedepends
else ArchList []
, arch_depends =
(if not (isLibrary)
then
ArchList [ArchDep (Dependency (PackageName "gmp") AnyVersion)]
`mappend`
anyClibraries
else ArchList [])
`mappend`
(if hasLibrary then my_makedepends
else ArchList [])
, arch_source = ArchList . return $
"http://hackage.haskell.org/packages/archive/"
++ (display name </> display vers </> display name <-> display vers <.> "tar.gz")
, arch_build =
[ "cd ${srcdir}/" </> display name <-> display vers
, "runhaskell Setup configure --prefix=/usr --docdir=/usr/share/doc/${pkgname}"
, "runhaskell Setup build"
] ++
(if hasLibrary
then
[ "runhaskell Setup haddock"
, "runhaskell Setup register --gen-script"
, "runhaskell Setup unregister --gen-script"
]
else [])
, arch_package =
[ "cd ${srcdir}/" </> display name <-> display vers ] ++
(if hasLibrary
then
[ "install -D -m744 register.sh ${pkgdir}/usr/share/haskell/${pkgname}/register.sh"
, "install -m744 unregister.sh ${pkgdir}/usr/share/haskell/${pkgname}/unregister.sh"
, "install -d -m755 ${pkgdir}/usr/share/doc/ghc/html/libraries"
, "ln -s /usr/share/doc/${pkgname}/html ${pkgdir}/usr/share/doc/ghc/html/libraries/" ++ (display name)
]
else [])
++
["runhaskell Setup copy --destdir=${pkgdir}"]
++
(if not (null (licenseFile cabal)) && (case license cabal of GPL {} -> False; LGPL {} -> False; _ -> True)
then
[ "install -D -m644 " ++ licenseFile cabal ++ " ${pkgdir}/usr/share/licenses/${pkgname}/LICENSE"
, "rm -f ${pkgdir}/usr/share/doc/${pkgname}/LICENSE"
]
else [])
, arch_install = if hasLibrary then Just $ install_hook_name archName
else Nothing
}, if hasLibrary
then Just (install_hook archName)
else Nothing
)
where
archName = map toLower (if isLibrary then "haskell-" ++ display name else display name)
name = pkgName (package cabal)
vers = pkgVersion (package cabal)
my_makedepends =
(arch_makedepends emptyPkgBuild)
`mappend`
ArchList
[ ArchDep (Dependency (PackageName $
if d `notElem` shouldNotBeLibraries
then "haskell" <-> map toLower (display d) else display d) v)
| Dependency (PackageName d) v <- gtk2hsIfy (buildDepends cabal) ]
`mappend`
anyClibraries
`mappend`
ArchList [ ArchDep d' | b <- allBuildInfo cabal
, d@(Dependency n _) <- buildTools b
, n /= PackageName "hsc2hs"
, let d' | n `elem` gtkTools
= Dependency (PackageName "gtk2hs-buildtools") AnyVersion
| otherwise = d
]
gtkTools = map PackageName ["gtk2hsTypeGen" , "gtk2hsHookGenerator", "gtk2hsC2hs"]
hasLibrary = isJust (library cabal)
isLibrary = isJust (library cabal)
&& map toLower (display name) `notElem` shouldNotBeLibraries
anyClibraries | null libs = ArchList []
| otherwise = ArchList libs
where
libs = [ ArchDep (Dependency (PackageName s) AnyVersion) | s <- nub (findCLibs cabal) ]
(<->) :: String -> String -> String
x <-> y = x ++ "-" ++ y
install_hook_name :: String -> String
install_hook_name pkgname = pkgname <.> "install"
install_hook :: String -> String
install_hook pkgname = unlines
[ "HS_DIR=/usr/share/haskell/" ++ pkgname
, "post_install() {"
, " ${HS_DIR}/register.sh"
, " (cd /usr/share/doc/ghc/html/libraries; ./gen_contents_index)"
, "}"
, "pre_upgrade() {"
, " ${HS_DIR}/unregister.sh"
, "}"
, "post_upgrade() {"
, " ${HS_DIR}/register.sh"
, " (cd /usr/share/doc/ghc/html/libraries; ./gen_contents_index)"
, "}"
, "pre_remove() {"
, " ${HS_DIR}/unregister.sh"
, "}"
, "post_remove() {"
, " (cd /usr/share/doc/ghc/html/libraries; ./gen_contents_index)"
, "}"
, "op=$1"
, "shift"
, "$op $*" ]
findCLibs :: PackageDescription -> [String]
findCLibs (PackageDescription { library = lib, executables = exe }) =
filter (not . null) $ map (canonicalise . map toLower) (some ++ rest)
where
some = concatMap (extraLibs.buildInfo) exe
rest = case lib of
Nothing -> []
Just l -> extraLibs (libBuildInfo l) ++
map (\(Dependency (PackageName n) _) ->
if '-' `elem` n
then reverse . drop 1 . dropWhile (/= '-') . reverse $ n
else n)
(pkgconfigDepends (libBuildInfo l))
canonicalise k = case M.lookup k translationTable of
Nothing -> trace ("WARNING: this library depends on a C library we do not know the pacman name for (" ++ map toLower k ++ ") . Check the C library names in the generated PKGBUILD File") $ map toLower k
Just s -> s
translationTable = M.fromList
[("Imlib2", "imlib2")
,("SDL", "sdl")
,("adns", "adns")
,("alut", "freealut")
,("bz2", "bzip2")
,("cblas", "blas")
,("crack", "cracklib")
,("crypto", "openssl")
,("curl", "curl")
,("freetype", "freetype2")
,("glib", "glib2")
,("wmflite", "libwmf")
,("il", "devil")
,("jpeg", "libjpeg")
,("ldap", "libldap")
,("pcap", "libpcap")
,("png", "libpng")
,("x11", "libx11")
,("xrandr", "libxrandr")
,("xml2", "libxml2")
,("exif", "libexif")
,("tiff", "libtiff")
,("sndfile", "libsndfile")
,("gcrypt", "libgcrypt")
,("fftw3", "fftw")
,("pq", "postgresql")
,("ssl", "openssl")
,("wx", "wxgtk")
,("xenctrl", "xen")
,("odbc", "unixodbc")
,("z", "zlib")
,("curses", "ncurses")
,("xslt", "libxslt")
,("csound64", "csound5")
,("uuid", "e2fsprogs")
,("doublefann", "fann")
,("ev", "libev")
,("pthread", "")
,("m", "")
,("gl", "")
,("glu", "")
,("db_cxx", "")
,("db_cxx", "")
,("xdamage", "")
,("icui18n", "icu")
,("icuuc", "icu")
,("icudata", "icu")
,("netsnmp", "net-snmp")
,("asound", "alsa-lib")
,("ffi", "libffi")
,("ogg", "libogg")
,("theora", "libtheora")
,("mtp", "libmtp")
,("zmq", "zeromq")
,("cv", "opencv")
,("highgui", "opencv")
,("xss", "libxss")
,("idn", "libidn")
,("libgsasl", "gsasl")
,("event", "libevent")
,("gcc_s", "gcc-libs")
,("gobject", "")
,("gmodule", "glib2")
,("gio", "")
,("gthread", "")
,("gnome-vfs-module", "")
,("gstreamer-audio", "")
,("gstreamer-base", "")
,("gstreamer-controller", "")
,("gstreamer-dataprotocol", "")
,("gstreamer-net", "")
,("ogremain", "")
,("gnutls-extra", "gnutls")
,("pangocairo", "pango")
,("webkit", "libwebkit")
,("gtk+", "gtk")
,("gdk", "gtk")
,("gdk-x11-2.0", "gtk2")
,("gtk-x11-2.0", "gtk2")
,("xine", "xine-lib")
,("ncursesw", "ncurses")
,("panel", "ncurses")
,("gstreamer", "gstreamer0.10")
,("gstreamer-plugins-base", "gstreamer0.10-base")
]
shouldNotBeLibraries :: [String]
shouldNotBeLibraries =
["xmonad"
,"gitit"
,"yavie"
,"berp"
,"l-seed"
,"hspresent"
,"haskell-platform"
,"xmonad-contrib"
,"lambdabot"
,"piet"
,"hsffig"
,"yi"
,"haddock"
,"hscolour"
,"line2pdf"
,"distract"
,"derive"
,"Hedi"
,"conjure"
,"clevercss"
,"cpphs"
,"backdropper"
,"darcs-beta"
,"gtk2hs"
,"darcs"
,"greencard"
,"pugs-drift"
,"wol"
,"timepiece"
,"hledger"
,"hp2any-graph"
,"hp2any-manager"
]
gtk2hsIfy :: [Dependency] -> [Dependency]
gtk2hsIfy = id
type Warnings = String
recentCabal2ArchVersion :: Maybe Version
recentCabal2ArchVersion = case simpleParse "0.7" of
Nothing -> error "Unable to parse cabal2arch version"
Just v -> Just v
oldCabal2Arch :: AnnotatedPkgBuild -> Bool
oldCabal2Arch s
| isNothing (pkgBuiltWith s)
= True
| pkgBuiltWith s < recentCabal2ArchVersion
= True
| otherwise = False