11#!/usr/bin/env runhaskell
2- {-# LANGUAGE RecordWildCards #-}
2+ {-# LANGUAGE RecordWildCards, NamedFieldPuns #-}
33import Distribution.Simple
4+ import Distribution.Simple.Utils
45import Distribution.Simple.Setup
56import Distribution.Simple.Install
67import Distribution.Simple.Register
7- import Distribution.Simple.InstallDirs as ID
8+ import Distribution.Simple.BuildPaths
9+ import qualified Distribution.Simple.InstallDirs as ID
810import Distribution.Simple.LocalBuildInfo
911import Distribution.PackageDescription
1012
13+ import qualified Data.Map as M
14+ import Data.Map (Map )
15+
1116import Control.Arrow
1217import Control.Applicative
1318import Control.Monad
@@ -18,37 +23,130 @@ import Data.Monoid
1823import System.Process
1924import System.Exit
2025import System.FilePath
21-
22- import SetupCompat
26+ import System.Directory (renameFile )
2327
2428main :: IO ()
2529main = defaultMainWithHooks $ simpleUserHooks {
30+ instHook = inst,
31+ copyHook = copy,
32+
2633 confHook = \ (gpd, hbi) cf ->
27- xBuildDependsLike <$> (confHook simpleUserHooks) (gpd, hbi) cf
34+ xBuildDependsLike <$> (confHook simpleUserHooks) (gpd, hbi) cf,
35+
36+ buildHook = \ pd lbi hooks flags -> (buildHook simpleUserHooks) pd (patchLibexecdir lbi) hooks flags
2837 }
2938
39+ patchLibexecdir :: LocalBuildInfo -> LocalBuildInfo
40+ patchLibexecdir lbi = let
41+ idirtpl = installDirTemplates lbi
42+ libexecdir' = toPathTemplate $ fromPathTemplate (libexecdir idirtpl) </> " $abi/$pkgid"
43+ lbi' = lbi { installDirTemplates = idirtpl { libexecdir = libexecdir' } }
44+ in
45+ lbi'
46+
47+
3048xBuildDependsLike :: LocalBuildInfo -> LocalBuildInfo
3149xBuildDependsLike lbi =
3250 let
3351 cc = componentsConfigs lbi
3452 pd = localPkgDescr lbi
3553 deps = dependsMap lbi
36- in setComponentsConfigs lbi
37- [ (cn, updateClbi deps comp clbi, cdeps)
38- | (cn, clbi, cdeps) <- cc
39- , let comp = getComponent pd cn
40- ]
41-
54+ in lbi {
55+ componentsConfigs =
56+ [ (cn, updateClbi deps comp clbi, cdeps)
57+ | (cn, clbi, cdeps) <- cc
58+ , let comp = getComponent pd cn
59+ ]
60+ }
4261 where
4362 updateClbi deps comp clbi = setUnionDeps (otherDeps deps comp) clbi
4463
4564 dependsMap ::
46- LocalBuildInfo -> [(ComponentName , Deps )]
65+ LocalBuildInfo -> [(ComponentName , ([( UnitId , PackageId )], Map PackageName ModuleRenaming ) )]
4766 dependsMap lbi =
48- second getDeps <$> allComponentsInBuildOrder lbi
67+ second (componentPackageDeps &&& componentPackageRenaming)
68+ <$> allComponentsInBuildOrder lbi
4969
50- otherDeps :: [(ComponentName , Deps )] -> Component -> Deps
51- otherDeps deps comp = fromMaybe noDeps $
70+ otherDeps :: [(ComponentName , ([( UnitId , PackageId )], Map PackageName ModuleRenaming ))] -> Component -> ([( UnitId , PackageId )], Map PackageName ModuleRenaming )
71+ otherDeps deps comp = fromMaybe ( [] , M. empty) $
5272 flip lookup deps =<< read <$> lookup " x-build-depends-like" fields
5373 where
5474 fields = customFieldsBI (componentBuildInfo comp)
75+
76+ setComponentPackageRenaming clbi cprn =
77+ clbi { componentPackageRenaming =
78+ componentPackageRenaming clbi `M.union` cprn }
79+
80+ setUnionDeps :: ([(UnitId , PackageId )], Map PackageName ModuleRenaming ) -> ComponentLocalBuildInfo -> ComponentLocalBuildInfo
81+ setUnionDeps (deps, rns) clbi = let
82+ clbi' = setComponentPackageRenaming clbi rns
83+ cpdeps = componentPackageDeps clbi
84+ in
85+ clbi' {
86+ componentPackageDeps = cpdeps `union` deps
87+ }
88+
89+
90+ -- mostly copypasta from 'defaultInstallHook'
91+ inst ::
92+ PackageDescription -> LocalBuildInfo -> UserHooks -> InstallFlags -> IO ()
93+ inst pd lbi _uf ifl = do
94+ let copyFlags = defaultCopyFlags {
95+ copyDistPref = installDistPref ifl,
96+ copyDest = toFlag NoCopyDest ,
97+ copyVerbosity = installVerbosity ifl
98+ }
99+ xInstallTarget pd lbi copyFlags (\ pd' lbi' -> install pd' lbi' copyFlags)
100+ let registerFlags = defaultRegisterFlags {
101+ regDistPref = installDistPref ifl,
102+ regInPlace = installInPlace ifl,
103+ regPackageDB = installPackageDB ifl,
104+ regVerbosity = installVerbosity ifl
105+ }
106+ when (hasLibs pd) $ register pd lbi registerFlags
107+
108+ copy :: PackageDescription -> LocalBuildInfo -> UserHooks -> CopyFlags -> IO ()
109+ copy pd lbi _uh cf =
110+ xInstallTarget pd lbi cf (\ pd' lbi' -> install pd' lbi' cf)
111+
112+ xInstallTarget :: PackageDescription
113+ -> LocalBuildInfo
114+ -> CopyFlags
115+ -> (PackageDescription -> LocalBuildInfo -> IO () )
116+ -> IO ()
117+ xInstallTarget pd lbi cf fn = do
118+ let (extended, regular) = partition isInternal (executables pd)
119+
120+ let pd_regular = pd { executables = regular }
121+
122+ _ <- flip mapM extended $ \ exe -> do
123+ let pd_extended = onlyExePackageDesc [exe] pd
124+ fn pd_extended lbi
125+
126+ let lbi' = patchLibexecdir lbi
127+ copydest = fromFlag (copyDest cf)
128+ verbosity = fromFlag (copyVerbosity cf)
129+ InstallDirs { bindir, libexecdir } = absoluteInstallDirs pd lbi' copydest
130+ progprefix = substPathTemplate (packageId pd) lbi (progPrefix lbi)
131+ progsuffix = substPathTemplate (packageId pd) lbi (progSuffix lbi)
132+ fixedExeBaseName = progprefix ++ exeName exe ++ progsuffix
133+
134+ fixedExeFileName = bindir </> fixedExeBaseName <.> exeExtension
135+ newExeFileName = libexecdir </> fixedExeBaseName <.> exeExtension
136+
137+ when (exeName exe == " ghc-mod-real" ) $ do
138+ createDirectoryIfMissingVerbose verbosity True libexecdir
139+ renameFile fixedExeFileName newExeFileName
140+
141+ fn pd_regular lbi
142+
143+ where
144+ isInternal :: Executable -> Bool
145+ isInternal exe =
146+ fromMaybe False $ (== " True" ) <$> lookup " x-internal" (customFieldsBI $ buildInfo exe)
147+
148+ onlyExePackageDesc :: [Executable ] -> PackageDescription -> PackageDescription
149+ onlyExePackageDesc exes pd = emptyPackageDescription {
150+ package = package pd
151+ , executables = exes
152+ }
0 commit comments