Skip to content

Commit f3cacff

Browse files
authored
Haddock: Generate haddock for components
Currently settings documentation: true enables documentation generation via haddock for your whole package, including tests and benchmarks. However, there are additional flags to control generation of documentation for these "second class" documentation targets, which are currently not honored at the cabal-install side of things. Namely, tests, benchmarks, executables, etc. provided under the haddock section in your $CABAL_HOME/config. This patch adds a more sensible approach to documentation generation via haddock. The new behaviour works like this: Setting documentation: true or passing --enable-documentation to cabal-install enables documentation for any component in the build plan honoring the respective flags for "second class" doc targets from configuration or CLI. Invoking new-haddock with a target selector will make sure the respective flags for "second class" doc targets are set correctly. E.g. $ new-haddock tests Will generate documentation for the test suite of your package even if you have tests: false in your haddock configuration. Merge pull request #5226 from alexbiehl/pr/haddock-components
2 parents 30d0c10 + d095feb commit f3cacff

File tree

11 files changed

+120
-25
lines changed

11 files changed

+120
-25
lines changed

Cabal/ChangeLog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
into per-component condition trees anyway. Now it's finally been put
88
out of its misery (#4383).
99
* Added `Eta` to `CompilerFlavor` and to known compilers.
10+
* `cabal haddock` now generates per-component documentation (#5226).
1011

1112
----
1213

Cabal/Distribution/Simple.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ haddockAction hooks flags args = do
329329

330330
hookedAction preHaddock haddockHook postHaddock
331331
(return lbi { withPrograms = progs })
332-
hooks flags' args
332+
hooks flags' { haddockArgs = args } args
333333

334334
cleanAction :: UserHooks -> CleanFlags -> Args -> IO ()
335335
cleanAction hooks flags args = do

Cabal/Distribution/Simple/Haddock.hs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ import Distribution.Types.ForeignLib
3636
import Distribution.Types.UnqualComponentName
3737
import Distribution.Types.ComponentLocalBuildInfo
3838
import Distribution.Types.ExecutableScope
39+
import Distribution.Types.LocalBuildInfo
40+
import Distribution.Types.TargetInfo
3941
import Distribution.Package
4042
import qualified Distribution.ModuleName as ModuleName
4143
import Distribution.PackageDescription as PD hiding (Flag)
@@ -46,6 +48,7 @@ import Distribution.Simple.Program
4648
import Distribution.Simple.PreProcess
4749
import Distribution.Simple.Setup
4850
import Distribution.Simple.Build
51+
import Distribution.Simple.BuildTarget
4952
import Distribution.Simple.InstallDirs
5053
import Distribution.Simple.LocalBuildInfo hiding (substPathTemplate)
5154
import Distribution.Simple.BuildPaths
@@ -199,7 +202,18 @@ haddock pkg_descr lbi suffixes flags' = do
199202
, fromFlags (haddockTemplateEnv lbi (packageId pkg_descr)) flags
200203
, fromPackageDescription haddockTarget pkg_descr ]
201204

202-
withAllComponentsInBuildOrder pkg_descr lbi $ \component clbi -> do
205+
targets <- readTargetInfos verbosity pkg_descr lbi (haddockArgs flags)
206+
207+
let
208+
targets' =
209+
case targets of
210+
[] -> allTargetsInBuildOrder' pkg_descr lbi
211+
_ -> targets
212+
213+
for_ targets' $ \target -> do
214+
let component = targetComponent target
215+
clbi = targetCLBI target
216+
203217
componentInitialBuildSteps (flag haddockDistPref) pkg_descr lbi clbi verbosity
204218
preprocessComponent pkg_descr component lbi clbi False verbosity suffixes
205219
let

Cabal/Distribution/Simple/Setup.hs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1470,7 +1470,8 @@ data HaddockFlags = HaddockFlags {
14701470
haddockDistPref :: Flag FilePath,
14711471
haddockKeepTempFiles:: Flag Bool,
14721472
haddockVerbosity :: Flag Verbosity,
1473-
haddockCabalFilePath :: Flag FilePath
1473+
haddockCabalFilePath :: Flag FilePath,
1474+
haddockArgs :: [String]
14741475
}
14751476
deriving (Show, Generic)
14761477

@@ -1494,7 +1495,8 @@ defaultHaddockFlags = HaddockFlags {
14941495
haddockDistPref = NoFlag,
14951496
haddockKeepTempFiles= Flag False,
14961497
haddockVerbosity = Flag normal,
1497-
haddockCabalFilePath = mempty
1498+
haddockCabalFilePath = mempty,
1499+
haddockArgs = mempty
14981500
}
14991501

15001502
haddockCommand :: CommandUI HaddockFlags
@@ -1504,8 +1506,10 @@ haddockCommand = CommandUI
15041506
, commandDescription = Just $ \_ ->
15051507
"Requires the program haddock, version 2.x.\n"
15061508
, commandNotes = Nothing
1507-
, commandUsage = \pname ->
1508-
"Usage: " ++ pname ++ " haddock [FLAGS]\n"
1509+
, commandUsage = usageAlternatives "haddock" $
1510+
[ "[FLAGS]"
1511+
, "COMPONENTS [FLAGS]"
1512+
]
15091513
, commandDefaultFlags = defaultHaddockFlags
15101514
, commandOptions = \showOrParseArgs ->
15111515
haddockOptions showOrParseArgs

Cabal/Distribution/Simple/UserHooks.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ emptyUserHooks
207207
preDoctest = rn,
208208
doctestHook = ru,
209209
postDoctest = ru,
210-
preHaddock = rn,
210+
preHaddock = rn',
211211
haddockHook = ru,
212212
postHaddock = ru,
213213
preTest = rn',

Cabal/doc/nix-local-build.rst

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -437,9 +437,13 @@ they are up to date.
437437
cabal new-haddock
438438
-----------------
439439

440-
``cabal new-haddock [FLAGS] TARGET`` builds Haddock documentation for
440+
``cabal new-haddock [FLAGS] [TARGET]`` builds Haddock documentation for
441441
the specified packages within the project.
442442

443+
If a target is not a library :cfg-field:`haddock-benchmarks`,
444+
:cfg-field:`haddock-executables`, :cfg-field:`haddock-internal`,
445+
:cfg-field:`haddock-tests` will be implied as necessary.
446+
443447
cabal new-exec
444448
---------------
445449

@@ -1534,9 +1538,6 @@ Coverage options
15341538
Haddock options
15351539
^^^^^^^^^^^^^^^
15361540

1537-
Documentation building support is fairly sparse at the moment. Let us
1538-
know if it's a priority for you!
1539-
15401541
.. cfg-field:: documentation: boolean
15411542
--enable-documentation
15421543
--disable-documentation
@@ -1549,6 +1550,11 @@ know if it's a priority for you!
15491550
The command line variant of this flag is ``--enable-documentation``
15501551
and ``--disable-documentation``.
15511552

1553+
`documentation: true` does not imply :cfg-field:`haddock-benchmarks`,
1554+
:cfg-field:`haddock-executables`, :cfg-field:`haddock-internal` or
1555+
:cfg-field:`haddock-tests`. These need to be enabled separately if
1556+
desired.
1557+
15521558
.. cfg-field:: doc-index-file: templated path
15531559
--doc-index-file=TEMPLATE
15541560
:synopsis: Path to haddock templates.

cabal-install/Distribution/Client/Config.hs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,8 @@ instance Semigroup SavedConfig where
413413
haddockDistPref = combine haddockDistPref,
414414
haddockKeepTempFiles = combine haddockKeepTempFiles,
415415
haddockVerbosity = combine haddockVerbosity,
416-
haddockCabalFilePath = combine haddockCabalFilePath
416+
haddockCabalFilePath = combine haddockCabalFilePath,
417+
haddockArgs = lastNonEmpty haddockArgs
417418
}
418419
where
419420
combine = combine' savedHaddockFlags

