archlinux-0.3.4: Distribution/ArchLinux/CabalTranslation.hs
-- |
-- Module : Distribution.ArchLinux.CabalTranslation
-- Copyright : (c) Don Stewart, 2008-2010, Rémy Oudompheng 2010
-- License : BSD3
--
-- Maintainer: Arch Haskell Team <arch-haskell@haskell.org>
--
module Distribution.ArchLinux.CabalTranslation (
preprocessCabal,
cabal2pkg,
oldCabal2Arch,
install_hook_name
) where
-- Cabal modules
import Distribution.Package
import Distribution.PackageDescription
import Distribution.PackageDescription.Configuration
import Distribution.License
import Distribution.Version
import Distribution.Compiler
import Distribution.System
-- Archlinux modules
import Distribution.ArchLinux.PkgBuild
-- Standard types
import Distribution.Text
import Data.Char
import Data.List
import qualified Data.Map as M
import Data.Maybe
import Data.Monoid
import System.FilePath
-- Debugging
import Debug.Trace
--
-- | Configure package for system
--
preprocessCabal :: GenericPackageDescription -> Maybe PackageDescription
preprocessCabal cabalsrc =
case finalizePackageDescription
[]
(const True) -- could check against prefered pkgs....
(Platform X86_64 buildOS) -- linux/x86_64
(CompilerId GHC (Version [6,10,3] []))
-- now constrain it to solve in the context of a modern ghc only
corePackages
cabalsrc
of
Left deps -> trace ("Unresolved dependencies: " ++show deps) Nothing
Right (pkg,_) -> Just pkg { buildDepends = removeCoreFrom (buildDepends pkg) }
-- attempt to filter out core packages we've already satisified
-- not actuall correct, since it doesn't take any version
-- info into account.
--
-- TODO this should use configDependency to find the precise
-- versions we have available on Arch.
--
removeCoreFrom :: [Dependency] -> [Dependency]
removeCoreFrom [] = []
removeCoreFrom (x@(Dependency n vr):xs) =
case find (\(Dependency k _) -> n == k) corePackages of
-- haskell-parsec, haskell-quickcheck
Just (Dependency _ (ThisVersion v'))
| withinRange v' vr -> removeCoreFrom xs
Just (Dependency (PackageName "base") _)
-> removeCoreFrom xs
Just (Dependency _ AnyVersion) -> removeCoreFrom xs
_ -> x : removeCoreFrom xs
--
-- Core packages and their versions. These come with
-- ghc, so we should be right.
--
-- http://haskell.org/haskellwiki/Libraries_released_with_GHC
--
-- And what Arch Linux thinks GHC provides:
--
-- http://repos.archlinux.org/wsvn/packages/ghc/repos/extra-x86_64/PKGBUILD
--
-- Note: we could just list these directly, and have yaourt solve them.
--
-- NEW POLICY:
-- We rely on all "provides" from the GHC library to be listed explicitly.
--
corePackages :: [Dependency]
corePackages =
[
-- Magic packages we have to remove
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)
-- Official Provides: http://repos.archlinux.org/wsvn/packages/ghc/repos/extra-x86_64/PKGBUILD
-- ,Dependency (PackageName "array") (ThisVersion (Version [0,3,0,0] []))
-- ,Dependency (PackageName "bytestring") (ThisVersion (Version [0,9,1,5] []))
-- ,Dependency (PackageName "Cabal") (ThisVersion (Version [1,8,0,2] []))
-- ,Dependency (PackageName "containers") (ThisVersion (Version [0,3,0,0] []))
-- ,Dependency (PackageName "directory") (ThisVersion (Version [1,0,1,0] []))
-- ,Dependency (PackageName "extensible-exceptions") (AnyVersion)
-- ,Dependency (PackageName "filepath") (ThisVersion (Version [1,1,0,3] []))
-- ,Dependency (PackageName "haskell98") (ThisVersion (Version [1,0,1,1] []))
-- ,Dependency (PackageName "hpc") (ThisVersion (Version [0,5,0,4] []))
-- ,Dependency (PackageName "old-locale") (ThisVersion (Version [1,0,0,2] []))
-- ,Dependency (PackageName "old-time") (ThisVersion (Version [1,0,0,1] []))
-- ,Dependency (PackageName "pretty") (ThisVersion (Version [1,0,1,1] []))
-- ,Dependency (PackageName "process") (ThisVersion (Version [1,0,1,2] []))
-- ,Dependency (PackageName "random") (ThisVersion (Version [1,0,0,2] []))
-- ,Dependency (PackageName "syb") (ThisVersion (Version [0,1,0,2] []))
-- ,Dependency (PackageName "template-haskell") (ThisVersion (Version [2,4,0,0] []))
-- ,Dependency (PackageName "time") (ThisVersion (Version [1,1,4] []))
-- ,Dependency (PackageName "unix") (ThisVersion (Version [2,4,0,0] []))
-- utf8-string
-- Removed in 6.12.x
-- ,Dependency (PackageName "html") (ThisVersion (Version [1,0,1,2] []))
-- ,Dependency (PackageName "integer") (ThisVersion (Version [0,1,0,0] []))
-- ,Dependency (PackageName "QuickCheck") (ThisVersion (Version [1,2,0,0] []))
-- ,Dependency (PackageName "haskell-src") (ThisVersion (Version [1,0,1,3] []))
-- ,Dependency (PackageName "parsec") (ThisVersion (Version [2,1,0,0] []))
-- ,Dependency (PackageName "packedstring") (ThisVersion (Version [0,1,0,1] []))
-- ,Dependency (PackageName "parallel") (ThisVersion (Version [1,1,0,0] []))
-- ,Dependency (PackageName "network") (ThisVersion (Version [2,2,0,1] []))
-- ,Dependency (PackageName "mtl") (ThisVersion (Version [1,1,0,2] []))
-- ,Dependency (PackageName "stm") (ThisVersion (Version [2,1,1,2] []))
-- ,Dependency (PackageName "HUnit") (ThisVersion (Version [1,2,0,3] []))
-- ,Dependency (PackageName "xhtml") (ThisVersion (Version [3000,2,0,1] []))
-- ,Dependency (PackageName "regex-base") (ThisVersion (Version [0,72,0,2] []))
-- ,Dependency (PackageName "regex-compat") (ThisVersion (Version [0,71,0,1] []))
-- ,Dependency (PackageName "regex-posix") (ThisVersion (Version [0,72,0,2] []))
-- Removed in 6.10.x
-- ,Dependency (PackageName "editline") (AnyVersion)
-- Dependency (PackageName "ALUT") (ThisVersion (Version [2,1,0,0] []))
-- ,Dependency (PackageName "cgi") (ThisVersion (Version [3001,1,5,1] []))
-- ,Dependency (PackageName "fgl") (ThisVersion (Version [5,4,1,1] [])) -- gone
-- ,Dependency (PackageName "GLUT") (ThisVersion (Version [2,1,1,1] []))
-- ,Dependency (PackageName "OpenAL") (ThisVersion (Version [1,3,1,1] [])) -- gone
-- ,Dependency (PackageName "readline") (ThisVersion (Version [1,0,1,0] []))
]
------------------------------------------------------------------------------------
--
-- | Translate a generic cabal file into a PGKBUILD
--
cabal2pkg :: PackageDescription -> (PkgBuild, Maybe String)
cabal2pkg cabal
-- TODO decide if it's a library or an executable,
-- handle multipackages
-- extract C dependencies
-- = trace (show cabal) $
=
(emptyPkgBuild
{ arch_pkgname = archName
, arch_pkgver = vers
, arch_url = "http://hackage.haskell.org/package/"++display name
-- else homepage cabal
, 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)
-- All Hackage packages depend on GHC at build time
-- All Haskell libraries are prefixed with "haskell-"
, arch_makedepends = if not hasLibrary
then my_makedepends
else ArchList [] -- makedepends should not duplicate depends
, arch_depends =
(if not (isLibrary)
then
ArchList [ArchDep (Dependency (PackageName "gmp") AnyVersion)]
`mappend`
anyClibraries
else ArchList [])
`mappend`
-- libraries have 'register-time' dependencies on
-- their dependent Haskell libraries.
--
(if hasLibrary then my_makedepends
else ArchList [])
-- need the dependencies of all flags that are on by default, for all libraries and executables
-- Hackage programs only need their own source to build
, 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"
] ++
-- Only needed for libraries:
(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 ] ++
-- Only needed for libraries:
(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 [])
-- if its a library:
, 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)
-- build time dependencies
my_makedepends =
(arch_makedepends emptyPkgBuild)
`mappend`
-- Haskell libraries
-- TODO: use a real package spec to compute these names
-- based on what is in Arch.
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"]
-- TODO: need a 'nub' in here.
hasLibrary = isJust (library cabal)
isLibrary = isJust (library cabal) -- && null (executables 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
--
-- post install, and pre-remove hooks to run, to sync up ghc-pkg
--
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 }) =
-- warn for packages not in list.
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
-- known pacman packages for C libraries we use:
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")
-- subsumed into glib
,("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")
]
-- atlas
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"
-- the pandoc package doesnt' ship haskell-pandoc
-- ,"pandoc"
,"pugs-drift"
,"wol"
,"timepiece"
,"hledger"
,"hp2any-graph"
,"hp2any-manager"
]
-- translate some library dependencies to gtk names
--
gtk2hsIfy :: [Dependency] -> [Dependency]
gtk2hsIfy = id
{-
gtk2hsIfy [] = []
gtk2hsIfy xs | foundSome = Dependency (PackageName "gtk2hs") AnyVersion :
[ v | v@(Dependency n _) <- xs
, n `notElem` gtkLibs ]
| otherwise = xs
where
foundSome = not . null $ filter (`elem` gtkLibs) (map unDep xs)
unDep (Dependency n _) = n
-}
---------------------------------------------------------------------------
{-
# Contributor: Arch Haskell Team <arch-haskell@haskell.org>
# Package generated by cabal2arch 0.6.1
pkgname=haskell-pcre-light
pkgrel=2
pkgver=0.3.1
pkgdesc="A small, efficient and portable regex library for Perl 5 compatible regular expressions"
url="http://hackage.haskell.org/package/pcre-light"
license=('custom:BSD3')
arch=('i686' 'x86_64')
makedepends=()
depends=('ghc' 'haskell-cabal' 'pcre')
options=('strip')
source=(http://hackage.haskell.org/packages/archive/pcre-light/0.3.1/pcre-light-0.3.1.tar.gz)
install=haskell-pcre-light.install
md5sums=('14d8d6e2fd200c385b1d63c888794014')
build() {
cd ${srcdir}/pcre-light-0.3.1
runhaskell Setup configure --prefix=/usr --docdir=/usr/share/doc/${pkgname} || return 1
runhaskell Setup build || return 1
runhaskell Setup haddock || return 1
runhaskell Setup register --gen-script || return 1
runhaskell Setup unregister --gen-script || return 1
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/libraries
ln -s /usr/share/doc/${pkgname}/html ${pkgdir}/usr/share/doc/ghc/libraries/pcre-light
runhaskell Setup copy --destdir=${pkgdir} || return 1
install -D -m644 LICENSE ${pkgdir}/usr/share/licenses/$pkgname/LICENSE || return 1
rm -f ${pkgdir}/usr/share/doc/${pkgname}/LICENSE
}
-}
------------------------------------------------------------------------
-- Checker
--
type Warnings = String
-- Hard code the cabal2arch version
recentCabal2ArchVersion :: Maybe Version
recentCabal2ArchVersion = case simpleParse "0.7" of -- XXX
Nothing -> error "Unable to parse cabal2arch version"
Just v -> Just v
-- | Look for problems in the PKGBUILD
oldCabal2Arch :: AnnotatedPkgBuild -> Bool
oldCabal2Arch s
| isNothing (pkgBuiltWith s)
= True
| pkgBuiltWith s < recentCabal2ArchVersion
= True -- ["Old version of cabal2arch: " ++ display (fromJust (pkgBuiltWith s))]
| otherwise = False