on 0875310 help sign in
Idris-dev/Setup.hs
215 lines 7.6 kB history raw
1{-# LANGUAGE CPP #-}
2import Control.Monad
3import Data.IORef
4import Control.Exception (SomeException, catch)
6import Distribution.Simple
7import Distribution.Simple.BuildPaths (autogenModulesDir)
8import Distribution.Simple.InstallDirs as I
9import Distribution.Simple.LocalBuildInfo as L
10import qualified Distribution.Simple.Setup as S
11import qualified Distribution.Simple.Program as P
12import Distribution.Simple.Utils (createDirectoryIfMissingVerbose, rewriteFile)
13import Distribution.PackageDescription
14import Distribution.Text
16import System.Exit
17import System.FilePath ((</>), splitDirectories)
18import System.Directory
19import qualified System.FilePath.Posix as Px
20import System.Process
21import qualified Data.Text as T
22import qualified Data.Text.IO as TIO
24-- After Idris is built, we need to check and install the prelude and other libs
26-- -----------------------------------------------------------------------------
27-- Idris Command Path
29-- make on mingw32 exepects unix style separators
30#ifdef mingw32_HOST_OS
31(<//>) = (Px.</>)
32idrisCmd local = Px.joinPath $ splitDirectories $ ".." <//> ".." <//> buildDir local <//> "idris" <//> "idris"
33#else
34idrisCmd local = ".." </> ".." </> buildDir local </> "idris" </> "idris"
35#endif
37-- -----------------------------------------------------------------------------
38-- Make Commands
40-- use GNU make on FreeBSD
41#if defined(freebsd_HOST_OS) || defined(dragonfly_HOST_OS)
42mymake = "gmake"
43#else
44mymake = "make"
45#endif
46make verbosity =
47 P.runProgramInvocation verbosity . P.simpleProgramInvocation mymake
49-- -----------------------------------------------------------------------------
50-- Flags
52usesLLVM :: S.ConfigFlags -> Bool
53usesLLVM flags =
54 case lookup (FlagName "llvm") (S.configConfigurationsFlags flags) of
55 Just True -> True
56 Just False -> False
57 Nothing -> True
59usesGMP :: S.ConfigFlags -> Bool
60usesGMP flags =
61 case lookup (FlagName "gmp") (S.configConfigurationsFlags flags) of
62 Just True -> True
63 Just False -> False
64 Nothing -> True
66isRelease :: S.ConfigFlags -> Bool
67isRelease flags =
68 case lookup (FlagName "release") (S.configConfigurationsFlags flags) of
69 Just True -> True
70 Just False -> False
71 Nothing -> False
73-- -----------------------------------------------------------------------------
74-- Clean
76idrisClean _ flags _ _ = do
77 cleanStdLib
78 cleanLLVM
79 where
80 verbosity = S.fromFlag $ S.cleanVerbosity flags
82 cleanStdLib = do
83 makeClean "libs"
85 cleanLLVM = makeClean "llvm"
87 makeClean dir = make verbosity [ "-C", dir, "clean", "IDRIS=idris" ]
90-- -----------------------------------------------------------------------------
91-- Configure
93gitHash :: IO String
94gitHash = do h <- Control.Exception.catch (readProcess "git" ["rev-parse", "--short", "HEAD"] "")
95 (\e -> let e' = (e :: SomeException) in return "PRE")
96 return $ takeWhile (/= '\n') h
98-- Put the Git hash into a module for use in the program
99-- For release builds, just put the empty string in the module
100generateVersionModule verbosity dir release = do
101 hash <- gitHash
102 let versionModulePath = dir </> "Version_idris" Px.<.> "hs"
103 putStrLn $ "Generating " ++ versionModulePath ++
104 if release then " for release" else (" for prerelease " ++ hash)
105 createDirectoryIfMissingVerbose verbosity True dir
106 rewriteFile versionModulePath (versionModuleContents hash)
108 where versionModuleContents h = "module Version_idris where\n\n" ++
109 "gitHash :: String\n" ++
110 if release
111 then "gitHash = \"\"\n"
112 else "gitHash = \"-git:" ++ h ++ "\"\n"
114idrisConfigure _ flags _ local = do
115 configureRTS
116 generateVersionModule verbosity (autogenModulesDir local) (isRelease (configFlags local))
117 where
118 verbosity = S.fromFlag $ S.configVerbosity flags
119 version = pkgVersion . package $ localPkgDescr local
121 -- This is a hack. I don't know how to tell cabal that a data file needs
122 -- installing but shouldn't be in the distribution. And it won't make the
123 -- distribution if it's not there, so instead I just delete
124 -- the file after configure.
125 configureRTS = make verbosity ["-C", "rts", "clean"]
127idrisPreSDist args flags = do
128 let dir = S.fromFlag (S.sDistDirectory flags)
129 let verb = S.fromFlag (S.sDistVerbosity flags)
130 generateVersionModule verb ("src") True
131 preSDist simpleUserHooks args flags
133idrisPostSDist args flags desc lbi = do
134 Control.Exception.catch (do let file = "src" </> "Version_idris" Px.<.> "hs"
135 putStrLn $ "Removing generated module " ++ file
136 removeFile file)
137 (\e -> let e' = (e :: SomeException) in return ())
138 postSDist simpleUserHooks args flags desc lbi
140-- -----------------------------------------------------------------------------
141-- Build
143getVersion :: Args -> S.BuildFlags -> IO HookedBuildInfo
144getVersion args flags = do
145 hash <- gitHash
146 let buildinfo = (emptyBuildInfo { cppOptions = ["-DVERSION="++hash] }) :: BuildInfo
147 return (Just buildinfo, [])
149idrisBuild _ flags _ local = do
150 buildStdLib
151 buildRTS
152 when (usesLLVM $ configFlags local) buildLLVM
153 where
154 verbosity = S.fromFlag $ S.buildVerbosity flags
156 buildStdLib = do
157 putStrLn "Building libraries..."
158 makeBuild "libs"
159 where
160 makeBuild dir = make verbosity [ "-C", dir, "build" , "IDRIS=" ++ idrisCmd local]
162 buildRTS = make verbosity (["-C", "rts", "build"] ++
163 gmpflag (usesGMP (configFlags local)))
165 buildLLVM = make verbosity ["-C", "llvm", "build"]
167 gmpflag False = []
168 gmpflag True = ["GMP=-DIDRIS_GMP"]
171-- -----------------------------------------------------------------------------
172-- Copy/Install
174idrisInstall verbosity copy pkg local = do
175 installStdLib
176 installRTS
177 when (usesLLVM $ configFlags local) installLLVM
178 where
179 target = datadir $ L.absoluteInstallDirs pkg local copy
181 installStdLib = do
182 putStrLn $ "Installing libraries in " ++ target
183 makeInstall "libs" target
185 installRTS = do
186 let target' = target </> "rts"
187 putStrLn $ "Installing run time system in " ++ target'
188 makeInstall "rts" target'
190 installLLVM = do
191 let target' = target </> "llvm"
192 putStrLn $ "Installing LLVM library in " ++ target
193 makeInstall "llvm" target'
195 makeInstall src target =
196 make verbosity [ "-C", src, "install" , "TARGET=" ++ target, "IDRIS=" ++ idrisCmd local]
198-- -----------------------------------------------------------------------------
199-- Main
201-- Install libraries during both copy and install
202-- See http://hackage.haskell.org/trac/hackage/ticket/718
203main = defaultMainWithHooks $ simpleUserHooks
204 { postClean = idrisClean
205 , postConf = idrisConfigure
206 , postBuild = idrisBuild
207 , postCopy = \_ flags pkg local ->
208 idrisInstall (S.fromFlag $ S.copyVerbosity flags)
209 (S.fromFlag $ S.copyDest flags) pkg local
210 , postInst = \_ flags pkg local ->
211 idrisInstall (S.fromFlag $ S.installVerbosity flags)
212 NoCopyDest pkg local
213 , preSDist = idrisPreSDist --do { putStrLn (show args) ; putStrLn (show flags) ; return emptyHookedBuildInfo }
214 , postSDist = idrisPostSDist
215 }