cabal-install/Distribution/Client/ProjectBuilding.hs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -366,11 +366,12 @@ packageFileMonitorKeyValues elab =
366366
--
367367
elab_config =
368368
elab {
369-
elabBuildTargets = [],
370-
elabTestTargets = [],
369+
elabBuildTargets = [],
370+
elabTestTargets = [],
371371
elabBenchTargets = [],
372-
elabReplTarget = Nothing,
373-
elabBuildHaddocks = False
372+
elabReplTarget = Nothing,
373+
elabHaddockTargets = [],
374+
elabBuildHaddocks = False
374375
}
375376

376377
-- The second part is the value used to guard the build step. So this is
@@ -1220,7 +1221,7 @@ buildInplaceUnpackedPackage verbosity
12201221
-- Haddock phase
12211222
whenHaddock $
12221223
annotateFailureNoLog HaddocksFailed $ do
1223-
setup haddockCommand haddockFlags []
1224+
setup haddockCommand haddockFlags haddockArgs
12241225
let haddockTarget = elabHaddockForHackage pkg
12251226
when (haddockTarget == Cabal.ForHackage) $ do
12261227
let dest = distDirectory </> name <.> "tar.gz"
@@ -1307,6 +1308,7 @@ buildInplaceUnpackedPackage verbosity
13071308
haddockCommand = Cabal.haddockCommand
13081309
haddockFlags _ = setupHsHaddockFlags pkg pkgshared
13091310
verbosity builddir
1311+
haddockArgs = setupHsHaddockArgs pkg
13101312

