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

show-build-info (exe:cabal part plus tests) #6241

Closed
wants to merge 24 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
c183666
Add show-build-info command
bgamari Aug 16, 2015
26c3d91
Rebase work of cfraz89 and bgamari
fendor Sep 14, 2019
5338fdc
Improve s-b-i frontend command and add tests
fendor Sep 14, 2019
6faaac9
Get cabal-install building again
lukel97 Apr 30, 2020
d0cf8d7
Fix typo
lukel97 May 1, 2020
b17c1cc
Don't hardcode cabal version in showbuildinfo tests
lukel97 May 1, 2020
815a16d
Remove some unnecessary files from test package
lukel97 May 3, 2020
3a956b1
Refactor show-build-info tests
lukel97 May 3, 2020
947a908
Undo some changes no longer needed in Main.hs
lukel97 May 3, 2020
f3bafbe
Add back explicit exports and fix typos
lukel97 May 3, 2020
781695b
Tidy up imports
lukel97 May 3, 2020
fe2bab9
Update showBuildInfoAction documentation
lukel97 May 4, 2020
af54a71
Cosmetic fixes
lukel97 Jun 1, 2020
9708c4b
Modernize CmdShowBuildInfo
lukel97 Jun 2, 2020
7a59fd4
Rework show-build-info command to avoid wrapper
lukel97 Jun 3, 2020
554f679
Fix haddock parsing in TargetProblem
lukel97 Jun 4, 2020
08a5e93
Build dependencies in show-build-info
lukel97 Jun 4, 2020
4c1978f
Update .prod/.zinz templates
lukel97 Jun 4, 2020
6180494
Silence Haddock output
lukel97 Jun 4, 2020
6daaa52
Add AmbiguityResolver to decide how to resolve ambiguty
lukel97 Jun 5, 2020
d52bdde
Add --pick-first-target flag
lukel97 Jun 8, 2020
23b8870
Don't output haddock stdout if verbosity is silent
lukel97 Jun 8, 2020
25aef99
Generate autogen files
lukel97 Jun 8, 2020
84aa560
Rework show-build-info to use ProjectPlanning/Building infrastructure
lukel97 Jul 7, 2020
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
4 changes: 2 additions & 2 deletions Cabal/Cabal.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,7 @@ library
Distribution.Utils.NubList
Distribution.Utils.ShortText
Distribution.Utils.Progress
Distribution.Utils.Json
Distribution.Verbosity
Distribution.Verbosity.Internal
Distribution.Version
Expand Down Expand Up @@ -609,7 +610,6 @@ library
Distribution.Simple.GHC.EnvironmentParser
Distribution.Simple.GHC.Internal
Distribution.Simple.GHC.ImplInfo
Distribution.Simple.Utils.Json
Distribution.ZinzaPrelude
Paths_Cabal

Expand Down Expand Up @@ -689,7 +689,7 @@ test-suite unit-tests
Distribution.Described
Distribution.Utils.CharSet
Distribution.Utils.GrammarRegex

main-is: UnitTests.hs
build-depends:
array,
Expand Down
33 changes: 19 additions & 14 deletions Cabal/Distribution/Simple.hs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ import Data.List (unionBy, (\\))

import Distribution.PackageDescription.Parsec

import qualified Data.Text.IO as T

-- | A simple implementation of @main@ for a Cabal setup script.
-- It reads the package description file using IO, and performs the
-- action specified on the command line.
Expand Down Expand Up @@ -265,31 +267,34 @@ buildAction hooks flags args = do
hooks flags' { buildArgs = args } args

