Skip to content

Commit

Permalink
Add --haddock-output-dir flag to cabal haddock.
Browse files Browse the repository at this point in the history
This flag gives the user full control over the directory where the documentation is placed.
  • Loading branch information
LiisiKerik committed Apr 9, 2023
1 parent 6f9acee commit 7291b92
Show file tree
Hide file tree
Showing 35 changed files with 203 additions and 32 deletions.
5 changes: 3 additions & 2 deletions Cabal/src/Distribution/Simple/Flag.hs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveFoldable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE FlexibleContexts #-}
-----------------------------------------------------------------------------
-- |
Expand Down Expand Up @@ -53,7 +54,7 @@ import Distribution.Compat.Stack
-- Its monoid instance gives us the behaviour where it starts out as
-- 'NoFlag' and later flags override earlier ones.
--
data Flag a = Flag a | NoFlag deriving (Eq, Generic, Show, Read, Typeable)
data Flag a = Flag a | NoFlag deriving (Eq, Generic, Show, Read, Typeable, Foldable, Traversable)

instance Binary a => Binary (Flag a)
instance Structured a => Structured (Flag a)
Expand Down
7 changes: 6 additions & 1 deletion Cabal/src/Distribution/Simple/Haddock.hs
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,12 @@ haddock pkg_descr lbi suffixes flags' = do
fromFlagOrDefault ForDevelopment (haddockForHackage flags')

libdirArgs <- getGhcLibDir verbosity lbi
let commonArgs = mconcat
-- The haddock-output-dir flag overrides any other documentation placement concerns.
-- The point is to give the user full freedom over the location if they need it.
let overrideWithOutputDir args = case haddockOutputDir flags of
NoFlag -> args
Flag dir -> args { argOutputDir = Dir dir }
let commonArgs = overrideWithOutputDir $ mconcat
[ libdirArgs
, fromFlags (haddockTemplateEnv lbi (packageId pkg_descr)) flags
, fromPackageDescription haddockTarget pkg_descr ]
Expand Down
16 changes: 15 additions & 1 deletion Cabal/src/Distribution/Simple/Setup/Haddock.hs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ data HaddockFlags = HaddockFlags {
haddockCabalFilePath :: Flag FilePath,
haddockBaseUrl :: Flag String,
haddockLib :: Flag String,
haddockOutputDir :: Flag FilePath,
haddockArgs :: [String]
}
deriving (Show, Generic, Typeable)
Expand Down Expand Up @@ -123,6 +124,7 @@ defaultHaddockFlags = HaddockFlags {
haddockIndex = NoFlag,
haddockBaseUrl = NoFlag,
haddockLib = NoFlag,
haddockOutputDir = NoFlag,
haddockArgs = mempty
}

Expand Down Expand Up @@ -267,6 +269,11 @@ haddockOptions showOrParseArgs =
"location of Haddocks static / auxiliary files"
haddockLib (\v flags -> flags { haddockLib = v})
(reqArgFlag "DIR")

,option "" ["output-dir"]
"Generate haddock documentation into this directory. This flag is provided as a technology preview and is subject to change in the next releases."
haddockOutputDir (\v flags -> flags { haddockOutputDir = v })
(reqArgFlag "DIR")
]

emptyHaddockFlags :: HaddockFlags
Expand Down Expand Up @@ -343,7 +350,8 @@ data HaddockProjectFlags = HaddockProjectFlags {
haddockProjectKeepTempFiles:: Flag Bool,
haddockProjectVerbosity :: Flag Verbosity,
-- haddockBaseUrl is not supported, a fixed value is provided
haddockProjectLib :: Flag String
haddockProjectLib :: Flag String,
haddockProjectOutputDir :: Flag FilePath
}
deriving (Show, Generic, Typeable)

