What does eval $(opam env) do, does it activate a opam environment? [duplicate]
Asked Answered
V

1

1

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: What is the use of eval `opam config env`?

cross posted: https://discuss.ocaml.org/t/what-does-eval-opam-env-do-does-it-activate-a-opam-environment/9990


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 What is the use of eval `opam config env`? very related (though I don't know the difference for sure)

Vern answered 6/6, 2022 at 19:7 Comment(14)
Do you know what opam env outputs? What eval does?Deadwood
@Deadwood I also don't know what $(...) does and how it interacts with the commands you mentioned.Vern
@Deadwood you are the one running on assumptions here that I've not been doing my research. Will provide all the links I'm reading. Btw they have content inside of them I don't understand e.g. one talks about "toolchains" whatever that means. askubuntu.com/questions/833833/what-does-command-do, google.com/…, opam.ocaml.org/doc/man/opam-env.html, en.wikipedia.org/wiki/Command_substitution,Vern
here are some more: unix.stackexchange.com/questions/23111/…, #30156460, discuss.ocaml.org/t/…Vern
We can only go by what's in your question; if you have done research, as How to Ask tells you, show it. You can answer one of the questions I've asked by just running it, for example.Deadwood
perhaps if you know the answer you can just answer.Vern
I am familiar with the options available, thank you.Deadwood
I mean, you could just write opam env in your terminal and see the output and check what eval does. Voting to close this questionDerickderide
I see this: This is most usefully used as eval $(opam env) to have further shell commands be evaluated in the proper opam context. in opam.ocaml.org/doc/man/opam-env.html what does it mean?Vern
check this post too: discuss.ocaml.org/t/…Vern
Also see What is the difference between $(command) and `command` in shell programming?Unparliamentary
BTW, note that eval $(anything) is buggy, and would be more correctly written as eval "$(anything)". Documentation that does not recommend the double quotes is faulty and should have bug reports filed against it.Unparliamentary
related: #72549204Vern
@CharlieParker Toolchain? It's what it sounds like: a suite of tools. Perhaps a more correct term - and one that is recognised by the dictionary - is toolkit. That's putting it simply of course because it might be that different authors have different ideas but that's the concept anyway.Leapt
V
2

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. 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: https://ocaml.org/docs/up-and-running


also see:


All details that lead to this answer:

From the man page for opam env:

This is most usefully used as eval $(opam env) to have further shell commands be evaluated in the proper opam context.

see: https://opam.ocaml.org/doc/man/opam-env.html


Slightly more details:

Finally, to get all the pieces together, what is the difference between command substitution (e.g. $( ) or ) and evaluating an expression (e.g. eval string or eval $(cmd) ) (in bash mainly). Ref: https://unix.stackexchange.com/a/23116/55620. My understanding is that $( ) runs a command in a subshells and outputs the string so that it's string is an input to another command e.g. eval. So to my understanding you can think of $(cmd) as replacing that expression and pasting the string of it back to to the command line for another commadn e.g. eval.  While eval will take in the string and evaluate the expression in it instead. So what eval $(cmd) does is first evaluate $(cmd) replace it with the output string of running cmd in a subshell and then feeding it to eval -- where eval will pretend that input is code and evaluate it, parse and run it. So $(...) is usually done to nest command inside other commands. 

The only puzzling thing to me is why $(cmd) without a cmd2 (eg eval) in the front interprets the strings of $(cmd) as bash commands to run instead of just evaluting e.g. (iit_synthesis) brandomiranda~ ❯ $(echo v=1) zsh: command not found: v=1

but

(iit_synthesis) brandomiranda~ ❯ v=1 (iit_synthesis) brandomiranda~ ❯ echo $v 1

does evaluate my string v=1 and then run it. 

Thus what eval $(opam env) does is command substitute $(opam env) i.e. run opam env in a subshell return the string it outputted and then given to eval to evaluate as bash code. 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 its bash (is my guess)


Long answer with all details:

toolchain = In software, a toolchain is a set of programming tools that is used to perform a complex software development task or to create a software product, which is typically another computer program or a set of related programs. https://www.google.com/search?q=toolchain&oq=toolchain&aqs=chrome..69i57j0i512l9.209j0j7&sourceid=chrome&ie=UTF-8

(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; so opam env outputs a bunch of paths that are needed for the toolchain to work...perhaps here toolchain == opam? Based on What is the use of eval `opam config env` or eval $(opam env) and their difference? (question for eval opam config env ) I am inferring that what it means is that these are the bash env variables needed to "activate the ocaml/opam environment". Concluded that because opam env outputs a bunch of env variables. 

So running opam env by itself only prints the output to the terminal the output of the command opam env

$ usually refers that the identifier is a variable. e.g. $x is the variable x while x in the terminal is literally the string x (or command x if it exists).

$(command) or command is command substitution. So doing $(command) runs the output (e.g. the script that would have been printed to the terminal after running command) of command. I assume it's called command substitution because we substitute command with the output of it and try to run it. e.g. it says: In computing, command substitution is a facility that allows a command to be run and its output to be pasted back on the command line as arguments to another command in the wikipedia article so yes. https://en.wikipedia.org/wiki/Command_substitution

opam env = opam-env - Prints appropriate shell variable assignments to stdout. 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. https://opam.ocaml.org/doc/man/opam-env.html note that same opam man page says This is most usefully used as eval $(opam env) to have further shell commands be evaluated in the proper opam context.

Finally, to get all the pieces together, what is the difference between command substitution (e.g. $( ) or ) and evaluating an expression (e.g. eval string or eval $(cmd) ) (in bash mainly). Ref: https://unix.stackexchange.com/a/23116/55620. My understanding is that $( ) runs a command in a subshells and outputs the string so that it's string is an input to another command e.g. eval. So to my understanding you can think of $(cmd) as replacing that expression and pasting the string of it back to to the command line for another commadn e.g. eval.  While eval will take in the string and evaluate the expression in it instead. So what eval $(cmd) does is first evaluate $(cmd) replace it with the output string of running cmd in a subshell and then feeding it to eval -- where eval will pretend that input is code and evaluate it, parse and run it. So $(...) is usually done to nest command inside other commands. 

The only puzzling thing to me is why $(cmd) without a cmd2 (eg eval) in the front interprets the strings of $(cmd) as bash commands to run instead of just evaluting e.g. (iit_synthesis) brandomiranda~ ❯ $(echo v=1) zsh: command not found: v=1

but

(iit_synthesis) brandomiranda~ ❯ v=1 (iit_synthesis) brandomiranda~ ❯ echo $v 1

does evaluate my string v=1 and then run it. 

Thus what eval $(opam env) does is command substitute $(opam env) i.e. run opam env in a subshell return the string it outputted and then given to eval to evaluate as bash code. 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 its bash (is my guess)


Eval vs $( ) details:

Playground 1

(iit_synthesis) brandomiranda~ ❯ clear
(iit_synthesis) brandomiranda~ ❯ $(echo v=1)
zsh: command not found: v=1
(iit_synthesis) brandomiranda~ ❯ v=1
(iit_synthesis) brandomiranda~ ❯ echo $v
1

Playground 2

(iit_synthesis) brandomiranda~ ❯ echo vv=2
vv=2
(iit_synthesis) brandomiranda~ ❯ $(echo vv=2)
zsh: command not found: vv=2
(iit_synthesis) brandomiranda~ ❯ eval $(echo vv=2)
(iit_synthesis) brandomiranda~ ❯ echo $vv
2
Vern answered 6/6, 2022 at 19:7 Comment(1)
might put answer here: discuss.ocaml.org/t/…Vern

© 2022 - 2024 — McMap. All rights reserved.