What does eval $(opam env) do, does it activate a opam environment?

I keep seeing

eval $(opam env)

e.g. when I try to install coq:

# brew install opam  # for mac
# for ubuntu
conda install -c conda-forge opam
opam init
# if doing local env?
# eval $(opam env)

# - install coq
# local install
#opam switch create . 4.12.1
#eval $(opam env)
#opam repo add coq-released https://coq.inria.fr/opam/released
#opam install coq

# If you want a single global (wrt conda) coq installation (for say your laptop):
opam switch create 4.12.1
opam switch 4.12.1
opam repo add coq-released https://coq.inria.fr/opam/released
opam install coq

but I never know what it does (nor no one I talk to knows) and when I google it this comes up instead: ocaml - What is the use of eval `opam config env`? - Stack Overflow

cross posted: What does eval $(opam env) do, does it activate a opam environment? - Stack Overflow


Clarification

Note that

eval `opam config env`

might be very similar. In the sense that I think the dashes '' are also command substitution as in $(...) but not sure. Which might make ocaml - What is the use of eval `opam config env`? - Stack Overflow very related (though I don’t know the difference for sure)

1 Like

Be curious ;–) invoke opam env.

9 Likes

If you check Get Up and Running With OCaml · OCaml Tutorials , there is a note there which explains it.

1 Like

Honestly you are right, I could have been more curious (btw I did run that before your post).

It just seemed bizarre to me that there was no explanation or question of such a common and cryptic command. You need to know what $() is and also the ' ' since there are different ways to do the same. The difference of that and eval, what opam env…and to be honest, who truly likes coding in bash? Hard to be curious about such an ugly language. Ocaml and Coq are so much better :slight_smile:

Anyway, will post an answer soon. I’ve made good progress on this.


Actually, in case I forget to answer here, I most likely will post my answer here: What does eval $(opam env) do, does it activate a opam environment? - Stack Overflow

1 Like

Explanation in the link I posted:

Please note : The back ticks shown around opam env after eval are essential. They change the order of application, which is very important. The back ticks tells the system to first evaluate opam env (which returns a string of commands) and then eval executes those commands in the string. Executing them doesn’t return anything, but it initializes the Opam environment behind the scenes.

1 Like

tldr: it activates your opam context according to your current switch – similar to how a python virtual env is activated in python but for opam.

What eval $(opam env) does is command substitute $(opam env) i.e. run opam env in a subshell (that’s what $( ) does) return the string it outputted and then give it to eval to evaluate as bash code. Command substitution is usually done to next the output of commands in bash. In python eval would interpret the input string to it as literal python code to evaluate, parse, run here similarly it would do the same but assume it’s bash (is my guess).

What does opam env does? It returns the current bash env variables for the current swithc (i.e. siwth approximately euqal to opam environment). So therefore, doing:

eval $(opam env)

does this:

  1. first runs in a subshell because thats what $(cmd) does. It’s [command substitution][1]. Usually used to nest commands.
  2. then it’s output (so the output string of $(opam env)) is given to eval. opam env returns a string of env variables needed to "activate: the current opam env (similar to how you activate virtual envs in python).
  3. finally eval evaluates the string it receives from the command substitution i.e. it parses the string as a bash command and runs it.

For compeleteness see the output of opam env:

(iit_synthesis) brandomiranda~ ❯ opam env
OPAM_SWITCH_PREFIX='/Users/brandomiranda/.opam/4.12.1'; export OPAM_SWITCH_PREFIX;
CAML_LD_LIBRARY_PATH='/Users/brandomiranda/.opam/4.12.1/lib/stublibs:/Users/brandomiranda/.opam/4.12.1/lib/ocaml/stublibs:/Users/brandomiranda/.opam/4.12.1/lib/ocaml'; export CAML_LD_LIBRARY_PATH;
OCAML_TOPLEVEL_PATH='/Users/brandomiranda/.opam/4.12.1/lib/toplevel'; export OCAML_TOPLEVEL_PATH;
PATH='/Users/brandomiranda/.opam/4.12.1/bin:/Users/brandomiranda/miniconda/envs/iit_synthesis/bin:/Users/brandomiranda/miniconda/condabin:/usr/local/bin:/Users/brandomiranda/.opam/4.12.1/bin:/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin'; export PATH;

