module Distribution.ArchLinux.CabalTranslation (
preprocessCabal,
cabal2pkg, 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.ArchLinux.SystemProvides
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 -> SystemProvides -> Maybe PackageDescription
preprocessCabal cabalsrc systemContext =
case finalizePackageDescription
[]
(const True)
(Platform X86_64 buildOS)
(CompilerId GHC (Version [6,12,3] []))
(corePackages systemContext ++ platformPackages systemContext)
cabalsrc
of
Left deps -> trace ("Unresolved dependencies: " ++show deps) Nothing
Right (pkg,_) -> Just pkg { buildDepends = removeCoreFrom (buildDepends pkg) systemContext }
removeCoreFrom :: [Dependency] -> SystemProvides -> [Dependency]
removeCoreFrom [] _ = []
removeCoreFrom (x@(Dependency n vr):xs) systemContext =
case find (\(Dependency k _) -> n == k) $ corePackages systemContext of
Just (Dependency (PackageName "base") _)
-> removeCoreFrom xs systemContext
Just (Dependency _ corevr)
| isAnyVersion corevr -> removeCoreFrom xs systemContext
| isJust isspef && (withinRange (fromJust isspef) vr)
-> removeCoreFrom xs systemContext
where isspef = isSpecificVersion corevr
_ -> x : removeCoreFrom xs systemContext
cabal2pkg :: PackageDescription -> SystemProvides -> (AnnotatedPkgBuild, Maybe String)
cabal2pkg cabal systemContext = cabal2pkg' cabal archName 1 systemContext
where
archName = map toLower (if isLibrary then "haskell-" ++ display name else display name)
name = pkgName (package cabal)
isLibrary = isJust (library cabal) && map toLower (display name) `notElem` shouldNotBeLibraries
cabal2pkg' :: PackageDescription -> String -> Int -> SystemProvides -> (AnnotatedPkgBuild, Maybe String)
cabal2pkg' cabal archName release systemContext
= ( emptyPkg {
pkgHeader = []
, hkgName = display name
, pkgBody = stub {
arch_pkgname = archName
, arch_pkgver = vers
, arch_pkgrel = release
, 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_package = (arch_package stub) ++
(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 hasLibrary
then Just (install_hook archName)
else Nothing
)
where
stub = if hasLibrary
then (stubPackageLibrary $ display name) {
arch_depends = (
if not (isLibrary)
then ArchList [ArchDep (Dependency (PackageName "gmp") anyVersion)]
`mappend` anyClibraries
else ArchList []) `mappend` my_makedepends
}
else (stubPackageProgram $ display name) {
arch_makedepends = my_makedepends
, arch_depends = ArchList [ArchDep (Dependency (PackageName "gmp") anyVersion)]
`mappend` anyClibraries
}
name = pkgName (package cabal)
vers = pkgVersion (package cabal)
my_makedepends =
ArchList
[(ArchDep (Dependency (PackageName "ghc") anyVersion))]
`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 systemContext) ]
(<->) :: String -> String -> String
x <-> y = x ++ "-" ++ y
stubPackageLibrary :: String -> PkgBuild
stubPackageLibrary _ = emptyPkgBuild {
arch_url = "http://hackage.haskell.org/package/${_hkgname}"
, arch_makedepends = ArchList []
, arch_source = ArchList . return $
"http://hackage.haskell.org/packages/archive/${_hkgname}/${pkgver}/${_hkgname}-${pkgver}.tar.gz"
, arch_build =
[ "cd ${srcdir}/${_hkgname}-${pkgver}"
, "runhaskell Setup configure -O --enable-split-objs --enable-shared \\"
, " --prefix=/usr --docdir=/usr/share/doc/${pkgname} --libsubdir=\\$compiler/site-local/\\$pkgid"
, "runhaskell Setup build"
, "runhaskell Setup haddock"
, "runhaskell Setup register --gen-script"
, "runhaskell Setup unregister --gen-script"
, "sed -i -r -e \"s|ghc-pkg.*unregister[^ ]* |&'--force' |\" unregister.sh"
]
, arch_package =
[ "cd ${srcdir}/${_hkgname}-${pkgver}"
, "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/${_hkgname}"
,"runhaskell Setup copy --destdir=${pkgdir}"]
, arch_install = Just "${pkgname}.install"
}
stubPackageProgram :: String -> PkgBuild
stubPackageProgram _ = emptyPkgBuild {
arch_url = "http://hackage.haskell.org/package/${_hkgname}"
, arch_source = ArchList . return $
"http://hackage.haskell.org/packages/archive/${_hkgname}/${pkgver}/${_hkgname}-${pkgver}.tar.gz"
, arch_build =
[ "cd ${srcdir}/${_hkgname}-${pkgver}"
, "runhaskell Setup configure --prefix=/usr --docdir=/usr/share/doc/${pkgname} -O"
, "runhaskell Setup build"
]
, arch_package =
[ "cd ${srcdir}/${_hkgname}-${pkgver}"
, "runhaskell Setup copy --destdir=${pkgdir}"]
, arch_install = Nothing
}
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)"
, "}" ]
findCLibs :: PackageDescription -> SystemProvides -> [String]
findCLibs (PackageDescription { library = lib, executables = exe }) sysContext =
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 sysContext) 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
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
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