Skip to content
This repository was archived by the owner on Apr 25, 2020. It is now read-only.

Commit ec6761a

Browse files
committed
Support installing multiple ghc-mod instances
1 parent 9ef3e67 commit ec6761a

File tree

5 files changed

+344
-393
lines changed

5 files changed

+344
-393
lines changed

Setup.hs

Lines changed: 113 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
#!/usr/bin/env runhaskell
2-
{-# LANGUAGE RecordWildCards #-}
2+
{-# LANGUAGE RecordWildCards, NamedFieldPuns #-}
33
import Distribution.Simple
4+
import Distribution.Simple.Utils
45
import Distribution.Simple.Setup
56
import Distribution.Simple.Install
67
import Distribution.Simple.Register
7-
import Distribution.Simple.InstallDirs as ID
8+
import Distribution.Simple.BuildPaths
9+
import qualified Distribution.Simple.InstallDirs as ID
810
import Distribution.Simple.LocalBuildInfo
911
import Distribution.PackageDescription
1012

13+
import qualified Data.Map as M
14+
import Data.Map (Map)
15+
1116
import Control.Arrow
1217
import Control.Applicative
1318
import Control.Monad
@@ -18,37 +23,130 @@ import Data.Monoid
1823
import System.Process
1924
import System.Exit
2025
import System.FilePath
21-
22-
import SetupCompat
26+
import System.Directory (renameFile)
2327

2428
main :: IO ()
2529
main = 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+
3048
xBuildDependsLike :: LocalBuildInfo -> LocalBuildInfo
3149
xBuildDependsLike 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+
}

SetupCompat.hs

Lines changed: 0 additions & 195 deletions
This file was deleted.

0 commit comments

Comments
 (0)