showBuildInfoAction :: UserHooks -> ShowBuildInfoFlags -> Args -> IO ()
showBuildInfoAction hooks (ShowBuildInfoFlags flags fileOutput) args = do
distPref <- findDistPrefOrDefault (buildDistPref flags)
let verbosity = fromFlag $ buildVerbosity flags
showBuildInfoAction hooks flags args = do
let buildFlags = buildInfoBuildFlags flags
distPref <- findDistPrefOrDefault (buildDistPref buildFlags)
let verbosity = fromFlag $ buildVerbosity buildFlags
lbi <- getBuildConfig hooks verbosity distPref
let flags' = flags { buildDistPref = toFlag distPref
, buildCabalFilePath = maybeToFlag (cabalFilePath lbi)
}
let buildFlags' =
buildFlags { buildDistPref = toFlag distPref
, buildCabalFilePath = maybeToFlag (cabalFilePath lbi)
}

progs <- reconfigurePrograms verbosity
(buildProgramPaths flags')
(buildProgramArgs flags')
(buildProgramPaths buildFlags')
(buildProgramArgs buildFlags')
(withPrograms lbi)

pbi <- preBuild hooks args flags'
pbi <- preBuild hooks args buildFlags'
let lbi' = lbi { withPrograms = progs }
pkg_descr0 = localPkgDescr lbi'
pkg_descr = updatePackageDescription pbi pkg_descr0
-- TODO: Somehow don't ignore build hook?
buildInfoString <- showBuildInfo pkg_descr lbi' flags

case fileOutput of
Nothing -> putStr buildInfoString
Just fp -> writeFile fp buildInfoString
buildInfoText <- showBuildInfo pkg_descr lbi' flags

case buildInfoOutputFile flags of
Nothing -> T.putStr buildInfoText
Just fp -> T.writeFile fp buildInfoText

postBuild hooks args flags' pkg_descr lbi'
postBuild hooks args buildFlags' pkg_descr lbi'

replAction :: UserHooks -> ReplFlags -> Args -> IO ()
replAction hooks flags args = do
Expand Down
26 changes: 18 additions & 8 deletions Cabal/Distribution/Simple/Build.hs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ module Distribution.Simple.Build (
import Prelude ()
import Distribution.Compat.Prelude
import Distribution.Utils.Generic
import Distribution.Utils.Json

import Distribution.Types.ComponentLocalBuildInfo
import Distribution.Types.ComponentRequestedSpec
Expand Down Expand Up @@ -76,7 +77,6 @@ import Distribution.Simple.Configure
import Distribution.Simple.Register
import Distribution.Simple.Test.LibV09
import Distribution.Simple.Utils
import Distribution.Simple.Utils.Json

import Distribution.System
import Distribution.Pretty
Expand All @@ -89,6 +89,7 @@ import Control.Monad
import qualified Data.Set as Set
import System.FilePath ( (</>), (<.>), takeDirectory )
import System.Directory ( getCurrentDirectory )
import qualified Data.Text as Text

-- -----------------------------------------------------------------------------
-- |Build the libraries and executables in this package.
Expand Down Expand Up @@ -133,15 +134,24 @@ build pkg_descr lbi flags suffixes = do


showBuildInfo :: PackageDescription -- ^ Mostly information from the .cabal file
-> LocalBuildInfo -- ^ Configuration information
-> BuildFlags -- ^ Flags that the user passed to build
-> IO String
-> LocalBuildInfo -- ^ Configuration information
-> ShowBuildInfoFlags -- ^ Flags that the user passed to build
-> IO Text.Text
showBuildInfo pkg_descr lbi flags = do
let verbosity = fromFlag (buildVerbosity flags)
targets <- readTargetInfos verbosity pkg_descr lbi (buildArgs flags)
let buildFlags = buildInfoBuildFlags flags
verbosity = fromFlag (buildVerbosity buildFlags)
targets <- readTargetInfos verbosity pkg_descr lbi (buildArgs buildFlags)
pwd <- getCurrentDirectory
let targetsToBuild = neededTargetsInBuildOrder' pkg_descr lbi (map nodeKey targets)
doc = mkBuildInfo pkg_descr lbi flags targetsToBuild
return $ renderJson doc ""
result
| fromFlag (buildInfoComponentsOnly flags) =
let components = map (mkComponentInfo pwd pkg_descr lbi . targetCLBI)
targetsToBuild
in Text.unlines $ map (flip renderJson mempty) components
| otherwise =
let json = mkBuildInfo pwd pkg_descr lbi buildFlags targetsToBuild
in renderJson json mempty
return result


repl :: PackageDescription -- ^ Mostly information from the .cabal file
Expand Down
2 changes: 1 addition & 1 deletion Cabal/Distribution/Simple/BuildTarget.hs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ import System.Directory ( doesFileExist, doesDirectoryExist )
import qualified Data.Map as Map

-- | Take a list of 'String' build targets, and parse and validate them
-- into actual 'TargetInfo's to be built/registered/whatever.
-- into actual 'TargetInfo's to be built\/registered\/whatever.
readTargetInfos :: Verbosity -> PackageDescription -> LocalBuildInfo -> [String] -> IO [TargetInfo]
readTargetInfos verbosity pkg_descr lbi args = do
build_targets <- readBuildTargets verbosity pkg_descr args
Expand Down
4 changes: 3 additions & 1 deletion Cabal/Distribution/Simple/Haddock.hs
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,9 @@ runHaddock verbosity tmpFileOpts comp platform haddockProg args
renderArgs verbosity tmpFileOpts haddockVersion comp platform args $
\(flags,result)-> do

runProgram verbosity haddockProg flags
haddockOut <- getProgramOutput verbosity haddockProg flags
unless (verbosity <= silent) $
putStr haddockOut

notice verbosity $ "Documentation created: " ++ result

Expand Down
17 changes: 12 additions & 5 deletions Cabal/Distribution/Simple/Setup.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2217,15 +2217,18 @@ optionNumJobs get set =
-- ------------------------------------------------------------

data ShowBuildInfoFlags = ShowBuildInfoFlags
{ buildInfoBuildFlags :: BuildFlags
, buildInfoOutputFile :: Maybe FilePath
{ buildInfoBuildFlags :: BuildFlags
, buildInfoOutputFile :: Maybe FilePath
, buildInfoComponentsOnly :: Flag Bool
-- ^ If 'True' then only print components, each separated by a newline
} deriving (Show, Typeable)

defaultShowBuildFlags :: ShowBuildInfoFlags
defaultShowBuildFlags =
ShowBuildInfoFlags
{ buildInfoBuildFlags = defaultBuildFlags
, buildInfoOutputFile = Nothing
{ buildInfoBuildFlags = defaultBuildFlags
, buildInfoOutputFile = Nothing
, buildInfoComponentsOnly = Flag False
}

showBuildInfoCommand :: ProgramDb -> CommandUI ShowBuildInfoFlags
Expand Down Expand Up @@ -2262,8 +2265,12 @@ showBuildInfoCommand progDb = CommandUI
++
[ option [] ["buildinfo-json-output"]
"Write the result to the given file instead of stdout"
buildInfoOutputFile (\pf flags -> flags { buildInfoOutputFile = pf })
buildInfoOutputFile (\v flags -> flags { buildInfoOutputFile = v })
(reqArg' "FILE" Just (maybe [] pure))
, option [] ["buildinfo-components-only"]
"Print out only the component info, each separated by a newline"
buildInfoComponentsOnly (\v flags -> flags { buildInfoComponentsOnly = v})
trueArg
]

}
Expand Down
135 changes: 76 additions & 59 deletions Cabal/Distribution/Simple/ShowBuildInfo.hs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
-- This module defines a simple JSON-based format for exporting basic
-- information about a Cabal package and the compiler configuration Cabal
-- would use to build it. This can be produced with the
-- @cabal new-show-build-info@ command.
-- @cabal show-build-info@ command.
--
--
-- This format is intended for consumption by external tooling and should
Expand Down Expand Up @@ -54,7 +54,12 @@
-- Note: At the moment this is only supported when using the GHC compiler.
--

module Distribution.Simple.ShowBuildInfo (mkBuildInfo) where
{-# LANGUAGE OverloadedStrings #-}

module Distribution.Simple.ShowBuildInfo
( mkBuildInfo, mkBuildInfo', mkCompilerInfo, mkComponentInfo ) where

import qualified Data.Text as T

import Distribution.Compat.Prelude
import Prelude ()
Expand All @@ -70,84 +75,95 @@ import Distribution.Simple.LocalBuildInfo
import Distribution.Simple.Program
import Distribution.Simple.Setup
import Distribution.Simple.Utils (cabalVersion)
import Distribution.Simple.Utils.Json
import Distribution.Utils.Json
import Distribution.Types.TargetInfo
import Distribution.Text
import Distribution.Pretty

-- | Construct a JSON document describing the build information for a
-- package.
mkBuildInfo
:: PackageDescription -- ^ Mostly information from the .cabal file
:: FilePath -- ^ The source directory of the package
-> PackageDescription -- ^ Mostly information from the .cabal file
-> LocalBuildInfo -- ^ Configuration information
-> BuildFlags -- ^ Flags that the user passed to build
-> [TargetInfo]
-> Json
mkBuildInfo pkg_descr lbi _flags targetsToBuild = info
where
targetToNameAndLBI target =
(componentLocalName $ targetCLBI target, targetCLBI target)
componentsToBuild = map targetToNameAndLBI targetsToBuild
(.=) :: String -> Json -> (String, Json)
k .= v = (k, v)
mkBuildInfo wdir pkg_descr lbi _flags targetsToBuild =
JsonObject $
mkBuildInfo' (mkCompilerInfo (withPrograms lbi) (compiler lbi))
(map (mkComponentInfo wdir pkg_descr lbi . targetCLBI) targetsToBuild)

info = JsonObject
[ "cabal-version" .= JsonString (display cabalVersion)
, "compiler" .= mkCompilerInfo
, "components" .= JsonArray (map mkComponentInfo componentsToBuild)
]
-- | A variant of 'mkBuildInfo' if you need to call 'mkCompilerInfo' and
-- 'mkComponentInfo' yourself.
mkBuildInfo'
:: Json -- ^ The 'Json' from 'mkCompilerInfo'
-> [Json] -- ^ The 'Json' from 'mkComponentInfo'
-> [(T.Text, Json)]
mkBuildInfo' cmplrInfo componentInfos =
[ "cabal-version" .= JsonString (T.pack (display cabalVersion))
, "compiler" .= cmplrInfo
, "components" .= JsonArray componentInfos
]

mkCompilerInfo = JsonObject
[ "flavour" .= JsonString (prettyShow $ compilerFlavor $ compiler lbi)
, "compiler-id" .= JsonString (showCompilerId $ compiler lbi)
, "path" .= path
]
where
path = maybe JsonNull (JsonString . programPath)
$ (flavorToProgram . compilerFlavor $ compiler lbi)
>>= flip lookupProgram (withPrograms lbi)
mkCompilerInfo :: ProgramDb -> Compiler -> Json
mkCompilerInfo programDb cmplr = JsonObject
[ "flavour" .= JsonString (T.pack (prettyShow $ compilerFlavor cmplr))
, "compiler-id" .= JsonString (T.pack (showCompilerId cmplr))
, "path" .= path
]
where
path = maybe JsonNull (JsonString . T.pack . programPath)
$ (flavorToProgram . compilerFlavor $ cmplr)
>>= flip lookupProgram programDb

flavorToProgram :: CompilerFlavor -> Maybe Program
flavorToProgram GHC = Just ghcProgram
flavorToProgram GHCJS = Just ghcjsProgram
flavorToProgram UHC = Just uhcProgram
flavorToProgram JHC = Just jhcProgram
flavorToProgram _ = Nothing
flavorToProgram :: CompilerFlavor -> Maybe Program
flavorToProgram GHC = Just ghcProgram
flavorToProgram GHCJS = Just ghcjsProgram
flavorToProgram UHC = Just uhcProgram
flavorToProgram JHC = Just jhcProgram
flavorToProgram _ = Nothing

mkComponentInfo (name, clbi) = JsonObject
[ "type" .= JsonString compType
, "name" .= JsonString (prettyShow name)
, "unit-id" .= JsonString (prettyShow $ componentUnitId clbi)
, "compiler-args" .= JsonArray (map JsonString $ getCompilerArgs bi lbi clbi)
, "modules" .= JsonArray (map (JsonString . display) modules)
, "src-files" .= JsonArray (map JsonString sourceFiles)
, "src-dirs" .= JsonArray (map JsonString $ hsSourceDirs bi)
]
where
bi = componentBuildInfo comp
comp = fromMaybe (error $ "mkBuildInfo: no component " ++ prettyShow name) $ lookupComponent pkg_descr name
compType = case comp of
CLib _ -> "lib"
CExe _ -> "exe"
CTest _ -> "test"
CBench _ -> "bench"
CFLib _ -> "flib"
modules = case comp of
CLib lib -> explicitLibModules lib
CExe exe -> exeModules exe
_ -> []
sourceFiles = case comp of
CLib _ -> []
CExe exe -> [modulePath exe]
_ -> []
mkComponentInfo :: FilePath -> PackageDescription -> LocalBuildInfo -> ComponentLocalBuildInfo -> Json
mkComponentInfo wdir pkg_descr lbi clbi = JsonObject $
[ "type" .= JsonString compType
, "name" .= JsonString (T.pack $ prettyShow name)
, "unit-id" .= JsonString (T.pack $ prettyShow $ componentUnitId clbi)
, "compiler-args" .= JsonArray (map JsonString $ getCompilerArgs bi lbi clbi)
, "modules" .= JsonArray (map (JsonString . T.pack . display) modules)
, "src-files" .= JsonArray (map (JsonString . T.pack) sourceFiles)
, "hs-src-dirs" .= JsonArray (map (JsonString . T.pack) $ hsSourceDirs bi)
, "src-dir" .= JsonString (T.pack wdir)
] <> cabalFile
where
name = componentLocalName clbi
bi = componentBuildInfo comp
comp = fromMaybe (error $ "mkBuildInfo: no component " ++ prettyShow name) $ lookupComponent pkg_descr name
compType = case comp of
CLib _ -> "lib"
CExe _ -> "exe"
CTest _ -> "test"
CBench _ -> "bench"
CFLib _ -> "flib"
modules = case comp of
CLib lib -> explicitLibModules lib
CExe exe -> exeModules exe
_ -> []
sourceFiles = case comp of
CLib _ -> []
CExe exe -> [modulePath exe]
_ -> []
cabalFile
| Just fp <- pkgDescrFile lbi = [("cabal-file", JsonString (T.pack fp))]
| otherwise = []

-- | Get the command-line arguments that would be passed
-- to the compiler to build the given component.
getCompilerArgs
:: BuildInfo
-> LocalBuildInfo
-> ComponentLocalBuildInfo
-> [String]
-> [T.Text]
getCompilerArgs bi lbi clbi =
case compilerFlavor $ compiler lbi of
GHC -> ghc
Expand All @@ -156,6 +172,7 @@ getCompilerArgs bi lbi clbi =
"build arguments for compiler "++show c
where
-- This is absolutely awful
ghc = GHC.renderGhcOptions (compiler lbi) (hostPlatform lbi) baseOpts
ghc = T.pack <$>
GHC.renderGhcOptions (compiler lbi) (hostPlatform lbi) baseOpts
where
baseOpts = GHC.componentGhcOptions normal lbi bi clbi (buildDir lbi)
Loading