Expand Down Expand Up @@ -371,6 +379,7 @@ defaultHaddockProjectFlags = HaddockProjectFlags {
haddockProjectKeepTempFiles= Flag False,
haddockProjectVerbosity = Flag normal,
haddockProjectLib = NoFlag,
haddockProjectOutputDir = NoFlag,
haddockProjectInterfaces = NoFlag
}

Expand Down Expand Up @@ -505,6 +514,11 @@ haddockProjectOptions _showOrParseArgs =
"location of Haddocks static / auxiliary files"
haddockProjectLib (\v flags -> flags { haddockProjectLib = v})
(reqArgFlag "DIR")

,option "" ["output-dir"]
"Generate haddock documentation into this directory. This flag is provided as a technology preview and is subject to change in the next releases."
haddockProjectOutputDir (\v flags -> flags { haddockProjectOutputDir = v})
(reqArgFlag "DIR")
]


Expand Down
2 changes: 1 addition & 1 deletion cabal-install/src/Distribution/Client/CmdClean.hs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ cleanAction CleanFlags{..} extraArgs _ = do

projectRoot <- either throwIO return =<< findProjectRoot verbosity mprojectDir mprojectFile

let distLayout = defaultDistDirLayout projectRoot mdistDirectory
let distLayout = defaultDistDirLayout projectRoot mdistDirectory Nothing

-- Do not clean a project if just running a script in it's directory
when (null extraArgs || isJust mdistDirectory) $ do
Expand Down
36 changes: 29 additions & 7 deletions cabal-install/src/Distribution/Client/CmdHaddock.hs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ module Distribution.Client.CmdHaddock (

import Distribution.Client.Compat.Prelude
import Prelude ()
import System.Directory (makeAbsolute)

import Distribution.Client.ProjectConfig.Types
(PackageConfig (..), ProjectConfig (..))
import Distribution.Client.ProjectOrchestration
import Distribution.Client.ProjectPlanning
( ElaboratedSharedConfig(..) )
Expand Down Expand Up @@ -83,20 +86,44 @@ haddockOptions _ =
openInBrowser (\v f -> f { openInBrowser = v}) trueArg
]

mkConfigAbsolute :: ProjectConfig -> IO ProjectConfig
mkConfigAbsolute relConfig = do
let relPackageConfig = projectConfigLocalPackages relConfig
absHaddockOutputDir <- traverse makeAbsolute (packageConfigHaddockOutputDir relPackageConfig)
return (relConfig { projectConfigLocalPackages = relPackageConfig {
packageConfigHaddockOutputDir = absHaddockOutputDir} })

mkFlagsAbsolute :: NixStyleFlags ClientHaddockFlags -> IO (NixStyleFlags ClientHaddockFlags)
mkFlagsAbsolute relFlags = do
let relHaddockFlags = haddockFlags relFlags
absHaddockOutputDir <- traverse makeAbsolute (haddockOutputDir relHaddockFlags)
return (relFlags { haddockFlags = relHaddockFlags { haddockOutputDir = absHaddockOutputDir } })

-- | The @haddock@ command is TODO.
--
-- For more details on how this works, see the module
-- "Distribution.Client.ProjectOrchestration"
--
haddockAction :: NixStyleFlags ClientHaddockFlags -> [String] -> GlobalFlags -> IO ()
haddockAction flags@NixStyleFlags {..} targetStrings globalFlags = do
haddockAction relFlags targetStrings globalFlags = do
-- It's important to make --haddock-output-dir absolute since we change the working directory later.
flags@NixStyleFlags {..} <- mkFlagsAbsolute relFlags

let
verbosity = fromFlagOrDefault normal (configVerbosity configFlags)
installDoc = fromFlagOrDefault True (installDocumentation installFlags)
flags' = flags { installFlags = installFlags { installDocumentation = Flag installDoc } }
cliConfig = commandLineFlagsToProjectConfig globalFlags flags' mempty -- ClientInstallFlags, not needed here

