1 {-# LANGUAGE FlexibleContexts #-}
2 {-# LANGUAGE RankNTypes #-}
4 module Distribution
.Simple
.HaskellSuite
where
6 import Distribution
.Compat
.Prelude
9 import qualified Data
.List
.NonEmpty
as NE
11 import Distribution
.InstalledPackageInfo
hiding (includeDirs
)
12 import Distribution
.Package
13 import Distribution
.PackageDescription
14 import Distribution
.Parsec
(simpleParsec
)
15 import Distribution
.Pretty
16 import Distribution
.Simple
.BuildPaths
17 import Distribution
.Simple
.Compiler
18 import Distribution
.Simple
.Errors
19 import Distribution
.Simple
.LocalBuildInfo
20 import Distribution
.Simple
.PackageIndex
as PackageIndex
21 import Distribution
.Simple
.Program
22 import Distribution
.Simple
.Program
.Builtin
23 import Distribution
.Simple
.Utils
24 import Distribution
.System
(Platform
)
25 import Distribution
.Utils
.Path
26 import Distribution
.Verbosity
27 import Distribution
.Version
28 import Language
.Haskell
.Extension
35 -> IO (Compiler
, Maybe Platform
, ProgramDb
)
36 configure verbosity mbHcPath hcPkgPath progdb0
= do
37 -- We have no idea how a haskell-suite tool is named, so we require at
38 -- least some information from the user.
40 let msg
= "You have to provide name or path of a haskell-suite tool (-w PATH)"
41 in maybe (dieWithException verbosity
$ ProvideHaskellSuiteTool msg
) return mbHcPath
43 when (isJust hcPkgPath
) $
44 warn verbosity
"--with-hc-pkg option is ignored for haskell-suite"
46 (comp
, confdCompiler
, progdb1
) <- configureCompiler hcPath progdb0
48 -- Update our pkg tool. It uses the same executable as the compiler, but
49 -- all command start with "pkg"
50 (confdPkg
, _
) <- requireProgram verbosity haskellSuitePkgProgram progdb1
54 { programLocation
= programLocation confdCompiler
55 , programDefaultArgs
= ["pkg"]
59 return (comp
, Nothing
, progdb2
)
61 configureCompiler hcPath progdb0
' = do
63 haskellSuiteProgram
' =
65 { programFindLocation
= \v p
-> findProgramOnSearchPath v p hcPath
68 -- NB: cannot call requireProgram right away — it'd think that
69 -- the program is already configured and won't reconfigure it again.
70 -- Instead, call configureProgram directly first.
71 progdb1
<- configureProgram verbosity haskellSuiteProgram
' progdb0
'
72 (confdCompiler
, progdb2
) <- requireProgram verbosity haskellSuiteProgram
' progdb1
74 extensions
<- getExtensions verbosity confdCompiler
75 languages
<- getLanguages verbosity confdCompiler
76 (compName
, compVersion
) <-
77 getCompilerVersion verbosity confdCompiler
82 { compilerId
= CompilerId
(HaskellSuite compName
) compVersion
83 , compilerAbiTag
= NoAbiTag
85 , compilerLanguages
= languages
86 , compilerExtensions
= extensions
87 , compilerProperties
= mempty
90 return (comp
, confdCompiler
, progdb2
)
92 hstoolVersion
:: Verbosity
-> FilePath -> IO (Maybe Version
)
93 hstoolVersion
= findProgramVersion
"--hspkg-version" id
95 numericVersion
:: Verbosity
-> FilePath -> IO (Maybe Version
)
96 numericVersion
= findProgramVersion
"--compiler-version" (fromMaybe "" . safeLast
. words)
98 getCompilerVersion
:: Verbosity
-> ConfiguredProgram
-> IO (String, Version
)
99 getCompilerVersion verbosity prog
= do
100 output
<- rawSystemStdout verbosity
(programPath prog
) ["--compiler-version"]
103 name
= concat $ safeInit parts
-- there shouldn't be any spaces in the name anyway
104 versionStr
= fromMaybe "" $ safeLast parts
107 (dieWithException verbosity CannotDetermineCompilerVersion
)
109 $ simpleParsec versionStr
110 return (name
, version
)
112 getExtensions
:: Verbosity
-> ConfiguredProgram
-> IO [(Extension
, Maybe CompilerFlag
)]
113 getExtensions verbosity prog
= do
116 `
fmap` rawSystemStdout verbosity
(programPath prog
) ["--supported-extensions"]
118 [(ext
, Just
$ "-X" ++ prettyShow ext
) | Just ext
<- map simpleParsec extStrs
]
120 getLanguages
:: Verbosity
-> ConfiguredProgram
-> IO [(Language
, CompilerFlag
)]
121 getLanguages verbosity prog
= do
124 `
fmap` rawSystemStdout verbosity
(programPath prog
) ["--supported-languages"]
126 [(ext
, "-G" ++ prettyShow ext
) | Just ext
<- map simpleParsec langStrs
]
128 -- Other compilers do some kind of a packagedb stack check here. Not sure
129 -- if we need something like that as well.
134 -> IO InstalledPackageIndex
135 getInstalledPackages verbosity packagedbs progdb
=
136 liftM (PackageIndex
.fromList
. concat) $ for packagedbs
$ \packagedb
->
141 haskellSuitePkgProgram
143 ["dump", packageDbOpt packagedb
]
144 `catchExit`
\_
-> dieWithException verbosity PkgDumpFailed
146 case parsePackages str
of
147 Right ok
-> return ok
148 _
-> dieWithException verbosity FailedToParseOutput
151 case partitionEithers
$ map (parseInstalledPackageInfo
. toUTF8BS
) (splitPkgs str
) of
152 ([], ok
) -> Right
[pkg |
(_
, pkg
) <- ok
]
153 (msgss
, _
) -> Left
(foldMap NE
.toList msgss
)
155 splitPkgs
:: String -> [String]
156 splitPkgs
= map unlines . splitWith
("---" ==) . lines
158 splitWith
:: (a
-> Bool) -> [a
] -> [[a
]]
162 _
: ws
-> splitWith p ws
164 (ys
, zs
) = break p xs
168 -> PackageDescription
171 -> ComponentLocalBuildInfo
173 buildLib verbosity pkg_descr lbi lib clbi
= do
174 -- In future, there should be a mechanism for the compiler to request any
175 -- number of the above parameters (or their parts) — in particular,
176 -- pieces of PackageDescription.
178 -- For now, we only pass those that we know are used.
180 let odir
= buildDir lbi
181 bi
= libBuildInfo lib
182 srcDirs
= map getSymbolicPath
(hsSourceDirs bi
) ++ [odir
]
183 dbStack
= withPackageDB lbi
184 language
= fromMaybe Haskell98
(defaultLanguage bi
)
185 progdb
= withPrograms lbi
186 pkgid
= packageId pkg_descr
188 runDbProgram verbosity haskellSuiteProgram progdb
$
189 ["compile", "--build-dir", odir
]
190 ++ concat [["-i", d
] | d
<- srcDirs
]
194 [ autogenComponentModulesDir lbi clbi
195 , autogenPackageModulesDir lbi
200 ++ [packageDbOpt pkgDb | pkgDb
<- dbStack
]
201 ++ ["--package-name", prettyShow pkgid
]
203 [ ["--package-id", prettyShow ipkgid
]
204 |
(ipkgid
, _
) <- componentPackageDeps clbi
206 ++ ["-G", prettyShow language
]
207 ++ concat [["-X", prettyShow ex
] | ex
<- usedExtensions bi
]
208 ++ cppOptions
(libBuildInfo lib
)
209 ++ [prettyShow modu | modu
<- allLibModules lib clbi
]
215 -- ^ install location
217 -- ^ install location for dynamic libraries
220 -> PackageDescription
222 -> ComponentLocalBuildInfo
224 installLib verbosity lbi targetDir dynlibTargetDir builtDir pkg lib clbi
= do
225 let progdb
= withPrograms lbi
226 runDbProgram verbosity haskellSuitePkgProgram progdb
$
232 , "--dynlib-target-dir"
235 , prettyShow
$ packageId pkg
237 ++ map prettyShow
(allLibModules lib clbi
)
243 -> InstalledPackageInfo
245 registerPackage verbosity progdb packageDbs installedPkgInfo
= do
246 (hspkg
, _
) <- requireProgram verbosity haskellSuitePkgProgram progdb
248 runProgramInvocation verbosity
$
251 ["update", packageDbOpt
$ registrationPackageDB packageDbs
]
253 { progInvokeInput
= Just
$ IODataText
$ showInstalledPackageInfo installedPkgInfo
256 initPackageDB
:: Verbosity
-> ProgramDb
-> FilePath -> IO ()
257 initPackageDB verbosity progdb dbPath
=
260 haskellSuitePkgProgram
264 packageDbOpt
:: PackageDB
-> String
265 packageDbOpt GlobalPackageDB
= "--global"
266 packageDbOpt UserPackageDB
= "--user"
267 packageDbOpt
(SpecificPackageDB db
) = "--package-db=" ++ db