Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build haddocks for dependencies (#143) #362

Merged
merged 2 commits into from
Jun 21, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions src/Options/Applicative/Builder/Extra.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

module Options.Applicative.Builder.Extra
(boolFlags
,boolFlagsNoDefault
,maybeBoolFlags
,enableDisableFlags
,enableDisableFlagsNoDefault
,extraHelpOption
,execExtraHelp)
where
Expand All @@ -17,13 +19,23 @@ import System.FilePath (takeBaseName)
boolFlags :: Bool -> String -> String -> Mod FlagFields Bool -> Parser Bool
boolFlags defaultValue = enableDisableFlags defaultValue True False

-- | Enable/disable flags for a @Bool@, without a default case (to allow chaining @<|>@s).
boolFlagsNoDefault :: String -> String -> Mod FlagFields Bool -> Parser Bool
boolFlagsNoDefault = enableDisableFlagsNoDefault True False

-- | Enable/disable flags for a @(Maybe Bool)@.
maybeBoolFlags :: String -> String -> Mod FlagFields (Maybe Bool) -> Parser (Maybe Bool)
maybeBoolFlags = enableDisableFlags Nothing (Just True) (Just False)

-- | Enable/disable flags for any type.
enableDisableFlags :: a -> a -> a -> String -> String -> Mod FlagFields a -> Parser a
enableDisableFlags defaultValue enabledValue disabledValue name helpSuffix mods =
enableDisableFlagsNoDefault enabledValue disabledValue name helpSuffix mods <|>
pure defaultValue

-- | Enable/disable flags for any type, without a default (to allow chaining @<|>@s)
enableDisableFlagsNoDefault :: a -> a -> String -> String -> Mod FlagFields a -> Parser a
enableDisableFlagsNoDefault enabledValue disabledValue name helpSuffix mods =
flag' enabledValue
(long name <>
help ("Enable " ++ helpSuffix) <>
Expand All @@ -41,8 +53,7 @@ enableDisableFlags defaultValue enabledValue disabledValue name helpSuffix mods
(internal <>
long ("disable-" ++ name) <>
help ("Disable " ++ helpSuffix) <>
mods) <|>
pure defaultValue
mods)

-- | Show an extra help option (e.g. @--docker-help@ shows help for all @--docker*@ args).
-- To actually show have that help appear, use 'execExtraHelp' before executing the main parser.
Expand Down
8 changes: 7 additions & 1 deletion src/Stack/Build.hs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import Control.Monad.Trans.Resource
import Data.Function
import Data.Map.Strict (Map)
import qualified Data.Map as Map
import Data.Maybe (fromMaybe)
import Network.HTTP.Client.Conduit (HasHttpManager)
import Path.IO
import Prelude hiding (FilePath, writeFile)
Expand Down Expand Up @@ -55,7 +56,12 @@ build bopts = do
menv <- getMinimalEnvOverride

(mbp, locals, extraToBuild, sourceMap) <- loadSourceMap bopts
(installedMap, locallyRegistered) <- getInstalled menv profiling sourceMap
(installedMap, locallyRegistered) <-
getInstalled menv
GetInstalledOpts
{ getInstalledProfiling = profiling
, getInstalledHaddock = fromMaybe (boptsHaddock bopts) (boptsDepsHaddock bopts) }
sourceMap

baseConfigOpts <- mkBaseConfigOpts bopts
plan <- withLoadPackage menv $ \loadPackage ->
Expand Down
31 changes: 20 additions & 11 deletions src/Stack/Build/ConstructPlan.hs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ data Ctx = Ctx
, callStack :: ![PackageName]
, extraToBuild :: !(Set PackageName)
, latestVersions :: !(Map PackageName Version)
, wanted :: !(Set PackageName)
}

instance HasStackRoot Ctx
Expand Down Expand Up @@ -161,6 +162,7 @@ constructPlan mbp0 baseConfigOpts0 locals extraToBuild0 locallyRegistered loadPa
, callStack = []
, extraToBuild = extraToBuild0
, latestVersions = latest
, wanted = wantedLocalPackages locals
}
toolMap = getToolMap mbp0

