Setting up a new OCaml environment in 2026 is not yet a fluid experience

Good to know. However, I was rather referring to the fact that it’s cumbersome to have non-fatal warnings in the dev profile, one needs to update dune-project with an esoteric (in particular for students) stanza:

(env (dev (flags (:standard -warn-error -A))))

(also: IIRC, a recompilation does not show unsolved issues again if the situation hasn’t changed, which is also an issue for students working in small steps)

Dune is simple to use for simple projects (a main.ml file that use a some other files), and even for more complicated ones (project decomposed in libraries). I find it easier to setup and maintain than Make (where each new file should be registered). Then a beginner should be happy with it.

Sure, if you want to make something fancy, the “opiniotated” way could harm, but it doesn’t happend to me.

I don’t understand. If a program doesn’t compile and if you don’t fix all things, trying to compile it again will fail displaying the same old issues.

1 Like

This makes sense if they have disabled dune’s warnings-as-errors configuration, which the dune people recommend against for exactly this reason.

1 Like

Je connais cette théorie (OSS 117) :slight_smile: (French joke)

To me, the definition of a simple project for dune is too simple.

I am a casual developer (a researcher developing proofs of concept from time to time), so much that I re-learn dune each time I start a project. But when I develop, I routinely use ocamlformat, Menhir, Ocamllex, testing tools, bisect_ppx, some ppx_deriving plugins (required by some tools), environment variables switching the state of compilation, generate an OPAM file, open @c-cube ‘s Containers in every file by default… Having a working, stable-over-years configuration of dune + opam + ocamlformat for this kind of project, which I find pretty classic, is IMO not simple at all. I still prefer to use these tools because, once they work and as long as you don’t change anything, they are indeed simple to run and provide with nice features out of the box (speed, watch mode, promote…). And I thank their developers for that. But, simple to use, definitely not. (For the sake of completeness, you can totally avoid to register all files in a makefile.)

Not necessarily with non-fatal warnings indeed. IIRC it already happened with failing tests for some of my students (I had to dune clean and then dune test for them to see pending issues).

Well, another solution would be to show all issues in all dune executions… I personally use fatal warnings for my projects, because I’m convinced it’s worth the cost. But, for students, I think it’s OK to start learning with non-fatal warnings rather than bother them with compilation errors just because they have unused identifiers (which is common for beginners who iterate over their program).

I guess that most build tool would have the same issue. With Make, if the compiler has produced an object file, it won’t be rexecuted twice because of warnings. It compiles only a source file when no corresponding object file exists (or when the source is newer, of course).

(Granted, but as I said, I seem to recall this kind of situation also happened to some of my students for failed tests. In any case, this is secondary w.r.t the main issues I tried to raise.)

I will agree that the concept of switches is has an awful UX* and having the user in some kind of weird ambient state that they are in charge of managing is not great (this is not an OCaml specific issue, I hated virtualenvwrapper back in the day in Python as well. This is always what happens if the compiler doesn’t deal with package management).

Joke as much as you want about node_modules but having each project have its own dependencies and Node automatically doing the Right Thing™ was so much better. And also easier, as you don’t have to tell people how to eval $(some command) and help them debug issues with it.

So I might be tooting my own horn here but doing away with switches is one of the big features of Dune package management. You specify the dependencies you want in a file, Dune installs dependencies for you. You don’t need to make sure you’re in the right switch, in the right folder, messed up your switch, share a switch between different projects etc. The dependencies are local to a project, as they should be. You don’t need to make sure you’re practising proper switch hygiene. If you delete a project, it’s dependencies are also gone.

*Well, switches were an amazing improvement when they came out as a better alternative to “installing things globally on the system” and local switches were an amazing improvement to “you need to manage your switches separately from your projects” but over years of using them there’s a lot of discipline you need to have and I’d rather have my tools manage dependencies instead of me.

2 Likes

Depends :–) Just bear in mind that what you describe here is just one use case.

For someone like me who manages ~40 packages on the opam repository ~15 unpublished ones and a couple of apps which sometimes depend on the HEAD of any of these packages, having two switches (one for the lower OCaml bound I support and one for the OCaml version I use) makes it actually much leaner to handle all that.

Having 60 * 2 local switches in each of these repos would not be helpful, on the contrary, more than once pins on the HEAD showed me breakage I did not intend which I wouldn’t see or much later (or too late) if I were to use the closed worlds you suggest.

3 Likes

You specify the dependencies you want in a file, Dune installs dependencies for you.

does that include ocamlformat? That formatting is version-dependent makes it a bit of a pain to contribute to a project that’s using a different version.

1 Like

I have at time of writing 42 switches (I sometimes delete some), which means I’ve been sitting through the installation 42 times. This is still better for me than to deal with what happens if one of the projects wants one version of cmdliner and the other projects wants another. This way I can pull any project and update the switch to the current dependencies via opam install --deps-only <…> . without the worry that if I go back to another project the dependencies in that other projects are a mess because of shared state.

Conceptually Dune can share installed dependencies via the Dune cache, so one wouldn’t need to rebuild the same things 42 times, but this isn’t tested too well. However with the merge of the relocatable patches in OCaml 5.5 a lot of things are falling into place for this to work and people are actively working on making this be fast in the future.

However, I think the main thing is that the current switch management overhead is a burden on all users, even if they just care about a few packages, with one configuration.

If you want to manage your switches e.g to have multiple compilers to test your code against you can still do that, it’s also fully supported as it was before.

The main though behind it is that easy things should be easy (and easier as now), and hard things (should stay) possible.

