on dfa272d help sign in
Idris-dev/Setup.hs
256 lines 10.0 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.Environment
17import System.Exit
18import System.FilePath ((</>), splitDirectories,isAbsolute)
19import System.Directory
20import qualified System.FilePath.Posix as Px
21import System.Process
22import qualified Data.Text as T
23import qualified Data.Text.IO as TIO
25-- After Idris is built, we need to check and install the prelude and other libs
27-- -----------------------------------------------------------------------------
28-- Idris Command Path
30-- make on mingw32 exepects unix style separators
31#ifdef mingw32_HOST_OS
32(<//>) = (Px.</>)
33idrisCmd local = Px.joinPath $ splitDirectories $ ".." <//> ".." <//> buildDir local <//> "idris" <//> "idris"
34#else
35idrisCmd local = ".." </> ".." </> buildDir local </> "idris" </> "idris"
36#endif
38-- -----------------------------------------------------------------------------
39-- Make Commands
41-- use GNU make on FreeBSD
42#if defined(freebsd_HOST_OS) || defined(dragonfly_HOST_OS)
43mymake = "gmake"
44#else
45mymake = "make"
46#endif
47make verbosity =
48 P.runProgramInvocation verbosity . P.simpleProgramInvocation mymake
50-- -----------------------------------------------------------------------------
51-- Flags
53usesLLVM :: S.ConfigFlags -> Bool
54usesLLVM flags =
55 case lookup (FlagName "llvm") (S.configConfigurationsFlags flags) of
56 Just True -> True
57 Just False -> False
58 Nothing -> True
60usesGMP :: S.ConfigFlags -> Bool
61usesGMP flags =
62 case lookup (FlagName "gmp") (S.configConfigurationsFlags flags) of
63 Just True -> True
64 Just False -> False
65 Nothing -> True
67isRelease :: S.ConfigFlags -> Bool
68isRelease flags =
69 case lookup (FlagName "release") (S.configConfigurationsFlags flags) of
70 Just True -> True
71 Just False -> False
72 Nothing -> False
74isFreestanding :: S.ConfigFlags -> Bool
75isFreestanding flags =
76 case lookup (FlagName "freestanding") (S.configConfigurationsFlags flags) of
77 Just True -> True
78 Just False -> False
79 Nothing -> False
80-- -----------------------------------------------------------------------------
81-- Clean
83idrisClean _ flags _ _ = do
84 cleanStdLib
85 cleanLLVM
86 where
87 verbosity = S.fromFlag $ S.cleanVerbosity flags
89 cleanStdLib = do
90 makeClean "libs"
92 cleanLLVM = makeClean "llvm"
94 makeClean dir = make verbosity [ "-C", dir, "clean", "IDRIS=idris" ]
97-- -----------------------------------------------------------------------------
98-- Configure
100gitHash :: IO String
101gitHash = do h <- Control.Exception.catch (readProcess "git" ["rev-parse", "--short", "HEAD"] "")
102 (\e -> let e' = (e :: SomeException) in return "PRE")
103 return $ takeWhile (/= '\n') h
105-- Put the Git hash into a module for use in the program
106-- For release builds, just put the empty string in the module
107generateVersionModule verbosity dir release = do
108 hash <- gitHash
109 let versionModulePath = dir </> "Version_idris" Px.<.> "hs"
110 putStrLn $ "Generating " ++ versionModulePath ++
111 if release then " for release" else (" for prerelease " ++ hash)
112 createDirectoryIfMissingVerbose verbosity True dir
113 rewriteFile versionModulePath (versionModuleContents hash)
115 where versionModuleContents h = "module Version_idris where\n\n" ++
116 "gitHash :: String\n" ++
117 if release
118 then "gitHash = \"\"\n"
119 else "gitHash = \"-git:" ++ h ++ "\"\n"
121-- Generate a module that contains the lib path for a freestanding Idris
122generateTargetModule verbosity dir targetDir = do
123 absPath <- return $ isAbsolute targetDir
124 let targetModulePath = dir </> "Target_idris" Px.<.> "hs"
125 putStrLn $ "Generating " ++ targetModulePath
126 createDirectoryIfMissingVerbose verbosity True dir
127 rewriteFile targetModulePath (versionModuleContents absPath targetDir)
128 where versionModuleContents absolute td = "module Target_idris where\n\n" ++
129 "import System.FilePath\n" ++
130 "import System.Environment\n" ++
131 "getDataDir :: IO String\n" ++
132 if absolute
133 then "getDataDir = return \"" ++ td ++ "\"\n"
134 else "getDataDir = do \n" ++
135 " expath <- getExecutablePath\n" ++
136 " execDir <- return $ dropFileName expath\n" ++
137 " return $ execDir ++ \"" ++ td ++ "\"\n"
138 ++ "getDataFileName :: FilePath -> IO FilePath\n"
139 ++ "getDataFileName name = do\n"
140 ++ " dir <- getDataDir\n"
141 ++ " return (dir ++ \"/\" ++ name)"
144idrisConfigure _ flags _ local = do
145 configureRTS
146 generateVersionModule verbosity (autogenModulesDir local) (isRelease (configFlags local))
147 when (isFreestanding $ configFlags local) (do
148 targetDir <- lookupEnv "IDRIS_INSTALL_DIR"
149 case targetDir of
150 Just d -> generateTargetModule verbosity (autogenModulesDir local) d
151 Nothing -> error $ "Trying to build freestanding without a target directory."
152 ++ " Set it by defining IDRIS_INSTALL_DIR.")
153 where
154 verbosity = S.fromFlag $ S.configVerbosity flags
155 version = pkgVersion . package $ localPkgDescr local
157 -- This is a hack. I don't know how to tell cabal that a data file needs
158 -- installing but shouldn't be in the distribution. And it won't make the
159 -- distribution if it's not there, so instead I just delete
160 -- the file after configure.
161 configureRTS = make verbosity ["-C", "rts", "clean"]
163idrisPreSDist args flags = do
164 let dir = S.fromFlag (S.sDistDirectory flags)
165 let verb = S.fromFlag (S.sDistVerbosity flags)
166 generateVersionModule verb ("src") True
167 generateTargetModule verb "src" "./libs"
168 preSDist simpleUserHooks args flags
170idrisPostSDist args flags desc lbi = do
171 Control.Exception.catch (do let file = "src" </> "Version_idris" Px.<.> "hs"
172 let targetFile = "src" </> "Target_idris" Px.<.> "hs"
173 putStrLn $ "Removing generated modules:\n "
174 ++ file ++ "\n" ++ targetFile
175 removeFile file
176 removeFile targetFile)
177 (\e -> let e' = (e :: SomeException) in return ())
178 postSDist simpleUserHooks args flags desc lbi
180-- -----------------------------------------------------------------------------
181-- Build
183getVersion :: Args -> S.BuildFlags -> IO HookedBuildInfo
184getVersion args flags = do
185 hash <- gitHash
186 let buildinfo = (emptyBuildInfo { cppOptions = ["-DVERSION="++hash] }) :: BuildInfo
187 return (Just buildinfo, [])
189idrisBuild _ flags _ local = do
190 buildStdLib
191 buildRTS
192 when (usesLLVM $ configFlags local) buildLLVM
193 where
194 verbosity = S.fromFlag $ S.buildVerbosity flags
196 buildStdLib = do
197 putStrLn "Building libraries..."
198 makeBuild "libs"
199 where
200 makeBuild dir = make verbosity [ "-C", dir, "build" , "IDRIS=" ++ idrisCmd local]
202 buildRTS = make verbosity (["-C", "rts", "build"] ++
203 gmpflag (usesGMP (configFlags local)))
205 buildLLVM = make verbosity ["-C", "llvm", "build"]
207 gmpflag False = []
208 gmpflag True = ["GMP=-DIDRIS_GMP"]
212-- -----------------------------------------------------------------------------
213-- Copy/Install
215idrisInstall verbosity copy pkg local = do
216 installStdLib
217 installRTS
218 when (usesLLVM $ configFlags local) installLLVM
219 where
220 target = datadir $ L.absoluteInstallDirs pkg local copy
222 installStdLib = do
223 putStrLn $ "Installing libraries in " ++ target
224 makeInstall "libs" target
226 installRTS = do
227 let target' = target </> "rts"
228 putStrLn $ "Installing run time system in " ++ target'
229 makeInstall "rts" target'
231 installLLVM = do
232 let target' = target </> "llvm"
233 putStrLn $ "Installing LLVM library in " ++ target
234 makeInstall "llvm" target'
236 makeInstall src target =
237 make verbosity [ "-C", src, "install" , "TARGET=" ++ target, "IDRIS=" ++ idrisCmd local]
239-- -----------------------------------------------------------------------------
240-- Main
242-- Install libraries during both copy and install
243-- See http://hackage.haskell.org/trac/hackage/ticket/718
244main = defaultMainWithHooks $ simpleUserHooks
245 { postClean = idrisClean
246 , postConf = idrisConfigure
247 , postBuild = idrisBuild
248 , postCopy = \_ flags pkg local ->
249 idrisInstall (S.fromFlag $ S.copyVerbosity flags)
250 (S.fromFlag $ S.copyDest flags) pkg local
251 , postInst = \_ flags pkg local ->
252 idrisInstall (S.fromFlag $ S.installVerbosity flags)
253 NoCopyDest pkg local
254 , preSDist = idrisPreSDist --do { putStrLn (show args) ; putStrLn (show flags) ; return emptyHookedBuildInfo }
255 , postSDist = idrisPostSDist
256 }