Expand Down Expand Up @@ -197,7 +199,7 @@ addFinal lp = do
allDeps
True -- wanted
Local
(packageFlags package)
package
, taskPresent = present
, taskType = TTLocal lp
}
Expand Down Expand Up @@ -239,7 +241,7 @@ addDep'' name = do
installPackage name ps
Just (PIBoth ps installed) -> do
tellExecutables name ps
needInstall <- checkNeedInstall name ps installed
needInstall <- checkNeedInstall name ps installed (wanted ctx)
if needInstall
then installPackage name ps
else return $ Right $ ADRFound (piiLocation ps) (piiVersion ps) installed
Expand Down Expand Up @@ -290,22 +292,22 @@ installPackage name ps = do
-- An assertion to check for a recurrence of
-- https://github.com/commercialhaskell/stack/issues/345
(assert (destLoc == piiLocation ps) destLoc)
(packageFlags package)
package
, taskPresent = present
, taskType =
case ps of
PSLocal lp -> TTLocal lp
PSUpstream _ loc _ -> TTUpstream package $ loc <> minLoc
}

checkNeedInstall :: PackageName -> PackageSource -> Installed -> M Bool
checkNeedInstall name ps installed = assert (piiLocation ps == Local) $ do
checkNeedInstall :: PackageName -> PackageSource -> Installed -> Set PackageName -> M Bool
checkNeedInstall name ps installed wanted = assert (piiLocation ps == Local) $ do
package <- psPackage name ps
depsRes <- addPackageDeps package
case depsRes of
Left _e -> return True -- installPackage will find the error again
Right (missing, present, _loc)
| Set.null missing -> checkDirtiness ps installed package present
| Set.null missing -> checkDirtiness ps installed package present wanted
| otherwise -> return True

addPackageDeps :: Package -> M (Either ConstructPlanException (Set PackageIdentifier, Set GhcPkgId, Location))
Expand Down Expand Up @@ -345,28 +347,35 @@ checkDirtiness :: PackageSource
-> Installed
-> Package
-> Set GhcPkgId
-> Set PackageName
-> M Bool
checkDirtiness ps installed package present = do
checkDirtiness ps installed package present wanted = do
ctx <- ask
moldOpts <- tryGetFlagCache installed
let configOpts = configureOpts
(getEnvConfig ctx)
(baseConfigOpts ctx)
present
(psWanted ps)
(piiLocation ps) -- should be Local always
(packageFlags package)
configCache = ConfigCache
package
buildOpts = bcoBuildOpts (baseConfigOpts ctx)
wantConfigCache = ConfigCache
{ configCacheOpts = map encodeUtf8 configOpts
, configCacheDeps = present
, configCacheComponents =
case ps of
PSLocal lp -> Set.map encodeUtf8 $ lpComponents lp
PSUpstream _ _ _ -> Set.empty
, configCacheHaddock =
shouldBuildHaddock buildOpts wanted (packageName package) ||
-- Disabling haddocks when old config had haddocks doesn't make dirty.
maybe False configCacheHaddock moldOpts
}
moldOpts <- tryGetFlagCache installed
case moldOpts of
Nothing -> return True
Just oldOpts -> return $ oldOpts /= configCache || psDirty ps
Just oldOpts -> return $ oldOpts /= wantConfigCache ||
psDirty ps

psDirty :: PackageSource -> Bool
psDirty (PSLocal lp) = lpDirtyFiles lp
Expand Down
72 changes: 15 additions & 57 deletions src/Stack/Build/Execute.hs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import Data.Map.Strict (Map)
import qualified Data.Map.Strict as M
import qualified Data.Map.Strict as Map
import Data.Maybe
import Data.Set (Set)
import qualified Data.Set as Set
import Data.Streaming.Process hiding (callProcess, env)
import qualified Data.Streaming.Process as Process
Expand Down Expand Up @@ -115,7 +116,6 @@ printPlan finalAction plan = do
DoNothing -> Nothing
DoBenchmarks -> Just "benchmark"
DoTests -> Just "test"
DoHaddock -> Just "haddock"
case mfinalLabel of
Nothing -> return ()
Just finalLabel -> do
Expand Down Expand Up @@ -174,6 +174,7 @@ data ExecuteEnv = ExecuteEnv
, eeSetupHs :: !(Path Abs File)
, eeCabalPkgVer :: !Version
, eeTotalWanted :: !Int
, eeWanted :: !(Set PackageName)
}

-- | Perform the actual plan
Expand Down Expand Up @@ -208,6 +209,7 @@ executePlan menv bopts baseConfigOpts locals plan = do
, eeSetupHs = setupHs
, eeCabalPkgVer = cabalPkgVer
, eeTotalWanted = length $ filter lpWanted locals
, eeWanted = wantedLocalPackages locals
}

