Interleaving per-component hooks with build
ÉRDI Gergő
gergo at erdi.hu
Sun Mar 14 11:15:00 UTC 2021
Hi,
I've made some progress on this, but I still have some questions. My new
idea is to use withAllComponentsInBuildOrder to do the preprocessing
before handing it over to buildHook simpleUserHooks. So then the next
missing piece of the puzzle is how to arrange for buildHook
simpleUserHooks to only build a single component:
```
myBuildHook pkg localInfo userHooks buildFlags = do
withAllComponentsInBuildOrder pkg localInfo $ \c clbi -> do
localInfo <- return $ restrictLocalInfo c clbi localInfo
buildFlags <- return $ restrictBuildFlags c buildFlags
bi <- preprocessBuildInfo localInfo buildFlags c
pkg <- return $ updateBuildInfo c bi pkg
buildHook simpleUserHooks pkg localInfo userHooks buildFlags
```
All the magic is supposed to happen in `restrictLocalInfo` and
`restrictBuildFlags` to restrict the `LocalInfo` and the `BuildFlags` so
that `buildHook simpleUserHooks` will only build the single given
component.
My first idea was to edit the `componentEnableSpec` / `componentGraph` /
`componentNameMap` to be singleton lists:
```
restrictLocalInfo :: Component -> ComponentLocalBuildInfo -> LocalBuildInfo -> LocalBuildInfo
restrictLocalInfo c clbi localInfo = localInfo
{ componentEnabledSpec = OneComponentRequestedSpec $ componentName c
, componentGraph = G.insert clbi G.empty
, componentNameMap = M.singleton (componentName c) [clbi]
}
```
If I try this, building fails if some components are explicitly requested:
setup: Cannot process the executable 'compucolor2-cpu-screen' because this
package was configured only to build lib. Re-run configure with the argument
executable 'compucolor2-cpu-screen'
So next idea was to also delete the `buildArgs`:
```
restrictBuildFlags :: Component -> BuildFlags -> BuildFlags
restrictBuildFlags c buildFlags = buildFlags
{ buildArgs = []
}
```
This gets us over building the lib, but now the exes fail:
Preprocessing executable 'compucolor2-cpu-textscreen' for
compucolor2-0.1.0..
Building executable 'compucolor2-cpu-textscreen' for compucolor2-0.1.0..
<command line>: cannot satisfy -package-id compucolor2-0.1.0-1E5h9nTsLCR9N8r4sKLlg5
(use -v for more information)
My other idea is to NOT change the LocalInfo, and instead only edit
`buildArgs` to contain only the current component. I haven't managed to
get this quite right either:
* If I only put the current component's name (via `prettyShow . componentName`)
in the `buildArgs` list, then that fails for libraries: `prettyShow .
componentName` for the library component is `"lib"`, but it seems that
Cabal actually expects `"lib:packagename"` as the argument.
* If I hack it by hardcoding the addition of `"lib:mylibname"` to the
`buildArgs`, then the library is built and re-built and re-built for each
component again and again. Of course, these "builds" finish quickly
because nothing has changed, but it's still a nuisance.
* The whole point of this exercise is to have access to already built
libraries when preprocessing executables. But it seems that that is not as
simple as adding `absolutePackaBgeDBPaths $ withPackageDB localInfo` to
the package DB path when building, since that directory doesn't have a
pkgconf file for the just-built library. So how do I use just-built
dependency libraries?
Thanks,
Gergo
On Wed, 3 Mar 2021, ÉRDI Gergő wrote:
> I am looking for a way to do custom preprocessing for each component (of type
> `UnitId -> IO ()`) but this preprocessing depends on the dependencies of the
> component being already built. So imagine a Cabal file which defines a
> library and an exe, with the exe depending on the library. Then, I would need
> the following sequence of events to happen during `buildHook`:
>
> 1. myPreprocessing unitIdOfLibrary
> 2. standard build of library
> 3. myPreprocessing unitIdOfExe
> 4. standard build of exe
>
> How can I achieve that without copy-pasting large parts of the internals of
> `buildHook simpleUserHooks`?
More information about the cabal-devel
mailing list