projCtx <- establishProjectBaseContext verbosity cliConfig HaddockCommand

let baseCtx
let relBaseCtx@ProjectBaseContext { projectConfig = relProjectConfig }
| fromFlagOrDefault False (openInBrowser extraFlags)
= projCtx { buildSettings = (buildSettings projCtx) { buildSettingHaddockOpen = True } }
| otherwise
= projCtx
absProjectConfig <- mkConfigAbsolute relProjectConfig
let baseCtx = relBaseCtx { projectConfig = absProjectConfig }

targetSelectors <- either (reportTargetSelectorProblems verbosity) return
=<< readTargetSelectors (localPackages baseCtx) Nothing targetStrings
Expand Down Expand Up @@ -141,11 +168,6 @@ haddockAction flags@NixStyleFlags {..} targetStrings globalFlags = do

buildOutcomes <- runProjectBuildPhase verbosity baseCtx buildCtx'
runProjectPostBuildPhase verbosity baseCtx buildCtx' buildOutcomes
where
verbosity = fromFlagOrDefault normal (configVerbosity configFlags)
installDoc = fromFlagOrDefault True (installDocumentation installFlags)
flags' = flags { installFlags = installFlags { installDocumentation = Flag installDoc } }
cliConfig = commandLineFlagsToProjectConfig globalFlags flags' mempty -- ClientInstallFlags, not needed here

-- | This defines what a 'TargetSelector' means for the @haddock@ command.
-- It selects the 'AvailableTarget's that the 'TargetSelector' refers to,
Expand Down
1 change: 1 addition & 0 deletions cabal-install/src/Distribution/Client/CmdHaddockProject.hs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ haddockProjectAction flags _extraArgs globalFlags = do
, haddockKeepTempFiles= haddockProjectKeepTempFiles flags
, haddockVerbosity = haddockProjectVerbosity flags
, haddockLib = haddockProjectLib flags
, haddockOutputDir = haddockProjectOutputDir flags
}
nixFlags = (commandDefaultFlags CmdHaddock.haddockCommand)
{ NixStyleOptions.haddockFlags = haddockFlags
Expand Down
2 changes: 1 addition & 1 deletion cabal-install/src/Distribution/Client/CmdOutdated.hs
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ depsFromNewFreezeFile verbosity httpTransport compiler (Platform arch os) mproje
projectRoot <- either throwIO return =<<
findProjectRoot verbosity mprojectDir mprojectFile
let distDirLayout = defaultDistDirLayout projectRoot
{- TODO: Support dist dir override -} Nothing
{- TODO: Support dist dir override -} Nothing Nothing
projectConfig <- runRebuild (distProjectRootDirectory distDirLayout) $ do
pcs <- readProjectLocalFreezeConfig verbosity httpTransport distDirLayout
pure $ instantiateProjectConfigSkeletonWithCompiler os arch (compilerInfo compiler) mempty pcs
Expand Down
1 change: 1 addition & 0 deletions cabal-install/src/Distribution/Client/Config.hs
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,7 @@ instance Semigroup SavedConfig where
haddockIndex = combine haddockIndex,
haddockBaseUrl = combine haddockBaseUrl,
haddockLib = combine haddockLib,
haddockOutputDir = combine haddockOutputDir,
haddockArgs = lastNonEmpty haddockArgs
}
where
Expand Down
14 changes: 10 additions & 4 deletions cabal-install/src/Distribution/Client/DistDirLayout.hs
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,10 @@ data DistDirLayout = DistDirLayout {
distTempDirectory :: FilePath,
distBinDirectory :: FilePath,

distPackageDB :: CompilerId -> PackageDB
distPackageDB :: CompilerId -> PackageDB,

-- | Is needed when `--haddock-output-dir` flag is used.
distHaddockOutputDir :: Maybe FilePath
}


Expand Down Expand Up @@ -180,14 +183,15 @@ defaultProjectFile :: FilePath
defaultProjectFile = "cabal.project"

