A purely consumerist approach to the use of the package eco-system.
Regarding 1. you already have a bunch of volunteers who make sure things works without a hitch when you install stuff – as witnessed by the excellent build plan that was offered by opam in this case, which actually allowed the person to start building immediately without suffering cryptic build failures; great user experience if you ask me. I don’t think it’s reasonable to ask these people to also make sure that every library they may not even personally care about in the repo works on the latest version of OCaml. In this case the only reasonable and scalable answer I see is to ask users of the package to take care of it if upstream’s maintenance is dropping the ball and they care enough about it – if you are unhappy about that then just don’t use that component.
Regarding 2. people should remember that they didn’t come to build something, they came to build something with the help of tools that are mostly developed on unpaid (or paid largely below the professions’ standard) labor. I don’t think it’s worth trying to “meet” people who do not realize this and come to you feeling entitled to everything working for them.
More generally this is not a problem with OCaml as the OP ridiculously insinuated, it’s a problem with any eco-system that is developed along the bazaar model. I don’t think there’s much you can do about it, but I have to say, given my experience with other eco-systems, the experience here is already vastly superior. Bit-rotting systems usually fail with cryptic build errors and can get you stuck for a couple of hours – as @jrfondren brilliantly quipped “you are understimating hell by a lot here”.
Interesting, I did not know it was so easy to create an unconstrained switch. Also the behavior seems to be a bit random. In my case, it chose to install OCaml 5.2.1, for no apparent reason. (But if I do opam switch create . --empty && opam install ocaml, it correctly chooses to install the most recent version of the compiler.)
And where they ended up was a working installation of the libraries they requested. This whole topic could easily have been “OCaml successfully gave me a working environment; now I’m wondering how to use the very latest compiler” but the OP seems to have been in a bad mood and decided to spread their malaise.
I agree that we could do with some support in opam to make the compiler package invariants clearer in the UI: I have also noticed the lack of an invariant when using local switches, but doing so is as simple as:
(but I always forget to specify the compiler and end up without an invariant)
I’ve recently been coding in other ecosystems like npm and have observed exactly the same problems with upper bounds (just try upgrading to Vite8 and rolldown in pnpm). In those cases, my coding agents cut through the issue in minutes and helped me find the right command line magic. OCaml is no different in this regard: all the AI agents work just fine in my experience. What these agents cannot do, however, is to encourage constructive public communication about issues found that makes volunteer maintainers want to help a stranger out.
We’re getting there (well, @dra27 is). The latest opam package is “relocatable” which packages can issue a conflict against if they are not relocatable. After that, binary caching will be a breeze until you get to third-party system shared libraries being upgraded under our feet by the system package manager, but we wouldn’t want life to be too easy right? @mtelvers has also built a system that can bulk build all opam packages in 30 minutes on one machine, which unlocks the ability to build quick binary snaps on Linux/amd64/arm64. macOS and Windows will remain a pain.
My 22 year old PhD OCaml code still compiles today with the only breakage being the switch to safe-string! Sadly aging the code hasn’t improved the quality of what I wrote back then.
I entirely agree about taking responsibility in ‘industrial’ software of dependencies. I wrote up our experiences in using OCaml in Docker in this year’s ICFP and that uses a monorepo with manual imports from opam every so often. This is necessary not just for basic security hygiene of inspecting third-party updates, but also for determinism and calculation of licensing strings for products embedding other people’s code.
I have went through ocaml / opam / lsp… etc conflicts during 5.3.0 migration ~> 5.4.0 on Ubuntu 26.04 due to some libraries locked from 24.04 that system can’t upgrade immediately. Which like you, it also caused me to downgrade ocaml version back to old one.
This indeed a common weakness in nowadays ecosystem, where external dependencies are like plagues.
i think many libraries need to be dissolved into one stable version at some point to reduce the time & complexity with external dependencies. Most important blockchains did this to reduce build time, improve security & optimization.
But another aspect of Ocaml is that it’s a GC based language, which always requires wrapping another native C library into its convention.
So you can’t just include it directly into code without that wrapper like C or many llvm based languages out there
maybe, this would be good time to think about that : a non-GC functional language like Ocaml but on llvm/c that can import any native library easily. So no package man is needed ( like Odin).
I guess that depends on the definition of “fundamental”. It’s selecting a slightly, albeit increasingly, out-of-date version, not preventing its installation. Both explicitly requesting a compiler version, or requiring a package which needs OCaml 5.3+ both cause the compiler to be upgraded.
This is correct. I had a not-unrelated experience with Rust. [I think Rust is a -great- language: you can program at the level of C/C++, but do it with the mindset of OCaml, and that’s -miraculous-, so this is no complaint] I was hacking on
(1) package D, which depended on package C, A
(2) C depended on B
(3) both B,C depended on A. But somehow, Rust’s package-manager decided to “auto-vendor” the version of A that B would get, but -not- that which C would get, even though there were no indications that that was going to happen. So effectively you got :
(a) A1,A2 in the build
(b) B depends on A1
(c) C depends on A2, B
(d) D depends on A1, C
And then (haha) C exported a type from A (== A2) so you got a type mismatch at the D→C interface. Or something like that. And again, there was no indication in the package manifests asking for vendoring. So it was mysterious, and there was no way to turn it off! Turned out, Rust’s cargo package manager had “auto-vendoring” for all packages less than version=1.0. Which is (haha) all packages pretty much (since Rust is so young). Just crazy.
I forget how I worked around the problem, but there it is. So it ain’t like somehow opam is unique in presenting these sorts of issues to users.
Thanks for the amusing anecdote @Chet_Murthy. Stories like this make me wonder if Rust’s support for multiple lib versions in the same build is really a net win, all things considered.
In Rust’s (Cargo’s) defense, AFAICT this was a -policy- decision imposed on <1.0 version packages. IIUC Cargo -does- support vendoring (multiple lib version etc, etc), but outside of this policy default, it’s much more ….. restrained. At least, that what I understood: it’s been quite a while since I hacked on Rust, and I could be wrong.
Vendoring is fine I guess: I personally find it objectionable, but hey, I’ve seen a number of languages/package-managers that support it, and it seems OK, works fine, doesn’t blow up at scale. Again, I personally think it’s a bad idea, and I always figure out how to upgrade everything so that I can have one version of each lib/package in a project.
ETA; I feel it might be relevant to add that even though Rust really does have a bazaar-like model, I think the strong culture of testing (and the strong support for testing in Rust’s tooling) mitigate what might otherwise be more chaos. I feel the same about the Opam CI process: it is a strong cultural and process-based pushback against what might otherwise be a chaos-inducing bazaar.
The opam (and repository esp) maintainers do yeoman’s work.
Learning a new language is much much more than just the language. A language is a whole ecosystem. I think it should be approached with curiosity, patience and humility, like moving to a new country. Specially for a very old language with a long heritage and established ecosystem. Curiosity, patience and humility. Unfortunately in this ugly new world these are in very short supply. Discomfort is something we all need to tolerate, it’s the price of change, something we pay before we can harvest the rewards.