forked from klauspost/reedsolomon
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Setup.hs
151 lines (123 loc) · 6.46 KB
/
Setup.hs
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
{-# LANGUAGE RecordWildCards #-}
import Prelude hiding ((<$>))
import Control.Applicative ((<$>))
import Control.Exception (bracket)
import Control.Monad (unless, when)
import Data.Maybe (fromMaybe, isJust)
import System.Directory hiding (makeAbsolute, withCurrentDirectory)
import System.FilePath
import Distribution.PackageDescription
import Distribution.Simple
import Distribution.Simple.LocalBuildInfo
import Distribution.Simple.Program.Builtin (arProgram, ghcProgram)
import qualified Distribution.Simple.Program.Db as Db
import Distribution.Simple.Program.Types (ConfiguredProgram(..), Program(..), ProgramLocation(..))
import Distribution.Simple.Setup
import Distribution.Simple.Utils
import Distribution.Verbosity
main :: IO ()
main = defaultMainWithHooks customHooks
where
customHooks = simpleUserHooks { confHook = customConfHook (confHook simpleUserHooks)
, buildHook = customBuildHook (buildHook simpleUserHooks)
, preSDist = customPreSDist (preSDist simpleUserHooks)
}
customConfHook :: (a -> b -> IO LocalBuildInfo)
-> a
-> b
-> IO LocalBuildInfo
customConfHook innerHook a b = do
localBuildInfo <- innerHook a b
root <- makeAbsolute =<< getCurrentDirectory
let cabalBuildDir = buildDir localBuildInfo
sh = "sh"
Just ar = Db.lookupProgram arProgram (withPrograms localBuildInfo)
arLocation = resolveProgramLocation ar
arWrapperPath = root </> "build-tools" </> "ar-wrapper"
arWrapper = ar { programDefaultArgs = arWrapperPath : arLocation : programDefaultArgs ar
, programLocation = UserSpecified sh
, programOverrideEnv = ("CABAL_BUILD_DIR", Just cabalBuildDir) : programOverrideEnv ar
}
Just ghc = Db.lookupProgram ghcProgram (withPrograms localBuildInfo)
ghcLocation = resolveProgramLocation ghc
ghcWrapperPath = root </> "build-tools" </> "ghc-wrapper"
ghcWrapper = ghc { programDefaultArgs = ghcWrapperPath : ghcLocation : programDefaultArgs ghc
, programLocation = UserSpecified sh
, programOverrideEnv = ("CABAL_BUILD_DIR", Just cabalBuildDir) : programOverrideEnv ghc
}
withPrograms' = Db.updateProgram arWrapper $
Db.updateProgram ghcWrapper $
withPrograms localBuildInfo
return localBuildInfo { withPrograms = withPrograms' }
where
resolveProgramLocation prog = case programLocation prog of
UserSpecified path -> path
FoundOnSystem path -> path
customBuildHook :: (PackageDescription -> LocalBuildInfo -> UserHooks -> BuildFlags -> IO ())
-> PackageDescription
-> LocalBuildInfo
-> UserHooks
-> BuildFlags
-> IO ()
customBuildHook innerHook packageDescription@PackageDescription{..} localBuildInfo@LocalBuildInfo{..} userHooks buildFlags = do
let wantSIMD = fromMaybe True $ lookup (FlagName "simd") $ configConfigurationsFlags configFlags
verbosity = fromFlag $ buildVerbosity buildFlags
version = pkgVersion package
root <- makeAbsolute =<< getCurrentDirectory
absBuildDir <- makeAbsolute buildDir
let cbitsBuildDir = absBuildDir </> "cbits"
when wantSIMD $ do
let configure = root </> "cbits" </> "configure"
configureExists <- doesFileExist configure
unless configureExists $
die $ concat [ "'configure' script not found. "
, "If this is not a release version, you probably need "
, "to run 'autoreconf -i' in the 'cbits' directory to generate it."
]
createDirectoryIfMissing True cbitsBuildDir
hasMakefile <- doesFileExist (cbitsBuildDir </> "Makefile")
unless hasMakefile $
withCurrentDirectory cbitsBuildDir $ do
let libOptions = case versionBranch version of
[999] -> []
_ -> ["--disable-maintainer-mode"]
fromWindows = map (\c -> if c == '\\' then '/' else c)
rawSystemExit verbosity "sh" $ [ fromWindows configure
] ++ libOptions
rawSystemExit verbosity "make" ["-C", cbitsBuildDir, "--no-print-directory"]
let addIncludeDir info = info { includeDirs = cbitsBuildDir : includeDirs info }
packageDescription' = if wantSIMD
then mapBuildInfo addIncludeDir packageDescription
else packageDescription
innerHook packageDescription' localBuildInfo userHooks buildFlags
mapBuildInfo :: (BuildInfo -> BuildInfo) -> PackageDescription -> PackageDescription
mapBuildInfo f desc = desc { library = fmap (\l -> l { libBuildInfo = f (libBuildInfo l) }) (library desc)
, executables = map (\e -> e { buildInfo = f (buildInfo e) }) (executables desc)
, testSuites = map (\t -> t { testBuildInfo = f (testBuildInfo t) }) (testSuites desc)
, benchmarks = map (\b -> b { benchmarkBuildInfo = f (benchmarkBuildInfo b) }) (benchmarks desc)
}
makeAbsolute :: FilePath -> IO FilePath
makeAbsolute = (normalise <$>) . absolutize
where absolutize path -- avoid the call to `getCurrentDirectory` if we can
| isRelative path = (</> path) . addTrailingPathSeparator <$>
getCurrentDirectory
| otherwise = return path
withCurrentDirectory :: FilePath -- ^ Directory to execute in
-> IO a -- ^ Action to be executed
-> IO a
withCurrentDirectory dir action =
bracket getCurrentDirectory setCurrentDirectory $ \ _ -> do
setCurrentDirectory dir
action
customPreSDist :: (Args -> SDistFlags -> IO HookedBuildInfo)
-> Args
-> SDistFlags
-> IO HookedBuildInfo
customPreSDist innerHook args flags = do
hookedBuildInfo <- innerHook args flags
root <- makeAbsolute =<< getCurrentDirectory
let cbits = root </> "cbits"
verbosity = fromFlag (sDistVerbosity flags)
withCurrentDirectory cbits $
rawSystemExit verbosity "autoreconf" ["-f", "-i"]
return hookedBuildInfo