Support GHC 9.12
[cabal.git] / Cabal / src / Distribution / Simple / ShowBuildInfo.hs
blob4f84f3ed8e487ac84b2bee983ac1c79fc4051fa0
1 {-# LANGUAGE OverloadedStrings #-}
3 -- |
4 -- This module defines a simple JSON-based format for exporting basic
5 -- information about a Cabal package and the compiler configuration Cabal
6 -- would use to build it. This can be produced with the
7 -- @cabal build --enable-build-info@ command.
8 --
9 --
10 -- This format is intended for consumption by external tooling and should
11 -- therefore be rather stable. Moreover, this allows tooling users to avoid
12 -- linking against Cabal. This is an important advantage as direct API usage
13 -- tends to be rather fragile in the presence of user-initiated upgrades of
14 -- Cabal.
16 -- Below is an example of the output this module produces,
18 -- @
19 -- { "cabal-lib-version": "1.23.0.0",
20 -- "compiler": {
21 -- "flavour": "GHC",
22 -- "compiler-id": "ghc-7.10.2",
23 -- "path": "/usr/bin/ghc",
24 -- },
25 -- "components": [
26 -- { "type": "lib",
27 -- "name": "lib:Cabal",
28 -- "compiler-args":
29 -- ["-O", "-XHaskell98", "-Wall",
30 -- "-package-id", "parallel-3.2.0.6-b79c38c5c25fff77f3ea7271851879eb"]
31 -- "modules": ["Project.ModA", "Project.ModB", "Paths_project"],
32 -- "src-files": [],
33 -- "src-dirs": ["src"]
34 -- }
35 -- ]
36 -- }
37 -- @
39 -- The output format needs to be validated against 'doc/json-schemas/build-info.schema.json'.
40 -- If the format changes, update the schema as well!
42 -- The @cabal-lib-version@ property provides the version of the Cabal library
43 -- which generated the output. The @compiler@ property gives some basic
44 -- information about the compiler Cabal would use to compile the package.
46 -- The @components@ property gives a list of the Cabal 'Component's defined by
47 -- the package. Each has,
49 -- * @type@: the type of the component (one of @lib@, @exe@,
50 -- @test@, @bench@, or @flib@)
51 -- * @name@: a string serving to uniquely identify the component within the
52 -- package.
53 -- * @compiler-args@: the command-line arguments Cabal would pass to the
54 -- compiler to compile the component
55 -- * @modules@: the modules belonging to the component
56 -- * @src-dirs@: a list of directories where the modules might be found
57 -- * @src-files@: any other Haskell sources needed by the component
59 -- Note: At the moment this is only supported when using the GHC compiler.
60 module Distribution.Simple.ShowBuildInfo
61 ( mkBuildInfo
62 , mkBuildInfo'
63 , mkCompilerInfo
64 , mkComponentInfo
65 ) where
67 import System.FilePath
69 import Distribution.Compat.Prelude
70 import Prelude ()
72 import qualified Distribution.Simple.GHC as GHC
73 import qualified Distribution.Simple.Program.GHC as GHC
75 import Distribution.Compiler
76 import Distribution.PackageDescription
77 import Distribution.Pretty
78 import Distribution.Simple.Compiler (Compiler, compilerFlavor, showCompilerId)
79 import Distribution.Simple.Program
80 import Distribution.Simple.Setup.Build (BuildFlags)
81 import Distribution.Simple.Utils (cabalVersion)
82 import Distribution.Text
83 import Distribution.Types.Component
84 import Distribution.Types.ComponentLocalBuildInfo
85 import Distribution.Types.LocalBuildInfo
86 import Distribution.Types.TargetInfo
87 import Distribution.Utils.Json
88 import Distribution.Verbosity
90 -- | Construct a JSON document describing the build information for a
91 -- package.
92 mkBuildInfo
93 :: FilePath
94 -- ^ The source directory of the package
95 -> PackageDescription
96 -- ^ Mostly information from the .cabal file
97 -> LocalBuildInfo
98 -- ^ Configuration information
99 -> BuildFlags
100 -- ^ Flags that the user passed to build
101 -> (ConfiguredProgram, Compiler)
102 -- ^ Compiler information.
103 -- Needs to be passed explicitly, as we can't extract that information here
104 -- without some partial function.
105 -> [TargetInfo]
106 -> ([String], Json)
107 -- ^ Json representation of buildinfo alongside generated warnings
108 mkBuildInfo wdir pkg_descr lbi _flags compilerInfo targetsToBuild = (warnings, JsonObject buildInfoFields)
109 where
110 buildInfoFields = mkBuildInfo' (uncurry mkCompilerInfo compilerInfo) componentInfos
111 componentInfosWithWarnings = map (mkComponentInfo wdir pkg_descr lbi . targetCLBI) targetsToBuild
112 componentInfos = map snd componentInfosWithWarnings
113 warnings = concatMap fst componentInfosWithWarnings
115 -- | A variant of 'mkBuildInfo' if you need to call 'mkCompilerInfo' and
116 -- 'mkComponentInfo' yourself.
118 -- If you change the format or any name in the output json, don't forget to update
119 -- the schema at @\/doc\/json-schemas\/build-info.schema.json@ and the docs of
120 -- @--enable-build-info@\/@--disable-build-info@.
121 mkBuildInfo'
122 :: Json
123 -- ^ The 'Json' from 'mkCompilerInfo'
124 -> [Json]
125 -- ^ The 'Json' from 'mkComponentInfo'
126 -> [(String, Json)]
127 mkBuildInfo' compilerInfo componentInfos =
128 [ "cabal-lib-version" .= JsonString (display cabalVersion)
129 , "compiler" .= compilerInfo
130 , "components" .= JsonArray componentInfos
133 mkCompilerInfo :: ConfiguredProgram -> Compiler -> Json
134 mkCompilerInfo compilerProgram compilerInfo =
135 JsonObject
136 [ "flavour" .= JsonString (prettyShow $ compilerFlavor compilerInfo)
137 , "compiler-id" .= JsonString (showCompilerId compilerInfo)
138 , "path" .= JsonString (programPath compilerProgram)
141 mkComponentInfo :: FilePath -> PackageDescription -> LocalBuildInfo -> ComponentLocalBuildInfo -> ([String], Json)
142 mkComponentInfo wdir pkg_descr lbi clbi =
143 ( warnings
144 , JsonObject $
145 [ "type" .= JsonString compType
146 , "name" .= JsonString (prettyShow name)
147 , "unit-id" .= JsonString (prettyShow $ componentUnitId clbi)
148 , "compiler-args" .= JsonArray (map JsonString compilerArgs)
149 , "modules" .= JsonArray (map (JsonString . display) modules)
150 , "src-files" .= JsonArray (map JsonString sourceFiles)
151 , "hs-src-dirs" .= JsonArray (map (JsonString . prettyShow) $ hsSourceDirs bi)
152 , "src-dir" .= JsonString (addTrailingPathSeparator wdir)
154 <> cabalFile
156 where
157 (warnings, compilerArgs) = getCompilerArgs bi lbi clbi
158 name = componentLocalName clbi
159 bi = componentBuildInfo comp
160 -- If this error happens, a cabal invariant has been violated
161 comp = fromMaybe (error $ "mkBuildInfo: no component " ++ prettyShow name) $ lookupComponent pkg_descr name
162 compType = case comp of
163 CLib _ -> "lib"
164 CExe _ -> "exe"
165 CTest _ -> "test"
166 CBench _ -> "bench"
167 CFLib _ -> "flib"
168 modules = case comp of
169 CLib lib -> explicitLibModules lib
170 CExe exe -> exeModules exe
171 CTest test ->
172 case testInterface test of
173 TestSuiteExeV10 _ _ -> []
174 TestSuiteLibV09 _ modName -> [modName]
175 TestSuiteUnsupported _ -> []
176 CBench bench -> benchmarkModules bench
177 CFLib flib -> foreignLibModules flib
178 sourceFiles = case comp of
179 CLib _ -> []
180 CExe exe -> [modulePath exe]
181 CTest test ->
182 case testInterface test of
183 TestSuiteExeV10 _ fp -> [fp]
184 TestSuiteLibV09 _ _ -> []
185 TestSuiteUnsupported _ -> []
186 CBench bench -> case benchmarkInterface bench of
187 BenchmarkExeV10 _ fp -> [fp]
188 BenchmarkUnsupported _ -> []
189 CFLib _ -> []
190 cabalFile
191 | Just fp <- pkgDescrFile lbi = [("cabal-file", JsonString fp)]
192 | otherwise = []
194 -- | Get the command-line arguments that would be passed
195 -- to the compiler to build the given component.
196 getCompilerArgs
197 :: BuildInfo
198 -> LocalBuildInfo
199 -> ComponentLocalBuildInfo
200 -> ([String], [String])
201 getCompilerArgs bi lbi clbi =
202 case compilerFlavor $ compiler lbi of
203 GHC -> ([], ghc)
204 GHCJS -> ([], ghc)
205 c ->
207 [ "ShowBuildInfo.getCompilerArgs: Don't know how to get build "
208 ++ " arguments for compiler "
209 ++ show c
211 , []
213 where
214 -- This is absolutely awful
215 ghc = GHC.renderGhcOptions (compiler lbi) (hostPlatform lbi) baseOpts
216 where
217 baseOpts = GHC.componentGhcOptions normal lbi bi clbi (buildDir lbi)