#!/usr/bin/env runhaskell {-# LANGUAGE RecordWildCards #-} import Distribution.Simple import Distribution.Simple.Setup import Distribution.Simple.Install import Distribution.Simple.Register import Distribution.Simple.InstallDirs as ID import Distribution.Simple.LocalBuildInfo import Distribution.Simple.Program import Distribution.PackageDescription import Control.Applicative import Control.Monad import Data.List import Data.Maybe import System.FilePath main :: IO () main = defaultMainWithHooks $ simpleUserHooks { instHook = inst, copyHook = copy, hookedPrograms = [ simpleProgram "cabal" ] } -- mostly copypasta from 'defaultInstallHook' inst :: PackageDescription -> LocalBuildInfo -> UserHooks -> InstallFlags -> IO () inst pd lbi _uf ifl = do let copyFlags = defaultCopyFlags { copyDistPref = installDistPref ifl, copyDest = toFlag NoCopyDest, copyVerbosity = installVerbosity ifl } xInstallTarget pd lbi (\pd' lbi' -> install pd' lbi' copyFlags) let registerFlags = defaultRegisterFlags { regDistPref = installDistPref ifl, regInPlace = installInPlace ifl, regPackageDB = installPackageDB ifl, regVerbosity = installVerbosity ifl } when (hasLibs pd) $ register pd lbi registerFlags copy :: PackageDescription -> LocalBuildInfo -> UserHooks -> CopyFlags -> IO () copy pd lbi _uh cf = xInstallTarget pd lbi (\pd' lbi' -> install pd' lbi' cf) xInstallTarget :: PackageDescription -> LocalBuildInfo -> (PackageDescription -> LocalBuildInfo -> IO ()) -> IO () xInstallTarget pd lbi fn = do let (extended, regular) = partition (isJust . installTarget) (executables pd) let pd_regular = pd { executables = regular } _ <- flip mapM extended $ \exe -> do putStrLn $ "extended " ++ show (exeName exe) let idirtpl = installDirTemplates lbi env = installDirsTemplateEnv idirtpl libexecdir' = fromPathTemplate (libexecdir idirtpl) pd_extended = onlyExePackageDesc [exe] pd install_target = fromJust $ installTarget exe install_target' = ID.substPathTemplate env install_target -- $libexec isn't a real thing :/ so we have to simulate it install_target'' = substLibExec' libexecdir' install_target' let lbi' = lbi { installDirTemplates = (installDirTemplates lbi) { bindir = install_target'' } } fn pd_extended lbi' fn pd_regular lbi where installTarget :: Executable -> Maybe PathTemplate installTarget exe = toPathTemplate <$> lookup "x-install-target" (customFieldsBI $ buildInfo exe) substLibExec libexecdir "$libexecdir" = libexecdir substLibExec _ comp = comp substLibExec' dir = withPT $ withSP $ map (substLibExec dir . dropTrailingPathSeparator) withPT f pt = toPathTemplate $ f (fromPathTemplate pt) withSP f p = joinPath $ f (splitPath p) onlyExePackageDesc :: [Executable] -> PackageDescription -> PackageDescription onlyExePackageDesc exes pd = emptyPackageDescription { package = package pd , executables = exes }