cabal
cabal copied to clipboard
Using Cabal to create autogenerated files, without building anything else
The Stack project is thinking about what Stack needs to do to prepare for Cabal's changing approach to hooks (https://github.com/commercialhaskell/stack/issues/6542).
Currently, before Stack makes use of ghc --interactive (the stack ghci or stack repl commands), Stack uses Cabal (the library) to create the autogenerated files for every configured component of a package, without building everything. It does so by making use of Cabal's replHook and initialBuildSteps:
replHook :: PackageDescription -> LocalBuildInfo -> UserHooks -> ReplFlags -> [String] -> IO ()
initialBuildSteps :: FilePath -> PackageDescription -> LocalBuildInfo -> Verbosity -> IO ()
(The replHook function is supplied with the PackageDescription and LocalBuildInfo values and the FilePath and Verbosity values that are needed by initialBuildSteps are found within ReplFlags.)
I think there are two places Stack could do what it seeks to do:
- after everything is configured. However, the new scheme for hooks does not have a hook for when everything is configured;
PostConfPackageHookfires before components are configured and its inputLocalBuildConfigexcludes the part ofLocalBuildInfothatinitalBuildStepsneeds to know; and - before any building starts. The new scheme for hooks has
PreBuildComponentRules, but it is not clear to me that Cabal can be made to fire the pre-building hooks without actually building anything.
My questions are these:
- could Cabal have a 'configuration' hook that fires after everything is configured and that supplies (amongst other things) the part of
LocalBuildInfothatinitialBuildStepsneeds? and/or - is it possible to use Cabal (the library) in such a way that the pre-building hooks fire and then Cabal 'stops', without building everything?
May I 'pause' any consideration of this issue? I think I can take a different approach with Stack, where it does not need to use any hook to do what it seeks to do. EDIT: There is a Stack pull request that takes a direct approach to applying initialBuildSteps: https://github.com/commercialhaskell/stack/pull/6544
I believe the only way to run pre-build steps that works for packages with build-type: Custom is to use the Setup repl command. This should run all the necessary pre-build steps:
- generating Cabal autogenerated modules (such as the paths module),
- running any built-in preprocessors (such as
alex,happy,hsc2hs, ...), - running custom module generation logic and custom preprocessors.
Manually calling initialBuildSteps would only do (1), which would not (in general) allow the component to be loaded into GHCi.
The Setup repl command should not start building anything. For example the GHC build function skips building when called for an interactive repl session.
Please let me know if there is something that I have missed, and hopefully we can come up with a solution for stack's usage.
@sheaf, Stack's stack ghci opens GHCi set-up (as far as it can be) for a multi-package project. If I understand Cabal (the library)'s repl correctly from its in-app documentation, it opens GHCi set-up for one component ("The default component is the library itself, or the executable if that is the only component.") of a single package:
Usage: Setup.hs repl [COMPONENT] [FLAGS]
So, for Stack to use Cabal's repl to set things up (for each package in turn in the project), I think repl would need a flag to not open GHCi.
@mpilgrem Recent versions of cabal have such a flag (--repl-multi-file <dir>) which writes a file containing the arguments which would have been used to start the repl into the given directory. This also doesn't call ghc --interactive.
@mpickering, is that cabal-install? stack --snapshot nightly-2024-04-03 runghc -- Setup.hs repl --help (GHC 9.8.2, Cabal-3.10.2.0) does not mention that flag.
I think it is only going to be in the 3.12 release.. which still hasn't been released it seems.