Ocamlbuild looks for executables in `/usr/bin`
I'm using windows bash with opam to use ocamlbuild, which functions like Ubuntu for most things. Commands like
$which ocamlfind
~/.opam/4.04.0/bin/ocamlfind
and
$which ocamlbuild
~/.opam/4.04.0/bin/ocamlbuild
work fine, and I can invoke ocamlfind from the command line. When I try ocamlbuild though, I get
$ocamlbuild
/bin/sh: 1: /usr/bin/ocamlfind: not found
Failure: Error while running: /usr/bin/ocamlfind list.
Which implies to me that ocamlbuild is looking in /usr/bin/ for ocamlfind. I don't have ocaml installed there, so clearly it can't find the file, but surely the behavior should be for ocamlbuild to look in opam's bin folder for the executables first?
$PATH yields ~/.opam/4.04.0/bin/:..., and I put eval $(opam config env) in both my ~/.bashrc and my ~/.profile so even if ocamlbuild is launching some kind of sub-shell, the $PATH variable should still have my opam folder first. Notably, the error message reports for /bin/sh, so is it possible that that shell doesn't run my ~/.bashrc file, so doesn't have the $PATH variable set properly?
Is there some config file I can edit that tells ocamlbuild where it expects to find ocamlfind and other executables?
This looks like it may be some misconfiguration issue. Unfortunately there is no runtime option to have ocamlbuild reports on its configuration right now, so could you instead execute the following piece of code?
module Conf = Ocamlbuild_pack.Ocamlbuild_config
let () =
let s = Printf.printf "%s = %S\n%!" in
let b = Printf.printf "%s = %B\n%!" in
s "bindir" Conf.bindir;
s "libdir" Conf.libdir;
s "ocaml_libdir" Conf.ocaml_libdir;
s "libdir_abs" Conf.libdir_abs;
b "ocaml_native" Conf.ocaml_native;
b "ocaml_native_tools" Conf.ocaml_native_tools;
b "supports_shared_libraries" Conf.supports_shared_libraries;
s "a" Conf.a;
s "o" Conf.o;
s "so" Conf.so;
s "ext_dll" Conf.ext_dll;
s "exe" Conf.exe;
s "version" Conf.version;
()
If you write this to a printconf.ml file, there should be two ways to run it. The first is
ocamlfind ocamlc -package ocamlbuild -linkpkg -o printconf printconf.ml
./printconf
The second is to open an ocaml toplevel in the same directory as printconf.ml and run the following commands:
#use "topfind";;
#require "ocamlbuild";;
#use "printconf.ml";;
bindir = "~/.opam/4.04.0/bin"
libdir = "~/.opam/4.04.0/lib"
ocaml_libdir = "~/.opam/4.04.0/lib/ocaml"
libdir_abs = ~/.opam/4.04.0/lib"
ocaml_native = true
ocaml_native_tools = true
supports_shared_libraries = true
a = "a"
o = "o"
so = "so"
ext_dll = ".so"
exe = ""
version = "0.12.0"
Is what I get when I run that. The bindir printout is the most surprising to me, given that ocamlbuild is definitely looking for executables in /usr/bin, but given the error message that I'm getting, I think it's possible that ocamlbuild is launching another shell that isn't set up with eval $(opam config env). Is there a way to control which shell ocamlbuild uses, so that I can force it to use bash, where the opam line in my .bashrc will set up my $PATH properly?
For reference:
ls ~/.opam/4.04.0/bin/
oasis ocamlcp ocamldoc.opt ocamlmklib.opt ocamlopt ocamlprof.opt
ocaml ocamlcp.byte ocamlfind ocamlmktop ocamlopt.byte ocamlrun
ocamlbuild ocamlcp.opt ocamlify ocamlmktop.byte ocamlopt.opt ocamlrund
ocamlbuild.byte ocamldebug ocamllex ocamlmktop.opt ocamloptp ocamlyacc
ocamlbuild.native ocamldep ocamllex.byte ocamlmod ocamloptp.byte safe_camlp4
ocamlc ocamldep.byte ocamllex.opt ocamlobjinfo ocamloptp.opt
ocamlc.byte ocamldep.opt ocamlmklib ocamlobjinfo.byte ocamlprof
ocamlc.opt ocamldoc ocamlmklib.byte ocamlobjinfo.opt ocamlprof.byte
I belive that your hypothesis on .bashrc trouble is exactly right, as I look at this code which implements OCamlbuild's command-invocation logic. In the Windows case, it invokes bash --norc, which precisely does not get your opam settings.
The --norc is there for performance reason and was put because of this issue report in 2013.
I could remove it now, and I guess your life would improve, but I don't understand why this is needed. As far as I can tell, eval $(opam env) executes export PATH, so the current PATH value should be in the environment inherited by the sub-processes (for example, env | grep PATH should show you the opam bin in the path). So why isn't the bash --norc inheriting the expected environment, with opam enabled in the right switch?
I have
#Sys.os_type;;
- : string = "Unix"
Since I'm on windows, but using the Ubuntu subsystem.
Ah, so that wasn't it. The quest goes on...
I think ocamlfind list should be asked by ocamlbuild when you do not use the -use-ocamlfind switch. Do you also get problems if you invoke ocamlbuild with the -use-ocamlfind option?