1 module Distribution
.Client
.CmdHaddockProject
2 ( haddockProjectCommand
7 import Data
.Bool (bool
)
8 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
(DistDirLayout
(..)
16 import Distribution
.Client
.InstallPlan
(foldPlanPackage
)
17 import qualified Distribution
.Client
.InstallPlan
as InstallPlan
18 import qualified Distribution
.Client
.NixStyleOptions
as NixStyleOptions
19 import Distribution
.Client
.ProjectOrchestration
21 ,AvailableTargetStatus
(..)
23 ,ProjectBaseContext
(..)
24 ,ProjectBuildContext
(..)
27 ,pruneInstallPlanToTargets
29 ,runProjectPreBuildPhase
30 ,selectComponentTargetBasic
)
31 import Distribution
.Client
.ProjectPlanning
(ElaboratedConfiguredPackage
(..)
32 ,ElaboratedInstallPlan
33 ,ElaboratedSharedConfig
(..)
35 import Distribution
.Client
.ProjectPlanning
.Types
37 import Distribution
.Client
.Setup
(GlobalFlags
(..)
39 import Distribution
.Client
.ScriptUtils
(AcceptNoTargets
(..)
41 ,updateContextAndWriteProjectFile
42 ,withContextAndSelectors
)
43 import Distribution
.Client
.TargetProblem
(TargetProblem
(..))
45 import Distribution
.Types
.PackageId
(pkgName
)
46 import Distribution
.Types
.PackageName
(unPackageName
)
47 import Distribution
.Types
.Version
(mkVersion
)
48 import Distribution
.Types
.VersionRange
(orLaterVersion
)
49 import Distribution
.Types
.InstalledPackageInfo
(InstalledPackageInfo
(..))
50 import Distribution
.Simple
.Command
52 import Distribution
.Simple
.Compiler
54 import Distribution
.Simple
.Flag
61 import Distribution
.Simple
.InstallDirs
63 import Distribution
.Simple
.Haddock
(createHaddockIndex
)
64 import Distribution
.Simple
.Utils
65 ( die
', createDirectoryIfMissingVerbose
66 , copyDirectoryRecursive
, warn
)
67 import Distribution
.Simple
.Program
.Builtin
69 import Distribution
.Simple
.Program
.Db
70 ( addKnownProgram
, reconfigurePrograms
, requireProgramVersion
)
71 import Distribution
.Simple
.Setup
72 ( HaddockFlags
(..), defaultHaddockFlags
73 , HaddockProjectFlags
(..)
75 , haddockProjectCommand
77 import Distribution
.Verbosity
as Verbosity
80 import System
.FilePath ( takeDirectory
, normalise
, (</>), (<.>) )
81 import System
.Directory
( doesDirectoryExist, doesFileExist )
83 haddockProjectAction
:: HaddockProjectFlags
-> [String] -> GlobalFlags
-> IO ()
84 haddockProjectAction flags _extraArgs globalFlags
= do
85 -- create destination directory if it does not exist
86 let outputDir
= normalise
$ fromFlag
(haddockProjectDir flags
)
87 createDirectoryIfMissingVerbose verbosity
True outputDir
90 ( flagElim
0 (bool
0 1) (haddockProjectHackage flags
)
91 + flagElim
0 (bool
0 1) (haddockProjectLocal flags
)
92 + flagElim
0 (const 1) (haddockProjectHtmlLocation flags
)
94 die
' verbosity
"Options `--local`, `--hackage` and `--html-location` are mutually exclusive`"
96 warn verbosity
"haddock-project command is experimental, it might break in the future"
98 -- build all packages with appropriate haddock flags
99 let haddockFlags
= defaultHaddockFlags
100 { haddockHtml
= Flag
True
101 -- one can either use `--haddock-base-url` or
102 -- `--haddock-html-location`.
103 , haddockBaseUrl
= if localStyle
106 , haddockProgramPaths
= haddockProjectProgramPaths flags
107 , haddockProgramArgs
= haddockProjectProgramArgs flags
108 , haddockHtmlLocation
= if fromFlagOrDefault
False (haddockProjectHackage flags
)
109 then Flag
"https://hackage.haskell.org/package/$pkg-$version/docs"
110 else haddockProjectHtmlLocation flags
111 , haddockHoogle
= haddockProjectHoogle flags
112 , haddockExecutables
= haddockProjectExecutables flags
113 , haddockTestSuites
= haddockProjectTestSuites flags
114 , haddockBenchmarks
= haddockProjectBenchmarks flags
115 , haddockForeignLibs
= haddockProjectForeignLibs flags
116 , haddockInternal
= haddockProjectInternal flags
117 , haddockCss
= haddockProjectCss flags
118 , haddockLinkedSource
= if localOrHackage
120 else haddockProjectLinkedSource flags
121 , haddockQuickJump
= if localOrHackage
123 else haddockProjectQuickJump flags
124 , haddockHscolourCss
= haddockProjectHscolourCss flags
125 , haddockContents
= if localStyle
then Flag
(toPathTemplate
"../index.html")
127 , haddockIndex
= if localStyle
then Flag
(toPathTemplate
"../doc-index.html")
129 , haddockKeepTempFiles
= haddockProjectKeepTempFiles flags
130 , haddockVerbosity
= haddockProjectVerbosity flags
131 , haddockLib
= haddockProjectLib flags
133 nixFlags
= (commandDefaultFlags CmdHaddock
.haddockCommand
)
134 { NixStyleOptions
.haddockFlags
= haddockFlags
135 , NixStyleOptions
.configFlags
=
136 (NixStyleOptions
.configFlags
(commandDefaultFlags CmdBuild
.buildCommand
))
137 { configVerbosity
= haddockProjectVerbosity flags
}
141 -- Construct the build plan and infer the list of packages which haddocks
145 withContextAndSelectors RejectNoTargets Nothing nixFlags
["all"] globalFlags HaddockCommand
$ \targetCtx ctx targetSelectors
-> do
146 baseCtx
<- case targetCtx
of
147 ProjectContext
-> return ctx
148 GlobalContext
-> return ctx
149 ScriptContext path exemeta
-> updateContextAndWriteProjectFile ctx path exemeta
150 let distLayout
= distDirLayout baseCtx
151 cabalLayout
= cabalDirLayout baseCtx
153 runProjectPreBuildPhase verbosity baseCtx
$ \elaboratedPlan
-> do
154 -- Interpret the targets on the command line as build targets
155 -- (as opposed to say repl or haddock targets).
156 targets
<- either reportTargetProblems
return
159 selectComponentTargetBasic
164 let elaboratedPlan
' = pruneInstallPlanToTargets
168 return (elaboratedPlan
', targets
)
170 printPlan verbosity baseCtx buildCtx
172 let elaboratedPlan
:: ElaboratedInstallPlan
173 elaboratedPlan
= elaboratedPlanOriginal buildCtx
175 sharedConfig
:: ElaboratedSharedConfig
176 sharedConfig
= elaboratedShared buildCtx
178 pkgs
:: [Either InstalledPackageInfo ElaboratedConfiguredPackage
]
179 pkgs
= matchingPackages elaboratedPlan
181 progs
<- reconfigurePrograms verbosity
182 (haddockProjectProgramPaths flags
)
183 (haddockProjectProgramArgs flags
)
184 -- we need to insert 'haddockProgram' before we reconfigure it,
186 . addKnownProgram haddockProgram
187 . pkgConfigCompilerProgs
189 let sharedConfig
' = sharedConfig
{ pkgConfigCompilerProgs
= progs
}
191 _
<- requireProgramVersion
192 verbosity haddockProgram
193 (orLaterVersion
(mkVersion
[2,26,1])) progs
196 -- Build haddocks of each components
199 CmdHaddock
.haddockAction
205 -- Copy haddocks to the destination folder
208 packageInfos
<- fmap (nub . concat) $ for pkgs
$ \pkg
->
210 Left _ |
not localStyle
->
213 let packageName
= unPackageName
(pkgName
$ sourcePackageId package
)
214 destDir
= outputDir
</> packageName
215 fmap catMaybes $ for
(haddockInterfaces package
) $ \interfacePath
-> do
216 let docDir
= takeDirectory interfacePath
217 a
<- doesFileExist interfacePath
219 True -> copyDirectoryRecursive verbosity docDir destDir
220 >> return (Just
( packageName
224 False -> return Nothing
227 case elabLocalToProject package
of
229 let distDirParams
= elabDistDirParams sharedConfig
' package
230 buildDir
= distBuildDirectory distLayout distDirParams
231 packageName
= unPackageName
(pkgName
$ elabPkgSourceId package
)
232 let docDir
= buildDir
235 destDir
= outputDir
</> packageName
236 interfacePath
= destDir
237 </> packageName
<.> "haddock"
238 a
<- doesDirectoryExist docDir
240 True -> copyDirectoryRecursive verbosity docDir destDir
241 >> return [( packageName
246 False |
not localStyle
->
249 let packageName
= unPackageName
(pkgName
$ elabPkgSourceId package
)
250 packageDir
= storePackageDirectory
(cabalStoreDirLayout cabalLayout
)
251 (compilerId
(pkgConfigCompiler sharedConfig
'))
253 docDir
= packageDir
</> "share" </> "doc" </> "html"
254 destDir
= outputDir
</> packageName
255 interfacePath
= destDir
256 </> packageName
<.> "haddock"
257 a
<- doesDirectoryExist docDir
259 True -> copyDirectoryRecursive verbosity docDir destDir
260 -- non local packages will be hidden in haddock's
261 -- generated contents page
262 >> return [( packageName
269 -- generate index, content, etc.
273 { haddockProjectDir
= Flag outputDir
274 , haddockProjectGenIndex
= if localOrHackage
276 else haddockProjectGenIndex flags
277 , haddockProjectGenContents
= if localOrHackage
279 else haddockProjectGenContents flags
280 , haddockProjectQuickJump
= if localOrHackage
282 else haddockProjectQuickJump flags
283 , haddockProjectLinkedSource
= haddockLinkedSource haddockFlags
284 , haddockProjectInterfaces
= Flag
290 |
(packageName
, interfacePath
, visibility
) <- packageInfos
293 createHaddockIndex verbosity
294 (pkgConfigCompilerProgs sharedConfig
')
295 (pkgConfigCompiler sharedConfig
')
296 (pkgConfigPlatform sharedConfig
')
299 verbosity
= fromFlagOrDefault normal
(haddockProjectVerbosity flags
)
301 -- Build a self contained directory which contains haddocks of all
302 -- transitive dependencies; or depend on `--haddocks-html-location` to
303 -- provide location of the documentation of dependencies.
305 let local
= fromFlagOrDefault
False (haddockProjectLocal flags
)
306 hackage
= fromFlagOrDefault
False (haddockProjectHackage flags
)
307 location
= fromFlagOrDefault
False (const True <$> haddockProjectHtmlLocation flags
)
308 in local
&& not hackage
&& not location
309 -- or if none of the flags is given set `localStyle` to `True`
310 ||
not local
&& not hackage
&& not location
314 any id $ flagToList
(haddockProjectLocal flags
)
315 ++ flagToList
(haddockProjectHackage flags
)
317 reportTargetProblems
:: Show x
=> [x
] -> IO a
318 reportTargetProblems
=
319 die
' verbosity
. unlines . map show
321 -- TODO: this is just a sketch
322 selectPackageTargets
:: TargetSelector
323 -> [AvailableTarget k
]
324 -> Either (TargetProblem
()) [k
]
325 selectPackageTargets _ ts
= Right
$
327 (\t -> case availableTargetStatus t
of
328 TargetBuildable k _ | availableTargetLocalToProject t
333 matchingPackages
:: ElaboratedInstallPlan
334 -> [Either InstalledPackageInfo ElaboratedConfiguredPackage
]
336 fmap (foldPlanPackage Left Right
)