-
Notifications
You must be signed in to change notification settings - Fork 24
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
Work better with Haskell.nix? #57
Comments
I have to read this properly, but I have a quick comment: cabal-install doesn’t use per-component build for cabal-doctest is a hack, and I really really don’t want to make it more hacky. So option 3: Nothing is very tempting. |
Okay, let me put that PR up anyway, and you can decide if it makes the code noticeably worse. I'll go out of my way to not break any prior functionality. It will just generate new things in |
At least one build system [Haskell.nix](https://github.com/input-output-hk/haskell.nix) builds Haskell projects a component at a time. This breaks cabal-doctest's expected usage of getting configuration from the Cabal components for libraries and executables under test. By recording flags for the test component, we introduce another possible usage where all information we need comes from the test component alone. See issue ulidtko#57 for more discussion and details.
We used to only get module sources from library and executable components. So the `Build_doctests` module wouldn't show up. But for issue ulidtko#57 we're now getting module sources for the test suites as well, and Cabal nags us with the warning: <no location info>: warning: [-Wmissing-home-modules] These modules are needed for compilation but not listed in your .cabal file's other-modules: Build_doctests So people are likely to follow the warning and put in Build_doctests into their Cabal file, and then be annoyed that it breaks their tests. Because `Build_doctests` is autogenerated by Cabal-doctests, we know it will never have doctests itself, so it can be safely filtered out.
The main motivation of the commits for issue ulidtko#57 is to make it easier to use Cabal-doctests with Haskell.nix. Haskell.nix has built everything by the time everything is run, so there are no intermediate directories around like `build/` or `dist/`. What Haskell.nix does instead is just make the original source available. So it seems convenient to include not just absolute paths, but relative paths as well. Otherwise, we have to munge the "-i" flags after the fact.
The main motivation of the commits for issue ulidtko#57 is to make it easier to use Cabal-doctests with Haskell.nix. Haskell.nix has built everything by the time everything is run, so there are no intermediate directories around like `build/` or `dist/`. What Haskell.nix does instead is just make the original source available. So it seems convenient to include not just absolute paths, but relative paths as well. Otherwise, we have to munge the "-i" flags after the fact.
Hi!
I tried to integrate two things new to me recently, Cabal-doctest and Haskell.nix. As you might expect, Doctests are already pretty hacky when it comes to Cabal integration. It only gets trickier when you throw in Nix. Actually, the default way of building Haskell projects with Nix (Nixpkgs) didn't give me a problem with Doctests, even with Cabal-doctest. But Haskell.nix, specifically, causes me issues.
I have a couple ideas on how we might improve the state of things.
Background on Nix and Haskell.nix
I don't know much you already know about Nix and Haskell.nix, but I figured it would be good to spell out some relevant context, even if for others finding this ticket.
In Nix, everything is cached at the level of a Nix derivation. A derivation sets up a very hygenic/controlled environment, with all of the files/folders/permissions/envvars explicitly specified. Then the crank is turned, and specific outputs are cached as the output of the derivation. These can then be used to set up the environment for subsequent derivations. This is important, because it means that transient build artifacts from a previous derivation are not just lying around for the next derivation. They have to be explicitly copied over.
What Haskell.nix does that breaks the normal Cabal-doctest workflow is have a separate derivation for each component in a Cabal project. So the libraries, executables, and test suites each get their own derivation. Furthermore, there is even a separate derivation to run a test that is different from the one that builds the test code. This is kind of nice because it gives developers more control. A developer can make sure all these tests build without actually running the tests. But then, because in Nix everything is cached at the derivation-level, we can run the tests later and use the same artifacts we cached previously. Stack/Cabal users take this for granted, but in Nix we have to make Nix expressions to regain this flexibility, which is one of the reasons the Haskell.nix project exists as a alternative to the default way of building things with Nix (Nixpkgs).
What's going wrong with Haskell.nix + Cabal-doctest
Components are seen only one at a time
The code for Cabal-doctest assumes that most of the flags we need are derived from the library and executable components. But in a Haskell.nix derivation for a test component, there are no library or executable components. They have already been built and made available in the package database provided to the derivation's Cabal run. However, the source code of these components can be made available (obviously needed for the authored doctests themselves).
Right now, Cabal-doctest when running in a Haskell.nix derivation won't output any flags, packages, or module sources. Because these flags are output only for libraries and executables, which are not available when compiling the test component. What would be useful is to get the at least the packages flags (possibly the rest too) from the test component. The code I need to load up in my doctests have already been shuttled into a package database. And I can access this package database for normal dependencies from my doctest. This does mean to list dependencies I need for doctests on my test component, not just the dependencies needed for the doctest fixture. But that seems like an okay compromise to me.
Some references to missing artifacts
All the references to
build/
anddist/
, but alsoBuild_doctests
aren't useful for a Haskell.nix derivation. All of this stuff is in the package database.Possible solutions (not mutually exclusive)
1. At least output flags for the test component
I made a patch of cabal-doctest that does this (not cleaned up for a PR yet, and not sure if you want to go this direction anyway), and it makes this following
Build_doctests.hs
file:2. Eliding problematic missing references
Although there's a few references to artifacts that are missing:
-i/build/exceptions-checked/dist/build/doctests/autogen
-i/build/exceptions-checked/dist/build
-i/build/exceptions-checked/test
-i/build/exceptions-checked/test
-package-db=dist/package.conf.inplace
-optPdist/build/doctests/autogen/cabal_macros.h
Build_doctests
The only ones that really cause my Haskell.nix build trouble are the two bolded above. The
Build_doctests
file should be elided frommodule_sources_test_*
always, I think. If we did nothing with the missingdist/package.conf.inplace
I can always do aghc-pkg init dist/package.conf.inplace
in my Haskell.nix configuration. It's a small one-liner.We could possibly make an option to elide the "inplace" package flag. But we'd need this flag for non-Haskell.nix builds. I'd much more prefer to have a static Cabal configuration and source code that works with all builds systems. Small tweaks seem better on the Nix side than that Cabal side.
3. Nothing
I list this for completeness. I kind of understand the argument that Cabal-doctest is complicated enough as it stands. Is Haskell.nix breaking an invariant expected of Cabal?
I'm probably going to point some Haskell.nix developers at this ticket. Maybe there's something about the Haskell.nix implementation that can be changed to allows all the components to show up in the
LocalBuildInfo
whenSetup.hs
runs.The text was updated successfully, but these errors were encountered: