From 77949ee0bbd7ff91f06156b0bde474b8af8701a6 Mon Sep 17 00:00:00 2001 From: Michael Snoyman Date: Thu, 15 Sep 2016 09:26:16 +0300 Subject: [PATCH] Add dump-logs (fixes #426) --- ChangeLog.md | 3 +++ doc/yaml_configuration.md | 14 +++++++++++++ src/Stack/Build/Execute.hs | 33 ++++++++++++++++++++++++++++++- src/Stack/Config.hs | 1 + src/Stack/Options/ConfigParser.hs | 7 ++++++- src/Stack/Types/Config.hs | 8 ++++++++ 6 files changed, 64 insertions(+), 2 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 1fcc3436f0..21daa72090 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -20,6 +20,9 @@ Other enhancements: 16.10) and adjusts the GHC `configure` options accordingly. [#2542](https://github.com/commercialhaskell/stack/issues/2542) * Upload to Hackage with HTTP digest instead of HTTP basic. +* Add the `dump-logs` config option and `--dump-logs` command line + option to get full build output on the + console. [#426](https://github.com/commercialhaskell/stack/issues/426) Bug fixes: diff --git a/doc/yaml_configuration.md b/doc/yaml_configuration.md index 2633153faf..dcd9ed8fc9 100644 --- a/doc/yaml_configuration.md +++ b/doc/yaml_configuration.md @@ -596,6 +596,20 @@ The meanings of these settings correspond directly with the CLI flags of the same name. See the [build command docs](build_command.md) and the [users guide](GUIDE.md#the-build-command) for more info. +### dump-logs + +(Since XXX) + +Tell Stack to print the log output from all local non-dependency +packages to the console. By default, Stack will only do this when +building a single target package, to avoid generating unnecessarily +verbose output. This can be useful when you want to see warnings from +all of your packages. + +```yaml +dump-logs: true +``` + ### templates Templates used with `stack new` have a number of parameters that affect the diff --git a/src/Stack/Build/Execute.hs b/src/Stack/Build/Execute.hs index 45ad553b84..cc8f255e42 100644 --- a/src/Stack/Build/Execute.hs +++ b/src/Stack/Build/Execute.hs @@ -224,6 +224,7 @@ data ExecuteEnv = ExecuteEnv , eeGlobalDumpPkgs :: !(Map GhcPkgId (DumpPackage () ())) , eeSnapshotDumpPkgs :: !(TVar (Map GhcPkgId (DumpPackage () ()))) , eeLocalDumpPkgs :: !(TVar (Map GhcPkgId (DumpPackage () ()))) + , eeLogFiles :: !(TChan (Path Abs File)) } -- | Get a compiled Setup exe @@ -315,6 +316,7 @@ withExecuteEnv menv bopts boptsCli baseConfigOpts locals globalPackages snapshot globalDB <- getGlobalDB menv =<< getWhichCompiler snapshotPackagesTVar <- liftIO $ newTVarIO (toDumpPackagesByGhcPkgId snapshotPackages) localPackagesTVar <- liftIO $ newTVarIO (toDumpPackagesByGhcPkgId localPackages) + logFilesTChan <- liftIO $ atomically newTChan inner ExecuteEnv { eeEnvOverride = menv , eeBuildOpts = bopts @@ -338,10 +340,32 @@ withExecuteEnv menv bopts boptsCli baseConfigOpts locals globalPackages snapshot , eeGlobalDumpPkgs = toDumpPackagesByGhcPkgId globalPackages , eeSnapshotDumpPkgs = snapshotPackagesTVar , eeLocalDumpPkgs = localPackagesTVar - } + , eeLogFiles = logFilesTChan + } `finally` dumpLogs logFilesTChan where toDumpPackagesByGhcPkgId = Map.fromList . map (\dp -> (dpGhcPkgId dp, dp)) + dumpLogs chan = do + toDump <- asks (configDumpLogs . getConfig) + when toDump loop + where + loop = do + mfilepath <- liftIO $ atomically $ tryReadTChan chan + case mfilepath of + Nothing -> return () + Just filepath -> do + dumpLog filepath + loop + + dumpLog filepath = do + $logInfo $ T.pack $ "\nDumping log file: " ++ toFilePath filepath ++ "\n" + runResourceT + $ CB.sourceFile (toFilePath filepath) + $$ CT.decodeUtf8Lenient + =$ CT.lines + =$ CL.mapM_ $logInfo + $logInfo $ T.pack $ "\nEnd of log file: " ++ toFilePath filepath ++ "\n" + -- | Perform the actual plan executePlan :: M env m => EnvOverride @@ -801,6 +825,13 @@ withSingleContext runInBase ActionContext {..} ExecuteEnv {..} task@Task {..} md logPath <- buildLogPath package msuffix ensureDir (parent logPath) let fp = toFilePath logPath + + -- We only want to dump logs for local non-dependency packages + case taskType of + TTLocal lp | lpWanted lp -> + liftIO $ atomically $ writeTChan eeLogFiles logPath + _ -> return () + bracket (liftIO $ openBinaryFile fp WriteMode) (liftIO . hClose) diff --git a/src/Stack/Config.hs b/src/Stack/Config.hs index b7410a1962..f258d26f36 100644 --- a/src/Stack/Config.hs +++ b/src/Stack/Config.hs @@ -311,6 +311,7 @@ configFromConfigMonoid configStackRoot configUserConfigPath mresolver mproject C configApplyGhcOptions = fromFirst AGOLocals configMonoidApplyGhcOptions configAllowNewer = fromFirst False configMonoidAllowNewer configDefaultTemplate = getFirst configMonoidDefaultTemplate + configDumpLogs = fromFirst False configMonoidDumpLogs configAllowDifferentUser <- case getFirst configMonoidAllowDifferentUser of diff --git a/src/Stack/Options/ConfigParser.hs b/src/Stack/Options/ConfigParser.hs index 42b4e7ef28..04decb9cdb 100644 --- a/src/Stack/Options/ConfigParser.hs +++ b/src/Stack/Options/ConfigParser.hs @@ -17,7 +17,7 @@ import Stack.Types.Config -- | Command-line arguments parser for configuration. configOptsParser :: GlobalOptsContext -> Parser ConfigMonoid configOptsParser hide0 = - (\stackRoot workDir buildOpts dockerOpts nixOpts systemGHC installGHC arch ghcVariant ghcBuild jobs includes libs overrideGccPath skipGHCCheck skipMsys localBin modifyCodePage allowDifferentUser -> mempty + (\stackRoot workDir buildOpts dockerOpts nixOpts systemGHC installGHC arch ghcVariant ghcBuild jobs includes libs overrideGccPath skipGHCCheck skipMsys localBin modifyCodePage allowDifferentUser dumpLogs -> mempty { configMonoidStackRoot = stackRoot , configMonoidWorkDir = workDir , configMonoidBuildOpts = buildOpts @@ -37,6 +37,7 @@ configOptsParser hide0 = , configMonoidLocalBinPath = localBin , configMonoidModifyCodePage = modifyCodePage , configMonoidAllowDifferentUser = allowDifferentUser + , configMonoidDumpLogs = dumpLogs }) <$> optionalFirst (absDirOption ( long stackRootOptionName @@ -118,4 +119,8 @@ configOptsParser hide0 = ("permission for users other than the owner of the stack root " ++ "directory to use a stack installation (POSIX only)") hide + <*> firstBoolFlags + "dump-logs" + "dump the build output logs for local packages to the console" + hide where hide = hideMods (hide0 /= OuterGlobalOpts) diff --git a/src/Stack/Types/Config.hs b/src/Stack/Types/Config.hs index a73dc5ccc7..a0cdb3fa41 100644 --- a/src/Stack/Types/Config.hs +++ b/src/Stack/Types/Config.hs @@ -340,6 +340,8 @@ data Config = -- installation. ,configPackageCaches :: !(IORef (Maybe (Map PackageIdentifier (PackageIndex, PackageCache)))) -- ^ In memory cache of hackage index. + ,configDumpLogs :: !Bool + -- ^ Dump logs of local non-dependencies when doing a build. ,configMaybeProject :: !(Maybe (Project, Path Abs File)) } @@ -864,6 +866,8 @@ data ConfigMonoid = , configMonoidAllowDifferentUser :: !(First Bool) -- ^ Allow users other than the stack root owner to use the stack -- installation. + , configMonoidDumpLogs :: !(First Bool) + -- ^ See 'configDumpLogs' } deriving (Show, Generic) @@ -931,6 +935,7 @@ parseConfigMonoidJSON obj = do configMonoidAllowNewer <- First <$> obj ..:? configMonoidAllowNewerName configMonoidDefaultTemplate <- First <$> obj ..:? configMonoidDefaultTemplateName configMonoidAllowDifferentUser <- First <$> obj ..:? configMonoidAllowDifferentUserName + configMonoidDumpLogs <- First <$> obj ..:? configMonoidDumpLogsName return ConfigMonoid {..} where @@ -1058,6 +1063,9 @@ configMonoidDefaultTemplateName = "default-template" configMonoidAllowDifferentUserName :: Text configMonoidAllowDifferentUserName = "allow-different-user" +configMonoidDumpLogsName :: Text +configMonoidDumpLogsName = "dump-logs" + data ConfigException = ParseConfigFileException (Path Abs File) ParseException | ParseCustomSnapshotException Text ParseException