ocaml / opam

opam is a source-based package manager. It supports multiple simultaneous compiler installations, flexible package constraints, and a Git-friendly development workflow.
https://opam.ocaml.org
Other
1.25k stars 360 forks source link

Check correct version of system compiler in `PATH` #4923

Open patricoferris opened 2 years ago

patricoferris commented 2 years ago

Whenever using system OCaml compilers in switches it can be easy to accidentally have the wrong system compiler in PATH when you have multiple compilers. This leads to accidentally creating a new switch with say a 4.13.1 compiler and then installing packages with a 4.12.1 compiler. I realise the PATH management is the user's responsibility but (if possible) it might be useful for opam to be able to detect that something isn't quite right when using a different system compiler?

More concretely assume I have a 4.13.1 switch in /foo/bin and a 4.12.1 compiler in the more conventional /usr/local/bin with the former not in PATH. I create a new switch:

$ PATH=/foo/bin:$PATH opam switch create system 4.13.1

Opam creates a new switch called system with the 4.13.1 compiler it found in PATH. Now I install say ocaml-lsp-server forgetting to set PATH correctly such that the 4.13.1 compiler is the first compiler that will be found:

$ opam install -y ocaml-lsp-server
...
[ERROR] The compilation of ocaml-lsp-server.1.9.0~4.13preview failed at "dune build -j 7 ocaml-lsp-server.install
        --release".

#=== ERROR while compiling ocaml-lsp-server.1.9.0~4.13preview =================#
# context     2.1.0 | linux/x86_64 | ocaml-system.4.13.1 | https://opam.ocaml.org#e813807e
# path        ~/.opam/system/.opam-switch/build/ocaml-lsp-server.1.9.0~4.13preview
# command     ~/.opam/system/bin/dune build -j 7 ocaml-lsp-server.install --release
# exit-code   1
# env-file    ~/.opam/log/ocaml-lsp-server-15176-1a7960.env
# output-file ~/.opam/log/ocaml-lsp-server-15176-1a7960.out
### output ###
#     ocamlopt ocaml-lsp-server/vendor/merlin/src/ocaml/utils/.utils.objs/native/warnings.{cmx,o} (exit 2)
# (cd _build/default && /usr/local/bin/ocamlopt.opt -open Merlin_utils -w -a -g -I ocaml-lsp-server/vendor/merlin/src/ocaml/utils/.utils.objs/byte -I ocaml-lsp-server/vendor/merlin/src/ocaml/utils/.utils.objs/native -I ocaml-lsp-server/vendor/merlin/src/config/.config.objs/byte -I ocaml-lsp-server/vendor/merlin/src/config/.config.objs/native -I ocaml-lsp-server/vendor/merlin/src/utils/.merlin_u[...]
# File "ocaml-lsp-server/vendor/merlin/src/ocaml/utils/warnings.ml", line 566, characters 37-44:
# 566 |           List.fold_left (fun l x -> Int.max l (List.length x))
#                                            ^^^^^^^
# Error: Unbound value Int.max

I realise this is pretty niche but I was just wondering if there is some sort of check that could be done to provide a better error message perhaps? Opam does catch if the system compiler is no longer in the right place i.e. if you mv /foo/bin /bar/bin and then opam install you get:

[WARNING] System file /foo/bin/ocamlc, which package ocaml-system.4.13.1 depends upon, no longer
          exists.
          The package will need to either be removed, or reinstalled. You may need to restore its system dependencies for
          the latter.

Thanks :))

Config Report
# opam config report
# opam-version         2.1.0 
# self-upgrade         no
# system               arch=x86_64 os=linux os-distribution=ubuntu os-version=20.04
# solver               builtin-mccs+glpk
# install-criteria     -removed,-count[avoid-version,changed],-count[version-lag,request],-count[version-lag,changed],-count[missing-depexts,changed],-changed
# upgrade-criteria     -removed,-count[avoid-version,changed],-count[version-lag,solution],-count[missing-depexts,changed],-new
# jobs                 7
# repositories         1 (http) (default repo at e813807e)
# pinned               0
# current-switch       system
# ocaml:native         true
# ocaml:native-tools   true
# ocaml:native-dynlink true
# ocaml:stubsdir       /home/patrickferris/sys/4.13.1/lib/ocaml/stublibs:/home/patrickferris/sys/4.13.1/lib/ocaml
# ocaml:preinstalled   true
# ocaml:compiler       system
# ocaml-system:path    /home/patrickferris/sys/4.13.1/bin
rjbou commented 2 years ago

The compiler itself is something abstract for opam. It only knows about a package that have the flag compiler, and that need to perform specific actions with it (for switch eg.). What makes ocaml-system detect ocamlc move, is that ocaml-system config file contains the detected path, and this path (and its checksum) is checked afterwards by opam. As long the file is unchanged, opam won't notice.

What can be done is to check if it is an executable, and in this case check if it is reachable from PATH.