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

Conversation

fendor
Copy link
Collaborator

@fendor fendor commented Sep 14, 2019


Please include the following checklist in your PR:

  • Patches conform to the coding conventions.
  • Any changes that could be relevant to users have been recorded in the changelog.
  • The documentation has been updated, if necessary.
  • If the change is docs-only, [ci skip] is used to avoid triggering the build bots.

Please also shortly describe how you tested your change. Bonus points for added tests!

Since #6108 merged parts of #5954, the original pr #5954 got obsolete.
This now is the second part that contains only changes to cabal-install and the test-suite.
This is a push to get s-b-i merged for exe:cabal, enabling further improvements to it.

cc @hvr, @DanielG, @mpickering

cabal-install/Distribution/Client/CmdShowBuildInfo.hs Outdated Show resolved Hide resolved
@@ -304,7 +305,8 @@ mainWorker args = do
, hiddenCmd win32SelfUpgradeCommand win32SelfUpgradeAction
, hiddenCmd actAsSetupCommand actAsSetupAction
, hiddenCmd manpageCommand (manpageAction commandSpecs)

, hiddenCmd CmdShowBuildInfo.showBuildInfoCommand
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should it be a hidden command?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any reason to hide it. We're treating it like an API, right? What is our API guarantee for the returned JSON anyways? Should probably write that down somewhere.

No breaking changes within a Cabal major version? No breaking changes ever?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Someone else needs to define this, I dont know enough of the process and the ramifications of such promises.

@fendor
Copy link
Collaborator Author

fendor commented Sep 15, 2019

CI fail seems to be unrelated to this pr.

@fendor fendor requested a review from DanielG September 19, 2019 16:25
Copy link
Collaborator

@DanielG DanielG left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pushing this through! Functionality loooks good apart from the fact that we still don't have any tests that actually use the build info we get to run GHC or anything.

While testing out the lib:Cabal side show-build-info I noticed that what we get back from that doesn't include the inplace package-db because that's added very late by the build command. See the createInternalPackageDB calls in Simple/Build.hs.

Some pretty basic tests that call GHC would have cought this, just saying ;) I found it because I have such tests in cabal-helper.

I think we should definetly fix that issue before merging but we can just fix it up on the cabal-install side for now, I'm not sure it even makes sense to fix that on the Cabal side anyways.

Other minor things:

  • The code is still a bit messy and needs quite some cleanup.
  • I'd like to see some deduplication of the test code.

cabal-testsuite/PackageTests/ShowBuildInfo/B/B.cabal Outdated Show resolved Hide resolved
cabal-testsuite/PackageTests/ShowBuildInfo/B/B.cabal Outdated Show resolved Hide resolved
cabal-install/Distribution/Client/CmdShowBuildInfo.hs Outdated Show resolved Hide resolved
cabal-install/main/Main.hs Outdated Show resolved Hide resolved
cabal-install/main/Main.hs Outdated Show resolved Hide resolved
@@ -0,0 +1,12 @@
# cabal show-build-info
cabal: Internal error in target matching. It should always be possible to find a syntax that's sufficiently qualified to give an unambiguous match. However when matching 'exe:B' we found exe:B (unknown-component) which does not have an unambiguous syntax. The possible syntax and the targets they match are as follows:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Um, this sounds like a cabal bug to me. Certainly nothing that should be expected test output or ever seen by users! Please find out what's going on here.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That error message looks like #5081.

cabal-testsuite/PackageTests/ShowBuildInfo/A/cabal.project Outdated Show resolved Hide resolved
@lukel97
Copy link
Contributor

lukel97 commented Jun 1, 2020

I've been trying to integrate this with hie-bios and it's been going well so far. There are some things I would like to see addressed first though:

  • runghc Setup.hs show-build-info returns one JSON object, whereas cabal show-build-info returns an array of JSON objects, one for each component/unit it plans on building, namely due to how it is calling the wrapper several times. But this seems to me to defeat the purpose of the components array, as it is possible to get runghc Setup.hs show-build-info to return one object containing all the components needed
  • With runghc Setup.hs show-build-info, you need to configure it first with --enable-tests/--enable-benchmarks to see the build info for tests and benchmarks respectively. This makes sense for the Setup.hs method, but you also need to do the same for cabal show-build-info. For the sake of tooling integration I think cabal show-build-info should default to including tests and benchmarks without having to pass --enable-tests/--enable-benchmarks

@lukel97
Copy link
Contributor

lukel97 commented Jun 3, 2020

@phadej @fendor I've changed this to avoid calling Setup.hs to get the show-build-info result (It still uses it for configuring the components). That way we can collect the component information separately and use the correct compiler information, and return just one build info object rather than several, whilst also avoiding the temporary files. So there's a bit of poking about done with LocalBuildInfo here which I'm aware seems to be taboo within cabal-install

test.hs Outdated
build-depends: base
with-compiler: ghc-8.6.5
-}
main = putStrLn "hey"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ugh accidentally added this and hie.yaml during a rebase. Will fix

@lukel97
Copy link
Contributor

lukel97 commented Jun 3, 2020

I think cabal show-build-info should implicitly build dependencies, much like cabal repl, otherwise it will fail on a clean project when trying to configure. It should behave equivalently to

cabal build --only-dependencies <targets>  && cabal show-build-info <targets>

Passing the targets to the build part will be important, as with cabal repl only the dependencies of the target need to be buildable before ghci can be launched with the right flags

