1 -- This is Setup.hs script from idris-1.1.1
5 Copyright (c) 2011 Edwin Brady
6 School of Computer Science, University of St Andrews
9 This code is derived from software written by Edwin Brady
10 (eb@cs.st-andrews.ac.uk).
12 Redistribution and use in source and binary forms, with or without
13 modification, are permitted provided that the following conditions
15 1. Redistributions of source code must retain the above copyright
16 notice, this list of conditions and the following disclaimer.
17 2. Redistributions in binary form must reproduce the above copyright
18 notice, this list of conditions and the following disclaimer in the
19 documentation and/or other materials provided with the distribution.
20 3. None of the names of the copyright holders may be used to endorse
21 or promote products derived from this software without specific
22 prior written permission.
24 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
25 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
27 PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE
28 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
31 BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
33 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
34 IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *** End of disclaimer. ***
41 {-# OPTIONS_GHC -w #-}
42 module IdrisSetup
(main
) where
44 #if !defined
(MIN_VERSION_Cabal
)
45 # define MIN_VERSION_Cabal
(x
,y
,z
) 0
48 #if !defined
(MIN_VERSION_base
)
49 # define MIN_VERSION_base
(x
,y
,z
) 0
54 import Control
.Exception
(SomeException
, catch)
55 import Data
.String (fromString
)
57 import Distribution
.Simple
58 import Distribution
.Simple
.BuildPaths
59 import Distribution
.Simple
.InstallDirs
as I
60 import Distribution
.Simple
.LocalBuildInfo
as L
61 import qualified Distribution
.Simple
.Setup
as S
62 import qualified Distribution
.Simple
.Program
as P
63 import Distribution
.Simple
.Utils
(createDirectoryIfMissingVerbose
, notice
, installOrdinaryFiles
)
64 import Distribution
.Simple
.Utils
(rewriteFileEx
)
65 import Distribution
.Compiler
66 import Distribution
.PackageDescription
67 import Distribution
.Text
69 import System
.Environment
71 import System
.FilePath ((</>), splitDirectories
,isAbsolute
)
72 import System
.Directory
73 import qualified System
.FilePath.Posix
as Px
76 -- This is difference from vanilla idris-1.1.1
77 configConfigurationsFlags
:: S
.ConfigFlags
-> [(FlagName
, Bool)]
78 #if MIN_VERSION_Cabal
(2,1,0)
79 configConfigurationsFlags
= unFlagAssignment
. S
.configConfigurationsFlags
81 configConfigurationsFlags
= S
.configConfigurationsFlags
84 #if !MIN_VERSION_base
(4,6,0)
85 lookupEnv
:: String -> IO (Maybe String)
86 lookupEnv v
= lookup v `
fmap` getEnvironment
89 -- After Idris is built, we need to check and install the prelude and other libs
91 -- -----------------------------------------------------------------------------
94 -- make on mingw32 expects unix style separators
95 #ifdef mingw32_HOST_OS
97 idrisCmd local
= Px
.joinPath
$ splitDirectories
$ ".." <//> ".." <//> buildDir local
<//> "idris" <//> "idris"
99 idrisCmd local
= ".." </> ".." </> buildDir local
</> "idris" </> "idris"
102 -- -----------------------------------------------------------------------------
105 -- use GNU make on FreeBSD
106 #if defined
(freebsd_HOST_OS
) || defined
(dragonfly_HOST_OS
)\
107 || defined
(openbsd_HOST_OS
) || defined
(netbsd_HOST_OS
)
113 P
.runProgramInvocation verbosity
. P
.simpleProgramInvocation mymake
115 #ifdef mingw32_HOST_OS
116 windres verbosity
= P
.runProgramInvocation verbosity
. P
.simpleProgramInvocation
"windres"
118 -- -----------------------------------------------------------------------------
121 usesGMP
:: S
.ConfigFlags
-> Bool
123 case lookup (mkFlagName
"gmp") (configConfigurationsFlags flags
) of
128 execOnly
:: S
.ConfigFlags
-> Bool
130 case lookup (mkFlagName
"execonly") (configConfigurationsFlags flags
) of
135 isRelease
:: S
.ConfigFlags
-> Bool
137 case lookup (mkFlagName
"release") (configConfigurationsFlags flags
) of
142 isFreestanding
:: S
.ConfigFlags
-> Bool
143 isFreestanding flags
=
144 case lookup (mkFlagName
"freestanding") (configConfigurationsFlags flags
) of
149 #if !(MIN_VERSION_Cabal
(2,0,0))
150 mkFlagName
:: String -> FlagName
151 mkFlagName
= FlagName
154 -- -----------------------------------------------------------------------------
157 idrisClean _ flags _ _
= cleanStdLib
159 verbosity
= S
.fromFlag
$ S
.cleanVerbosity flags
161 cleanStdLib
= makeClean
"libs"
163 makeClean dir
= make verbosity
[ "-C", dir
, "clean", "IDRIS=idris" ]
165 -- -----------------------------------------------------------------------------
169 gitHash
= do h
<- Control
.Exception
.catch (readProcess
"git" ["rev-parse", "--short", "HEAD"] "")
170 (\e
-> let e
' = (e
:: SomeException
) in return "PRE")
171 return $ takeWhile (/= '\n') h
173 -- Put the Git hash into a module for use in the program
174 -- For release builds, just put the empty string in the module
175 generateVersionModule verbosity dir release
= do
177 let versionModulePath
= dir
</> "Version_idris" Px
.<.> "hs"
178 putStrLn $ "Generating " ++ versionModulePath
++
179 if release
then " for release" else " for prerelease " ++ hash
180 createDirectoryIfMissingVerbose verbosity
True dir
181 rewriteFileEx verbosity versionModulePath
(versionModuleContents hash
)
183 where versionModuleContents h
= "module Version_idris where\n\n" ++
184 "gitHash :: String\n" ++
186 then "gitHash = \"\"\n"
187 else "gitHash = \"git:" ++ h
++ "\"\n"
189 -- Generate a module that contains the lib path for a freestanding Idris
190 generateTargetModule verbosity dir targetDir
= do
191 let absPath
= isAbsolute targetDir
192 let targetModulePath
= dir
</> "Target_idris" Px
.<.> "hs"
193 putStrLn $ "Generating " ++ targetModulePath
194 createDirectoryIfMissingVerbose verbosity
True dir
195 rewriteFileEx verbosity targetModulePath
(versionModuleContents absPath targetDir
)
196 where versionModuleContents
absolute td
= "module Target_idris where\n\n" ++
197 "import System.FilePath\n" ++
198 "import System.Environment\n" ++
199 "getDataDir :: IO String\n" ++
201 then "getDataDir = return \"" ++ td
++ "\"\n"
202 else "getDataDir = do \n" ++
203 " expath <- getExecutablePath\n" ++
204 " execDir <- return $ dropFileName expath\n" ++
205 " return $ execDir ++ \"" ++ td
++ "\"\n"
206 ++ "getDataFileName :: FilePath -> IO FilePath\n"
207 ++ "getDataFileName name = do\n"
208 ++ " dir <- getDataDir\n"
209 ++ " return (dir ++ \"/\" ++ name)"
211 -- a module that has info about existence and location of a bundled toolchain
212 generateToolchainModule verbosity srcDir toolDir
= do
213 let commonContent
= "module Tools_idris where\n\n"
214 let toolContent
= case toolDir
of
215 Just dir
-> "hasBundledToolchain = True\n" ++
216 "getToolchainDir = \"" ++ dir
++ "\"\n"
217 Nothing
-> "hasBundledToolchain = False\n" ++
218 "getToolchainDir = \"\""
219 let toolPath
= srcDir
</> "Tools_idris" Px
.<.> "hs"
220 createDirectoryIfMissingVerbose verbosity
True srcDir
221 rewriteFileEx verbosity toolPath
(commonContent
++ toolContent
)
223 idrisConfigure _ flags pkgdesc local
= do
225 withLibLBI pkgdesc local
$ \_ libcfg
-> do
226 let libAutogenDir
= autogenComponentModulesDir local libcfg
227 generateVersionModule verbosity libAutogenDir
(isRelease
(configFlags local
))
228 if isFreestanding
$ configFlags local
230 toolDir
<- lookupEnv
"IDRIS_TOOLCHAIN_DIR"
231 generateToolchainModule verbosity libAutogenDir toolDir
232 targetDir
<- lookupEnv
"IDRIS_LIB_DIR"
234 Just d
-> generateTargetModule verbosity libAutogenDir d
235 Nothing
-> error $ "Trying to build freestanding without a target directory."
236 ++ " Set it by defining IDRIS_LIB_DIR."
238 generateToolchainModule verbosity libAutogenDir Nothing
240 verbosity
= S
.fromFlag
$ S
.configVerbosity flags
241 version
= pkgVersion
. package
$ localPkgDescr local
243 -- This is a hack. I don't know how to tell cabal that a data file needs
244 -- installing but shouldn't be in the distribution. And it won't make the
245 -- distribution if it's not there, so instead I just delete
246 -- the file after configure.
247 configureRTS
= make verbosity
["-C", "rts", "clean"]
249 #if !(MIN_VERSION_Cabal
(2,0,0))
250 autogenComponentModulesDir lbi _
= autogenModulesDir lbi
253 #if !MIN_VERSION_Cabal
(3,0,0)
254 idrisPreSDist args flags
= do
255 let dir
= S
.fromFlag
(S
.sDistDirectory flags
)
256 let verb
= S
.fromFlag
(S
.sDistVerbosity flags
)
257 generateVersionModule verb
"src" True
258 generateTargetModule verb
"src" "./libs"
259 generateToolchainModule verb
"src" Nothing
260 preSDist simpleUserHooks args flags
262 idrisSDist sdist pkgDesc bi hooks flags
= do
263 pkgDesc
' <- addGitFiles pkgDesc
264 sdist pkgDesc
' bi hooks flags
266 addGitFiles
:: PackageDescription
-> IO PackageDescription
267 addGitFiles pkgDesc
= do
269 return $ pkgDesc
{ extraSrcFiles
= extraSrcFiles pkgDesc
++ files
}
270 gitFiles
:: IO [FilePath]
271 gitFiles
= liftM lines (readProcess
"git" ["ls-files"] "")
273 idrisPostSDist args flags desc lbi
= do
274 Control
.Exception
.catch (do let file
= "src" </> "Version_idris" Px
.<.> "hs"
275 let targetFile
= "src" </> "Target_idris" Px
.<.> "hs"
276 putStrLn $ "Removing generated modules:\n "
277 ++ file
++ "\n" ++ targetFile
279 removeFile targetFile
)
280 (\e
-> let e
' = (e
:: SomeException
) in return ())
281 postSDist simpleUserHooks args flags desc lbi
284 -- -----------------------------------------------------------------------------
287 getVersion
:: Args
-> S
.BuildFlags
-> IO HookedBuildInfo
288 getVersion args flags
= do
290 let buildinfo
= (emptyBuildInfo
{ cppOptions
= ["-DVERSION="++hash
] }) :: BuildInfo
291 return (Just buildinfo
, [])
293 idrisPreBuild args flags
= do
294 #ifdef mingw32_HOST_OS
295 createDirectoryIfMissingVerbose verbosity
True dir
296 windres verbosity
["icons/idris_icon.rc","-o", dir
++"/idris_icon.o"]
297 return (Nothing
, [(fromString
"idris", emptyBuildInfo
{ ldOptions
= [dir
++ "/idris_icon.o"] })])
299 verbosity
= S
.fromFlag
$ S
.buildVerbosity flags
300 dir
= S
.fromFlagOrDefault
"dist" $ S
.buildDistPref flags
305 idrisBuild _ flags _ local
306 = if (execOnly
(configFlags local
)) then buildRTS
310 verbosity
= S
.fromFlag
$ S
.buildVerbosity flags
313 putStrLn "Building libraries..."
316 makeBuild dir
= make verbosity
[ "-C", dir
, "build" , "IDRIS=" ++ idrisCmd local
]
318 buildRTS
= make verbosity
(["-C", "rts", "build"] ++
319 gmpflag
(usesGMP
(configFlags local
)))
322 gmpflag
True = ["GMP=-DIDRIS_GMP"]
324 -- -----------------------------------------------------------------------------
327 idrisInstall verbosity copy pkg local
328 = if (execOnly
(configFlags local
)) then installRTS
329 else do installStdLib
333 target
= datadir
$ L
.absoluteInstallDirs pkg local copy
336 let target
' = target
-- </> "libs"
337 putStrLn $ "Installing libraries in " ++ target
'
338 makeInstall
"libs" target
'
341 let target
' = target
</> "rts"
342 putStrLn $ "Installing run time system in " ++ target
'
343 makeInstall
"rts" target
'
346 let mandest
= mandir
(L
.absoluteInstallDirs pkg local copy
) ++ "/man1"
347 notice verbosity
$ unwords ["Copying man page to", mandest
]
348 installOrdinaryFiles verbosity mandest
[("man", "idris.1")]
350 makeInstall src target
=
351 make verbosity
[ "-C", src
, "install" , "TARGET=" ++ target
, "IDRIS=" ++ idrisCmd local
]
353 -- -----------------------------------------------------------------------------
356 -- There are two "dataDir" in cabal, and they don't relate to each other.
357 -- When fetching modules, idris uses the second path (in the pkg record),
358 -- which by default is the root folder of the project.
359 -- We want it to be the install directory where we put the idris libraries.
360 fixPkg pkg target
= pkg
{ dataDir
= target
}
362 idrisTestHook args pkg local hooks flags
= do
363 let target
= datadir
$ L
.absoluteInstallDirs pkg local NoCopyDest
364 testHook simpleUserHooks args
(fixPkg pkg target
) local hooks flags
366 -- -----------------------------------------------------------------------------
369 -- Install libraries during both copy and install
370 -- See https://github.com/haskell/cabal/issues/709
371 main
= defaultMainWithHooks
$ simpleUserHooks
372 { postClean
= idrisClean
373 , postConf
= idrisConfigure
374 , preBuild
= idrisPreBuild
375 , postBuild
= idrisBuild
376 , postCopy
= \_ flags pkg local
->
377 idrisInstall
(S
.fromFlag
$ S
.copyVerbosity flags
)
378 (S
.fromFlag
$ S
.copyDest flags
) pkg local
379 , postInst
= \_ flags pkg local
->
380 idrisInstall
(S
.fromFlag
$ S
.installVerbosity flags
)
382 #if !MIN_VERSION_Cabal
(3,0,0)
383 , preSDist
= idrisPreSDist
384 , sDistHook
= idrisSDist
(sDistHook simpleUserHooks
)
385 , postSDist
= idrisPostSDist
387 , testHook
= idrisTestHook