How long does stack keep the packages in its cache? - haskell

I'm working with the Lean theorem prover and I would like to build features like those of stack and start building library caches. One thing that I'm unsure about is when to delete older packages in the cache. I could think that, if I have two versions of Lean installed, say 3.3.0 and 3.3.1, I could argue for keeping all the versions of all the packages that work on those. Since the Lean syntax moves fast, it is quite restrictive.
On the other hand, I could see keeping only 10 versions of any given package. This could be the 10 most recent versions or the 10 most recently requested versions.
I'd love to know some of the ideas considered in building stack and related tools.

stack keeps packages in cache forever. Or until you manually delete those packages. There's no snapshot garbage collection implemented in stack. So what you can only do is to manually call
rm -rf ~/.stack
to remove whole stack cache. It's in general good practice to do it periodically to remove outdated packages which were accumulated for some period of time. But make sure to backup .stack/global-project/stack.yaml if you changed it manually.
stack command which handles cache removal for you is under development:
https://github.com/commercialhaskell/stack/issues/133

Related

How to Cache a Haskell Dependency to Speed Up Compilation Time?

Problem: I'm working on a Haskell project that uses stack (+ nix). We have a dependency that takes 10+ minutes to compile. Every time we clean our .stack-work, we have to wait for this huge package to compile, and it's really hurting our project's efficiency. The package name is godot-haskell, and here is how the package is depended upon in our stack.yaml:
extra-deps:
- godot-haskell-0.1.0.0#sha256:9d92ff27c7b6c6d2155286f04ba2c432f96460f448fd976654ef26a84f0e35a6,26290
Question: Is there a way for us to somehow cache this package (in stack, or even in nix) so that it locally never has to get compiled (or has to get compiled at most once, even if the .stack-work directory is deleted)?
For the currently released Stack, the best way to make this happen is to put the extra-dep into a custom snapshot file instead of the extra-deps in the stack.yaml file. (The upcoming Stack release has a feature referred to as "implicit snapshots" which sidesteps this.) You can see an example of this in the Stack repo itself:
https://github.com/commercialhaskell/stack/blob/master/stack.yaml#L1
https://github.com/commercialhaskell/stack/blob/master/snapshot.yaml

How do I remove copies of GHC that were installed by Stack?

Like the poster in this Reddit thread, I am running low on drive space and would like to get rid of some of the older versions of GHC that Stack installed for me. (I have five versions installed and they’re taking up over 6 GB.) Is it safe just to remove the individual versions’ folders from ~/.stack/programs/x86_64-osx, or is there a better way?
Yes, deleting those directories is safe.

Speeding up Haskell stack project compilation and git branches

I cannot change GHC's compilation times, but I can control the environment in which things are compiled. What can I do with git and stack to minimize downtime due to (re-)building?
Haskell stack caches compiled dependencies in the .stack-work directory, and it great for working on one thing at a time. However, I find myself switching back and forth between branches. I've done git checkout in place, and perhaps some of the .stack-work cache is usable. But I greatly prefer git worktree to get a copy of a branch in a different directory altogether. Worktree is especially hard on build times as each worktree directory will have its own .stack-work, and therefore must download/configure/compile/install its own dependencies instead of using existing ones.
I've been doing some reading about Nix and Haskell, but since stack creates its own cache, it ignores whatever Nix has compiled and installed. From what I've read, I really want Nix to handle dependencies and stack to handle my personal code. I get great benefit from stackage and stack solver, so I do not want to give them up. But when I see a screenful of "unregistering" messages when running stack build --only-dependencies && stack ghci, I know that I've got at least 10-15 minutes before I get a prompt.
Many thanks!

how to force stack to use newer version of local package