Comment on backard ticks:

Please note : The back ticks shown around opam env after eval are essential. They change the order of application, which is very important. The back ticks tells the system to first evaluate opam env (which returns a string of commands) and then eval executes those commands in the string. Executing them doesn’t return anything, but it initializes the Opam environment behind the scenes.
ref: Get Up and Running With OCaml · OCaml Tutorials


also see:

2 Likes

related: Why does command substitution with a command in front e.g. eval interprets the string as literal bash commands to execute? - Stack Overflow details of how command substitution works

@yawaramin Trying to understand a few things. First when is eval $(opam env) or
eval ‘opam env’ (use the other tick sorry don’t know how to display it) supposed to be ran? If I understand it correct, it “activates the opam environmen for a switch” so one is supposed to get into a switch first (e.g. opam switch 4.12.1), then one does eval $(opam env) to fully activate the env for that switch. Is that correct?

Related, I’m actually not sure what opam init does or why it’s needed despite reading multiple resources but my guess is that its only needed once during the first set up of opam. Is that right?


Context for question, I was told the following and trying to understand when to call eval $(opam env) correctly for the right switch I choose:

If you want a single global coq installation (for say your laptop):

opam switch create 4.12.1 opam switch 4.12.1 opam repo add coq-released Index of /opam/released opam install coq

If you want a local installation with a local opam environment:

opam switch create . 4.12.1 eval $(opam env) opam repo add coq-released Index of /opam/released opam install coq

The answer to both of your questions is, yes that is correct.

Now, another question may be, why even should opam require this eval $(opam env) dance? Can’t it just set up the environment without it? After all, we already need to run opam switch ... to select the opam switch we want to work in.

And that’s a valid question! Perhaps you would be interested in filing a ticket on the opam GitHub repo asking about this and seeing if it could be improved?

At least to answer the question of what opam init, opam switch and opam env do:

opam init --help
opam switch --help
opam env --help

For Opam, Dune and many other commands you will encounter in the OCaml community, they have decent --help pages. This fact won’t be obvious to people using OCaml for the first time. (An analog would be the Python community standardizing their documentation on Sphinx webpages like https://readthedocs.org, or the OpenBSD community standardizing their documentation on man pages. If someone hadn’t told you, you could get lost).


What is missing, and what I think you are asking, is how do all the individual commands connect? A --help page may not be sufficient. Here is a stab at describing the typical flow:

Command When DESCRIPTION from --help
opam init Once per machine opam init --help: The init command initialises a local “opam root” (by default, ~.opam) that holds opam’s data and packages. This is a necessary step for normal operation of opam. The initial software repositories are fetched …
opam switch create Once per project opam switch --help: This command is used to manage “switches”, which are independent installation prefixes with their own compiler and sets of installed and pinned packages. … opam switch set sets the default switch globally, but it is also possible to select a switch in a given shell session.
opam env --switch SWITCH Everytime you open a shell (ex. bash) terminal opam env --help: Returns the bindings for the environment variables set in the current switch, e.g. PATH, in a format intended to be evaluated by a shell. … This is most usefully used as eval $(opam env) to have further shell commands be evaluated in the proper opam context.

Note: There is a way to avoid having to type eval $(opam env) every time you open a terminal: use opam init --auto-setup once and use opam switch set SWITCH once. See the --help for what those do. I personally don’t use that approach; YMMV.

1 Like

@yawaramin when do we run eval $(opam env)? is eval $(opam env) supposed to be ran before opam init or after it or after the switch has been activated e.g. opam switch create debug_proj_4.09.1 4.09.1; opam switch debug_proj_4.09.1?

This is explained in the ‘Up and Running’ page I linked to above and also in Jonah’s great answer above. If anything is not clear, would you mind filing an issue? There’s a link at the bottom right of the ‘Up and Running’ page.