on 8935fed help sign in
Idris-dev/Setup.hs
261 lines 11 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
53usesGMP :: S.ConfigFlags -> Bool
54usesGMP flags =
55 case lookup (FlagName "gmp") (S.configConfigurationsFlags flags) of
56 Just True -> True
57 Just False -> False
58 Nothing -> True
60execOnly :: S.ConfigFlags -> Bool
61execOnly flags =
62 case lookup (FlagName "execonly") (S.configConfigurationsFlags flags) of
63 Just True -> True
64 Just False -> False
65 Nothing -> False
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 where
86 verbosity = S.fromFlag $ S.cleanVerbosity flags
88 cleanStdLib = do
89 makeClean "libs"
91 makeClean dir = make verbosity [ "-C", dir, "clean", "IDRIS=idris" ]
94-- -----------------------------------------------------------------------------
95-- Configure
97gitHash :: IO String
98gitHash = do h <- Control.Exception.catch (readProcess "git" ["rev-parse", "--short", "HEAD"] "")
99 (\e -> let e' = (e :: SomeException) in return "PRE")
100 return $ takeWhile (/= '\n') h
102-- Put the Git hash into a module for use in the program
103-- For release builds, just put the empty string in the module
104generateVersionModule verbosity dir release = do
105 hash <- gitHash
106 let versionModulePath = dir </> "Version_idris" Px.<.> "hs"
107 putStrLn $ "Generating " ++ versionModulePath ++
108 if release then " for release" else (" for prerelease " ++ hash)
109 createDirectoryIfMissingVerbose verbosity True dir
110 rewriteFile versionModulePath (versionModuleContents hash)
112 where versionModuleContents h = "module Version_idris where\n\n" ++
113 "gitHash :: String\n" ++
114 if release
115 then "gitHash = \"\"\n"
116 else "gitHash = \"git:" ++ h ++ "\"\n"
118-- Generate a module that contains the lib path for a freestanding Idris
119generateTargetModule verbosity dir targetDir = do
120 absPath <- return $ isAbsolute targetDir
121 let targetModulePath = dir </> "Target_idris" Px.<.> "hs"
122 putStrLn $ "Generating " ++ targetModulePath
123 createDirectoryIfMissingVerbose verbosity True dir
124 rewriteFile targetModulePath (versionModuleContents absPath targetDir)
125 where versionModuleContents absolute td = "module Target_idris where\n\n" ++
126 "import System.FilePath\n" ++
127 "import System.Environment\n" ++
128 "getDataDir :: IO String\n" ++
129 if absolute
130 then "getDataDir = return \"" ++ td ++ "\"\n"
131 else "getDataDir = do \n" ++
132 " expath <- getExecutablePath\n" ++
133 " execDir <- return $ dropFileName expath\n" ++
134 " return $ execDir ++ \"" ++ td ++ "\"\n"
135 ++ "getDataFileName :: FilePath -> IO FilePath\n"
136 ++ "getDataFileName name = do\n"
137 ++ " dir <- getDataDir\n"
138 ++ " return (dir ++ \"/\" ++ name)"
140-- a module that has info about existence and location of a bundled toolchain
141generateToolchainModule verbosity srcDir toolDir = do
142 let commonContent = "module Tools_idris where\n\n"
143 let toolContent = case toolDir of
144 Just dir -> "hasBundledToolchain = True\n" ++
145 "getToolchainDir = \"" ++ dir ++ "\"\n"
146 Nothing -> "hasBundledToolchain = False\n" ++
147 "getToolchainDir = \"\""
148 let toolPath = srcDir </> "Tools_idris" Px.<.> "hs"
149 createDirectoryIfMissingVerbose verbosity True srcDir
150 rewriteFile toolPath (commonContent ++ toolContent)
152idrisConfigure _ flags _ local = do
153 configureRTS
154 generateVersionModule verbosity (autogenModulesDir local) (isRelease (configFlags local))
155 if (isFreestanding $ configFlags local)
156 then (do
157 toolDir <- lookupEnv "IDRIS_TOOLCHAIN_DIR"
158 generateToolchainModule verbosity (autogenModulesDir local) toolDir
159 targetDir <- lookupEnv "IDRIS_LIB_DIR"
160 case targetDir of
161 Just d -> generateTargetModule verbosity (autogenModulesDir local) d
162 Nothing -> error $ "Trying to build freestanding without a target directory."
163 ++ " Set it by defining IDRIS_LIB_DIR.")
164 else
165 generateToolchainModule verbosity (autogenModulesDir local) Nothing
166 where
167 verbosity = S.fromFlag $ S.configVerbosity flags
168 version = pkgVersion . package $ localPkgDescr local
170 -- This is a hack. I don't know how to tell cabal that a data file needs
171 -- installing but shouldn't be in the distribution. And it won't make the
172 -- distribution if it's not there, so instead I just delete
173 -- the file after configure.
174 configureRTS = make verbosity ["-C", "rts", "clean"]
176idrisPreSDist args flags = do
177 let dir = S.fromFlag (S.sDistDirectory flags)
178 let verb = S.fromFlag (S.sDistVerbosity flags)
179 generateVersionModule verb ("src") True
180 generateTargetModule verb "src" "./libs"
181 generateToolchainModule verb "src" Nothing
182 preSDist simpleUserHooks args flags
184idrisPostSDist args flags desc lbi = do
185 Control.Exception.catch (do let file = "src" </> "Version_idris" Px.<.> "hs"
186 let targetFile = "src" </> "Target_idris" Px.<.> "hs"
187 putStrLn $ "Removing generated modules:\n "
188 ++ file ++ "\n" ++ targetFile
189 removeFile file
190 removeFile targetFile)
191 (\e -> let e' = (e :: SomeException) in return ())
192 postSDist simpleUserHooks args flags desc lbi
194-- -----------------------------------------------------------------------------
195-- Build
197getVersion :: Args -> S.BuildFlags -> IO HookedBuildInfo
198getVersion args flags = do
199 hash <- gitHash
200 let buildinfo = (emptyBuildInfo { cppOptions = ["-DVERSION="++hash] }) :: BuildInfo
201 return (Just buildinfo, [])
203idrisBuild _ flags _ local = unless (execOnly (configFlags local)) $ do
204 buildStdLib
205 buildRTS
206 where
207 verbosity = S.fromFlag $ S.buildVerbosity flags
209 buildStdLib = do
210 putStrLn "Building libraries..."
211 makeBuild "libs"
212 where
213 makeBuild dir = make verbosity [ "-C", dir, "build" , "IDRIS=" ++ idrisCmd local]
215 buildRTS = make verbosity (["-C", "rts", "build"] ++
216 gmpflag (usesGMP (configFlags local)))
218 gmpflag False = []
219 gmpflag True = ["GMP=-DIDRIS_GMP"]
223-- -----------------------------------------------------------------------------
224-- Copy/Install
226idrisInstall verbosity copy pkg local = unless (execOnly (configFlags local)) $ do
227 installStdLib
228 installRTS
229 where
230 target = datadir $ L.absoluteInstallDirs pkg local copy
232 installStdLib = do
233 putStrLn $ "Installing libraries in " ++ target
234 makeInstall "libs" target
236 installRTS = do
237 let target' = target </> "rts"
238 putStrLn $ "Installing run time system in " ++ target'
239 makeInstall "rts" target'
241 makeInstall src target =
242 make verbosity [ "-C", src, "install" , "TARGET=" ++ target, "IDRIS=" ++ idrisCmd local]
244-- -----------------------------------------------------------------------------
245-- Main
247-- Install libraries during both copy and install
248-- See http://hackage.haskell.org/trac/hackage/ticket/718
249main = defaultMainWithHooks $ simpleUserHooks
250 { postClean = idrisClean
251 , postConf = idrisConfigure
252 , postBuild = idrisBuild
253 , postCopy = \_ flags pkg local ->
254 idrisInstall (S.fromFlag $ S.copyVerbosity flags)
255 (S.fromFlag $ S.copyDest flags) pkg local
256 , postInst = \_ flags pkg local ->
257 idrisInstall (S.fromFlag $ S.installVerbosity flags)
258 NoCopyDest pkg local
259 , preSDist = idrisPreSDist --do { putStrLn (show args) ; putStrLn (show flags) ; return emptyHookedBuildInfo }
260 , postSDist = idrisPostSDist
261 }