I have a package A which is build with stack producing a library. The library is used in package B (i.e. A is a dependent package listed in B's cabal file). B is build with stack as well. Consider the four cases of changes in A and use of solver on B:
1 - When A changes then B continues to use the old state of A - this follows the guarantee of stack that a compilation always works the same way and is not influenced by changes in other programs.
2 - If the package A has a new version number, then stack build on A followed by stack build B does silently use the new version. I think this is wrong, as it violates the guarantee; it should continue to use the old version.
3 - If package A changes without a new version number and solver is run on B, packages B continues using the old state. I think this is wrong; after running solver, the guarantee does not apply and the new state should be used.
4 - if package A changes with a new version number and solver is run on B then B uses the new version. This is is correct.
I cannot understand this behavior and how version numbers and solver interact. How to control the use of a new state of a without each time bump the version number up? Changing version numbers all the time is inconvenient if two packages are worked on in parallel; it should be sufficient to run solver to bring the changes from A into B and without running solver, the package should always recompile, independent of changes in other packages.
For development, I wish there were an (additional) flag I could use in case 2 to set for stack to build always using the newest state of the dependent packages silently (as if there would be a new version, without bumping the version number up).
Do I misunderstand the guarantee of stack build or misunderstand the behavior of stack? The code I used to test is simplistic and is on github: git#github.com:andrewufrank/test-depProj.git.
The question is related to previous questions I asked regarding atoms or leksahs behavior in multi-project development. I found that the issue is essentially a question of the behavior of stack build and must be clarified for stack build first.
For clarification the stack.yam of A
flags: {}
extra-package-dbs: []
packages:
- .
extra-deps: []
resolver: lts-8.13
and for B
flags: {}
extra-package-dbs: []
packages:
- .
- ../a
extra-deps: []
resolver: lts-8.13
It seems to be a bug and I reported it.
The workaround is, as described by #duplode, to do stack build only in one project or to use the --force-dirty flag when stack-build.
The problem is seemingly caused by behavior of cabal, which reuses an ID even when the content of a package has changed. A fix was included in stack 1.4.0. (see stack issues #2904 #3047), but it appears this was not effective in all cases.

Haskell Environment

I recently finished the book "learnyouahaskell" and now I would like to apply my acquired knowledge by building a yesod application.
However I am not sure about how to get started.
There seems to be two options on how to set up a yesod project. One is with Stack, and the other is with cabal sandboxes.
But what are the differences (If any?) and the similarities between them? Does one count as best practice whereas the other doesn't?
The yesod quickstart suggests using stack, is this fine or should I use cabal sanbox?
There are actually three different packages that are being talked about here.
cabal-install is the current stable binary to build your applications.
stack was just released to the public recently. I believe it is trying to replace cabal-install as a better, more convenient tool. At the very least, it is showing the Haskell community a different way of something things.
Cabal is the library that both cabal-install and stack are based off of.
As for the differences between the first two tools.
cabal-install is a mature application used nearly everywhere within the Haskell community (at least in open source, I have no idea what people are doing behind closed doors).
stack is still a new (at least to the public) application used in some newer projects. Some more information can be found here. But some of the highlights are:
running stack build in a projects directory will install GHC (Haskell compiler) as well as the needed dependencies for the project.
stack, by default, runs off of stackage. Which is a curated version of hackage. Meaning you can expect the different packages to play nicely with each other. Leading to reproducible builds.
You can still fall back on hackage should you choose to.
The great thing about these two applications is that they can be used by different people for the same project. If you decide you want to use cabal-install with sandboxes, and someone comes along and wants to help with your project, they can just add the files that stack needs and they can use stack while you continue to use cabal-install. Or vice-versa.
here is one persons experience after using stack for the first time. They claim that it is a little bit easier to get started because there are a couple less steps required to get started. If nothing else, people highlight the pros and cons of each tool.
Note: I'm still fairly new to Haskell, and have never actually used stack. I've actually been told to stay away from it unless building something in yesod.
Edit: As stated in a comment under this answer, I believe I have mis-represented what people have told me about stack. The comments people have given me when I asked if I should switch over to stack were more along the lines of, If you are comfortable enough using cabal sandboxes, there is no reason to switch over to stack unless you are having issues.
The lead developer of Yesod (Michael Snoyman) is actively involved with the Stack tool. So, I would recommend you to set up Yesod with Stack. Also, Yesod has a quite a complex set of dependencies and using Stackage as the default curated source, helps very much in the installation process (which Stack takes care of by default).
Also read this post for understanding the differences of Stack from cabal.

Resources