1 {-# LANGUAGE FlexibleContexts #-}
2 {-# LANGUAGE RankNTypes #-}
4 -----------------------------------------------------------------------------
7 -- Module : Distribution.Simple.UHC
8 -- Copyright : Andres Loeh 2009
11 -- Maintainer : cabal-devel@haskell.org
12 -- Portability : portable
14 -- This module contains most of the UHC-specific code for configuring, building
15 -- and installing packages.
17 -- Thanks to the authors of the other implementation-specific files, in
18 -- particular to Isaac Jones, Duncan Coutts and Henning Thielemann, for
19 -- inspiration on how to design this module.
20 module Distribution
.Simple
.UHC
22 , getInstalledPackages
27 , inplacePackageDbPath
30 import Distribution
.Compat
.Prelude
33 import Distribution
.InstalledPackageInfo
34 import Distribution
.Package
hiding (installedUnitId
)
35 import Distribution
.PackageDescription
36 import Distribution
.Parsec
37 import Distribution
.Pretty
38 import Distribution
.Simple
.BuildPaths
39 import Distribution
.Simple
.Compiler
40 import Distribution
.Simple
.LocalBuildInfo
41 import Distribution
.Simple
.PackageIndex
42 import Distribution
.Simple
.Program
43 import Distribution
.Simple
.Utils
44 import Distribution
.System
45 import Distribution
.Types
.MungedPackageId
46 import Distribution
.Utils
.Path
47 import Distribution
.Verbosity
48 import Distribution
.Version
49 import Language
.Haskell
.Extension
51 import qualified Data
.Map
as Map
(empty)
52 import System
.Directory
53 import System
.FilePath
55 -- -----------------------------------------------------------------------------
63 -> IO (Compiler
, Maybe Platform
, ProgramDb
)
64 configure verbosity hcPath _hcPkgPath progdb
= do
65 (_uhcProg
, uhcVersion
, progdb
') <-
69 (orLaterVersion
(mkVersion
[1, 0, 2]))
70 (userMaybeSpecifyPath
"uhc" hcPath progdb
)
74 { compilerId
= CompilerId UHC uhcVersion
75 , compilerAbiTag
= NoAbiTag
77 , compilerLanguages
= uhcLanguages
78 , compilerExtensions
= uhcLanguageExtensions
79 , compilerProperties
= Map
.empty
81 compPlatform
= Nothing
82 return (comp
, compPlatform
, progdb
')
84 uhcLanguages
:: [(Language
, CompilerFlag
)]
85 uhcLanguages
= [(Haskell98
, "")]
87 -- | The flags for the supported extensions.
88 uhcLanguageExtensions
:: [(Extension
, Maybe CompilerFlag
)]
89 uhcLanguageExtensions
=
90 let doFlag
(f
, (enable
, disable
)) =
91 [ (EnableExtension f
, enable
)
92 , (DisableExtension f
, disable
)
94 alwaysOn
= (Nothing
, Nothing
{- wrong -})
97 [ (CPP
, (Just
"--cpp", Nothing
{- wrong -}))
98 , (PolymorphicComponents
, alwaysOn
)
99 , (ExistentialQuantification
, alwaysOn
)
100 , (ForeignFunctionInterface
, alwaysOn
)
101 , (UndecidableInstances
, alwaysOn
)
102 , (MultiParamTypeClasses
, alwaysOn
)
103 , (Rank2Types
, alwaysOn
)
104 , (PatternSignatures
, alwaysOn
)
105 , (EmptyDataDecls
, alwaysOn
)
106 , (ImplicitPrelude
, (Nothing
, Just
"--no-prelude" {- wrong -}))
107 , (TypeOperators
, alwaysOn
)
108 , (OverlappingInstances
, alwaysOn
)
109 , (FlexibleInstances
, alwaysOn
)
117 -> IO InstalledPackageIndex
118 getInstalledPackages verbosity comp packagedbs progdb
= do
119 let compilerid
= compilerId comp
120 systemPkgDir
<- getGlobalPackageDir verbosity progdb
121 userPkgDir
<- getUserPackageDir
122 let pkgDirs
= nub (concatMap (packageDbPaths userPkgDir systemPkgDir
) packagedbs
)
123 -- putStrLn $ "pkgdirs: " ++ show pkgDirs
125 liftM (map addBuiltinVersions
. concat) $
127 (\d
-> getDirectoryContents d
>>= filterM (isPkgDir
(prettyShow compilerid
) d
))
129 -- putStrLn $ "pkgs: " ++ show pkgs
131 map mkInstalledPackageInfo
$
132 concatMap parsePackage
$
134 -- putStrLn $ "installed pkgs: " ++ show iPkgs
135 return (fromList iPkgs
)
137 getGlobalPackageDir
:: Verbosity
-> ProgramDb
-> IO FilePath
138 getGlobalPackageDir verbosity progdb
= do
144 ["--meta-pkgdir-system"]
145 -- we need to trim because pkgdir contains an extra newline at the end
146 let pkgdir
= trimEnd output
149 trimEnd
= dropWhileEnd
isSpace
151 getUserPackageDir
:: IO FilePath
152 getUserPackageDir
= do
153 homeDir
<- getHomeDirectory
154 return $ homeDir
</> ".cabal" </> "lib" -- TODO: determine in some other way
156 packageDbPaths
:: FilePath -> FilePath -> PackageDB
-> [FilePath]
157 packageDbPaths user
system db
=
159 GlobalPackageDB
-> [system]
160 UserPackageDB
-> [user
]
161 SpecificPackageDB path
-> [path
]
163 -- | Hack to add version numbers to UHC-built-in packages. This should sooner or
164 -- later be fixed on the UHC side.
165 addBuiltinVersions
:: String -> String
167 addBuiltinVersions "uhcbase" = "uhcbase-1.0"
168 addBuiltinVersions "base" = "base-3.0"
169 addBuiltinVersions "array" = "array-0.2"
171 addBuiltinVersions xs
= xs
173 -- | Name of the installed package config file.
174 installedPkgConfig
:: String
175 installedPkgConfig
= "installed-pkg-config"
177 -- | Check if a certain dir contains a valid package. Currently, we are
178 -- looking only for the presence of an installed package configuration.
179 -- TODO: Actually make use of the information provided in the file.
180 isPkgDir
:: String -> String -> String -> IO Bool
181 isPkgDir _ _
('.' : _
) = return False -- ignore files starting with a .
182 isPkgDir c dir xs
= do
183 let candidate
= dir
</> uhcPackageDir xs c
184 -- putStrLn $ "trying: " ++ candidate
185 doesFileExist (candidate
</> installedPkgConfig
)
187 parsePackage
:: String -> [PackageId
]
188 parsePackage
= toList
. simpleParsec
190 -- | Create a trivial package info from a directory name.
191 mkInstalledPackageInfo
:: PackageId
-> InstalledPackageInfo
192 mkInstalledPackageInfo p
=
193 emptyInstalledPackageInfo
194 { installedUnitId
= mkLegacyUnitId p
195 , sourcePackageId
= p
198 -- -----------------------------------------------------------------------------
203 -> PackageDescription
206 -> ComponentLocalBuildInfo
208 buildLib verbosity pkg_descr lbi lib clbi
= do
209 systemPkgDir
<- getGlobalPackageDir verbosity
(withPrograms lbi
)
210 userPkgDir
<- getUserPackageDir
211 let runUhcProg
= runDbProgram verbosity uhcProgram
(withPrograms lbi
)
214 ["--pkg-build=" ++ prettyShow
(packageId pkg_descr
)]
215 -- common flags lib/exe
216 ++ constructUHCCmdLine
225 -- suboptimal: UHC does not understand module names, so
226 -- we replace periods by path separators
228 (map (\c
-> if c
== '.' then pathSeparator
else c
))
229 (map prettyShow
(allLibModules lib clbi
))
237 -> PackageDescription
240 -> ComponentLocalBuildInfo
242 buildExe verbosity _pkg_descr lbi exe clbi
= do
243 systemPkgDir
<- getGlobalPackageDir verbosity
(withPrograms lbi
)
244 userPkgDir
<- getUserPackageDir
245 let runUhcProg
= runDbProgram verbosity uhcProgram
(withPrograms lbi
)
247 -- common flags lib/exe
257 ++ ["--output", buildDir lbi
</> prettyShow
(exeName exe
)]
258 -- main source module
267 -> ComponentLocalBuildInfo
271 constructUHCCmdLine user
system lbi bi clbi odir verbosity
=
273 ( if verbosity
>= deafening
276 if verbosity
>= normal
281 -- flags for language extensions
282 ++ languageToFlags
(compiler lbi
) (defaultLanguage bi
)
283 ++ extensionsToFlags
(compiler lbi
) (usedExtensions bi
)
285 ++ ["--hide-all-packages"]
286 ++ uhcPackageDbOptions user
system (withPackageDB lbi
)
287 ++ ["--package=uhcbase"]
288 ++ ["--package=" ++ prettyShow
(mungedName pkgid
) |
(_
, pkgid
) <- componentPackageDeps clbi
]
291 ++ ["-i" ++ getSymbolicPath l | l
<- nub (hsSourceDirs bi
)]
292 ++ ["-i" ++ autogenComponentModulesDir lbi clbi
]
293 ++ ["-i" ++ autogenPackageModulesDir lbi
]
295 ++ ["--optP=" ++ opt | opt
<- cppOptions bi
]
297 ++ ["--odir=" ++ odir
]
299 ++ ( case withOptimization lbi
of
300 NoOptimisation
-> ["-O0"]
301 NormalOptimisation
-> ["-O1"]
302 MaximumOptimisation
-> ["-O2"]
305 uhcPackageDbOptions
:: FilePath -> FilePath -> PackageDBStack
-> [String]
306 uhcPackageDbOptions user
system db
=
308 (\x
-> "--pkg-searchpath=" ++ x
)
309 (concatMap (packageDbPaths user
system) db
)
311 -- -----------------------------------------------------------------------------
320 -> PackageDescription
322 -> ComponentLocalBuildInfo
324 installLib verbosity _lbi targetDir _dynlibTargetDir builtDir pkg _library _clbi
= do
325 -- putStrLn $ "dest: " ++ targetDir
326 -- putStrLn $ "built: " ++ builtDir
327 installDirectoryContents verbosity
(builtDir
</> prettyShow
(packageId pkg
)) targetDir
329 -- currently hard-coded UHC code generator and variant to use
330 uhcTarget
, uhcTargetVariant
:: String
332 uhcTargetVariant
= "plain"
334 -- root directory for a package in UHC
335 uhcPackageDir
:: String -> String -> FilePath
336 uhcPackageSubDir
:: String -> FilePath
337 uhcPackageDir pkgid compilerid
= pkgid
</> uhcPackageSubDir compilerid
338 uhcPackageSubDir compilerid
= compilerid
</> uhcTarget
</> uhcTargetVariant
340 -- -----------------------------------------------------------------------------
348 -> InstalledPackageInfo
350 registerPackage verbosity comp progdb packageDbs installedPkgInfo
= do
351 dbdir
<- case registrationPackageDB packageDbs
of
352 GlobalPackageDB
-> getGlobalPackageDir verbosity progdb
353 UserPackageDB
-> getUserPackageDir
354 SpecificPackageDB dir
-> return dir
355 let pkgdir
= dbdir
</> uhcPackageDir
(prettyShow pkgid
) (prettyShow compilerid
)
356 createDirectoryIfMissingVerbose verbosity
True pkgdir
358 (pkgdir
</> installedPkgConfig
)
359 (showInstalledPackageInfo installedPkgInfo
)
361 pkgid
= sourcePackageId installedPkgInfo
362 compilerid
= compilerId comp
364 inplacePackageDbPath
:: LocalBuildInfo
-> FilePath
365 inplacePackageDbPath lbi
= buildDir lbi