aboutsummaryrefslogtreecommitdiff
path: root/Setup.hs
blob: 4df40063ae1469e2023c0f7cc629b0dd2d645764 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
{-# LANGUAGE CPP, RecordWildCards, NamedFieldPuns #-}

#ifndef MIN_VERSION_Cabal
#define MIN_VERSION_Cabal(x,y,z) 0
#endif

#if MIN_VERSION_Cabal(2,0,0)

-- https://github.com/haskell/cabal/pull/4501 is upstream in 2.0, yey
import Distribution.Simple
main = defaultMain

#else

import Distribution.Simple
import Distribution.Simple.Utils
import Distribution.Simple.Setup
import Distribution.Simple.Install
import Distribution.Simple.Register
import Distribution.Simple.BuildPaths
import qualified Distribution.Simple.InstallDirs as ID
import Distribution.Simple.LocalBuildInfo
import Distribution.Simple.Program
import Distribution.PackageDescription

import Control.Monad
import Data.List
import Data.Maybe
import System.FilePath
import System.Directory (renameFile)

main :: IO ()
main = defaultMainWithHooks $ simpleUserHooks {
   instHook = inst,
   copyHook = copy,
   buildHook = \pd lbi hooks flags -> (buildHook simpleUserHooks) pd (patchLibexecdir lbi) hooks flags,
   hookedPrograms = [ simpleProgram "cabal" ]
 }

patchLibexecdir :: LocalBuildInfo -> LocalBuildInfo
patchLibexecdir lbi = let
    idirtpl     = installDirTemplates lbi
    libexecdir' = toPathTemplate $ fromPathTemplate (libexecdir idirtpl) </> "$abi/$pkgid"
    lbi' = lbi { installDirTemplates = idirtpl { libexecdir = libexecdir' } }
  in
    lbi'

-- 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 copyFlags (\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 cf (\pd' lbi' -> install pd' lbi' cf)

xInstallTarget :: PackageDescription
               -> LocalBuildInfo
               -> CopyFlags
               -> (PackageDescription -> LocalBuildInfo -> IO ())
               -> IO ()
xInstallTarget pd lbi cf fn = do
  let (extended, regular) = partition isExeScopePrivate (executables pd)

  let pd_regular = pd { executables = regular }

  _ <- flip mapM extended $ \exe -> do

    let pd_extended = onlyExePackageDesc [exe] pd

    fn pd_extended lbi

    let lbi' = patchLibexecdir lbi
        copydest  = fromFlag (copyDest cf)
        verbosity = fromFlag (copyVerbosity cf)
        InstallDirs { bindir, libexecdir } = absoluteInstallDirs pd lbi' copydest
        progprefix = substPathTemplate (packageId pd) lbi (progPrefix lbi)
        progsuffix = substPathTemplate (packageId pd) lbi (progSuffix lbi)
        fixedExeBaseName = progprefix ++ exeName exe ++ progsuffix

        fixedExeFileName = bindir </> fixedExeBaseName <.> exeExtension
        newExeFileName   = libexecdir </> fixedExeBaseName <.> exeExtension

    createDirectoryIfMissingVerbose verbosity True libexecdir
    renameFile fixedExeFileName newExeFileName

  fn pd_regular lbi

isExeScopePrivate :: Executable -> Bool
isExeScopePrivate exe =
  fromMaybe False $ (=="private") <$> lookup "x-scope" fields
 where
   fields = customFieldsBI $ buildInfo exe

onlyExePackageDesc :: [Executable] -> PackageDescription -> PackageDescription
onlyExePackageDesc exes pd = emptyPackageDescription {
                     package = package pd
                   , executables = exes
                   }

#endif