@phadej
Copy link
Collaborator

phadej commented Jun 3, 2020

--only-dependencies could fail easily: #6106

If project contains packages A and C, and there is third package B (on Hackage),
then if dependency graph is A -> B -> C, you essentially need to build also C to build B to configure A.

We don't have such more of operation currently. Would be good to have. Actually both:

  • build all dependencies you can without building local packages
  • build all dependencies, incl. some local packages, so all external dependencies are built. I.e. you can configure packages.

@lukel97
Copy link
Contributor

lukel97 commented Jun 4, 2020

I ran into this whilst testing out integrating this with hie-bios, #6874 and I think there should be a mechanism to allow for ambiguous target selectors to be resolved, e.g. by just selecting the first one. Namely, hie-bios isn't going to care what component's flags cabal show-build-info returns, as long as it can actually get the flags in the first place

@lukel97
Copy link
Contributor

lukel97 commented Jun 6, 2020

Todo

  • Make AmbiguousTargetResolver a command line flag so other commands can use it. --pick-first-target
  • Fix Haddock output interfering with stdout
  • Address autogen files

@lukel97
Copy link
Contributor

lukel97 commented Jun 12, 2020

Tricky situation with dependencies: Given this simple cabal file

cabal-version: 2.4
name:          C
version:       0.1.0.0
license:       BSD-3-Clause

library
  exposed-modules:  Lib
  build-depends:    base
  default-language: Haskell2010

test-suite tests
  type: exitcode-stdio-1.0
  main-is: Test.hs
  build-depends: base, C
  default-language: Haskell2010

If we are to run cabal show-build-info verbatim without passing any targets to it at all, it will fail at configuring the test-suite because the library C will not have been built. cabal show-build-info Test.hs does work though, as it seems to count the library C as a dependency in this scenario

Edit: this has been solved with a new prunePlanToAllDependencies function, a special case of prunePlanToDependencies

This means that cabal-install now extracts the LocalBuildInfo etc.
itself for each component, and now assembles the JSON without the need
for writing to temporary files. It also means that one build info JSON
object can be returned instead of an array. It works by configuring each
component separately as before, and instead of making its own build info
object, it just collects the component information.

This one build info object now reports the compiler used with the
ElaboratedSharedConfig, which is shared across all components.
Every other command defaults to what they used to do. show-build-info
now just chooses the first choice, since it doesn't care about
ambiguity.
@lukel97
Copy link
Contributor

lukel97 commented Jul 7, 2020

@DanielG Phew, reworked it to now use the nix stuff. Hopefully ci passes

@lukel97 lukel97 force-pushed the rebase-cabal-sbi branch 2 times, most recently from 5084eb1 to 00ba53b Compare July 8, 2020 10:29
@lukel97
Copy link
Contributor

lukel97 commented Jul 8, 2020

New and noteworthy things in this PR:

  • Added cabal-install show-build-info
  • --pick-first-target flag to resolve ambiguous target selectors to just the first target
  • show-build-info now returns the location of the cabal file as well as the unpacked source directory of the package (not the hs-src-directory, which is different)
  • show-build-info now uses Text rather than String internally
  • show-build-info has the buildinfo-components-only flag which spits out each component's json line by line. Used by cabal-install to piece together components that are split across multiple per-component packages

| JsonString !Text

-- | A type to mirror 'ShowS'
type ShowT = Text -> Text
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I spotted this via your comment. Why this and not https://hackage.haskell.org/package/text-1.2.4.0/docs/Data-Text-Lazy-Builder.html

The ShowT = Text -> Text is worse than ShowS, as it copies all intermediate values, causing quadratic behavior.

Yet, if you doing this for performance reasons, you should use ByteString and its builder, like aeson.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accidentally quadratic, how embarrassing! I'll switch this all over to ByteString, didn't realise Text was also locale dependent


case fileOutput of
Nothing -> T.putStrLn res
Just fp -> T.writeFile fp res
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is locale dependent, better to serialise to ByteString and write it.

@phadej
Copy link
Collaborator

phadej commented Jul 8, 2020

Separate JSON utility into own PR, it is independent and can be reviewed and committed independently.

This fixes a lot of edge cases for example where the package db wasn't
created at the time of configuring. Manually doing the setup.hs wrapper
stuff was hairy.

It also changes the internal representation of JSON to Text rather than
String, and introduces the buildinfo-components-only flag in the Cabal
part to make it easier to stitch back the JSON into an array in
cabal-install.

Turns out we do need to keep the show-build-info part inside Cabal as we
rely on LocalBuildInfo which can change between versions, and we would
need to do this anyway if we wanted to utilise the
ProjectPlanning/Building infrastructure.
@jneira
Copy link
Member

jneira commented Oct 18, 2021

@fendor has been this superseeded so we could close?

@fendor fendor closed this Oct 18, 2021
@masaeedu
Copy link

masaeedu commented Nov 5, 2021

@jneira @fendor Sorry, would you mind expanding on what this has been superseded with? There seems to now be a network of issues about show-build-info that are all pointing at each other saying X is superseded by Y and Y is superseded by Z and so on :)

Is there a "can i run cabal show-build-info yet" issue somewhere?

@fendor
Copy link
Collaborator Author

fendor commented Nov 5, 2021

This issue summarises the current ideas, discussions and efforts: #7489

Specifically this is a PR overview: #7489 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants