-
Notifications
You must be signed in to change notification settings - Fork 701
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
Add new-show-build-info command #5954
Changes from all commits
1e9de7f
0418c08
533d6bf
0469b47
c917a06
dae46d9
b0ecf2d
3ff9276
73c438d
dc93de6
8c61157
c677b5b
17cb804
316676b
167bc72
0b0bd5d
59d1f06
669c18b
c967931
d89ca8d
6f0cb5b
feefced
b62af6c
3dcc14a
a1b4f6a
114bb5a
b3b7ab1
70359c6
7014bb7
1bd70df
e213925
e1b3875
4562c8d
53aa595
928e92f
c0c1ac2
0c18343
041e370
83bf662
141d706
decab60
0d06867
457d8a5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
-- | | ||
-- 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. | ||
-- | ||
-- | ||
-- This format is intended for consumption by external tooling and should | ||
-- therefore be rather stable. Moreover, this allows tooling users to avoid | ||
-- linking against Cabal. This is an important advantage as direct API usage | ||
-- tends to be rather fragile in the presence of user-initiated upgrades of | ||
-- Cabal. | ||
-- | ||
-- Below is an example of the output this module produces, | ||
-- | ||
-- @ | ||
-- { "cabal-version": "1.23.0.0", | ||
-- "compiler": { | ||
-- "flavor": "GHC", | ||
-- "compiler-id": "ghc-7.10.2", | ||
-- "path": "/usr/bin/ghc", | ||
-- }, | ||
-- "components": [ | ||
-- { "type": "lib", | ||
-- "name": "lib:Cabal", | ||
-- "compiler-args": | ||
-- ["-O", "-XHaskell98", "-Wall", | ||
-- "-package-id", "parallel-3.2.0.6-b79c38c5c25fff77f3ea7271851879eb"] | ||
-- "modules": ["Project.ModA", "Project.ModB", "Paths_project"], | ||
-- "src-files": [], | ||
-- "src-dirs": ["src"] | ||
-- } | ||
-- ] | ||
-- } | ||
-- @ | ||
-- | ||
-- The @cabal-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. | ||
-- | ||
-- The @components@ property gives a list of the Cabal 'Component's defined by | ||
-- the package. Each has, | ||
-- | ||
-- * @type@: the type of the component (one of @lib@, @exe@, | ||
-- @test@, @bench@, or @flib@) | ||
-- * @name@: a string serving to uniquely identify the component within the | ||
-- package. | ||
-- * @compiler-args@: the command-line arguments Cabal would pass to the | ||
-- compiler to compile the component | ||
-- * @modules@: the modules belonging to the component | ||
-- * @src-dirs@: a list of directories where the modules might be found | ||
-- * @src-files@: any other Haskell sources needed by the component | ||
-- | ||
-- Note: At the moment this is only supported when using the GHC compiler. | ||
-- | ||
|
||
module Distribution.Simple.ShowBuildInfo (mkBuildInfo) where | ||
|
||
import qualified Distribution.Simple.GHC as GHC | ||
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.Program | ||
import Distribution.Simple.Setup | ||
import Distribution.Simple.Utils (cabalVersion) | ||
import Distribution.Simple.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 | ||
-> LocalBuildInfo -- ^ Configuration information | ||
-> BuildFlags -- ^ Flags that the user passed to build | ||
-> [TargetInfo] | ||
-> Json | ||
mkBuildInfo pkg_descr lbi _flags targetsToBuild = info | ||
where | ||
componentsToBuild = map (\target -> (componentLocalName $ targetCLBI target,targetCLBI target)) targetsToBuild | ||
(.=) :: String -> Json -> (String, Json) | ||
k .= v = (k, v) | ||
|
||
info = JsonObject | ||
[ "cabal-version" .= JsonString (display cabalVersion) | ||
, "compiler" .= mkCompilerInfo | ||
, "components" .= JsonArray (map mkComponentInfo componentsToBuild) | ||
] | ||
|
||
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) | ||
|
||
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 | ||
Just comp = 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] | ||
_ -> [] | ||
|
||
-- | Get the command-line arguments that would be passed | ||
-- to the compiler to build the given component. | ||
getCompilerArgs :: BuildInfo | ||
-> LocalBuildInfo | ||
-> ComponentLocalBuildInfo | ||
-> [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 | ||
where | ||
-- This is absolutely awful | ||
ghc = GHC.renderGhcOptions (compiler lbi) (hostPlatform lbi) baseOpts | ||
where | ||
baseOpts = GHC.componentGhcOptions normal lbi bi clbi (buildDir lbi) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
-- | Utility json lib for Cabal | ||
-- TODO: Remove it again. | ||
module Distribution.Simple.Utils.Json | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this file should be removed, is that still true? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, definitely! We already have a JSON library (which is more or less a derivative of http://hackage.haskell.org/package/microaeson-0.1.0.0/docs/Data-Aeson-Micro.html) inside By moving show-build-info into There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. At this point I don't care whether we address this as part of this PR, or at a later stage; so feel free to consider this issue of the JSON library duplication punted to a follow-up PR It may be worth leaving a TODO source-comment at the top of this module |
||
( Json(..) | ||
, renderJson | ||
) where | ||
|
||
data Json = JsonArray [Json] | ||
| JsonBool !Bool | ||
| JsonNull | ||
| JsonNumber !Int | ||
| JsonObject [(String, Json)] | ||
| JsonString !String | ||
|
||
renderJson :: Json -> ShowS | ||
renderJson (JsonArray objs) = | ||
surround "[" "]" $ intercalate "," $ map renderJson objs | ||
renderJson (JsonBool True) = showString "true" | ||
renderJson (JsonBool False) = showString "false" | ||
renderJson JsonNull = showString "null" | ||
renderJson (JsonNumber n) = shows n | ||
renderJson (JsonObject attrs) = | ||
surround "{" "}" $ intercalate "," $ map render attrs | ||
where | ||
render (k,v) = (surround "\"" "\"" $ showString' k) . showString ":" . renderJson v | ||
renderJson (JsonString s) = surround "\"" "\"" $ showString' s | ||
|
||
surround :: String -> String -> ShowS -> ShowS | ||
surround begin end middle = showString begin . middle . showString end | ||
|
||
showString' :: String -> ShowS | ||
showString' xs = showStringWorker xs | ||
where | ||
showStringWorker :: String -> ShowS | ||
showStringWorker ('\"':as) = showString "\\\"" . showStringWorker as | ||
showStringWorker ('\\':as) = showString "\\\\" . showStringWorker as | ||
showStringWorker ('\'':as) = showString "\\\'" . showStringWorker as | ||
showStringWorker (x:as) = showString [x] . showStringWorker as | ||
showStringWorker [] = showString "" | ||
|
||
intercalate :: String -> [ShowS] -> ShowS | ||
intercalate sep = go | ||
where | ||
go [] = id | ||
go [x] = x | ||
go (x:xs) = x . showString' sep . go xs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the functionality needs to be in
Distribution.Simple
, can't it be implemented solely incabal-install
. There should be a rationale why it cannot be, if there are legitimate reasons.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is, according to @hvr and @DanielG, and this pr is obsolete since the Cabal part has already been merged.
For discussions on cabal-install part, see: #6241
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good.
Sad we need support in
Cabal
though, as we have to worry aboutbuild-type: Custom
stuff.