-- | Make the default 'DistDirLayout' based on the project root dir and
-- optional overrides for the location of the @dist@ directory and the
-- @cabal.project@ file.
-- optional overrides for the location of the @dist@ directory, the
-- @cabal.project@ file and the documentation directory.
--
defaultDistDirLayout :: ProjectRoot -- ^ the project root
-> Maybe FilePath -- ^ the @dist@ directory or default
-- (absolute or relative to the root)
-> Maybe FilePath -- ^ the documentation directory
-> DistDirLayout
defaultDistDirLayout projectRoot mdistDirectory =
defaultDistDirLayout projectRoot mdistDirectory haddockOutputDir =
DistDirLayout {..}
where
(projectRootDir, projectFile) = case projectRoot of
Expand Down Expand Up @@ -272,6 +276,8 @@ defaultDistDirLayout projectRoot mdistDirectory =
distPackageDB :: CompilerId -> PackageDB
distPackageDB = SpecificPackageDB . distPackageDBPath

distHaddockOutputDir :: Maybe FilePath
distHaddockOutputDir = haddockOutputDir

defaultStoreDirLayout :: FilePath -> StoreDirLayout
defaultStoreDirLayout storeRoot =
Expand Down
2 changes: 2 additions & 0 deletions cabal-install/src/Distribution/Client/NixStyleOptions.hs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
{-# LANGUAGE StandaloneDeriving #-}

-- | Command line options for nix-style / v2 commands.
--
-- The commands take a lot of the same options, which affect how install plan
Expand Down
4 changes: 3 additions & 1 deletion cabal-install/src/Distribution/Client/PackageHash.hs
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,8 @@ data PackageHashConfigInputs = PackageHashConfigInputs {
pkgHashHaddockContents :: Maybe PathTemplate,
pkgHashHaddockIndex :: Maybe PathTemplate,
pkgHashHaddockBaseUrl :: Maybe String,
pkgHashHaddockLib :: Maybe String
pkgHashHaddockLib :: Maybe String,
pkgHashHaddockOutputDir :: Maybe FilePath

-- TODO: [required eventually] pkgHashToolsVersions ?
-- TODO: [required eventually] pkgHashToolsExtraOptions ?
Expand Down Expand Up @@ -317,6 +318,7 @@ renderPackageHashInputs PackageHashInputs{
, opt "haddock-index-location" Nothing (maybe "" fromPathTemplate) pkgHashHaddockIndex
, opt "haddock-base-url" Nothing (fromMaybe "") pkgHashHaddockBaseUrl
, opt "haddock-lib" Nothing (fromMaybe "") pkgHashHaddockLib
, opt "haddock-output-dir" Nothing (fromMaybe "") pkgHashHaddockOutputDir

] ++ Map.foldrWithKey (\prog args acc -> opt (prog ++ "-options") [] unwords args : acc) [] pkgHashProgramArgs
where
Expand Down
10 changes: 6 additions & 4 deletions cabal-install/src/Distribution/Client/ProjectBuilding.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1266,7 +1266,8 @@ buildInplaceUnpackedPackage verbosity
distDirLayout@DistDirLayout {
distTempDirectory,
distPackageCacheDirectory,
distDirectory
distDirectory,
distHaddockOutputDir
}
BuildTimeSettings{buildSettingNumJobs, buildSettingHaddockOpen}
registerLock cacheLock
Expand Down Expand Up @@ -1390,10 +1391,11 @@ buildInplaceUnpackedPackage verbosity
notice verbosity $ "Documentation tarball created: " ++ dest

when (buildSettingHaddockOpen && haddockTarget /= Cabal.ForHackage) $ do
let dest = docDir </> name </> "index.html"
let dest = docDir </> "index.html"
name = haddockDirName haddockTarget (elabPkgDescription pkg)
docDir = distBuildDirectory distDirLayout dparams
</> "doc" </> "html"
docDir = case distHaddockOutputDir of
Nothing -> distBuildDirectory distDirLayout dparams </> "doc" </> "html" </> name
Just dir -> dir
exe <- findOpenProgramLocation platform
case exe of
Right open -> runProgramInvocation verbosity (simpleProgramInvocation open [dest])
Expand Down
6 changes: 4 additions & 2 deletions cabal-install/src/Distribution/Client/ProjectConfig/Legacy.hs
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,8 @@ convertLegacyPerPackageFlags configFlags installFlags
haddockContents = packageConfigHaddockContents,
haddockIndex = packageConfigHaddockIndex,
haddockBaseUrl = packageConfigHaddockBaseUrl,
haddockLib = packageConfigHaddockLib
haddockLib = packageConfigHaddockLib,
haddockOutputDir = packageConfigHaddockOutputDir
} = haddockFlags

TestFlags {
Expand Down Expand Up @@ -985,6 +986,7 @@ convertToLegacyPerPackageConfig PackageConfig {..} =
haddockIndex = packageConfigHaddockIndex,
haddockBaseUrl = packageConfigHaddockBaseUrl,
haddockLib = packageConfigHaddockLib,
haddockOutputDir = packageConfigHaddockOutputDir,
haddockArgs = mempty
}

Expand Down Expand Up @@ -1305,7 +1307,7 @@ legacyPackageConfigFieldDescrs =
, "executables", "tests", "benchmarks", "all", "internal", "css"
, "hyperlink-source", "quickjump", "hscolour-css"
, "contents-location", "index-location", "keep-temp-files", "base-url"
, "lib"
, "lib", "output-dir"
]
. commandOptionsToFields
) (haddockOptions ParseArgs)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ data PackageConfig
packageConfigHaddockIndex :: Flag PathTemplate, --TODO: [required eventually] use this
packageConfigHaddockBaseUrl :: Flag String, --TODO: [required eventually] use this
packageConfigHaddockLib :: Flag String, --TODO: [required eventually] use this
packageConfigHaddockOutputDir :: Flag FilePath, --TODO: [required eventually] use this
packageConfigHaddockForHackage :: Flag HaddockTarget,
-- Test options
packageConfigTestHumanLog :: Flag PathTemplate,
Expand Down
5 changes: 3 additions & 2 deletions cabal-install/src/Distribution/Client/ProjectOrchestration.hs
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,8 @@ establishProjectBaseContextWithRoot
-> CurrentCommand
-> IO ProjectBaseContext
establishProjectBaseContextWithRoot verbosity cliConfig projectRoot currentCommand = do
let distDirLayout = defaultDistDirLayout projectRoot mdistDirectory
let haddockOutputDir = flagToMaybe (packageConfigHaddockOutputDir (projectConfigLocalPackages cliConfig))
let distDirLayout = defaultDistDirLayout projectRoot mdistDirectory haddockOutputDir

