My suggestion, look at how Stack (the tool) and Stackage (the platform) work:
https://docs.haskellstack.org/en/stable/README/
My suggestion, look at how Stack (the tool) and Stackage (the platform) work:
https://docs.haskellstack.org/en/stable/README/
Haskell Platform is a perfectly adequate example to take high-level inspiration for the core of this idea: use Cargo (which is like Stack/Stackage for rust) to help bootstrap Rust libraries when using rustup to install and upgrade (mostly equivalent to `stack setup`).
In Cargo jargon, a solutuon would be for metapackages could double as sources: `foo = { metapackage = bar }` to use foo from bar.
But we can do even better. In practice, while code will continue working
with an old metapackage version, people are going to want to upgrade.
We can smooth that process by allowing metapackage dependencies to be
overridden if they appear explicitly in the Cargo.toml file. [dependencies]
hyper = { metapackage = { rust-platform = "2.7" } }
I like the general theme of having the platform be just a set of known-compatible versions, but on the other hand this feels like it loses out on many of the ease-of-use advantages of just specifying a platform version and knowing that you have all the crates inside of it.I don't think we need to pick one way exclusivity. My specific use-case is making PRs for packages to work in kernelspace / in unikernels. The library night initially be packaged the easy way but then I'd use this. I don't want the PR recipient to also worry they might get out of sync with the platform as a side effect.
The problem with Haskell Platform came down to a set of intersecting issues:
- A culture of setting very strict & narrow version bounds. (Based on known-good rather than based on avoiding known-broken)
- Tools (Cabal) that enforce dependency version bounds. If there's mutual/transitive incompatibiltiy in version bounds - the build fails, period. You had to figure out the problem and fix it yourself if there was a truly irreconcilable issue.
- Recommended installer on the website (Platform) was unnecessarily installing packages into the global package database, making you "stuck" with those versions for _all_ packages you attempted to build. Cabal was restricted to finding builds that abide by dependency versions narrowed to the ones provided by the global package database.
These problems led to beginners being confused by seemingly spurious build failures because Platform would fall out of date with the rest of the ecosystem. Cabal would be unable to find sets of compatible dependencies and say it couldn't build the package.
What non-beginners were doing to avoid these problems was:
1. Install the bare compiler, no Platform
2. Use package database sandboxes for each project
All of these (UX and technical) problems were solved without compromising dependency conflict enforcement via Stackage and Stack.
Speaking hypothetically, if Cargo behaves like Maven or Ivy and pulls in two dependencies who want conflicting versions (1.1 and 1.2, say) of a particular library and just picks a winner, then you'll never see something like this.
In the sense of being a sucking chest wound driving new people away, I agree.
>just include both
makes my guts wrench a bit though. I understand how you're (currently) getting away with it but yikes.
EDIT: Apparently coolsunglasses was referring to the Platform, not Cargo, with this comment.
From my perspective: one of the biggest issues in cargo right now. I know it's not the same as the HP problem, but current cargo is definitely not good at solving this.
My email is what finally moved the committee and GHC devs on including Stack with the Platform and on some other decisions concerning the website.
Like I said, not all the downsides may be applicable to how Cargo works or what aturon has in mind, but please don't cite it as an exemplar of anything.
On the first front I guess it's alright (but stackage is better) and on the second front it's totally inadequate—maybe even harmful in that it probably made the problem just less painful enough to spur procrastination.
I think most of this lesson doesn't apply to rust, but still good to be aware. It certainly gave me a strong eversion to course-grained dependency management as a bandaid.
Were. Were hard. It's quite fine now with Stack. I know users of all kinds of languages that all miss Stack when they're working on their non-Haskell projects.
EDIT: To elaborate on why I like Stack:
+ Fully declarative. I don't run commands to edit my Stack environment, instead I modify the relevant stack.yml file. This means that the current environment can always be easily examined, committed to Git, etc.
+ Easy NixOS integration which means I can also describe the non-haskell dependencies for a project, and enforce that _absolutely_ nothing else on my system gets used. This is amazing.
+ I like that it uses Stackage by default, and that I can pin projects to LTS Stackage releases. This means that many users of my projects will probably already have most dependencies installed -- especially cool for small things like tutorials where users won't have the patience for long build times.
+ It reuses the already existing `.cabal` file format so it's easy to make libraries compatible with cabal-install, the other package manager in the Haskell ecosystem.
That said, nix-style builds don't actually address my issues with cabal-install. My (very personal) preference is to always have the current dependencies being used reflected exactly in a local file. I picked up this attitude from NixOS, but it's an extremely useful way of doing things -- the knowledge that as long as I don't lose that file I can always rebuild my current environment exactly is just too awesome.
I think that if you need to track version bounds as well (say you're developing a library) they should be kept in a separate file, and you should always have a master file that describes what you're currently using locally. Happily this is exactly what Stack does with my-project.cabal and stack.yml.
That said, I appreciate that others like cabal-install, so I do what I can to make my code easy to use with both package managers (the main thing is keeping aggressive upper bounds on the few libraries I maintain, which especially helps cabal-install users since they do dependency solving more).