Can I use an "opam switch" as an immutable base of another one?

I’m learning OCaml through various sources and trying out various libraries. Maybe it’s overkill but I’m creating a switch/sandbox every time I start a new tutorial/book; so I have to wait while these packages are recompiled each time.
I’m wondering, is it possible to have a base immutable switch with common packages: the compiler, utop, ocaml-lsp-server, ocamlformat, etc.; to be used as the basis of another switch?

In opam online docs I found something related: opam create switch my_project ocaml-system, to create a switch based an OCaml compiler installed in the operating system.

I found no hints on the opam man-page nor on the online manual that this is possible, but I’m still hoping. Can someone confirm, please?

4 Likes

I don’t know if this helps, for me
ocaml --version returns
The OCaml toplevel, version 4.13.1
And
which ocaml
/usr/home/x/.opam/4.13.1+options/bin/ocaml
I used an older ocaml “system”-compiler to compile and install a newer “user”-compiler.
The compiler that came with the OS. was:
ocaml-4.05.0_1

Hi @devosalain, thanks for the idea. That doesn’t seem what I’m looking for.
I am able to install a ‘switch’ with a new compiler. What I was hoping to do is to have a whole set of packages shared between different ‘switches’ so that I don’t have to recompile those packages every time. For instance, I’d like to have the latest compiler, utop, ocaml-lsp-server, and other packages used for development shared between ‘switches’.

To express the idea in a preudo-shell script:

opam switch create mybase-4.14.0 ocaml.4.14.0
eval (opam env --switch=mybase-4.14.0 --set-switch)
opam install utop ocaml-lsp-server ...etc
# then, in my imagination, I would issue the following command to create
#   a project-specific switch importing all the things in the previous one
opam switch create myproject --with-base=mybase-4.14.0
eval (opam env --switch=myproject --set-switch)
opam install my-project-specific-dependencies

I don’t know if it is a wise idea. Do you really need different compilers ?
opam switch list shows in my case an active recent one.
I think in general it is a bad idea to keep old compilers around unless there is a specific use case like old software-applications you don’t want to touch anymore, with future problems, which will arise over time.
You probably have done,
opam switch --help

1 Like

Opam can enforce a “switch invariant,” which can specify a set of packages that must be installed in the switch. I don’t think that there’s any ability to share artifacts between switches though.

You could probably make something like this work by creating a docker container for the base switch and layering your project specific stuff on top, but I expect it’d be a pain.

Maybe an opam expert can chime in here. This is a feature that I’d also like. At the moment, project specific switches are really unwieldy.

1 Like

I think there has been a misunderstanding. I don’t want to keep around old compilers. I want to share an arbitrary compiler (likely the latest one), and a number of utilities, between different switches by using a switch as the base one, in order to avoid recompiling such packages every time I start a new project.

It’s just for the sake of saving those minutes it takes to recompile those packages every time I create a new switch (and not questioning my compulsion of having a switch per project). As I’m in learning stage, I create many small projects, and having a blank slate every time is somewhat reassuring for me.

Does it make more sense?

Perhaps it’s worth questioning this compulsion? If you’re just starting-out, I would guess you’re not installing packages you write into OPAM-controlled directories, so what’s the upside of having separate switches per project? What do you gain?

Also, AFAIK, OCaml isn’t “relocatable” in this sense – you can’t build an OCaml with a certain “destdir” and then copy it elsewhere and have it work.

You should have a look at opam-bin.

1 Like

At the moment it’s just for my peace of mind. I don’t want to worry about running into dependency conflicts or documentation-implementation inconsistencies.

I also got the impression that one-switch per project is encouraged in OCaml-land from CS-3110 text book:

Create a switch for this semester’s CS 3110 […]

and from Real-World OCaml:

The next thing we need is a suitable environment for this project, with […] any […] dependencies available. The best way to do this is to create a new opam sandbox, via the opam switch create command.

I’m ok creating one switch per project even if it means recompiling every-time, I was just hoping there was a way to avoid recompiling package-versions that are already present in the opam installation (nixOS is a source of inspiration here).

You can get what you want by using esy.sh/. But of course it’s a different tool than opam. It works great though.

2 Likes