Ideally, dependencies should be in a ‘global’ (usually under the user’s home directory) store, addressed by compiler version, package name, and package version. The package/build manager should link them in by translating between the project’s library requirements and the concrete path to the package in the store.

This would save a huge amount of disk space, network, and recompilation. It’s what pnpm does: https://pnpm.io/

1 Like

Yes. Also Dune makes sure that the dependencies of dev-tools and projects don’t intersect so e.g. if you’re using base.v0.17 and ocamlformat uses base.v0.16 it works. It also reads your .ocamlformat to determine which version of ocamlformat to install.

(There are however a few caveats about dev-tools and we’re not particularly happy how it works in the moment, we’re tracking this in pkg: reworking dev tools · Issue #12914 · ocaml/dune · GitHub )

1 Like

You could consider the Dune cache to be this global store. From there cacheable artifacts can be restored via hardlinks into the projects’ _build.

Dune cache is for compiled artifacts, right? I am talking about the sources themselves. This way we save not only recompilation, but also disk space (we don’t need to duplicate the same packages for every project) and network (we don’t have to re-download the same packages for every project).

(If it veers to be too offtopic, mods please cut feel free to split out the topic)

The Dune cache is for outputs of Dune rules (very unspecifically). Downloading the sources is a Dune rule (fetch_rules.ml specifically) thus the sources that are downloaded already get cached in the Dune cache (if enabled) and don’t need to get downloaded again.

2 Likes

I use Terminal, which lets you start multiple shells (profiles) from a menu.

Go to Settings → Add a new profile → Duplicate a profile

and then I duplicate an existing CMD or PowerShell profile, I name it opam CMD or opam PowerShell and then in its configuration page → Command line:

%SystemRoot%\System32\cmd.exe /k for /f “tokens=*” %i in (‘opam env --switch=default’) do @%i for CMD

"C:\Program Files\PowerShell\7\pwsh.exe" -NoExit -Command "(& opam env) -split '\r?\n' | ForEach-Object { Invoke-Expression $_ }" for PowerShell

(or source a .bat file)

2 Likes

Sure that these too long “eval env” commands must be configured in a profile!

It seems that Powershell and Terminal (cmd) have not the same behaviour. Is it correct ?

How do you get completion for opam commands with PS or CMD? This is simple and powerful with debian/linux.

Totally, they’re completely different shells.

Beware of a potential confusion:
Terminal, in modern Windows, is just a Terminal application. One can run any shell in it.

PowerShell (recommended) and CMD (legacy) are just two different shells you can use with it.

(Back in the time, Terminal and CMD were pretty much the same thing in Windows).

You can also try NuShell, I see it recommended around, but I have no experience with it.

Can’t help with that, I’m a complete beginner in the whole OCaml world.
I do see that in PowerShell there’s a nice history, but that’s all.

1 Like

Just to add my 2 cents to the whole discussion re: beginners and re: Windows:

BG: did sporadic programming all my life, but never in a serious way. Python scripting inside 3D animation apps, ActionScript in Flash, etc. Started with Pascal in high-school.

Trying to learn proper programming now, doing the HtDP book with Racket, some JavaScript and turned my attention to OCaml. I’m on Windows.

I think OCaml is a fantastic teaching language, but I agree with lots of comments above: all the high-end stuff being thrown at you from the start (switches, build systems) is not a welcoming experience.

I just want to start exploring the language and programming, using some of the great books available.

Yet the message I get is: this is for the seasoned pros, go away and come back when you grow up. Which I feel to be in stark contrast with the nature of the language itself.

And I have to say, OCaml on Windows is not currently useable.

My Windows install went perfect, I could try some examples etc.

Then I decided to try Bogue and… well, in my experience it’s basically impossible to install on Windows, with the stadard (Mingw) OCaml installation.

(my struggles are documented here: Native Windows support · Issue #9 · sanette/tsdl-ttf · GitHub and here: Install error on Windows · Issue #42 · sanette/bogue · GitHub )

This abruptly cut off my ideas of eventually trying raylib/raygui and even of persisting with OCaml, as it seems a minefield on Windows, outside of the default install.

A very harsh contrast to any other language I tried (Racket, Node.js, Python, FreePascal). All of which require you to download an installer and have a working environment in 5 mins max.

2 Likes

Thank you very much for sharing your experience. I agree with some of your points; however, I think that many of the issues mentioned in this thread arise when beginners are not linear readers, and in those cases it is difficult to design a tutorial that works well for everyone.

  • In my case, when I compared beginner tutorials for Rust, Go, and Haskell, my honest opinion is that the OCaml tutorials are not worse. In some aspects they are better, and in others they could certainly be improved.

  • Note that if you follow the tutorial, it explicitly states (at the beginning) :

    Note: opam can manage something called switches. This is key when switching between several OCaml projects. However, in this “getting started” series of tutorials, switches are not needed. If you are interested, you can read an introduction to opam switches here.

  • Regarding build systems, this is simply the current trend: Go, Rust, and even Haskell introduce build tools from the very beginning. In my opinion, the tutorial provides an accessible introduction to the basic concepts of dune (some corners should be smoothed, yes). If you prefer the original compiler tools, you can read about them here.

  • Bogue is a library, so its portability and platforms support depend on its own developers. From my perspective, this should not be considered an OCaml platform issue… (but I understand your frustration when I beginner selected a library that fails)

  • Based on my personal experience on Linux/Mac, it is possible to have a pleasant, fast, and fully featured installation experience when using VS Code. That said, some friction is still possible depending on the user’s environment and setup. In my case, I was even able to install a OCaml environment in a user account on a Linux HPC system straightforwardly, something that was not possible for me with some other languages.

4 Likes