httpTransport <- configureTransport verbosity
(fromNubList . projectConfigProgPathExtra $ projectConfigShared cliConfig)
Expand Down Expand Up @@ -1359,7 +1360,7 @@ establishDummyProjectBaseContext verbosity projectConfig distDirLayout localPack

establishDummyDistDirLayout :: Verbosity -> ProjectConfig -> FilePath -> IO DistDirLayout
establishDummyDistDirLayout verbosity cliConfig tmpDir = do
let distDirLayout = defaultDistDirLayout projectRoot mdistDirectory
let distDirLayout = defaultDistDirLayout projectRoot mdistDirectory Nothing

-- Create the dist directories
createDirectoryIfMissingVerbose verbosity True $ distDirectory distDirLayout
Expand Down
5 changes: 4 additions & 1 deletion cabal-install/src/Distribution/Client/ProjectPlanning.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1983,6 +1983,7 @@ elaborateInstallPlan verbosity platform compiler compilerprogdb pkgConfigDB
elabHaddockIndex = perPkgOptionMaybe pkgid packageConfigHaddockIndex
elabHaddockBaseUrl = perPkgOptionMaybe pkgid packageConfigHaddockBaseUrl
elabHaddockLib = perPkgOptionMaybe pkgid packageConfigHaddockLib
elabHaddockOutputDir = perPkgOptionMaybe pkgid packageConfigHaddockOutputDir