unless (Map.null $ planInstallExes plan) $ do
Expand Down Expand Up @@ -372,7 +374,6 @@ toActions runInBase ee (mbuild, mfinal) =
DoNothing -> Nothing
DoTests -> Just (singleTest, checkTest)
DoBenchmarks -> Just (singleBench, checkBench)
DoHaddock -> Just (singleHaddock, const True)

checkTest task =
case taskType task of
Expand Down Expand Up @@ -419,6 +420,8 @@ ensureConfig pkgDir ExecuteEnv {..} Task {..} announce cabal cabalfp extra = do
case taskType of
TTLocal lp -> Set.map encodeUtf8 $ lpComponents lp
TTUpstream _ _ -> Set.empty
, configCacheHaddock =
shouldBuildHaddock eeBuildOpts eeWanted (packageIdentifierName taskProvides)
}

let needConfig = mOldConfigCache /= Just newConfigCache
Expand Down Expand Up @@ -593,6 +596,16 @@ singleBuild ac@ActionContext {..} ee@ExecuteEnv {..} task@Task {..} =
TTLocal lp -> "build" : map T.unpack (Set.toList $ lpComponents lp)
TTUpstream _ _ -> ["build"]

when (shouldBuildHaddock eeBuildOpts eeWanted (packageName package) &&
packageHasLibrary package &&
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this redundant with packageHasExposedModules? If not, under what circumstances may it be necessary? If it is redundant, looks like a good place to use assert.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty sure it's redundant (I think I wrote this before I added the packageHasExposedModules check to shouldBuildHaddock).

-- Works around haddock failing on bytestring-builder since it has no modules when
-- bytestring is new enough.
packageHasExposedModules package) $ do
announce "haddock"
hscolourExists <- doesExecutableExist eeEnvOverride "hscolour"
cabal False (concat [["haddock", "--html"]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth throwing in the --hoogle flag?

,["--hyperlink-source" | hscolourExists]])

withMVar eeInstallLock $ \() -> do
announce "install"
cabal False ["install"]
Expand Down Expand Up @@ -720,61 +733,6 @@ singleBench ac ee task =
announce "benchmarks"
cabal False ["bench"]

singleHaddock :: M env m
=> ActionContext
-> ExecuteEnv
-> Task
-> m ()
singleHaddock ac ee task =
withSingleContext ac ee task $ \_package _cabalfp _pkgDir cabal announce _console _mlogFile -> do
announce "haddock"
hscolourExists <- doesExecutableExist (eeEnvOverride ee) "hscolour"
{- EKB TODO: doc generation for stack-doc-server
#ifndef mingw32_HOST_OS
liftIO (removeDocLinks docLoc package)
#endif
ifcOpts <- liftIO (haddockInterfaceOpts docLoc package packages)
-}
cabal False (concat [["haddock", "--html"]
,["--hyperlink-source" | hscolourExists]])
{- EKB TODO: doc generation for stack-doc-server
,"--hoogle"
,"--html-location=../$pkg-$version/"
,"--haddock-options=" ++ intercalate " " ifcOpts ]
haddockLocs <-
liftIO (findFiles (packageDocDir package)
(\loc -> FilePath.takeExtensions (toFilePath loc) ==
"." ++ haddockExtension)
(not . isHiddenDir))
forM_ haddockLocs $ \haddockLoc ->
do let hoogleTxtPath = FilePath.replaceExtension (toFilePath haddockLoc) "txt"
hoogleDbPath = FilePath.replaceExtension hoogleTxtPath hoogleDbExtension
hoogleExists <- liftIO (doesFileExist hoogleTxtPath)
when hoogleExists
(callProcess
"hoogle"
["convert"
,"--haddock"
,hoogleTxtPath
,hoogleDbPath])
-}
{- EKB TODO: doc generation for stack-doc-server
#ifndef mingw32_HOST_OS
case setupAction of
DoHaddock -> liftIO (createDocLinks docLoc package)
_ -> return ()
#endif

-- | Package's documentation directory.
packageDocDir :: (MonadThrow m, MonadReader env m, HasPlatform env)
=> PackageIdentifier -- ^ Cabal version
-> Package
-> m (Path Abs Dir)
packageDocDir cabalPkgVer package' = do
dist <- distDirFromDir cabalPkgVer (packageDir package')
return (dist </> $(mkRelDir "doc/"))
--}

-- | Grab all output from the given @Handle@ and print it to stdout, stripping
-- Template Haskell "Loading package" lines. Does work in a separate thread.
printBuildOutput :: (MonadIO m, MonadBaseControl IO m, MonadLogger m)
Expand Down
Loading