Closed brandon-leapyear closed 7 months ago
:sparkles: This is an old work account. Please reference @brandonchinn178 for all future communication :sparkles:
Just doing a cursory investigation, it seems like the build cache is saved before the build is run? https://github.com/commercialhaskell/stack/blob/30224e347624f34c9ebbbb444c07339cd123eb4d/src/Stack/Build/Execute.hs#L1573-L1574
Why not do this at the end of realBuild
or maybe after/in postBuildCheck
?
I've also experienced this!
Here's a work-around for now. Put this on all of your library, executable, test, and benchmark declarations in your package.yaml
s.
when:
- condition: false
other-modules: Paths_<package_name>
You need to replace <package_name>
with the name of your package, but any dashes must be replaced with underscores. So if your package is named my-package
, you'd write: other-modules: Paths_my_package
.
Since there's not much activity on this bug, I'll mention that I'm also seeing this happen in practice: the second build of a given configuration always rebuilds from scratch. It happened in this GitHub Actions workflow, for example, with the "Test" step rebuilding unnecessarily after the "Build and Haddock" step built an identical configuration: https://github.com/google/hs-portray/runs/3644246045
A slightly easier repro than the one in the original bug: since adding --test
changes the hash, we can use that to trigger the bug:
% stack clean
% stack build # builds from scratch as expected
% stack test # rebuilds as expected because tests were added
% stack test # rebuilds unnecessarily because the last 'stack test' updated Paths_xyz.hs
Hey we have this too, but only since upgrading from 2.3.1 to 2.7.1.
I will try bisect the stack repo to find out where this appears
I suspect this also affects stackage builds (very badly)
This (and maybe other seemingly unnecessary full rebuilds) have been hurting us a lot. We recently estimated 30 seconds of build time per character changed in actual source code.
I'm trying @wraithm's workaround (thank you!) although I hate it because we have a lot of build targets.
@dten wrote:
Hey we have this too, but only since upgrading from 2.3.1 to 2.7.1.
I will try bisect the stack repo to find out where this appears
What did bisection find out?
Ah I never managed, sorry
I am closing this issue given the passage of time and because I could not reproduce the issue with Stack 2.15.5, following https://github.com/commercialhaskell/stack/issues/5503#issuecomment-922525225:
> stack new test5503
> cd test5503
> stack build # builds (lib + exe), including Paths_test5503
> stack test # builds (lib + exe + test), including Paths_test5503; runs test
> stack test # does not rebuild; runs test
General summary/comments (optional)
We have a large monorepo with multiple Haskell projects, and we've noticed that Stack recompiles much more often than it needs to. For example, we might run a
stack build
, which buildsA -> B -> C
, but then runningstack build
immediately afterwards would unregisterA
, forcing the recompilation ofB
andC
. I noticed that the unregistering output mentions thePaths_packageA.hs
file changing, which is odd because thestack build
commands run immediately after each other.After doing some digging, I noticed that if
Paths_packageA.hs
changes duringstack build
(i.e. gets regenerated), the nextstack build
compares the new version ofPaths_packageA.hs
with the version ofPaths_packageA.hs
before the previousstack build
call, not the version of it after.Steps to reproduce
stack purge
orgit clean -dfx
stack build
cat
on.stack-work/dist/*/*/build/*/autogen/Paths_*.hs
extra-deps
instack.yaml
stack build
-- this rightfully rebuildscat
on thePaths
file -- should have been regeneratedstack build
Expected
The last
stack build
command should not rebuildActual
The last
stack build
command rebuilds, withThe rebuild might be fast if you're in a repo with only one Haskell package, but in a repo with multiple Haskell packages depending on each other,
this would completely recompile everything downstream from the unregistered packageEDIT: I guess it doesn't recompile everything downstream, but it unregisters everything and forces everything downstream to rerun the configure + copy/register phase, which is still less than ideal for our system of ~20 packages.Stack version
Method of installation