13111313
scriptOptions = setupHsScriptOptions rpkg plan pkgshared
13121314
srcdir builddir

cabal-install/Distribution/Client/ProjectConfig/Legacy.hs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,8 @@ commandLineFlagsToProjectConfig globalFlags configFlags configExFlags
193193
splitConfig pc = (pc
194194
, mempty { packageConfigProgramPaths = packageConfigProgramPaths pc
195195
, packageConfigProgramArgs = packageConfigProgramArgs pc
196-
, packageConfigProgramPathExtra = packageConfigProgramPathExtra pc })
196+
, packageConfigProgramPathExtra = packageConfigProgramPathExtra pc
197+
, packageConfigDocumentation = packageConfigDocumentation pc })
197198

198199
-- | Convert from the types currently used for the user-wide @~/.cabal/config@
199200
-- file into the 'ProjectConfig' type.
@@ -733,7 +734,8 @@ convertToLegacyPerPackageConfig PackageConfig {..} =
733734
haddockDistPref = mempty,
734735
haddockKeepTempFiles = mempty,
735736
haddockVerbosity = mempty,
736-
haddockCabalFilePath = mempty
737+
haddockCabalFilePath = mempty,
738+
haddockArgs = mempty
737739
}
738740

739741

cabal-install/Distribution/Client/ProjectPlanning.hs

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ module Distribution.Client.ProjectPlanning (
5656
setupHsCopyFlags,
5757
setupHsRegisterFlags,
5858
setupHsHaddockFlags,
59+
setupHsHaddockArgs,
5960

6061
packageHashInputs,
6162

@@ -1727,6 +1728,8 @@ elaborateInstallPlan verbosity platform compiler compilerprogdb pkgConfigDB
17271728
elabTestTargets = []
17281729
elabBenchTargets = []
17291730
elabReplTarget = Nothing
1731+
elabHaddockTargets = []
1732+
17301733
elabBuildHaddocks =
17311734
perPkgOptionFlag pkgid False packageConfigDocumentation
17321735

@@ -2437,6 +2440,7 @@ pkgHasEphemeralBuildTargets elab =
24372440
isJust (elabReplTarget elab)
24382441
|| (not . null) (elabTestTargets elab)
24392442
|| (not . null) (elabBenchTargets elab)
2443+
|| (not . null) (elabHaddockTargets elab)
24402444
|| (not . null) [ () | ComponentTarget _ subtarget <- elabBuildTargets elab
24412445
, subtarget /= WholeComponent ]
24422446

@@ -2535,11 +2539,22 @@ setRootTargets targetAction perPkgTargetsMap =
25352539
(Just tgts, TargetActionBuild) -> elab { elabBuildTargets = tgts }
25362540
(Just tgts, TargetActionTest) -> elab { elabTestTargets = tgts }
25372541
(Just tgts, TargetActionBench) -> elab { elabBenchTargets = tgts }
2538-
(Just [tgt], TargetActionRepl) -> elab { elabReplTarget = Just tgt }
2539-
(Just _, TargetActionHaddock) -> elab { elabBuildHaddocks = True }
2542+
(Just [tgt], TargetActionRepl) -> elab { elabReplTarget = Just tgt
2543+
, elabBuildHaddocks = False }
2544+
(Just tgts, TargetActionHaddock) ->
2545+
foldr setElabHaddockTargets (elab { elabHaddockTargets = tgts
2546+
, elabBuildHaddocks = True }) tgts
25402547
(Just _, TargetActionRepl) ->
25412548
error "pruneInstallPlanToTargets: multiple repl targets"
25422549

2550+
setElabHaddockTargets tgt elab
2551+
| isTestComponentTarget tgt = elab { elabHaddockTestSuites = True }
2552+
| isBenchComponentTarget tgt = elab { elabHaddockBenchmarks = True }
2553+
| isForeignLibComponentTarget tgt = elab { elabHaddockForeignLibs = True }
2554+
| isExeComponentTarget tgt = elab { elabHaddockExecutables = True }
2555+
| isSubLibComponentTarget tgt = elab { elabHaddockInternal = True }
2556+
| otherwise = elab
2557+
25432558
-- | Assuming we have previously set the root build targets (i.e. the user
25442559
-- targets but not rev deps yet), the first pruning pass does two things:
25452560
--
@@ -2560,14 +2575,16 @@ pruneInstallPlanPass1 pkgs =
25602575
roots = mapMaybe find_root pkgs'
25612576

25622577
prune elab = PrunedPackage elab' (pruneOptionalDependencies elab')
2563-
where elab' = addOptionalStanzas elab
2578+
where elab' =
2579+
setDocumentation
2580+
$ addOptionalStanzas elab
25642581

