Description
Imported from reddit:
I got annoyed that every time I build something in a new cabal sandbox I have to wait for the same versions of lens
or haskell-src-exts
to compile forever.
Couldn't we just cache the build directory from which we installed a package instead of throwing it away after every build?
Cabal tries to guarantee that running cabal install
in a source directory always produces the correct result without us having to run cabal clean
first (so no matter what the state of the dist/
directory is). Cabal does this by using ghc --make
for building, which has very good recompilation avoidance and flag change detection.
This means that this kind of cache introduces no additional correctness guarantees we would have to provide, it is only relying on guarantees that cabal already tries to provide.
The cache does take some space in my home directory, but I accept that for the 20x faster build it allows.
For example, a no-op rebuild of for haskell-src-exts
is 7 seconds on my computer vs. a full build that takes 132 seconds.
This method will pick up changed dependencies (e.g. it will build correctly when the version of haskell-src-exts
's dependency pretty
changes between two builds) because ghc --make
notices that.
This method will also provide for cases where other approaches cannot. For example, as mentioned here and here, it can cache more than a nix-like approach can: With nix caching ends completely at the first dependency that has changed, while ghc --make
caches on the module level, recompiling only those modules that depend on changed code, not packages. Nevertheless, the biggest speedup to be expected is for CI systems like TravisCI, CircleCI etc., and sandboxes, as those compile share huge parts of the dependency graph where all code is exactly the same.
Here's a proof of concept patch: nh2/cabal@nh2:before-buildcache...buildcache
What do you think?
Some things we would need:
- Are you aware of any recent or past cabal bugs mentioning that
cabal clean
was necessary in order to build correctly? - Also I think that if we want to try this out, the best might be to hide it behind a
cabal install --cached
option defaulting to False, and if it works out well, make it the default at some point in the future. Do you agree?