-
Notifications
You must be signed in to change notification settings - Fork 696
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
code-generators field in test stanza. #7688
Conversation
This is amazing. |
I wonder, could this be generalized to make the existing preprocessor feature extensible? |
#7394?? |
that's in cabal-install, while I'm talking about the Cabal/.cabal feature: https://cabal.readthedocs.io/en/latest/cabal-package.html#modules-and-preprocessors #6726 mentions extensible preprocessors edit: #6232 too... I wish there was a (properly applied) "preprocessors" tag |
This is slightly different than standard preprocessors since it generates code from scratch, rather than turning an *.xyz file into a *.hs file. I certainly became familiar with the preprocessor code via working on this, but I think that generalizing preprocessors would have a different api design for how executables are expected to be invoked, etc. So it is related work, but sufficiently different I can't see a single generalization covering both. |
@gbaz Hi! I've taken a look at the PR and I was wondering: I see you've used the syntax |
That syntax is existing syntax for how The new thing is the code-generators field, which does not use that component syntax, but just looks up the tool by name in the program database. |
@gbaz Thank you very much! Do you still need a hand to finalise this PR? I would also enable the syntax in other places like library components |
As I discussed on irc I don't think it makes sense in library components because this enables things to generate new modules fed into the build pipeline. For libraries, we want all exposed modules declaratively specified in the file itself. I'm finishing up the test failures, then will add some tests and docs, but otherwise yeah I'd like some review on it. |
@gbaz Concretely what happens if a module isn't declared in From what @swamp-agr showed me in encoding, the process seems to be enforced just like you want for custom setups? |
I should clarify. The point of this field is that it can generate modules that are not listed in the cabal file, and make use of them. The use case of autogen-modules is totally different. It allows modules that are listed in the cabal file to not cause failures with sdist when their source does not appear: https://cabal.readthedocs.io/en/3.4/cabal-package.html#pkg-field-autogen-modules |
What is the point of https://github.com/haskell/cabal/blob/master/Cabal-tests/tests/UnitTests/Distribution/Utils/Structured.hs btw? Is it just to make us notice when we change the structure hash? I.e. this pr adds stuff to the TestSuite type, which necessarily affects the hash of GenericPackageDescription and LocalBuildInfo. But its ok to do that -- we've updated this file in the past to reflect changes to the hash. So what are we gaining by this? |
Ah I see, those two usecases are different. Thank you very much for the explanation. I imagine this justifies the separate
I think @phadej originally introduced it in #6255 / ae33fcf. |
|
Right. I understand and appreciate structured. Not a big deal but just remain unsure if there's ever a case where these tests will fail and it will mean some action other than "update the tests with the new hash". |
added changelog, docs, tests. ready for review and merge |
* wip to add test-code-generators field to test stanzas * fixups * change hashes * regen golden parser test output * docs and changelog * test * Update pr-7688 * tweak test Co-authored-by: Gershom Bazerman <gershom@arista.com>
* wip to add test-code-generators field to test stanzas * fixups * change hashes * regen golden parser test output * docs and changelog * test * Update pr-7688 * tweak test Co-authored-by: Gershom Bazerman <gershom@arista.com>
@@ -268,6 +268,7 @@ data TestSuiteStanza = TestSuiteStanza | |||
, _testStanzaMainIs :: Maybe FilePath | |||
, _testStanzaTestModule :: Maybe ModuleName | |||
, _testStanzaBuildInfo :: BuildInfo | |||
, _testStanzaCodeGenerators :: [String] |
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.
String
isn't a good name for a type as it does not reflect its intended semantics. It is also badly searchable across the code base.
type CodeGenerator = String
type CodeGenerators = [CodeGenerator]
and then use these type synonyms.
Extra points for a newtype
!
@@ -26,7 +26,8 @@ import qualified Distribution.Types.BuildInfo.Lens as L | |||
data TestSuite = TestSuite { | |||
testName :: UnqualComponentName, | |||
testInterface :: TestSuiteInterface, | |||
testBuildInfo :: BuildInfo | |||
testBuildInfo :: BuildInfo, | |||
testCodeGenerators :: [String] |
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.
A comment would be in order explaining this new field, maybe linking to this PR.
In particular I wonder, should this field be non-revisable on Hackage?
(By default, I suppose, "yes, cannot change in a revision". But on the other hand, what is the harm of revising this? It's just for the test suite. Also, version of dependencies can be arbitrary revised, to the point of completely changing functionality... Why not test generaters...?)
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.
our principle for allowing revisions has always been "by default, negative, and allow revision only if there's demonstrated need"
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.
Thanks for the justification.
@gbaz: what do you plan to do with the extra comments donated to you after the merge? |
They're useful comments, but I think too small to be actionable after the fact. |
@gbaz: Not sure I follow this logic. But I'd anyhow appreciate some discussion/justification about revisability decisions... |
I left a comment regarding revisability. Otherwise, I just meant, there's plenty else on my plate and I don't imagine I'll find time for stylistic/comment cleanup at this point. Maybe the next time somebody touches the relevant code they could do further work, but for now I'm going to focus elsewhere. |
Thanks! |
I'm not up to date with all the details of this proposal and, as I'm swamped with other obligations, I'm not planning to get too involved.
|
Thank you for your remarks. They make a lot of sense.
Could you elaborate which proposal you have in mind, e.g., which ticket? This PR is an implementation, not a proposal, and it's finalized and merged and used in (demos of) external tools. |
@sol what this feature (now merged) allows is writing small drivers so that one need not install Instead, with a single addition of a field and a supporting driver, one can simply run An example of such a cabal field and stanza (that works) is at: https://github.com/gbaz/cabal-doctest-demo/blob/main/cabal-doctest-demo.cabal#L36 The supporting driver is at: https://github.com/gbaz/cabal-doctest-demo/blob/main/doctest-codegen-driver/app/Main.hs |
This PR extends the
test
stanza of a cabal file with acode-generators:
field containing executables. These executables can be generated as dependencies via thebuild-tools-depends:
field. They are run during the build step after all other preprocessors, and before the main build step, and can be used to autogenerate modules for test suites, e.g. for doctests, or other "discover" style test running.These executables are expected to follow a very simple api. They are invoked as
exe-name TARGETDIR [SOURCEDIRS] -- [GHCOPTIONS]
-- where targetdir is a temp directory in thedist-newstyle
hierarchy where they are directed to place their generated code. This is followed by a list of source directories containing the source files of all the local lib components which the test stanza depends on. Finally, following a double-dash, are all the options that cabal would pass to ghc for a build.The expected output of these executables is a newline-separated list of names of all the generated modules. This PR also prevents checking for the existence of the main-is module in the preprocessor step, because that main module itself may be generated by the code generator.
A proof-of-concept of how this works is at https://github.com/gbaz/cabal-doctest-demo -- this repo gives a package that has two different doctest runners built on top of this functionality. One wraps up the
doctest
program with a wrapper generated from the ghc options (and so which does not rely on a ghc environment file to bring deps into scope, but rather extracts them directly form the build-depends). The other uses the lexer from https://github.com/phadej/cabal-extras/tree/master/cabal-docspec and generates a fully static tasty testsuite from the doctest comments in the source lib.I think this code is basically correct and clean. If people like it, to finish off this PR it needs a changelog, doc updates, and some proper extension of the cabal test suite.