25652582
find_root (InstallPlan.Configured (PrunedPackage elab _)) =
25662583
if not (null (elabBuildTargets elab)
25672584
&& null (elabTestTargets elab)
25682585
&& null (elabBenchTargets elab)
25692586
&& isNothing (elabReplTarget elab)
2570-
&& not (elabBuildHaddocks elab))
2587+
&& null (elabHaddockTargets elab))
25712588
then Just (installedUnitId elab)
25722589
else Nothing
25732590
find_root _ = Nothing
@@ -2613,6 +2630,26 @@ pruneInstallPlanPass1 pkgs =
26132630
<> optionalStanzasWithDepsAvailable availablePkgs elab pkg
26142631
addOptionalStanzas elab = elab
26152632

2633+
setDocumentation :: ElaboratedConfiguredPackage -> ElaboratedConfiguredPackage
2634+
setDocumentation elab@ElaboratedConfiguredPackage { elabPkgOrComp = ElabComponent comp } =
2635+
elab {
2636+
elabBuildHaddocks =
2637+
elabBuildHaddocks elab && documentationEnabled (compSolverName comp) elab
2638+
}
2639+
2640+
where
2641+
documentationEnabled c =
2642+
case c of
2643+
CD.ComponentLib -> const True
2644+
CD.ComponentSubLib _ -> elabHaddockInternal
2645+
CD.ComponentFLib _ -> elabHaddockForeignLibs
2646+
CD.ComponentExe _ -> elabHaddockExecutables
2647+
CD.ComponentTest _ -> elabHaddockTestSuites
2648+
CD.ComponentBench _ -> elabHaddockBenchmarks
2649+
CD.ComponentSetup -> const False
2650+
2651+
setDocumentation elab = elab
2652+
26162653
-- Calculate package dependencies but cut out those needed only by
26172654
-- optional stanzas that we've determined we will not enable.
26182655
-- These pruned deps are not persisted in this pass since they're based on
@@ -2639,6 +2676,7 @@ pruneInstallPlanPass1 pkgs =
26392676
++ elabTestTargets pkg
26402677
++ elabBenchTargets pkg
26412678
++ maybeToList (elabReplTarget pkg)
2679+
++ elabHaddockTargets pkg
26422680
, stanza <- maybeToList (componentOptionalStanza cname)
26432681
]
26442682

@@ -3393,9 +3431,15 @@ setupHsHaddockFlags (ElaboratedConfiguredPackage{..}) _ verbosity builddir =
33933431
haddockDistPref = toFlag builddir,
33943432
haddockKeepTempFiles = mempty, --TODO: from build settings
33953433
haddockVerbosity = toFlag verbosity,
3396-
haddockCabalFilePath = mempty
3434+
haddockCabalFilePath = mempty,
3435+
haddockArgs = mempty
33973436
}
33983437

3438+
setupHsHaddockArgs :: ElaboratedConfiguredPackage -> [String]
3439+
-- TODO: Does the issue #3335 affects test as well
3440+
setupHsHaddockArgs elab =
3441+
map (showComponentTarget (packageId elab)) (elabHaddockTargets elab)
3442+
33993443
{-
34003444
setupHsTestFlags :: ElaboratedConfiguredPackage
34013445
-> ElaboratedSharedConfig
@@ -3584,4 +3628,3 @@ inplaceBinRoot
35843628
inplaceBinRoot layout config package
35853629
= distBuildDirectory layout (elabDistDirParams config package)
35863630
</> "build"
3587-

0 commit comments

Comments
 (0)