1 module Distribution
.Client
.CmdHaddockProject
2 ( haddockProjectCommand
6 import Control
.Monad
(mapM)
7 import Distribution
.Client
.Compat
.Prelude
hiding (get
)
10 import qualified Distribution
.Client
.CmdBuild
as CmdBuild
11 import qualified Distribution
.Client
.CmdHaddock
as CmdHaddock
13 import Distribution
.Client
.DistDirLayout
18 import Distribution
.Client
.InstallPlan
(foldPlanPackage
)
19 import qualified Distribution
.Client
.InstallPlan
as InstallPlan
20 import qualified Distribution
.Client
.NixStyleOptions
as NixStyleOptions
21 import Distribution
.Client
.ProjectOrchestration
22 ( AvailableTarget
(..)
23 , AvailableTargetStatus
(..)
25 , ProjectBaseContext
(..)
26 , ProjectBuildContext
(..)
28 , pruneInstallPlanToTargets
30 , runProjectPreBuildPhase
31 , selectComponentTargetBasic
33 import Distribution
.Client
.ProjectPlanning
34 ( ElaboratedConfiguredPackage
(..)
35 , ElaboratedInstallPlan
36 , ElaboratedSharedConfig
(..)
39 import Distribution
.Client
.ProjectPlanning
.Types
42 import Distribution
.Client
.ScriptUtils
43 ( AcceptNoTargets
(..)
45 , updateContextAndWriteProjectFile
46 , withContextAndSelectors
48 import Distribution
.Client
.Setup
49 ( CommonSetupFlags
(setupVerbosity
)
53 import Distribution
.Client
.TargetProblem
(TargetProblem
(..))
55 import Distribution
.Simple
.BuildPaths
56 ( haddockBenchmarkDirPath
58 , haddockLibraryDirPath
63 import Distribution
.Simple
.Command
66 import Distribution
.Simple
.Flag
71 import Distribution
.Simple
.Haddock
(createHaddockIndex
)
72 import Distribution
.Simple
.InstallDirs
75 import Distribution
.Simple
.Program
.Builtin
78 import Distribution
.Simple
.Program
.Db
81 , requireProgramVersion
83 import Distribution
.Simple
.Setup
85 , HaddockProjectFlags
(..)
89 , haddockProjectCommand
91 import Distribution
.Simple
.Utils
92 ( copyDirectoryRecursive
93 , createDirectoryIfMissingVerbose
98 import Distribution
.Types
.InstalledPackageInfo
(InstalledPackageInfo
(..))
99 import Distribution
.Types
.PackageDescription
(PackageDescription
(benchmarks
, subLibraries
, testSuites
))
100 import Distribution
.Types
.PackageId
(pkgName
)
101 import Distribution
.Types
.PackageName
(unPackageName
)
102 import Distribution
.Types
.UnitId
(unUnitId
)
103 import Distribution
.Types
.Version
(mkVersion
)
104 import Distribution
.Types
.VersionRange
(orLaterVersion
)
105 import Distribution
.Verbosity
as Verbosity
109 import Distribution
.Client
.Errors
110 import System
.Directory
(doesDirectoryExist, doesFileExist)
111 import System
.FilePath (normalise
, takeDirectory
, (</>))
113 haddockProjectAction
:: HaddockProjectFlags
-> [String] -> GlobalFlags
-> IO ()
114 haddockProjectAction flags _extraArgs globalFlags
= do
115 -- create destination directory if it does not exist
116 let outputDir
= normalise
$ fromFlag
(haddockProjectDir flags
)
117 createDirectoryIfMissingVerbose verbosity
True outputDir
119 warn verbosity
"haddock-project command is experimental, it might break in the future"
122 -- Construct the build plan and infer the list of packages which haddocks
126 withContextAndSelectors
129 (commandDefaultFlags CmdBuild
.buildCommand
)
133 $ \targetCtx ctx targetSelectors
-> do
134 baseCtx
<- case targetCtx
of
135 ProjectContext
-> return ctx
136 GlobalContext
-> return ctx
137 ScriptContext path exemeta
-> updateContextAndWriteProjectFile ctx path exemeta
138 let distLayout
= distDirLayout baseCtx
139 cabalLayout
= cabalDirLayout baseCtx
141 runProjectPreBuildPhase verbosity baseCtx
$ \elaboratedPlan
-> do
142 -- Interpret the targets on the command line as build targets
143 -- (as opposed to say repl or haddock targets).
145 either reportTargetProblems
return $
148 selectComponentTargetBasic
153 let elaboratedPlan
' =
154 pruneInstallPlanToTargets
158 return (elaboratedPlan
', targets
)
160 let elaboratedPlan
:: ElaboratedInstallPlan
161 elaboratedPlan
= elaboratedPlanOriginal buildCtx
163 sharedConfig
:: ElaboratedSharedConfig
164 sharedConfig
= elaboratedShared buildCtx
166 pkgs
:: [Either InstalledPackageInfo ElaboratedConfiguredPackage
]
167 pkgs
= matchingPackages elaboratedPlan
172 (haddockProjectProgramPaths flags
)
173 (haddockProjectProgramArgs flags
)
174 -- we need to insert 'haddockProgram' before we reconfigure it,
176 . addKnownProgram haddockProgram
177 . pkgConfigCompilerProgs
179 let sharedConfig
' = sharedConfig
{pkgConfigCompilerProgs
= progs
}
182 requireProgramVersion
185 (orLaterVersion
(mkVersion
[2, 26, 1]))
189 -- Build project; we need to build dependencies.
195 (commandDefaultFlags CmdBuild
.buildCommand
)
200 -- Build haddocks of each components
203 CmdHaddock
.haddockAction
209 -- Copy haddocks to the destination folder
212 packageInfos
<- fmap (nub . concat) $ for pkgs
$ \pkg
->
214 Left package | localStyle
-> do
215 let packageName
= unPackageName
(pkgName
$ sourcePackageId package
)
216 destDir
= outputDir
</> packageName
217 fmap catMaybes $ for
(haddockInterfaces package
) $ \interfacePath
-> do
218 let docDir
= takeDirectory interfacePath
219 a
<- doesFileExist interfacePath
222 copyDirectoryRecursive verbosity docDir destDir
223 return $ Just
$ Right
(packageName
, interfacePath
, Hidden
)
224 False -> return Nothing
227 case elabLocalToProject package
of
229 let distDirParams
= elabDistDirParams sharedConfig
' package
230 pkg_descr
= elabPkgDescription package
232 packageName
= pkgName
$ elabPkgSourceId package
233 unitId
= elabUnitId package
234 packageDir
= haddockDirName ForDevelopment pkg_descr
235 destDir
= outputDir
</> packageDir
236 interfacePath
= destDir
</> haddockPath pkg_descr
238 buildDir
= distBuildDirectory distLayout distDirParams
245 a
<- doesDirectoryExist docDir
248 copyDirectoryRecursive verbosity docDir destDir
249 let infos
:: [(String, FilePath, Visibility
)]
251 (unPackageName packageName
, interfacePath
, Visible
)
252 : [ (sublibDirPath
, sublibInterfacePath
, Visible
)
253 | lib
<- subLibraries pkg_descr
254 , let sublibDirPath
= haddockLibraryDirPath ForDevelopment pkg_descr lib
255 sublibInterfacePath
=
258 </> haddockLibraryPath pkg_descr lib
260 ++ [ (testPath
, testInterfacePath
, Visible
)
261 | test
<- testSuites pkg_descr
262 , let testPath
= haddockTestDirPath ForDevelopment pkg_descr test
266 </> haddockPath pkg_descr
268 ++ [ (benchPath
, benchInterfacePath
, Visible
)
269 | bench
<- benchmarks pkg_descr
270 , let benchPath
= haddockBenchmarkDirPath ForDevelopment pkg_descr bench
274 </> haddockPath pkg_descr
278 ( \x
@(_
, path
, _
) -> do
279 e
<- doesFileExist path
292 ++ " not found in the store"
299 let pkg_descr
= elabPkgDescription package
300 unitId
= unUnitId
(elabUnitId package
)
302 storePackageDirectory
303 (cabalStoreDirLayout cabalLayout
)
304 (pkgConfigCompiler sharedConfig
')
306 -- TODO: use `InstallDirTemplates`
307 docDir
= packageDir
</> "share" </> "doc" </> "html"
308 destDir
= outputDir
</> haddockDirName ForDevelopment pkg_descr
309 interfacePath
= destDir
</> haddockPath pkg_descr
310 a
<- doesDirectoryExist docDir
313 copyDirectoryRecursive verbosity docDir destDir
314 -- non local packages will be hidden in haddock's
315 -- generated contents page
316 return [Right
(unitId
, interfacePath
, Hidden
)]
321 -- generate index, content, etc.
324 let (missingHaddocks
, packageInfos
') = partitionEithers packageInfos
325 when (not (null missingHaddocks
)) $ do
326 warn verbosity
"missing haddocks for some packages from the store"
327 -- Show the package list if `-v1` is passed; it's usually a long list.
328 -- One needs to add `package` stantza in `cabal.project` file for
329 -- `cabal` to include a version which has haddocks (or set
330 -- `documentation: True` in the global config).
331 info verbosity
(intercalate
"\n" missingHaddocks
)
335 { haddockProjectDir
= Flag outputDir
336 , haddockProjectInterfaces
=
343 |
(url
, interfacePath
, visibility
) <- packageInfos
'
345 , haddockProjectUseUnicode
= NoFlag
349 (pkgConfigCompilerProgs sharedConfig
')
350 (pkgConfigCompiler sharedConfig
')
351 (pkgConfigPlatform sharedConfig
')
355 -- build all packages with appropriate haddock flags
356 commonFlags
= haddockProjectCommonFlags flags
358 verbosity
= fromFlagOrDefault normal
(setupVerbosity commonFlags
)
362 { haddockCommonFlags
= commonFlags
363 , haddockHtml
= Flag
True
364 , -- one can either use `--haddock-base-url` or
365 -- `--haddock-html-location`.
370 , haddockProgramPaths
= haddockProjectProgramPaths flags
371 , haddockProgramArgs
= haddockProjectProgramArgs flags
372 , haddockHtmlLocation
=
373 if fromFlagOrDefault
False (haddockProjectHackage flags
)
374 then Flag
"https://hackage.haskell.org/package/$pkg-$version/docs"
375 else haddockProjectHtmlLocation flags
376 , haddockHoogle
= haddockProjectHoogle flags
377 , haddockExecutables
= haddockProjectExecutables flags
378 , haddockTestSuites
= haddockProjectTestSuites flags
379 , haddockBenchmarks
= haddockProjectBenchmarks flags
380 , haddockForeignLibs
= haddockProjectForeignLibs flags
381 , haddockInternal
= haddockProjectInternal flags
382 , haddockCss
= haddockProjectCss flags
383 , haddockLinkedSource
= Flag
True
384 , haddockQuickJump
= Flag
True
385 , haddockHscolourCss
= haddockProjectHscolourCss flags
388 then Flag
(toPathTemplate
"../index.html")
392 then Flag
(toPathTemplate
"../doc-index.html")
394 , haddockResourcesDir
= haddockProjectResourcesDir flags
395 , haddockUseUnicode
= haddockProjectUseUnicode flags
396 -- NOTE: we don't pass `haddockOutputDir`. If we do, we'll need to
397 -- make sure `InstalledPackageInfo` contains the right path to
398 -- haddock interfaces. Instead we build documentation inside
399 -- `dist-newstyle` directory and copy it to the output directory.
403 (commandDefaultFlags CmdHaddock
.haddockCommand
)
404 { NixStyleOptions
.haddockFlags
= haddockFlags
405 , NixStyleOptions
.configFlags
=
406 (NixStyleOptions
.configFlags
(commandDefaultFlags CmdBuild
.buildCommand
))
407 { configCommonFlags
= commonFlags
411 -- Build a self contained directory which contains haddocks of all
412 -- transitive dependencies; or depend on `--haddocks-html-location` to
413 -- provide location of the documentation of dependencies.
415 let hackage
= fromFlagOrDefault
False (haddockProjectHackage flags
)
416 location
= fromFlagOrDefault
False (const True <$> haddockProjectHtmlLocation flags
)
417 in not hackage
&& not location
419 reportTargetProblems
:: Show x
=> [x
] -> IO a
420 reportTargetProblems
=
421 dieWithException verbosity
. CmdHaddockReportTargetProblems
. map show
423 -- TODO: this is just a sketch
426 -> [AvailableTarget k
]
427 -> Either (TargetProblem
()) [k
]
428 selectPackageTargets _ ts
=
431 ( \t -> case availableTargetStatus t
of
433 | availableTargetLocalToProject t
->
440 :: ElaboratedInstallPlan
441 -> [Either InstalledPackageInfo ElaboratedConfiguredPackage
]
443 fmap (foldPlanPackage Left Right
)