diff --git a/.gitignore b/.gitignore index 97632785e28624313137fdb3c53bb3ca8117b89d..957786d7055a7b214b7b2ed741986c09593ddaed 100644 --- a/.gitignore +++ b/.gitignore @@ -98,6 +98,9 @@ bench.html # Emacs .projectile +# direnv +.envrc + ## Release Scripts # ignore the downloaded binary files diff --git a/Cabal/src/Distribution/Simple/Haddock.hs b/Cabal/src/Distribution/Simple/Haddock.hs index 2429362d72ee99a02826c2e4f3c6045d29d869f3..657991e16b1cf86270faa552c71bceffab2c10d3 100644 --- a/Cabal/src/Distribution/Simple/Haddock.hs +++ b/Cabal/src/Distribution/Simple/Haddock.hs @@ -83,7 +83,6 @@ import Distribution.Types.ComponentLocalBuildInfo import Distribution.Types.ExposedModule import Distribution.Types.LocalBuildInfo import Distribution.Types.TargetInfo -import Distribution.Utils.NubList import Distribution.Utils.Path hiding ( Dir ) @@ -92,8 +91,6 @@ import qualified Distribution.Utils.ShortText as ShortText import Distribution.Verbosity import Distribution.Version -import Language.Haskell.Extension - import Control.Monad import Data.Either (rights) import System.Directory (doesDirectoryExist, doesFileExist) @@ -153,7 +150,7 @@ data HaddockArgs = HaddockArgs -- ^ Re-exported modules , argTargets :: [FilePath] -- ^ Modules to process. - , argLib :: Flag String + , argResourcesDir :: Flag String -- ^ haddock's static \/ auxiliary files. } deriving (Generic) @@ -357,118 +354,112 @@ haddock_setupHooks in for_ mbPbcRules $ \pbcRules -> do (ruleFromId, _mons) <- SetupHooks.computeRules verbosity inputs pbcRules SetupHooks.executeRules verbosity lbi2 tgt ruleFromId - preBuildComponent runPreBuildHooks verbosity lbi' target - preprocessComponent pkg_descr component lbi' clbi False verbosity suffixes - let - doExe com = case (compToExe com) of - Just exe -> do - withTempDirectoryCwdEx verbosity tmpFileOpts mbWorkDir (buildDir lbi') "tmp" $ - \tmp -> do - exeArgs <- - fromExecutable - verbosity - tmp - lbi' - clbi - htmlTemplate - version - exe - let exeArgs' = commonArgs `mappend` exeArgs - runHaddock - verbosity - mbWorkDir - tmpFileOpts - comp - platform - haddockProg - True - exeArgs' - Nothing -> do - warn - verbosity - "Unsupported component, skipping..." - return () - -- We define 'smsg' once and then reuse it inside the case, so that - -- we don't say we are running Haddock when we actually aren't - -- (e.g., Haddock is not run on non-libraries) - smsg :: IO () - smsg = - setupMessage' - verbosity - "Running Haddock on" - (packageId pkg_descr) - (componentLocalName clbi) - (maybeComponentInstantiatedWith clbi) - ipi <- case component of - CLib lib -> do - withTempDirectoryCwdEx verbosity tmpFileOpts mbWorkDir (buildDir lbi) "tmp" $ - \tmp -> do - smsg - libArgs <- - fromLibrary + + -- See Note [Hi Haddock Recompilation Avoidance] + reusingGHCCompilationArtifacts verbosity tmpFileOpts mbWorkDir lbi bi clbi version $ \haddockArtifactsDirs -> do + preBuildComponent runPreBuildHooks verbosity lbi' target + preprocessComponent pkg_descr component lbi' clbi False verbosity suffixes + let + doExe com = case (compToExe com) of + Just exe -> do + exeArgs <- + fromExecutable verbosity - tmp + haddockArtifactsDirs lbi' clbi htmlTemplate - version - lib - let libArgs' = commonArgs `mappend` libArgs - runHaddock verbosity mbWorkDir tmpFileOpts comp platform haddockProg True libArgs' - inplaceDir <- absoluteWorkingDirLBI lbi - - let - ipi = - inplaceInstalledPackageInfo - inplaceDir - (flag $ setupDistPref . haddockCommonFlags) - pkg_descr - (mkAbiHash "inplace") - lib - lbi' - clbi - - debug verbosity $ - "Registering inplace:\n" - ++ (InstalledPackageInfo.showInstalledPackageInfo ipi) - - registerPackage + exe + let exeArgs' = commonArgs `mappend` exeArgs + runHaddock verbosity - (compiler lbi') - (withPrograms lbi') mbWorkDir - (withPackageDB lbi') - ipi - HcPkg.defaultRegisterOptions - { HcPkg.registerMultiInstance = True - } + tmpFileOpts + comp + platform + haddockProg + True + exeArgs' + Nothing -> do + warn + verbosity + "Unsupported component, skipping..." + return () + -- We define 'smsg' once and then reuse it inside the case, so that + -- we don't say we are running Haddock when we actually aren't + -- (e.g., Haddock is not run on non-libraries) + smsg :: IO () + smsg = + setupMessage' + verbosity + "Running Haddock on" + (packageId pkg_descr) + (componentLocalName clbi) + (maybeComponentInstantiatedWith clbi) + ipi <- case component of + CLib lib -> do + smsg + libArgs <- + fromLibrary + verbosity + haddockArtifactsDirs + lbi' + clbi + htmlTemplate + lib + let libArgs' = commonArgs `mappend` libArgs + runHaddock verbosity mbWorkDir tmpFileOpts comp platform haddockProg True libArgs' + inplaceDir <- absoluteWorkingDirLBI lbi + + let + ipi = + inplaceInstalledPackageInfo + inplaceDir + (flag $ setupDistPref . haddockCommonFlags) + pkg_descr + (mkAbiHash "inplace") + lib + lbi' + clbi - return $ PackageIndex.insert ipi index - CFLib flib -> - when - (flag haddockForeignLibs) - ( do - withTempDirectoryCwdEx verbosity tmpFileOpts mbWorkDir (buildDir lbi') "tmp" $ - \tmp -> do - smsg - flibArgs <- - fromForeignLib - verbosity - tmp - lbi' - clbi - htmlTemplate - version - flib - let libArgs' = commonArgs `mappend` flibArgs - runHaddock verbosity mbWorkDir tmpFileOpts comp platform haddockProg True libArgs' - ) - >> return index - CExe _ -> when (flag haddockExecutables) (smsg >> doExe component) >> return index - CTest _ -> when (flag haddockTestSuites) (smsg >> doExe component) >> return index - CBench _ -> when (flag haddockBenchmarks) (smsg >> doExe component) >> return index + debug verbosity $ + "Registering inplace:\n" + ++ (InstalledPackageInfo.showInstalledPackageInfo ipi) + + registerPackage + verbosity + (compiler lbi') + (withPrograms lbi') + mbWorkDir + (withPackageDB lbi') + ipi + HcPkg.defaultRegisterOptions + { HcPkg.registerMultiInstance = True + } + + return $ PackageIndex.insert ipi index + CFLib flib -> + when + (flag haddockForeignLibs) + ( do + smsg + flibArgs <- + fromForeignLib + verbosity + haddockArtifactsDirs + lbi' + clbi + htmlTemplate + flib + let libArgs' = commonArgs `mappend` flibArgs + runHaddock verbosity mbWorkDir tmpFileOpts comp platform haddockProg True libArgs' + ) + >> return index + CExe _ -> when (flag haddockExecutables) (smsg >> doExe component) >> return index + CTest _ -> when (flag haddockTestSuites) (smsg >> doExe component) >> return index + CBench _ -> when (flag haddockBenchmarks) (smsg >> doExe component) >> return index - return ipi + return ipi for_ (extraDocFiles pkg_descr) $ \fpath -> do files <- matchDirFileGlob verbosity (specVersion pkg_descr) mbWorkDir fpath @@ -525,7 +516,7 @@ fromFlags env flags = (haddockIndex flags) , argGenIndex = Flag False , argBaseUrl = haddockBaseUrl flags - , argLib = haddockLib flags + , argResourcesDir = haddockResourcesDir flags , argVerbose = maybe mempty (Any . (>= deafening)) . flagToMaybe @@ -552,7 +543,7 @@ fromHaddockProjectFlags flags = , argPrologueFile = haddockProjectPrologue flags , argInterfaces = fromFlagOrDefault [] (haddockProjectInterfaces flags) , argLinkedSource = Flag True - , argLib = haddockProjectLib flags + , argResourcesDir = haddockProjectResourcesDir flags } fromPackageDescription :: HaddockTarget -> PackageDescription -> HaddockArgs @@ -595,38 +586,70 @@ componentGhcOptions verbosity lbi bi clbi odir = ++ "haddock only supports GHC and GHCJS" in f verbosity lbi bi clbi odir +{- +Note [Hi Haddock Recompilation Avoidance] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Starting with Haddock 2.28, we no longer want to run Haddock's GHC session in +an arbitrary temporary directory. Doing so always causes recompilation during +documentation generation, which can now be avoided thanks to Hi Haddock. + +Instead, we want to re-use the interface and object files produced by GHC. +We copy these intermediate files produced by GHC to temporary directories and +point haddock to them. + +The reason why we can't use the GHC files /inplace/ is that haddock may have to +recompile (e.g. because of `haddock-options`). In that case, we want to be sure +the files produced by GHC do not get overwritten. + +See https://github.com/haskell/cabal/pull/9177 for discussion. + +(W.1) As it turns out, -stubdir is included in GHC's recompilation fingerprint. +This means that if we use a temporary directory for stubfiles produced by GHC +for the haddock invocation, haddock will trigger full recompilation since the +stubdir would be different. + +So we don't use a temporary stubdir, despite the tmp o-dir and hi-dir: + +We want to avoid at all costs haddock accidentally overwriting o-files and +hi-files (e.g. if a user specified haddock-option triggers recompilation), and +thus copy them to a temporary directory to pass them on to haddock. However, +stub files are much less problematic since ABI-incompatibility isn't at play +here, that is, there doesn't seem to be a GHC flag that could accidentally make +a stub file incompatible with the one produced by GHC from the same module. +-} + mkHaddockArgs :: Verbosity - -> SymbolicPath Pkg (Path.Dir Tmp) + -> (SymbolicPath Pkg (Path.Dir Artifacts), SymbolicPath Pkg (Path.Dir Artifacts), SymbolicPath Pkg (Path.Dir Artifacts)) + -- ^ Directories for -hidir, -odir, and -stubdir to GHC through Haddock. + -- See Note [Hi Haddock Recompilation Avoidance] -> LocalBuildInfo -> ComponentLocalBuildInfo -> Maybe PathTemplate -- ^ template for HTML location - -> Version -> [SymbolicPath Pkg File] -> BuildInfo -> IO HaddockArgs -mkHaddockArgs verbosity tmp lbi clbi htmlTemplate haddockVersion inFiles bi = do +mkHaddockArgs verbosity (tmpObjDir, tmpHiDir, tmpStubDir) lbi clbi htmlTemplate inFiles bi = do + let + vanillaOpts' = + componentGhcOptions normal lbi bi clbi (buildDir lbi) + vanillaOpts = + vanillaOpts' + { -- See Note [Hi Haddock Recompilation Avoidance] + ghcOptObjDir = toFlag tmpObjDir + , ghcOptHiDir = toFlag tmpHiDir + , ghcOptStubDir = toFlag tmpStubDir + } + sharedOpts = + vanillaOpts + { ghcOptDynLinkMode = toFlag GhcDynamicOnly + , ghcOptFPic = toFlag True + , ghcOptHiSuffix = toFlag "dyn_hi" + , ghcOptObjSuffix = toFlag "dyn_o" + , ghcOptExtra = hcSharedOptions GHC bi + } ifaceArgs <- getInterfaces verbosity lbi clbi htmlTemplate - let vanillaOpts = - (componentGhcOptions normal lbi bi clbi (buildDir lbi)) - { -- Noooooooooo!!!!!111 - -- haddock stomps on our precious .hi - -- and .o files. Workaround by telling - -- haddock to write them elsewhere. - ghcOptObjDir = toFlag $ coerceSymbolicPath tmp - , ghcOptHiDir = toFlag $ coerceSymbolicPath tmp - , ghcOptStubDir = toFlag $ coerceSymbolicPath tmp - } - `mappend` getGhcCppOpts haddockVersion bi - sharedOpts = - vanillaOpts - { ghcOptDynLinkMode = toFlag GhcDynamicOnly - , ghcOptFPic = toFlag True - , ghcOptHiSuffix = toFlag "dyn_hi" - , ghcOptObjSuffix = toFlag "dyn_o" - , ghcOptExtra = hcSharedOptions GHC bi - } opts <- if withVanillaLib lbi then return vanillaOpts @@ -644,24 +667,24 @@ mkHaddockArgs verbosity tmp lbi clbi htmlTemplate haddockVersion inFiles bi = do fromLibrary :: Verbosity - -> SymbolicPath Pkg (Path.Dir Tmp) + -> (SymbolicPath Pkg (Path.Dir Artifacts), SymbolicPath Pkg (Path.Dir Artifacts), SymbolicPath Pkg (Path.Dir Artifacts)) + -- ^ Directories for -hidir, -odir, and -stubdir to GHC through Haddock. + -- See Note [Hi Haddock Recompilation Avoidance] -> LocalBuildInfo -> ComponentLocalBuildInfo -> Maybe PathTemplate -- ^ template for HTML location - -> Version -> Library -> IO HaddockArgs -fromLibrary verbosity tmp lbi clbi htmlTemplate haddockVersion lib = do +fromLibrary verbosity haddockArtifactsDirs lbi clbi htmlTemplate lib = do inFiles <- map snd `fmap` getLibSourceFiles verbosity lbi lib clbi args <- mkHaddockArgs verbosity - tmp + haddockArtifactsDirs lbi clbi htmlTemplate - haddockVersion inFiles (libBuildInfo lib) return @@ -671,24 +694,24 @@ fromLibrary verbosity tmp lbi clbi htmlTemplate haddockVersion lib = do fromExecutable :: Verbosity - -> SymbolicPath Pkg (Path.Dir Tmp) + -> (SymbolicPath Pkg (Path.Dir Artifacts), SymbolicPath Pkg (Path.Dir Artifacts), SymbolicPath Pkg (Path.Dir Artifacts)) + -- ^ Directories for -hidir, -odir, and -stubdir to GHC through Haddock. + -- See Note [Hi Haddock Recompilation Avoidance] -> LocalBuildInfo -> ComponentLocalBuildInfo -> Maybe PathTemplate -- ^ template for HTML location - -> Version -> Executable -> IO HaddockArgs -fromExecutable verbosity tmp lbi clbi htmlTemplate haddockVersion exe = do +fromExecutable verbosity haddockArtifactsDirs lbi clbi htmlTemplate exe = do inFiles <- map snd `fmap` getExeSourceFiles verbosity lbi exe clbi args <- mkHaddockArgs verbosity - tmp + haddockArtifactsDirs lbi clbi htmlTemplate - haddockVersion inFiles (buildInfo exe) return @@ -699,24 +722,24 @@ fromExecutable verbosity tmp lbi clbi htmlTemplate haddockVersion exe = do fromForeignLib :: Verbosity - -> SymbolicPath Pkg (Path.Dir Tmp) + -> (SymbolicPath Pkg (Path.Dir Artifacts), SymbolicPath Pkg (Path.Dir Artifacts), SymbolicPath Pkg (Path.Dir Artifacts)) + -- ^ Directories for -hidir, -odir, and -stubdir to GHC through Haddock. + -- See Note [Hi Haddock Recompilation Avoidance] -> LocalBuildInfo -> ComponentLocalBuildInfo -> Maybe PathTemplate -- ^ template for HTML location - -> Version -> ForeignLib -> IO HaddockArgs -fromForeignLib verbosity tmp lbi clbi htmlTemplate haddockVersion flib = do +fromForeignLib verbosity haddockArtifactsDirs lbi clbi htmlTemplate flib = do inFiles <- map snd `fmap` getFLibSourceFiles verbosity lbi flib clbi args <- mkHaddockArgs verbosity - tmp + haddockArtifactsDirs lbi clbi htmlTemplate - haddockVersion inFiles (foreignLibBuildInfo flib) return @@ -767,28 +790,6 @@ getReexports LibComponentLocalBuildInfo{componentExposedModules = mods} = mapMaybe exposedReexport mods getReexports _ = [] -getGhcCppOpts - :: Version - -> BuildInfo - -> GhcOptions -getGhcCppOpts haddockVersion bi = - mempty - { ghcOptExtensions = toNubListR [EnableExtension CPP | needsCpp] - , ghcOptCppOptions = defines - } - where - needsCpp = EnableExtension CPP `elem` usedExtensions bi - defines = [haddockVersionMacro] - haddockVersionMacro = - "-D__HADDOCK_VERSION__=" - ++ show (v1 * 1000 + v2 * 10 + v3) - where - (v1, v2, v3) = case versionNumbers haddockVersion of - [] -> (0, 0, 0) - [x] -> (x, 0, 0) - [x, y] -> (x, y, 0) - (x : y : z : _) -> (x, y, z) - getGhcLibDir :: Verbosity -> LocalBuildInfo @@ -800,6 +801,47 @@ getGhcLibDir verbosity lbi = do _ -> error "haddock only supports GHC and GHCJS" return $ mempty{argGhcLibDir = Flag l} +-- | If Hi Haddock is supported, this function creates temporary directories +-- and copies existing interface and object files produced by GHC into them, +-- then passes them off to the given continuation. +-- +-- If Hi Haddock is _not_ supported, we can't re-use GHC's compilation files. +-- Instead, we use a clean temporary directory to the continuation, +-- with no hope for recompilation avoidance. +-- +-- See Note [Hi Haddock Recompilation Avoidance] +reusingGHCCompilationArtifacts + :: Verbosity + -> TempFileOptions + -> Maybe (SymbolicPath CWD (Path.Dir Pkg)) + -- ^ Working directory + -> LocalBuildInfo + -> BuildInfo + -> ComponentLocalBuildInfo + -> Version + -- ^ Haddock's version + -> ((SymbolicPath Pkg (Path.Dir Artifacts), SymbolicPath Pkg (Path.Dir Artifacts), SymbolicPath Pkg (Path.Dir Artifacts)) -> IO r) + -- ^ Continuation + -> IO r +reusingGHCCompilationArtifacts verbosity tmpFileOpts mbWorkDir lbi bi clbi version act + | version >= mkVersion [2, 28, 0] = do + withTempDirectoryCwdEx verbosity tmpFileOpts mbWorkDir (distPrefLBI lbi) "haddock-objs" $ \tmpObjDir -> + withTempDirectoryCwdEx verbosity tmpFileOpts mbWorkDir (distPrefLBI lbi) "haddock-his" $ \tmpHiDir -> do + -- Re-use ghc's interface and obj files, but first copy them to + -- somewhere where it is safe if haddock overwrites them + let + vanillaOpts = componentGhcOptions normal lbi bi clbi (buildDir lbi) + i = interpretSymbolicPath mbWorkDir + copyDir ghcDir tmpDir = copyDirectoryRecursive verbosity (i $ fromFlag $ ghcDir vanillaOpts) (i tmpDir) + copyDir ghcOptObjDir tmpObjDir + copyDir ghcOptHiDir tmpHiDir + -- copyDir ghcOptStubDir tmpStubDir -- (see W.1 in Note [Hi Haddock Recompilation Avoidance]) + + act (tmpObjDir, tmpHiDir, fromFlag $ ghcOptHiDir vanillaOpts) + | otherwise = do + withTempDirectoryCwdEx verbosity tmpFileOpts mbWorkDir (distPrefLBI lbi) "tmp" $ + \tmpFallback -> act (tmpFallback, tmpFallback, tmpFallback) + -- ------------------------------------------------------------------------------ -- | Call haddock with the specified arguments. @@ -993,7 +1035,11 @@ renderPureArgs version comp platform args = , isVersion 2 19 ] , argTargets $ args - , maybe [] ((: []) . ("--lib=" ++)) . flagToMaybe . argLib $ args + , maybe [] ((: []) . (resourcesDirFlag ++)) . flagToMaybe . argResourcesDir $ args + , -- Do not re-direct compilation output to a temporary directory (--no-tmp-comp-dir) + -- We pass this option by default to haddock to avoid recompilation + -- See Note [Hi Haddock Recompilation Avoidance] + ["--no-tmp-comp-dir" | version >= mkVersion [2, 28, 0]] ] where -- See Note [Symbolic paths] in Distribution.Utils.Path @@ -1037,6 +1083,9 @@ renderPureArgs version comp platform args = verbosityFlag | isVersion 2 5 = "--verbosity=1" | otherwise = "--verbose" + resourcesDirFlag + | isVersion 2 29 = "--resources-dir=" + | otherwise = "--lib=" haddockSupportsVisibility = version >= mkVersion [2, 26, 1] haddockSupportsPackageName = version > mkVersion [2, 16] haddockSupportsHyperlinkedSource = isVersion 2 17 @@ -1309,7 +1358,8 @@ hscolour' where outFile m = i outputDir - </> intercalate "-" (ModuleName.components m) <.> "html" + </> intercalate "-" (ModuleName.components m) + <.> "html" haddockToHscolour :: HaddockFlags -> HscolourFlags haddockToHscolour flags = diff --git a/Cabal/src/Distribution/Simple/Setup/Haddock.hs b/Cabal/src/Distribution/Simple/Setup/Haddock.hs index bcb2c9dbc5ed261f3124ccfd10f73cf726c24db0..402544ce5111754648a86b1260fd59dcc21c8d67 100644 --- a/Cabal/src/Distribution/Simple/Setup/Haddock.hs +++ b/Cabal/src/Distribution/Simple/Setup/Haddock.hs @@ -113,7 +113,7 @@ data HaddockFlags = HaddockFlags , haddockIndex :: Flag PathTemplate , haddockKeepTempFiles :: Flag Bool , haddockBaseUrl :: Flag String - , haddockLib :: Flag String + , haddockResourcesDir :: Flag String , haddockOutputDir :: Flag FilePath } deriving (Show, Generic, Typeable) @@ -168,7 +168,7 @@ defaultHaddockFlags = , haddockKeepTempFiles = Flag False , haddockIndex = NoFlag , haddockBaseUrl = NoFlag - , haddockLib = NoFlag + , haddockResourcesDir = NoFlag , haddockOutputDir = NoFlag } @@ -366,10 +366,10 @@ haddockOptions showOrParseArgs = (reqArgFlag "URL") , option "" - ["lib"] + ["resources-dir"] "location of Haddocks static / auxiliary files" - haddockLib - (\v flags -> flags{haddockLib = v}) + haddockResourcesDir + (\v flags -> flags{haddockResourcesDir = v}) (reqArgFlag "DIR") , option "" @@ -440,7 +440,7 @@ data HaddockProjectFlags = HaddockProjectFlags haddockProjectKeepTempFiles :: Flag Bool , haddockProjectVerbosity :: Flag Verbosity , -- haddockBaseUrl is not supported, a fixed value is provided - haddockProjectLib :: Flag String + haddockProjectResourcesDir :: Flag String , haddockProjectOutputDir :: Flag FilePath } deriving (Show, Generic, Typeable) @@ -464,7 +464,7 @@ defaultHaddockProjectFlags = , haddockProjectHscolourCss = NoFlag , haddockProjectKeepTempFiles = Flag False , haddockProjectVerbosity = Flag normal - , haddockProjectLib = NoFlag + , haddockProjectResourcesDir = NoFlag , haddockProjectOutputDir = NoFlag , haddockProjectInterfaces = NoFlag } @@ -608,10 +608,10 @@ haddockProjectOptions _showOrParseArgs = (\v flags -> flags{haddockProjectVerbosity = v}) , option "" - ["lib"] + ["resources-dir"] "location of Haddocks static / auxiliary files" - haddockProjectLib - (\v flags -> flags{haddockProjectLib = v}) + haddockProjectResourcesDir + (\v flags -> flags{haddockProjectResourcesDir = v}) (reqArgFlag "DIR") , option "" diff --git a/Cabal/src/Distribution/Types/LocalBuildInfo.hs b/Cabal/src/Distribution/Types/LocalBuildInfo.hs index a5706fff09a1108773f00b27eea2b70feb013b63..3f9d8d742682675e87a362a51fcbd7c06ce7f432 100644 --- a/Cabal/src/Distribution/Types/LocalBuildInfo.hs +++ b/Cabal/src/Distribution/Types/LocalBuildInfo.hs @@ -57,6 +57,7 @@ module Distribution.Types.LocalBuildInfo , buildDir , buildDirPBD , setupFlagsBuildDir + , distPrefLBI , packageRoot , progPrefix , progSuffix @@ -289,6 +290,9 @@ buildDirPBD (LBC.PackageBuildDescr{configFlags = cfg}) = setupFlagsBuildDir :: CommonSetupFlags -> SymbolicPath Pkg (Dir Build) setupFlagsBuildDir cfg = fromFlag (setupDistPref cfg) </> makeRelativePathEx "build" +distPrefLBI :: LocalBuildInfo -> SymbolicPath Pkg (Dir Dist) +distPrefLBI = fromFlag . setupDistPref . configCommonFlags . LBC.configFlags . LBC.packageBuildDescr . localBuildDescr + -- | The (relative or absolute) path to the package root, based on -- -- - the working directory flag diff --git a/cabal-install/src/Distribution/Client/CmdHaddockProject.hs b/cabal-install/src/Distribution/Client/CmdHaddockProject.hs index bf21de2d35274e4cb47a84612c2c07d86f131ceb..8c0c21a54272f8221f4041dce9bcdd19657ed592 100644 --- a/cabal-install/src/Distribution/Client/CmdHaddockProject.hs +++ b/cabal-install/src/Distribution/Client/CmdHaddockProject.hs @@ -148,7 +148,7 @@ haddockProjectAction flags _extraArgs globalFlags = do then Flag (toPathTemplate "../doc-index.html") else NoFlag , haddockKeepTempFiles = haddockProjectKeepTempFiles flags - , haddockLib = haddockProjectLib flags + , haddockResourcesDir = haddockProjectResourcesDir flags , haddockOutputDir = haddockProjectOutputDir flags } nixFlags = diff --git a/cabal-install/src/Distribution/Client/Config.hs b/cabal-install/src/Distribution/Client/Config.hs index fd9bd5af43224b659f3c32ada968900919c31e7f..d9b91c959d023e6ac83710b4aa199a6ea878c2d5 100644 --- a/cabal-install/src/Distribution/Client/Config.hs +++ b/cabal-install/src/Distribution/Client/Config.hs @@ -630,7 +630,7 @@ instance Semigroup SavedConfig where , haddockKeepTempFiles = combine haddockKeepTempFiles , haddockIndex = combine haddockIndex , haddockBaseUrl = combine haddockBaseUrl - , haddockLib = combine haddockLib + , haddockResourcesDir = combine haddockResourcesDir , haddockOutputDir = combine haddockOutputDir } where diff --git a/cabal-install/src/Distribution/Client/PackageHash.hs b/cabal-install/src/Distribution/Client/PackageHash.hs index f5387a37bd87004e19818fc0202a786fd2218f83..2e7b9320e3dec4008384694274aaaaefa0710c4a 100644 --- a/cabal-install/src/Distribution/Client/PackageHash.hs +++ b/cabal-install/src/Distribution/Client/PackageHash.hs @@ -238,7 +238,7 @@ data PackageHashConfigInputs = PackageHashConfigInputs , pkgHashHaddockContents :: Maybe PathTemplate , pkgHashHaddockIndex :: Maybe PathTemplate , pkgHashHaddockBaseUrl :: Maybe String - , pkgHashHaddockLib :: Maybe String + , pkgHashHaddockResourcesDir :: Maybe String , pkgHashHaddockOutputDir :: Maybe FilePath -- TODO: [required eventually] pkgHashToolsVersions ? -- TODO: [required eventually] pkgHashToolsExtraOptions ? @@ -347,7 +347,7 @@ renderPackageHashInputs , opt "haddock-contents-location" Nothing (maybe "" fromPathTemplate) pkgHashHaddockContents , opt "haddock-index-location" Nothing (maybe "" fromPathTemplate) pkgHashHaddockIndex , opt "haddock-base-url" Nothing (fromMaybe "") pkgHashHaddockBaseUrl - , opt "haddock-lib" Nothing (fromMaybe "") pkgHashHaddockLib + , opt "haddock-resources-dir" Nothing (fromMaybe "") pkgHashHaddockResourcesDir , opt "haddock-output-dir" Nothing (fromMaybe "") pkgHashHaddockOutputDir ] ++ Map.foldrWithKey (\prog args acc -> opt (prog ++ "-options") [] unwords args : acc) [] pkgHashProgramArgs diff --git a/cabal-install/src/Distribution/Client/ProjectConfig/Legacy.hs b/cabal-install/src/Distribution/Client/ProjectConfig/Legacy.hs index fe2e86d8cccaff1a63e9a9db81cbd38d4a69a161..ddb6f6152649f66a3f2b62d986a411708cda1c31 100644 --- a/cabal-install/src/Distribution/Client/ProjectConfig/Legacy.hs +++ b/cabal-install/src/Distribution/Client/ProjectConfig/Legacy.hs @@ -821,7 +821,7 @@ convertLegacyPerPackageFlags , haddockContents = packageConfigHaddockContents , haddockIndex = packageConfigHaddockIndex , haddockBaseUrl = packageConfigHaddockBaseUrl - , haddockLib = packageConfigHaddockLib + , haddockResourcesDir = packageConfigHaddockResourcesDir , haddockOutputDir = packageConfigHaddockOutputDir } = haddockFlags @@ -1218,7 +1218,7 @@ convertToLegacyPerPackageConfig PackageConfig{..} = , haddockKeepTempFiles = mempty , haddockIndex = packageConfigHaddockIndex , haddockBaseUrl = packageConfigHaddockBaseUrl - , haddockLib = packageConfigHaddockLib + , haddockResourcesDir = packageConfigHaddockResourcesDir , haddockOutputDir = packageConfigHaddockOutputDir } @@ -1619,7 +1619,7 @@ legacyPackageConfigFieldDescrs = , "index-location" , "keep-temp-files" , "base-url" - , "lib" + , "resources-dir" , "output-dir" ] . commandOptionsToFields diff --git a/cabal-install/src/Distribution/Client/ProjectConfig/Types.hs b/cabal-install/src/Distribution/Client/ProjectConfig/Types.hs index 3e8e3ba1b07d698369d283145df7015df9dc4299..2a6f9589cbb5104453952d5d13de6e20c6463a24 100644 --- a/cabal-install/src/Distribution/Client/ProjectConfig/Types.hs +++ b/cabal-install/src/Distribution/Client/ProjectConfig/Types.hs @@ -305,7 +305,7 @@ data PackageConfig = PackageConfig , packageConfigHaddockContents :: Flag PathTemplate -- TODO: [required eventually] use this , packageConfigHaddockIndex :: Flag PathTemplate -- TODO: [required eventually] use this , packageConfigHaddockBaseUrl :: Flag String -- TODO: [required eventually] use this - , packageConfigHaddockLib :: Flag String -- TODO: [required eventually] use this + , packageConfigHaddockResourcesDir :: Flag String -- TODO: [required eventually] use this , packageConfigHaddockOutputDir :: Flag FilePath -- TODO: [required eventually] use this , packageConfigHaddockForHackage :: Flag HaddockTarget , -- Test options diff --git a/cabal-install/src/Distribution/Client/ProjectPlanning.hs b/cabal-install/src/Distribution/Client/ProjectPlanning.hs index ea4fae8ab8caf599420edaa1ed41fa1485a0dc95..43c835f7a0dcc58611748fb518f68bcf64b98805 100644 --- a/cabal-install/src/Distribution/Client/ProjectPlanning.hs +++ b/cabal-install/src/Distribution/Client/ProjectPlanning.hs @@ -2163,6 +2163,13 @@ elaborateInstallPlan elabBuildHaddocks = perPkgOptionFlag pkgid False packageConfigDocumentation + -- `documentation: true` should imply `-haddock` for GHC + addHaddockIfDocumentationEnabled :: ConfiguredProgram -> ConfiguredProgram + addHaddockIfDocumentationEnabled cp@ConfiguredProgram{..} = + if programId == "ghc" && elabBuildHaddocks + then cp{programOverrideArgs = "-haddock" : programOverrideArgs} + else cp + elabPkgSourceLocation = srcloc elabPkgSourceHash = Map.lookup pkgid sourcePackageHashes elabLocalToProject = isLocalToProject pkg @@ -2242,7 +2249,7 @@ elaborateInstallPlan Map.fromList [ (programId prog, args) | prog <- configuredPrograms compilerprogdb - , let args = programOverrideArgs prog + , let args = programOverrideArgs $ addHaddockIfDocumentationEnabled prog , not (null args) ] <> perPkgOptionMapMappend pkgid packageConfigProgramArgs @@ -2271,7 +2278,7 @@ elaborateInstallPlan elabHaddockContents = perPkgOptionMaybe pkgid packageConfigHaddockContents elabHaddockIndex = perPkgOptionMaybe pkgid packageConfigHaddockIndex elabHaddockBaseUrl = perPkgOptionMaybe pkgid packageConfigHaddockBaseUrl - elabHaddockLib = perPkgOptionMaybe pkgid packageConfigHaddockLib + elabHaddockResourcesDir = perPkgOptionMaybe pkgid packageConfigHaddockResourcesDir elabHaddockOutputDir = perPkgOptionMaybe pkgid packageConfigHaddockOutputDir elabTestMachineLog = perPkgOptionMaybe pkgid packageConfigTestMachineLog @@ -4138,7 +4145,7 @@ setupHsHaddockFlags , haddockKeepTempFiles = toFlag keepTmpFiles , haddockIndex = maybe mempty toFlag elabHaddockIndex , haddockBaseUrl = maybe mempty toFlag elabHaddockBaseUrl - , haddockLib = maybe mempty toFlag elabHaddockLib + , haddockResourcesDir = maybe mempty toFlag elabHaddockResourcesDir , haddockOutputDir = maybe mempty toFlag elabHaddockOutputDir } @@ -4296,7 +4303,7 @@ packageHashConfigInputs shared@ElaboratedSharedConfig{..} pkg = , pkgHashHaddockContents = elabHaddockContents , pkgHashHaddockIndex = elabHaddockIndex , pkgHashHaddockBaseUrl = elabHaddockBaseUrl - , pkgHashHaddockLib = elabHaddockLib + , pkgHashHaddockResourcesDir = elabHaddockResourcesDir , pkgHashHaddockOutputDir = elabHaddockOutputDir } where diff --git a/cabal-install/src/Distribution/Client/ProjectPlanning/Types.hs b/cabal-install/src/Distribution/Client/ProjectPlanning/Types.hs index 5b4896b05685b91ef55bfa44c17dcb1195a15b88..352e35d415017304d47b49e513bb8b2669ac590a 100644 --- a/cabal-install/src/Distribution/Client/ProjectPlanning/Types.hs +++ b/cabal-install/src/Distribution/Client/ProjectPlanning/Types.hs @@ -300,7 +300,7 @@ data ElaboratedConfiguredPackage = ElaboratedConfiguredPackage , elabHaddockContents :: Maybe PathTemplate , elabHaddockIndex :: Maybe PathTemplate , elabHaddockBaseUrl :: Maybe String - , elabHaddockLib :: Maybe String + , elabHaddockResourcesDir :: Maybe String , elabHaddockOutputDir :: Maybe FilePath , elabTestMachineLog :: Maybe PathTemplate , elabTestHumanLog :: Maybe PathTemplate diff --git a/cabal-install/src/Distribution/Client/Setup.hs b/cabal-install/src/Distribution/Client/Setup.hs index ae21e7f37995d9e698f4b0afbbab02088dfe024b..8fea76bae3b99bd9cd55a7dbad21940b5419de6a 100644 --- a/cabal-install/src/Distribution/Client/Setup.hs +++ b/cabal-install/src/Distribution/Client/Setup.hs @@ -2435,7 +2435,7 @@ haddockOptions showOrParseArgs = , "use-index" , "for-hackage" , "base-url" - , "lib" + , "resources-dir" , "output-dir" ] ] diff --git a/cabal-install/tests/IntegrationTests2.hs b/cabal-install/tests/IntegrationTests2.hs index a917e48efadec0df1f5ca91a9691c623e576b42e..b5b49053b6d67200c17522c6e8298fe770202038 100644 --- a/cabal-install/tests/IntegrationTests2.hs +++ b/cabal-install/tests/IntegrationTests2.hs @@ -2099,6 +2099,7 @@ testConfigOptionComments = do " -- contents-location" @=? findLineWith True "contents-location" defaultConfigFile " -- index-location" @=? findLineWith True "index-location" defaultConfigFile " -- base-url" @=? findLineWith True "base-url" defaultConfigFile + " -- resources-dir" @=? findLineWith True "resources-dir" defaultConfigFile " -- output-dir" @=? findLineWith True "output-dir" defaultConfigFile " -- interactive" @=? findLineWith True "interactive" defaultConfigFile diff --git a/cabal-install/tests/UnitTests/Distribution/Client/ProjectConfig.hs b/cabal-install/tests/UnitTests/Distribution/Client/ProjectConfig.hs index abdc1e7939040b428e647831ff1d464f00715f76..946e0bf48fdba46321ed2182f5adb7caa7cd1548 100644 --- a/cabal-install/tests/UnitTests/Distribution/Client/ProjectConfig.hs +++ b/cabal-install/tests/UnitTests/Distribution/Client/ProjectConfig.hs @@ -791,7 +791,7 @@ instance Arbitrary PackageConfig where , packageConfigHaddockForHackage = x41 , packageConfigHaddockIndex = x54 , packageConfigHaddockBaseUrl = x55 - , packageConfigHaddockLib = x56 + , packageConfigHaddockResourcesDir = x56 , packageConfigHaddockOutputDir = x57 , packageConfigTestHumanLog = x44 , packageConfigTestMachineLog = x45 @@ -854,7 +854,7 @@ instance Arbitrary PackageConfig where , packageConfigHaddockForHackage = x41' , packageConfigHaddockIndex = x54' , packageConfigHaddockBaseUrl = x55' - , packageConfigHaddockLib = x56' + , packageConfigHaddockResourcesDir = x56' , packageConfigHaddockOutputDir = x57' , packageConfigTestHumanLog = x44' , packageConfigTestMachineLog = x45' diff --git a/cabal-testsuite/PackageTests/NewHaddock/Fails/cabal.out b/cabal-testsuite/PackageTests/NewHaddock/Fails/cabal.out index b1bcf12d3fa9acb405b947b6e28b22b390206782..bb0ee5b906d4c409ce6ddab1e090398aaba24644 100644 --- a/cabal-testsuite/PackageTests/NewHaddock/Fails/cabal.out +++ b/cabal-testsuite/PackageTests/NewHaddock/Fails/cabal.out @@ -11,7 +11,8 @@ Failed to build example-1.0-inplace. # cabal v2-haddock Build profile: -w ghc-<GHCVER> -O1 In order, the following will be built: - - example-1.0 (lib) (first run) + - example-1.0 (lib) (configuration changed) +Configuring library for example-1.0... Preprocessing library for example-1.0... Running Haddock on library for example-1.0... Error: [Cabal-7125] diff --git a/changelog.d/pr-9177 b/changelog.d/pr-9177 new file mode 100644 index 0000000000000000000000000000000000000000..6b1eb227350e94149769c44fb7e0ea68e0ee5eeb --- /dev/null +++ b/changelog.d/pr-9177 @@ -0,0 +1,31 @@ +synopsis: Enable recompilation avoidance during Haddock generation +packages: cabal-install +prs: #9177 +issues: #9175 + +description: { + +* Haddock no longer writes compilation files by default, so we do not need to + pass tmp dirs for `-hidir`, `-stubdir`, and `-odir` via `--optghc`. Indeed, we + do not *want* to do so, since it results in recompilation for every invocation + of Haddock via Cabal. We now stop this from happening for Haddock versions + 2.28 and greater, since that is when Hi Haddock was introduced. + +* We no longer define the `__HADDOCK_VERSION__` macro when invoking GHC through + Haddock, since doing so essentially guarantees recompilation during + documentation generation. We audited all uses of `__HADDOCK_VERSION__` in + hackage, ensuring there was a reasonable path forward to migrate away from + using `__HADDOCK_VERSION__` for each, while generating the same documentation + as it did before. + If you are a user of `__HADDOCK_VERSION__`, please take a look at the + discussion in https://github.com/haskell/cabal/pull/9177 and reach out to us + if your use case is not covered. + +* Rename the `--haddock-lib` flag to `--haddock-resources-dir` (and + `haddock-lib:` cabal.project field to `haddock-resources-dir:`), and add this + flag to the users guide since it was missing an entry. + +* `documentation: true` or `--enable-documentation` now implies `-haddock` for + GHC. + +} diff --git a/doc/cabal-project-description-file.rst b/doc/cabal-project-description-file.rst index b76d383daccb1ae4b819852e4d83b01ec9d19fbd..c1f29bfc052e93a1be82c3121b8f9b8d74c2be9c 100644 --- a/doc/cabal-project-description-file.rst +++ b/doc/cabal-project-description-file.rst @@ -1610,6 +1610,15 @@ running ``setup haddock``. This flag is provided as a technology preview and is subject to change in the next releases. +.. cfg-field:: haddock-resources-dir: DIR + --haddock-resources-dir=DIR + :synopsis: Location of Haddock's static/auxiliary files. + + Location of Haddock's static/auxiliary files. For Haddock distributed with + GHC (or, more precisely, built within the GHC source tree), this path should + be automatically inferred. For Haddock built from source, however, this path + should likely be explicitly set for every Haddock invocation. + .. cfg-field:: open: boolean --open :synopsis: Open generated documentation in-browser. diff --git a/release-notes/WIP-Cabal-3.12.x.0.md b/release-notes/WIP-Cabal-3.12.x.0.md new file mode 100644 index 0000000000000000000000000000000000000000..d1f2d17f04f12f70cc67b09fb60074f88a3e56f0 --- /dev/null +++ b/release-notes/WIP-Cabal-3.12.x.0.md @@ -0,0 +1,19 @@ +Cabal 3.12.1.0 changelog and release notes. + +This file will be edited and the changes incorprated into the official +3.12.1.0 Cabal and Cabal-syntax release notes. + +--- + +### Significant changes + +- Deprecation of the `__HADDOCK_VERSION__` macro: + In the next major version of Cabal, we no longer define the + `__HADDOCK_VERSION__` macro when invoking GHC through Haddock, since doing + so essentially guarantees recompilation during documentation generation. We + audited all uses of `__HADDOCK_VERSION__` in hackage, ensuring there was a + reasonable path forward to migrate away from using `__HADDOCK_VERSION__` for + each, while generating the same documentation as it did before. If you are + a user of `__HADDOCK_VERSION__`, please take a look at the discussion in + https://github.com/haskell/cabal/pull/9177 and reach out to us if your use + case is not covered. diff --git a/test/IntegrationTests2/config/default-config b/test/IntegrationTests2/config/default-config index 8e3aa02742c576313e6e9e0652e3ae1346754bcb..e74a2c9776411decebb13ff291f3bd15403c86b2 100644 --- a/test/IntegrationTests2/config/default-config +++ b/test/IntegrationTests2/config/default-config @@ -33,8 +33,8 @@ remote-repo-cache: /home/colton/.cabal/packages -- cabal-file: -- with-compiler: -- with-hc-pkg: --- program-prefix: --- program-suffix: +-- program-prefix: +-- program-suffix: -- library-vanilla: True -- library-profiling: -- shared: @@ -141,7 +141,7 @@ haddock -- contents-location: -- index-location: -- base-url: - -- lib: + -- resources-dir: -- output-dir: init diff --git a/test/IntegrationTests2/nix-config/default-config b/test/IntegrationTests2/nix-config/default-config index 8e3aa02742c576313e6e9e0652e3ae1346754bcb..e74a2c9776411decebb13ff291f3bd15403c86b2 100644 --- a/test/IntegrationTests2/nix-config/default-config +++ b/test/IntegrationTests2/nix-config/default-config @@ -33,8 +33,8 @@ remote-repo-cache: /home/colton/.cabal/packages -- cabal-file: -- with-compiler: -- with-hc-pkg: --- program-prefix: --- program-suffix: +-- program-prefix: +-- program-suffix: -- library-vanilla: True -- library-profiling: -- shared: @@ -141,7 +141,7 @@ haddock -- contents-location: -- index-location: -- base-url: - -- lib: + -- resources-dir: -- output-dir: init diff --git a/tests/IntegrationTests2/config/default-config b/tests/IntegrationTests2/config/default-config index 8e3aa02742c576313e6e9e0652e3ae1346754bcb..8d5b2ea1df658565ce9a2cb9cf8dd8594d739246 100644 --- a/tests/IntegrationTests2/config/default-config +++ b/tests/IntegrationTests2/config/default-config @@ -25,8 +25,8 @@ repository hackage.haskell.org -- store-dir: -- active-repositories: -- local-no-index-repo: -remote-repo-cache: /home/colton/.cabal/packages --- logs-dir: /home/colton/.cabal/logs +remote-repo-cache: /Users/finley/.cabal/packages +-- logs-dir: /Users/finley/.cabal/logs -- default-user-config: -- verbose: 1 -- compiler: ghc @@ -63,7 +63,7 @@ remote-repo-cache: /home/colton/.cabal/packages -- extra-lib-dirs: -- extra-lib-dirs-static: -- extra-framework-dirs: -extra-prog-path: /home/colton/.cabal/bin +-- extra-prog-path: -- instantiate-with: -- tests: False -- coverage: False @@ -104,12 +104,13 @@ extra-prog-path: /home/colton/.cabal/bin -- index-state: -- root-cmd: -- symlink-bindir: -build-summary: /home/colton/.cabal/logs/build.log +build-summary: /Users/finley/.cabal/logs/build.log -- build-log: remote-build-reporting: none -- report-planning-failure: False -- per-component: True -- run-tests: +-- semaphore: False jobs: $ncpus -- keep-going: False -- offline: False @@ -117,10 +118,11 @@ jobs: $ncpus -- package-env: -- overwrite-policy: -- install-method: -installdir: /home/colton/.cabal/bin +installdir: /Users/finley/.cabal/bin -- username: -- password: -- password-command: +-- multi-repl: -- builddir: haddock @@ -141,7 +143,7 @@ haddock -- contents-location: -- index-location: -- base-url: - -- lib: + -- resources-dir: -- output-dir: init @@ -160,7 +162,7 @@ init -- source-dir: src install-dirs user - -- prefix: /home/colton/.cabal + -- prefix: /Users/finley/.cabal -- bindir: $prefix/bin -- libdir: $prefix/lib -- libsubdir: $abi/$libname diff --git a/tests/IntegrationTests2/nix-config/default-config b/tests/IntegrationTests2/nix-config/default-config index 8e3aa02742c576313e6e9e0652e3ae1346754bcb..e74a2c9776411decebb13ff291f3bd15403c86b2 100644 --- a/tests/IntegrationTests2/nix-config/default-config +++ b/tests/IntegrationTests2/nix-config/default-config @@ -33,8 +33,8 @@ remote-repo-cache: /home/colton/.cabal/packages -- cabal-file: -- with-compiler: -- with-hc-pkg: --- program-prefix: --- program-suffix: +-- program-prefix: +-- program-suffix: -- library-vanilla: True -- library-profiling: -- shared: @@ -141,7 +141,7 @@ haddock -- contents-location: -- index-location: -- base-url: - -- lib: + -- resources-dir: -- output-dir: init