opam init should clear environment variables from previous nuked opam roots
Nuking one's opam root (aka. rm -rf ~/.opam) seems to be fairly common way for users to start from scratch when a problem occurs.
However doing this doesn't actually "start from scratch" as the environment variables set from the previous opam installation, stay behind.
Doing the following from a fresh zsh session (including no opam mentions in ~/.zshrc):
opam init --bare --disable-sandbox -a --shell=zsh
opam switch create problem ocaml-base-compiler.5.3.0
rm -rf ~/.opam
will leave behind
- the call to
~/.opam/opam-init/init.shin~/.zshrc - the following environment variables:
PATH=/root/.opam/problem/bin:$PATH OPAMNOENVNOTICE=true OPAM_SWITCH_PREFIX=/root/.opam/problem CAML_LD_LIBRARY_PATH=/root/.opam/problem/lib/stublibs:/root/.opam/problem/lib/ocaml/stublibs:/root/.opam/problem/lib/ocaml OCAMLTOP_INCLUDE_PATH=/root/.opam/problem/lib/toplevel OCAML_TOPLEVEL_PATH=/root/.opam/problem/lib/toplevel MANPATH=:/root/.opam/problem/man OPAM_LAST_ENV=/root/.opam/.last-env/env-483e11fe114374e8feace547c3c170f8-0
Following up with opam init -n --disable-sandbox, the environment now looks like this:
PATH=/root/.opam/default/bin:/root/.opam/problem/bin:$PATH
OPAMNOENVNOTICE=true
OPAM_SWITCH_PREFIX=/root/.opam/default
CAML_LD_LIBRARY_PATH=/root/.opam/default/lib/stublibs:/root/.opam/default/lib/ocaml/stublibs:/root/.opam/default/lib/ocaml
OCAMLTOP_INCLUDE_PATH=/root/.opam/default/lib/toplevel:/root/.opam/problem/lib/toplevel
OCAML_TOPLEVEL_PATH=/root/.opam/default/lib/toplevel
MANPATH=:/root/.opam/problem/man:/root/.opam/default/man
OPAM_LAST_ENV=/root/.opam/.last-env/env-291dfaf16ea7e7038eb704056d95c782-0
MANPATH, PATH and OCAMLTOP_INCLUDE_PATH all contain values from the nuked opam root. This can cause all sorts of problems and we should try our best to clear those variables.
Example of such issue can be seen in:
- https://github.com/ocaml/ocaml-lsp/discussions/1512
- https://github.com/dbuenzli/topkg/issues/142
That's a great find, I hope it does fix all these cases 🤞. I don't remember nuking my .opam recently but I might very well have done that at some point. What I frequently do, however, is to nuke local switches with rm -rf _opam. Is that safe ?
I got into a similar issue with, I believe, the following setup:
- I have 5.3.0 in my current global switch (set by default in .bashrc)
- I am working in a project-local switch with another version
- in the project-local switch, installing
topkgfails with the following error:
# File /home/gasche/.opam/5.3.0/lib/findlib/findlib.cma is not a bytecode object file.
# Exception: Compenv.Exit_with_status 125.
I observe, as discussed in https://github.com/dbuenzli/topkg/issues/142, that OCAMLTOP_INCLUDE_PATH is set incorrectly, and that unset-ting it solves the problem.
From a distance it looks like the problem is that eval $(opam env ...) does not cleanup this environment variable.
This is fairly annoying for users because there is no obvious link from the build failure to the workaround.
I was able to reproduce this with bash.
.profile:
if [ -n "$BASH_VERSION" ]; then
# include .bashrc if it exists
if [ -f "$HOME/.bashrc" ]; then
. "$HOME/.bashrc"
fi
fi
test -r $HOME/.opam/opam-init/init.sh && . $HOME/.opam/opam-init/init.sh > /dev/null 2> /dev/null || true
.bashrc:
test -r $HOME/.opam/opam-init/init.sh && . $HOME/.opam/opam-init/init.sh > /dev/null 2> /dev/null || true
No .bash_profile exist.
When running bash -l, both the codes in .profile and .bashrc are loaded and some environment variables end up duplicated. Moving to another (local in my case) switch, the second duplicated environment value are kept around.
This issue is thus related to https://github.com/ocaml/opam/issues/5819
related to #4201 #1447 #533
I was just poking at this again, and replicated https://github.com/ocaml/opam/issues/6455#issuecomment-3079206997. In addition to switching the recommendations, can't we just add this to the top of variables.sh?
test '/home/dra/.opam/ocaml-5.2' != "$OPAM_SWITCH_PREFIX" || return
i.e. we're setting OPAM_SWITCH_PREFIX to an effectively unique value - why don't we use it? The number of bug reports related to this (I'm wondering if the reports of bin directories of other switches remaining in PATH boil down to a similar thing?) suggest that double-sourcing this file is far more likely to happen than ending up with OPAM_SWITCH_PREFIX set but none of the other variables?
yeah that could help for this subset of bash related issues as a safeguard at least
Indeed - it feels like it's worth doing all these things!
maybe a different angle on the topic, I wonder if opam could have a way to detect "conflicting" environment. It could can the variables that get set by opam env and warn if it looks like they have been modified by more than opam. Maybe some kind of opam doctor
xref #601!
Discussed in dev meeting: We need to take account of the kind of variables, some are opam specific (and no other should change them), while others could be changed by user or another tool.