elabTestMachineLog = perPkgOptionMaybe pkgid packageConfigTestMachineLog
elabTestHumanLog = perPkgOptionMaybe pkgid packageConfigTestHumanLog
Expand Down Expand Up @@ -3797,6 +3798,7 @@ setupHsHaddockFlags (ElaboratedConfiguredPackage{..}) (ElaboratedSharedConfig{..
haddockIndex = maybe mempty toFlag elabHaddockIndex,
haddockBaseUrl = maybe mempty toFlag elabHaddockBaseUrl,
haddockLib = maybe mempty toFlag elabHaddockLib,
haddockOutputDir = maybe mempty toFlag elabHaddockOutputDir,
haddockArgs = mempty
}

Expand Down Expand Up @@ -3953,7 +3955,8 @@ packageHashConfigInputs shared@ElaboratedSharedConfig{..} pkg =
pkgHashHaddockContents = elabHaddockContents,
pkgHashHaddockIndex = elabHaddockIndex,
pkgHashHaddockBaseUrl = elabHaddockBaseUrl,
pkgHashHaddockLib = elabHaddockLib
pkgHashHaddockLib = elabHaddockLib,
pkgHashHaddockOutputDir = elabHaddockOutputDir
}
where
ElaboratedConfiguredPackage{..} = normaliseConfiguredPackage shared pkg
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@ data ElaboratedConfiguredPackage
elabHaddockIndex :: Maybe PathTemplate,
elabHaddockBaseUrl :: Maybe String,
elabHaddockLib :: Maybe String,
elabHaddockOutputDir :: Maybe FilePath,

elabTestMachineLog :: Maybe PathTemplate,
elabTestHumanLog :: Maybe PathTemplate,
Expand Down
2 changes: 1 addition & 1 deletion cabal-install/src/Distribution/Client/Setup.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1779,7 +1779,7 @@ haddockOptions showOrParseArgs
, name `elem` ["hoogle", "html", "html-location"
,"executables", "tests", "benchmarks", "all", "internal", "css"
,"hyperlink-source", "quickjump", "hscolour-css"
,"contents-location", "use-index", "for-hackage", "base-url", "lib"]
,"contents-location", "use-index", "for-hackage", "base-url", "lib", "output-dir"]
]

testOptions :: ShowOrParseArgs -> [OptionField TestFlags]
Expand Down
4 changes: 2 additions & 2 deletions cabal-install/tests/IntegrationTests2.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1665,7 +1665,7 @@ configureProject testdir cliConfig = do
let projectRoot
| isexplict = ProjectRootExplicit projectRootDir defaultProjectFile
| otherwise = ProjectRootImplicit projectRootDir
distDirLayout = defaultDistDirLayout projectRoot Nothing
distDirLayout = defaultDistDirLayout projectRoot Nothing Nothing

-- Clear state between test runs. The state remains if the previous run
-- ended in an exception (as we leave the files to help with debugging).
Expand Down Expand Up @@ -1758,7 +1758,7 @@ cleanProject testdir = do
when alreadyExists $ removePathForcibly distDir
where
projectRoot = ProjectRootImplicit (basedir </> testdir)
distDirLayout = defaultDistDirLayout projectRoot Nothing
distDirLayout = defaultDistDirLayout projectRoot Nothing Nothing
distDir = distDirectory distDirLayout


Expand Down
Loading

0 comments on commit 7291b92

Please sign in to comment.