From 449fa90d3e472c0c6353ceadd82f805dc866fb32 Mon Sep 17 00:00:00 2001 From: Fendor <power.walross@gmail.com> Date: Mon, 16 Aug 2021 11:35:39 +0200 Subject: [PATCH] Remove show-build-info command and generate build-info on build Removes 'show-build-info' command from 'lib:Cabal' and replaces it by generating build-info whenever a build happens. Add flag '--dump-buildinfo' to signal the build step to dump build information for the package/component we are currently building. --- .../src/Test/QuickCheck/Instances/Cabal.hs | 8 +- .../Distribution/Utils/Structured.hs | 2 +- .../src/Data/TreeDiff/Instances/Cabal.hs | 2 + Cabal/Cabal.cabal | 1 + Cabal/src/Distribution/Simple.hs | 32 ------ Cabal/src/Distribution/Simple/Build.hs | 52 ++++----- Cabal/src/Distribution/Simple/BuildPaths.hs | 6 +- Cabal/src/Distribution/Simple/Setup.hs | 103 ++++-------------- .../src/Distribution/Simple/ShowBuildInfo.hs | 76 +++++++------ Cabal/src/Distribution/Types/DumpBuildInfo.hs | 15 +++ .../src/Distribution/Client/Config.hs | 1 + .../Client/ProjectConfig/Legacy.hs | 42 +++++-- .../Client/ProjectConfig/Types.hs | 3 +- .../Distribution/Client/ProjectPlanning.hs | 4 + .../Client/ProjectPlanning/Types.hs | 4 +- .../src/Distribution/Client/Setup.hs | 7 +- .../Distribution/Client/ProjectConfig.hs | 8 +- 17 files changed, 173 insertions(+), 193 deletions(-) create mode 100644 Cabal/src/Distribution/Types/DumpBuildInfo.hs diff --git a/Cabal-QuickCheck/src/Test/QuickCheck/Instances/Cabal.hs b/Cabal-QuickCheck/src/Test/QuickCheck/Instances/Cabal.hs index 3d471ea628..b2b6853c60 100644 --- a/Cabal-QuickCheck/src/Test/QuickCheck/Instances/Cabal.hs +++ b/Cabal-QuickCheck/src/Test/QuickCheck/Instances/Cabal.hs @@ -25,7 +25,7 @@ import Distribution.ModuleName import Distribution.Simple.Compiler (DebugInfoLevel (..), OptimisationLevel (..), PackageDB (..), ProfDetailLevel (..), knownProfDetailLevels) import Distribution.Simple.Flag (Flag (..)) import Distribution.Simple.InstallDirs -import Distribution.Simple.Setup (HaddockTarget (..), TestShowDetails (..)) +import Distribution.Simple.Setup (HaddockTarget (..), TestShowDetails (..), DumpBuildInfo) import Distribution.SPDX import Distribution.System import Distribution.Types.Dependency @@ -486,6 +486,12 @@ instance Arbitrary PackageDB where , SpecificPackageDB <$> arbitraryShortToken ] +------------------------------------------------------------------------------- +-- DumpBuildInfo +------------------------------------------------------------------------------- + +instance Arbitrary DumpBuildInfo where + arbitrary = arbitraryBoundedEnum ------------------------------------------------------------------------------- -- Helpers diff --git a/Cabal-tests/tests/UnitTests/Distribution/Utils/Structured.hs b/Cabal-tests/tests/UnitTests/Distribution/Utils/Structured.hs index 1d715af86e..9ad401b4b1 100644 --- a/Cabal-tests/tests/UnitTests/Distribution/Utils/Structured.hs +++ b/Cabal-tests/tests/UnitTests/Distribution/Utils/Structured.hs @@ -29,7 +29,7 @@ tests = testGroup "Distribution.Utils.Structured" , testCase "GenericPackageDescription" $ md5Check (Proxy :: Proxy GenericPackageDescription) 0xa164cbe5092a1cd31da1f15358d1537a , testCase "LocalBuildInfo" $ - md5Check (Proxy :: Proxy LocalBuildInfo) 0xac70971ea59d30aab7e4b6dafc9113d4 + md5Check (Proxy :: Proxy LocalBuildInfo) 0x9ce83e4aec3b2fa6d7f999dbc32c2a33 #endif ] diff --git a/Cabal-tree-diff/src/Data/TreeDiff/Instances/Cabal.hs b/Cabal-tree-diff/src/Data/TreeDiff/Instances/Cabal.hs index 40765a6764..98bb586d50 100644 --- a/Cabal-tree-diff/src/Data/TreeDiff/Instances/Cabal.hs +++ b/Cabal-tree-diff/src/Data/TreeDiff/Instances/Cabal.hs @@ -29,6 +29,7 @@ import Distribution.Simple.Setup (HaddockTarget, TestShowDetai import Distribution.System import Distribution.Types.AbiHash (AbiHash) import Distribution.Types.ComponentId (ComponentId) +import Distribution.Types.DumpBuildInfo (DumpBuildInfo) import Distribution.Types.PackageVersionConstraint import Distribution.Types.UnitId (DefUnitId, UnitId) import Distribution.Utils.NubList (NubList) @@ -74,6 +75,7 @@ instance ToExpr CompilerId instance ToExpr ComponentId instance ToExpr DebugInfoLevel instance ToExpr DefUnitId +instance ToExpr DumpBuildInfo instance ToExpr ExeDependency instance ToExpr Executable instance ToExpr ExecutableScope diff --git a/Cabal/Cabal.cabal b/Cabal/Cabal.cabal index 8158d4640e..3991c48321 100644 --- a/Cabal/Cabal.cabal +++ b/Cabal/Cabal.cabal @@ -201,6 +201,7 @@ library Distribution.Types.ComponentInclude Distribution.Types.ConfVar Distribution.Types.Dependency + Distribution.Types.DumpBuildInfo Distribution.Types.ExeDependency Distribution.Types.LegacyExeDependency Distribution.Types.PkgconfigDependency diff --git a/Cabal/src/Distribution/Simple.hs b/Cabal/src/Distribution/Simple.hs index 1eb958a035..fe19558db1 100644 --- a/Cabal/src/Distribution/Simple.hs +++ b/Cabal/src/Distribution/Simple.hs @@ -104,7 +104,6 @@ import Distribution.Compat.Directory (makeAbsolute) import Distribution.Compat.Environment (getEnvironment) import Distribution.Compat.GetShortPathName (getShortPathName) -import qualified Data.ByteString.Lazy as B import Data.List (unionBy, (\\)) import Distribution.PackageDescription.Parsec @@ -179,7 +178,6 @@ defaultMainHelper hooks args = topHandler $ do [configureCommand progs `commandAddAction` \fs as -> configureAction hooks fs as >> return () ,buildCommand progs `commandAddAction` buildAction hooks - ,showBuildInfoCommand progs `commandAddAction` showBuildInfoAction hooks ,replCommand progs `commandAddAction` replAction hooks ,installCommand `commandAddAction` installAction hooks ,copyCommand `commandAddAction` copyAction hooks @@ -264,36 +262,6 @@ buildAction hooks flags args = do (return lbi { withPrograms = progs }) hooks flags' { buildArgs = args } args -showBuildInfoAction :: UserHooks -> ShowBuildInfoFlags -> Args -> IO () -showBuildInfoAction hooks flags args = do - let buildFlags = buildInfoBuildFlags flags - distPref <- findDistPrefOrDefault (buildDistPref buildFlags) - let verbosity = fromFlag $ buildVerbosity buildFlags - lbi <- getBuildConfig hooks verbosity distPref - let buildFlags' = - buildFlags { buildDistPref = toFlag distPref - , buildCabalFilePath = maybeToFlag (cabalFilePath lbi) - } - - progs <- reconfigurePrograms verbosity - (buildProgramPaths buildFlags') - (buildProgramArgs buildFlags') - (withPrograms lbi) - - 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? - - buildInfoByteString <- showBuildInfo pkg_descr lbi' flags - - case buildInfoOutputFile flags of - Nothing -> B.putStr buildInfoByteString - Just fp -> B.writeFile fp buildInfoByteString - - postBuild hooks args buildFlags' pkg_descr lbi' - replAction :: UserHooks -> ReplFlags -> Args -> IO () replAction hooks flags args = do distPref <- findDistPrefOrDefault (replDistPref flags) diff --git a/Cabal/src/Distribution/Simple/Build.hs b/Cabal/src/Distribution/Simple/Build.hs index 7c5bd280d8..78bf79feae 100644 --- a/Cabal/src/Distribution/Simple/Build.hs +++ b/Cabal/src/Distribution/Simple/Build.hs @@ -19,7 +19,7 @@ -- module Distribution.Simple.Build ( - build, showBuildInfo, repl, + build, repl, startInterpreter, initialBuildSteps, @@ -87,11 +87,10 @@ import Distribution.Version (thisVersion) import Distribution.Compat.Graph (IsNode(..)) import Control.Monad -import Data.ByteString.Lazy (ByteString) -import qualified Data.ByteString.Lazy.Char8 as LBS import qualified Data.Set as Set +import qualified Data.ByteString.Lazy as LBS import System.FilePath ( (</>), (<.>), takeDirectory ) -import System.Directory ( getCurrentDirectory ) +import System.Directory ( getCurrentDirectory, removeFile, doesFileExist ) -- ----------------------------------------------------------------------------- -- |Build the libraries and executables in this package. @@ -129,32 +128,33 @@ build pkg_descr lbi flags suffixes = do mb_ipi <- buildComponent verbosity (buildNumJobs flags) pkg_descr lbi' suffixes comp clbi distPref return (maybe index (Index.insert `flip` index) mb_ipi) + + when shouldDumpBuildInfo $ do + -- Changing this line might break consumers of the dumped build info. + -- Announce changes on mailing lists! + let activeTargets = allTargetsInBuildOrder' pkg_descr lbi + info verbosity $ "Dump build information for: " + ++ intercalate ", " + (map (showComponentName . componentLocalName . targetCLBI) + activeTargets) + pwd <- getCurrentDirectory + let (warns, json) = mkBuildInfo pwd pkg_descr lbi flags activeTargets + buildInfoText = renderJson json + unless (null warns) $ + warn verbosity $ "Encountered warnings while dumping build-info:\n" + ++ unlines warns + LBS.writeFile (buildInfoPref distPref) buildInfoText + + when (not shouldDumpBuildInfo) $ do + -- Remove existing build-info.json as it might be outdated now. + exists <- doesFileExist (buildInfoPref distPref) + when exists $ removeFile (buildInfoPref distPref) + return () where distPref = fromFlag (buildDistPref flags) verbosity = fromFlag (buildVerbosity flags) - - -showBuildInfo :: PackageDescription -- ^ Mostly information from the .cabal file - -> LocalBuildInfo -- ^ Configuration information - -> ShowBuildInfoFlags -- ^ Flags that the user passed to build - -> IO ByteString -showBuildInfo pkg_descr lbi flags = do - 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) - result - | fromFlag (buildInfoComponentsOnly flags) = - let components = map (mkComponentInfo pwd pkg_descr lbi . targetCLBI) - targetsToBuild - in LBS.unlines $ map renderJson components - | otherwise = - let json = mkBuildInfo pwd pkg_descr lbi buildFlags targetsToBuild - in renderJson json - return result - + shouldDumpBuildInfo = fromFlagOrDefault NoDumpBuildInfo (configDumpBuildInfo (configFlags lbi)) == DumpBuildInfo repl :: PackageDescription -- ^ Mostly information from the .cabal file -> LocalBuildInfo -- ^ Configuration information diff --git a/Cabal/src/Distribution/Simple/BuildPaths.hs b/Cabal/src/Distribution/Simple/BuildPaths.hs index 86df023663..733953747c 100644 --- a/Cabal/src/Distribution/Simple/BuildPaths.hs +++ b/Cabal/src/Distribution/Simple/BuildPaths.hs @@ -15,7 +15,7 @@ module Distribution.Simple.BuildPaths ( defaultDistPref, srcPref, - haddockDirName, hscolourPref, haddockPref, + buildInfoPref, haddockDirName, hscolourPref, haddockPref, autogenPackageModulesDir, autogenComponentModulesDir, @@ -67,6 +67,10 @@ srcPref distPref = distPref </> "src" hscolourPref :: HaddockTarget -> FilePath -> PackageDescription -> FilePath hscolourPref = haddockPref +-- | Build info json file, generated in every build +buildInfoPref :: FilePath -> FilePath +buildInfoPref distPref = distPref </> "build-info.json" + -- | This is the name of the directory in which the generated haddocks -- should be stored. It does not include the @<dist>/doc/html@ prefix. haddockDirName :: HaddockTarget -> PackageDescription -> FilePath diff --git a/Cabal/src/Distribution/Simple/Setup.hs b/Cabal/src/Distribution/Simple/Setup.hs index 8f0ad64de1..6ed08e7ed3 100644 --- a/Cabal/src/Distribution/Simple/Setup.hs +++ b/Cabal/src/Distribution/Simple/Setup.hs @@ -45,7 +45,7 @@ module Distribution.Simple.Setup ( HaddockFlags(..), emptyHaddockFlags, defaultHaddockFlags, haddockCommand, HscolourFlags(..), emptyHscolourFlags, defaultHscolourFlags, hscolourCommand, BuildFlags(..), emptyBuildFlags, defaultBuildFlags, buildCommand, - ShowBuildInfoFlags(..), defaultShowBuildFlags, showBuildInfoCommand, + DumpBuildInfo(..), ReplFlags(..), defaultReplFlags, replCommand, ReplOptions(..), CleanFlags(..), emptyCleanFlags, defaultCleanFlags, cleanCommand, @@ -99,6 +99,7 @@ import Distribution.Simple.InstallDirs import Distribution.Verbosity import Distribution.Utils.NubList import Distribution.Types.ComponentId +import Distribution.Types.DumpBuildInfo import Distribution.Types.GivenComponent import Distribution.Types.Module import Distribution.Types.PackageVersionConstraint @@ -274,6 +275,11 @@ data ConfigFlags = ConfigFlags { -- ^Halt and show an error message indicating an error in flag assignment configRelocatable :: Flag Bool, -- ^ Enable relocatable package built configDebugInfo :: Flag DebugInfoLevel, -- ^ Emit debug info. + configDumpBuildInfo :: Flag DumpBuildInfo, + -- ^ Should we dump available build information on build? + -- Dump build information to disk before attempting to build, + -- tooling can parse these files and use them to compile the + -- source files themselves. configUseResponseFiles :: Flag Bool, -- ^ Whether to use response files at all. They're used for such tools -- as haddock, or ld. @@ -343,6 +349,7 @@ instance Eq ConfigFlags where && equal configFlagError && equal configRelocatable && equal configDebugInfo + && equal configDumpBuildInfo && equal configUseResponseFiles where equal f = on (==) f a b @@ -393,6 +400,7 @@ defaultConfigFlags progDb = emptyConfigFlags { configFlagError = NoFlag, configRelocatable = Flag False, configDebugInfo = Flag NoDebugInfo, + configDumpBuildInfo = NoFlag, configUseResponseFiles = NoFlag } @@ -561,6 +569,17 @@ configureOptions showOrParseArgs = "Don't emit debug info" ] + , multiOption "build-info" + configDumpBuildInfo + (\v flags -> flags { configDumpBuildInfo = v }) + [noArg (Flag DumpBuildInfo) [] + ["enable-build-info"] + "Enable build information generation during project building", + noArg (Flag NoDumpBuildInfo) [] + ["disable-build-info"] + "Disable build information generation during project building" + ] + ,option "" ["library-for-ghci"] "compile library for use with GHCi" configGHCiLib (\v flags -> flags { configGHCiLib = v }) @@ -2183,88 +2202,6 @@ optionNumJobs get set = | otherwise -> Right (Just n) _ -> Left "The jobs value should be a number or '$ncpus'" - --- ------------------------------------------------------------ --- * show-build-info command flags --- ------------------------------------------------------------ - -data ShowBuildInfoFlags = ShowBuildInfoFlags - { 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 - , buildInfoComponentsOnly = Flag False - } - -showBuildInfoCommand :: ProgramDb -> CommandUI ShowBuildInfoFlags -showBuildInfoCommand progDb = CommandUI - { commandName = "show-build-info" - , commandSynopsis = "Emit details about how a package would be built." - , commandDescription = Just $ \_ -> wrapText $ - "Components encompass executables, tests, and benchmarks.\n" - ++ "\n" - ++ "Affected by configuration options, see `configure`.\n" - , commandNotes = Just $ \pname -> - "Examples:\n" - ++ " " ++ pname ++ " show-build-info " - ++ " All the components in the package\n" - ++ " " ++ pname ++ " show-build-info foo " - ++ " A component (i.e. lib, exe, test suite)\n\n" - ++ programFlagsDescription progDb ---TODO: re-enable once we have support for module/file targets --- ++ " " ++ pname ++ " show-build-info Foo.Bar " --- ++ " A module\n" --- ++ " " ++ pname ++ " show-build-info Foo/Bar.hs" --- ++ " A file\n\n" --- ++ "If a target is ambiguous it can be qualified with the component " --- ++ "name, e.g.\n" --- ++ " " ++ pname ++ " show-build-info foo:Foo.Bar\n" --- ++ " " ++ pname ++ " show-build-info testsuite1:Foo/Bar.hs\n" - , commandUsage = usageAlternatives "show-build-info" $ - [ "[FLAGS]" - , "COMPONENTS [FLAGS]" - ] - , commandDefaultFlags = defaultShowBuildFlags - , commandOptions = \showOrParseArgs -> - parseBuildFlagsForShowBuildInfoFlags showOrParseArgs progDb - ++ - [ option [] ["buildinfo-json-output"] - "Write the result to the given file instead of stdout" - 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 - ] - - } - -parseBuildFlagsForShowBuildInfoFlags :: ShowOrParseArgs -> ProgramDb -> [OptionField ShowBuildInfoFlags] -parseBuildFlagsForShowBuildInfoFlags showOrParseArgs progDb = - map - (liftOption - buildInfoBuildFlags - (\bf flags -> flags { buildInfoBuildFlags = bf } ) - ) - buildFlags - where - buildFlags = buildOptions progDb showOrParseArgs - ++ - [ optionVerbosity - buildVerbosity (\v flags -> flags { buildVerbosity = v }) - - , optionDistPref - buildDistPref (\d flags -> flags { buildDistPref = d }) showOrParseArgs - ] - -- ------------------------------------------------------------ -- * Other Utils -- ------------------------------------------------------------ diff --git a/Cabal/src/Distribution/Simple/ShowBuildInfo.hs b/Cabal/src/Distribution/Simple/ShowBuildInfo.hs index fbbebbe9e0..9bfda3eadd 100644 --- a/Cabal/src/Distribution/Simple/ShowBuildInfo.hs +++ b/Cabal/src/Distribution/Simple/ShowBuildInfo.hs @@ -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 build --enable-build-info@ command. -- -- -- This format is intended for consumption by external tooling and should @@ -14,7 +14,7 @@ -- Below is an example of the output this module produces, -- -- @ --- { "cabal-version": "1.23.0.0", +-- { "cabal-lib-version": "1.23.0.0", -- "compiler": { -- "flavour": "GHC", -- "compiler-id": "ghc-7.10.2", @@ -34,7 +34,10 @@ -- } -- @ -- --- The @cabal-version@ property provides the version of the Cabal library +-- The output format needs to be validated against 'doc/json-schemas/build-info.schema.json'. +-- If the format changes, update the schema as well! +-- +-- The @cabal-lib-version@ property provides the version of the Cabal library -- which generated the output. The @compiler@ property gives some basic -- information about the compiler Cabal would use to compile the package. -- @@ -56,8 +59,11 @@ {-# LANGUAGE OverloadedStrings #-} -module Distribution.Simple.ShowBuildInfo - ( mkBuildInfo, mkBuildInfo', mkCompilerInfo, mkComponentInfo ) where +module Distribution.Simple.ShowBuildInfo ( + mkBuildInfo, mkBuildInfo', mkCompilerInfo, mkComponentInfo + ) where + +import System.FilePath import Distribution.Compat.Prelude import Prelude () @@ -68,12 +74,14 @@ import qualified Distribution.Simple.Program.GHC as GHC import Distribution.PackageDescription import Distribution.Compiler import Distribution.Verbosity -import Distribution.Simple.Compiler -import Distribution.Simple.LocalBuildInfo +import Distribution.Simple.Compiler (Compiler, showCompilerId, compilerFlavor) import Distribution.Simple.Program import Distribution.Simple.Setup import Distribution.Simple.Utils (cabalVersion) import Distribution.Utils.Json +import Distribution.Types.Component +import Distribution.Types.ComponentLocalBuildInfo +import Distribution.Types.LocalBuildInfo import Distribution.Types.TargetInfo import Distribution.Text import Distribution.Pretty @@ -86,11 +94,13 @@ mkBuildInfo -> LocalBuildInfo -- ^ Configuration information -> BuildFlags -- ^ Flags that the user passed to build -> [TargetInfo] - -> Json -mkBuildInfo wdir pkg_descr lbi _flags targetsToBuild = - JsonObject $ - mkBuildInfo' (mkCompilerInfo (withPrograms lbi) (compiler lbi)) - (map (mkComponentInfo wdir pkg_descr lbi . targetCLBI) targetsToBuild) + -> ([String], Json) -- ^ Json representation of buildinfo alongside generated warnings +mkBuildInfo wdir pkg_descr lbi _flags targetsToBuild = (warnings, JsonObject buildInfoFields) + where + buildInfoFields = mkBuildInfo' (mkCompilerInfo (withPrograms lbi) (compiler lbi)) componentInfos + componentInfosWithWarnings = map (mkComponentInfo wdir pkg_descr lbi . targetCLBI) targetsToBuild + componentInfos = map snd componentInfosWithWarnings + warnings = concatMap fst componentInfosWithWarnings -- | A variant of 'mkBuildInfo' if you need to call 'mkCompilerInfo' and -- 'mkComponentInfo' yourself. @@ -98,21 +108,21 @@ mkBuildInfo' :: Json -- ^ The 'Json' from 'mkCompilerInfo' -> [Json] -- ^ The 'Json' from 'mkComponentInfo' -> [(String, Json)] -mkBuildInfo' cmplrInfo componentInfos = - [ "cabal-version" .= JsonString (display cabalVersion) - , "compiler" .= cmplrInfo - , "components" .= JsonArray componentInfos - ] +mkBuildInfo' compilerInfo componentInfos = + [ "cabal-lib-version" .= JsonString (display cabalVersion) + , "compiler" .= compilerInfo + , "components" .= JsonArray componentInfos + ] mkCompilerInfo :: ProgramDb -> Compiler -> Json -mkCompilerInfo programDb cmplr = JsonObject - [ "flavour" .= JsonString (prettyShow $ compilerFlavor cmplr) - , "compiler-id" .= JsonString (showCompilerId cmplr) +mkCompilerInfo programDb compilerInfo = JsonObject + [ "flavour" .= JsonString (prettyShow $ compilerFlavor compilerInfo) + , "compiler-id" .= JsonString (showCompilerId compilerInfo) , "path" .= path ] where path = maybe JsonNull (JsonString . programPath) - $ (flavorToProgram . compilerFlavor $ cmplr) + $ (flavorToProgram . compilerFlavor $ compilerInfo) >>= flip lookupProgram programDb flavorToProgram :: CompilerFlavor -> Maybe Program @@ -122,20 +132,22 @@ mkCompilerInfo programDb cmplr = JsonObject flavorToProgram JHC = Just jhcProgram flavorToProgram _ = Nothing -mkComponentInfo :: FilePath -> PackageDescription -> LocalBuildInfo -> ComponentLocalBuildInfo -> Json -mkComponentInfo wdir pkg_descr lbi clbi = JsonObject $ +mkComponentInfo :: FilePath -> PackageDescription -> LocalBuildInfo -> ComponentLocalBuildInfo -> ([String], Json) +mkComponentInfo wdir pkg_descr lbi clbi = (warnings, JsonObject $ [ "type" .= JsonString compType , "name" .= JsonString (prettyShow name) , "unit-id" .= JsonString (prettyShow $ componentUnitId clbi) - , "compiler-args" .= JsonArray (map JsonString $ getCompilerArgs bi lbi clbi) + , "compiler-args" .= JsonArray (map JsonString compilerArgs) , "modules" .= JsonArray (map (JsonString . display) modules) , "src-files" .= JsonArray (map JsonString sourceFiles) , "hs-src-dirs" .= JsonArray (map (JsonString . prettyShow) $ hsSourceDirs bi) - , "src-dir" .= JsonString wdir - ] <> cabalFile + , "src-dir" .= JsonString (addTrailingPathSeparator wdir) + ] <> cabalFile) where + (warnings, compilerArgs) = getCompilerArgs bi lbi clbi name = componentLocalName clbi bi = componentBuildInfo comp + -- If this error happens, a cabal invariant has been violated comp = fromMaybe (error $ "mkBuildInfo: no component " ++ prettyShow name) $ lookupComponent pkg_descr name compType = case comp of CLib _ -> "lib" @@ -176,13 +188,15 @@ getCompilerArgs :: BuildInfo -> LocalBuildInfo -> ComponentLocalBuildInfo - -> [String] + -> ([String], [String]) getCompilerArgs bi lbi clbi = case compilerFlavor $ compiler lbi of - GHC -> ghc - GHCJS -> ghc - c -> error $ "ShowBuildInfo.getCompilerArgs: Don't know how to get "++ - "build arguments for compiler "++show c + GHC -> ([], ghc) + GHCJS -> ([], ghc) + c -> + ( ["ShowBuildInfo.getCompilerArgs: Don't know how to get build " + ++ " arguments for compiler " ++ show c] + , []) where -- This is absolutely awful ghc = GHC.renderGhcOptions (compiler lbi) (hostPlatform lbi) baseOpts diff --git a/Cabal/src/Distribution/Types/DumpBuildInfo.hs b/Cabal/src/Distribution/Types/DumpBuildInfo.hs new file mode 100644 index 0000000000..5657a65aa7 --- /dev/null +++ b/Cabal/src/Distribution/Types/DumpBuildInfo.hs @@ -0,0 +1,15 @@ +{-# LANGUAGE DeriveDataTypeable #-} +{-# LANGUAGE DeriveGeneric #-} +module Distribution.Types.DumpBuildInfo + ( DumpBuildInfo(..) + ) where + +import Distribution.Compat.Prelude + +data DumpBuildInfo + = NoDumpBuildInfo + | DumpBuildInfo + deriving (Read, Show, Eq, Ord, Enum, Bounded, Generic, Typeable) + +instance Binary DumpBuildInfo +instance Structured DumpBuildInfo diff --git a/cabal-install/src/Distribution/Client/Config.hs b/cabal-install/src/Distribution/Client/Config.hs index 1c2df3dc71..c5ca5f1811 100644 --- a/cabal-install/src/Distribution/Client/Config.hs +++ b/cabal-install/src/Distribution/Client/Config.hs @@ -409,6 +409,7 @@ instance Semigroup SavedConfig where configFlagError = combine configFlagError, configRelocatable = combine configRelocatable, configUseResponseFiles = combine configUseResponseFiles, + configDumpBuildInfo = combine configDumpBuildInfo, configAllowDependingOnPrivateLibs = combine configAllowDependingOnPrivateLibs } diff --git a/cabal-install/src/Distribution/Client/ProjectConfig/Legacy.hs b/cabal-install/src/Distribution/Client/ProjectConfig/Legacy.hs index 0aca7ac2a4..38852d0fd0 100644 --- a/cabal-install/src/Distribution/Client/ProjectConfig/Legacy.hs +++ b/cabal-install/src/Distribution/Client/ProjectConfig/Legacy.hs @@ -54,7 +54,7 @@ import Distribution.Simple.Setup , HaddockFlags(..), haddockOptions, defaultHaddockFlags , TestFlags(..), testOptions', defaultTestFlags , BenchmarkFlags(..), benchmarkOptions', defaultBenchmarkFlags - , programDbPaths', splitArgs + , programDbPaths', splitArgs, DumpBuildInfo (NoDumpBuildInfo, DumpBuildInfo) ) import Distribution.Client.NixStyleOptions (NixStyleFlags (..)) import Distribution.Client.ProjectFlags (ProjectFlags (..), projectFlagsOptions, defaultProjectFlags) @@ -437,6 +437,7 @@ convertLegacyPerPackageFlags configFlags installFlags configCoverage = coverage, configLibCoverage = libcoverage, --deprecated configDebugInfo = packageConfigDebugInfo, + configDumpBuildInfo = packageConfigDumpBuildInfo, configRelocatable = packageConfigRelocatable } = configFlags packageConfigProgramPaths = MapLast (Map.fromList configProgramPaths) @@ -724,6 +725,7 @@ convertToLegacyAllPackageConfig configRelocatable = mempty, configDebugInfo = mempty, configUseResponseFiles = mempty, + configDumpBuildInfo = mempty, configAllowDependingOnPrivateLibs = mempty } @@ -797,6 +799,7 @@ convertToLegacyPerPackageConfig PackageConfig {..} = configRelocatable = packageConfigRelocatable, configDebugInfo = packageConfigDebugInfo, configUseResponseFiles = mempty, + configDumpBuildInfo = packageConfigDumpBuildInfo, configAllowDependingOnPrivateLibs = mempty } @@ -1083,6 +1086,7 @@ legacyPackageConfigFieldDescrs = dispFlagAssignment parsecFlagAssignment configConfigurationsFlags (\v conf -> conf { configConfigurationsFlags = v }) + , overrideDumpBuildInfo ] . filterFields [ "with-compiler", "with-hc-pkg" @@ -1180,6 +1184,23 @@ legacyPackageConfigFieldDescrs = (toFlag <$> parsec <|> pure mempty) configHcFlavor (\v flags -> flags { configHcFlavor = v }) + overrideDumpBuildInfo = + liftField configDumpBuildInfo + (\v flags -> flags { configDumpBuildInfo = v }) $ + let name = "build-info" in + FieldDescr name + (\f -> case f of + Flag NoDumpBuildInfo -> Disp.text "False" + Flag DumpBuildInfo -> Disp.text "True" + _ -> Disp.empty) + (\line str _ -> case () of + _ | str == "False" -> ParseOk [] (Flag NoDumpBuildInfo) + | str == "True" -> ParseOk [] (Flag DumpBuildInfo) + | lstr == "false" -> ParseOk [caseWarning name] (Flag NoDumpBuildInfo) + | lstr == "true" -> ParseOk [caseWarning name] (Flag DumpBuildInfo) + | otherwise -> ParseFailed (NoParse name line) + where + lstr = lowercase str) -- TODO: [code cleanup] The following is a hack. The "optimization" and -- "debug-info" fields are OptArg, and viewAsFieldDescr fails on that. @@ -1202,13 +1223,11 @@ legacyPackageConfigFieldDescrs = | str == "0" -> ParseOk [] (Flag NoOptimisation) | str == "1" -> ParseOk [] (Flag NormalOptimisation) | str == "2" -> ParseOk [] (Flag MaximumOptimisation) - | lstr == "false" -> ParseOk [caseWarning] (Flag NoOptimisation) - | lstr == "true" -> ParseOk [caseWarning] (Flag NormalOptimisation) + | lstr == "false" -> ParseOk [caseWarning name] (Flag NoOptimisation) + | lstr == "true" -> ParseOk [caseWarning name] (Flag NormalOptimisation) | otherwise -> ParseFailed (NoParse name line) where - lstr = lowercase str - caseWarning = PWarning $ - "The '" ++ name ++ "' field is case sensitive, use 'True' or 'False'.") + lstr = lowercase str) overrideFieldDebugInfo = liftField configDebugInfo (\v flags -> flags { configDebugInfo = v }) $ @@ -1227,13 +1246,14 @@ legacyPackageConfigFieldDescrs = | str == "1" -> ParseOk [] (Flag MinimalDebugInfo) | str == "2" -> ParseOk [] (Flag NormalDebugInfo) | str == "3" -> ParseOk [] (Flag MaximalDebugInfo) - | lstr == "false" -> ParseOk [caseWarning] (Flag NoDebugInfo) - | lstr == "true" -> ParseOk [caseWarning] (Flag NormalDebugInfo) + | lstr == "false" -> ParseOk [caseWarning name] (Flag NoDebugInfo) + | lstr == "true" -> ParseOk [caseWarning name] (Flag NormalDebugInfo) | otherwise -> ParseFailed (NoParse name line) where - lstr = lowercase str - caseWarning = PWarning $ - "The '" ++ name ++ "' field is case sensitive, use 'True' or 'False'.") + lstr = lowercase str) + + caseWarning name = PWarning $ + "The '" ++ name ++ "' field is case sensitive, use 'True' or 'False'." prefixTest name | "test-" `isPrefixOf` name = name | otherwise = "test-" ++ name diff --git a/cabal-install/src/Distribution/Client/ProjectConfig/Types.hs b/cabal-install/src/Distribution/Client/ProjectConfig/Types.hs index 92850b2792..eb32ce2741 100644 --- a/cabal-install/src/Distribution/Client/ProjectConfig/Types.hs +++ b/cabal-install/src/Distribution/Client/ProjectConfig/Types.hs @@ -59,7 +59,7 @@ import Distribution.Simple.Compiler ( Compiler, CompilerFlavor , OptimisationLevel(..), ProfDetailLevel, DebugInfoLevel(..) ) import Distribution.Simple.Setup - ( Flag, HaddockTarget(..), TestShowDetails(..) ) + ( Flag, HaddockTarget(..), TestShowDetails(..), DumpBuildInfo (..) ) import Distribution.Simple.InstallDirs ( PathTemplate ) import Distribution.Utils.NubList @@ -271,6 +271,7 @@ data PackageConfig packageConfigCoverage :: Flag Bool, packageConfigRelocatable :: Flag Bool, packageConfigDebugInfo :: Flag DebugInfoLevel, + packageConfigDumpBuildInfo :: Flag DumpBuildInfo, packageConfigRunTests :: Flag Bool, --TODO: [required eventually] use this packageConfigDocumentation :: Flag Bool, --TODO: [required eventually] use this -- Haddock options diff --git a/cabal-install/src/Distribution/Client/ProjectPlanning.hs b/cabal-install/src/Distribution/Client/ProjectPlanning.hs index 4113f5f1fb..1745f25632 100644 --- a/cabal-install/src/Distribution/Client/ProjectPlanning.hs +++ b/cabal-install/src/Distribution/Client/ProjectPlanning.hs @@ -115,6 +115,8 @@ import Distribution.ModuleName import Distribution.Package import Distribution.Types.AnnotatedId import Distribution.Types.ComponentName +import Distribution.Types.DumpBuildInfo + ( DumpBuildInfo (..) ) import Distribution.Types.LibraryName import Distribution.Types.GivenComponent (GivenComponent(..)) @@ -1838,6 +1840,7 @@ elaborateInstallPlan verbosity platform compiler compilerprogdb pkgConfigDB elabStripLibs = perPkgOptionFlag pkgid False packageConfigStripLibs elabStripExes = perPkgOptionFlag pkgid False packageConfigStripExes elabDebugInfo = perPkgOptionFlag pkgid NoDebugInfo packageConfigDebugInfo + elabDumpBuildInfo = perPkgOptionFlag pkgid NoDumpBuildInfo packageConfigDumpBuildInfo -- Combine the configured compiler prog settings with the user-supplied -- config. For the compiler progs any user-supplied config was taken @@ -3468,6 +3471,7 @@ setupHsConfigureFlags (ReadyPackage elab@ElaboratedConfiguredPackage{..}) configStripExes = toFlag elabStripExes configStripLibs = toFlag elabStripLibs configDebugInfo = toFlag elabDebugInfo + configDumpBuildInfo = toFlag elabDumpBuildInfo configConfigurationsFlags = elabFlagAssignment configConfigureArgs = elabConfigureScriptArgs diff --git a/cabal-install/src/Distribution/Client/ProjectPlanning/Types.hs b/cabal-install/src/Distribution/Client/ProjectPlanning/Types.hs index 2d5eecdd35..48d3fd6a62 100644 --- a/cabal-install/src/Distribution/Client/ProjectPlanning/Types.hs +++ b/cabal-install/src/Distribution/Client/ProjectPlanning/Types.hs @@ -95,7 +95,8 @@ import Distribution.Simple.LocalBuildInfo ( ComponentName(..), LibraryName(..) ) import qualified Distribution.Simple.InstallDirs as InstallDirs import Distribution.Simple.InstallDirs (PathTemplate) -import Distribution.Simple.Setup (HaddockTarget, TestShowDetails, ReplOptions) +import Distribution.Simple.Setup + ( HaddockTarget, TestShowDetails, DumpBuildInfo (..), ReplOptions ) import Distribution.Version import qualified Distribution.Solver.Types.ComponentDeps as CD @@ -261,6 +262,7 @@ data ElaboratedConfiguredPackage elabStripLibs :: Bool, elabStripExes :: Bool, elabDebugInfo :: DebugInfoLevel, + elabDumpBuildInfo :: DumpBuildInfo, elabProgramPaths :: Map String FilePath, elabProgramArgs :: Map String [String], diff --git a/cabal-install/src/Distribution/Client/Setup.hs b/cabal-install/src/Distribution/Client/Setup.hs index 13cd1001fb..033932a0e7 100644 --- a/cabal-install/src/Distribution/Client/Setup.hs +++ b/cabal-install/src/Distribution/Client/Setup.hs @@ -450,7 +450,7 @@ filterConfigureFlags :: ConfigFlags -> Version -> ConfigFlags filterConfigureFlags flags cabalLibVersion -- NB: we expect the latest version to be the most common case, -- so test it first. - | cabalLibVersion >= mkVersion [2,5,0] = flags_latest + | cabalLibVersion >= mkVersion [3,7,0] = flags_latest -- The naming convention is that flags_version gives flags with -- all flags *introduced* in version eliminated. -- It is NOT the latest version of Cabal library that @@ -483,7 +483,10 @@ filterConfigureFlags flags cabalLibVersion flags_3_7_0 = flags_latest { -- Cabal < 3.7 does not know about --extra-lib-dirs-static - configExtraLibDirsStatic = [] + configExtraLibDirsStatic = [], + + -- Cabal < 3.7 does not understand '--enable-build-info' or '--disable-build-info' + configDumpBuildInfo = NoFlag } flags_2_5_0 = flags_3_7_0 { diff --git a/cabal-install/tests/UnitTests/Distribution/Client/ProjectConfig.hs b/cabal-install/tests/UnitTests/Distribution/Client/ProjectConfig.hs index 95b7e1ccb7..fc9d0c36f7 100644 --- a/cabal-install/tests/UnitTests/Distribution/Client/ProjectConfig.hs +++ b/cabal-install/tests/UnitTests/Distribution/Client/ProjectConfig.hs @@ -559,7 +559,7 @@ instance Arbitrary PackageConfig where <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary - <*> arbitrary <*> arbitrary + <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary <*> arbitraryFlag arbitraryShortToken <*> arbitrary @@ -618,6 +618,7 @@ instance Arbitrary PackageConfig where , packageConfigCoverage = x25 , packageConfigRelocatable = x26 , packageConfigDebugInfo = x27 + , packageConfigDumpBuildInfo = x27_1 , packageConfigRunTests = x28 , packageConfigDocumentation = x29 , packageConfigHaddockHoogle = x30 @@ -674,6 +675,7 @@ instance Arbitrary PackageConfig where , packageConfigCoverage = x25' , packageConfigRelocatable = x26' , packageConfigDebugInfo = x27' + , packageConfigDumpBuildInfo = x27_1' , packageConfigRunTests = x28' , packageConfigDocumentation = x29' , packageConfigHaddockHoogle = x30' @@ -703,7 +705,7 @@ instance Arbitrary PackageConfig where (x10', x11', x12', x13', x14'), (x15', x16', x53', x17', x18', x19')), ((x20', x20_1', x21', x22', x23', x24'), - (x25', x26', x27', x28', x29'), + (x25', x26', x27', x27_1', x28', x29'), (x30', x31', x32', (x33', x33_1'), x34'), (x35', x36', x37', x38', x43', x39'), (x40', x41'), @@ -717,7 +719,7 @@ instance Arbitrary PackageConfig where map NonEmpty x18, x19)), ((x20, x20_1, x21, x22, x23, x24), - (x25, x26, x27, x28, x29), + (x25, x26, x27, x27_1, x28, x29), (x30, x31, x32, (x33, x33_1), x34), (x35, x36, fmap NonEmpty x37, x38, x43, fmap NonEmpty x39), (x40, x41), -- GitLab