Trouble loading cma with Topfind

Hi all,

I’m experimenting with compiler-libs.toplevel and findlib for some project, and I’m puzzled by the following problem. The following code loads the plplot library and calls a function from the library:

let eval_string s =
    let lexbuf = Lexing.from_string s in
    let phrase = !Toploop.parse_toplevel_phrase lexbuf in
    let success = Toploop.execute_phrase true Format.err_formatter phrase in
    ignore success

let () =
  Toploop.initialize_toplevel_env () ;
  Topdirs.dir_use Format.std_formatter "topfind";
  eval_string {|#require "plplot";;|};
  eval_string "Plplot.plinit ();;"

It works just the way I expect it to. Now when I replace the second item by:

let () =
    Toploop.initialize_toplevel_env () ;
    Findlib.init () ;
    Topfind.load_deeply ["plplot"] ;
    eval_string "Plplot.plinit ();;"

it doesn’t work anymore, I get a message saying:

The external function `camlidl_plplot_core_c_plinit' is not available

Since both versions work when I try to load a pure-OCaml library (like, say, containers), I suspect the problem comes from the C part (plplot is a binding). A further indication is that with the first version, findlib prints:

/home/pveber/.opam/4.11.1/lib/plplot: added to search path
/home/pveber/.opam/4.11.1/lib/plplot/plplot.cma: loaded

while the second version only prints the first of the two lines. When I check the code registered for the #require directive though, I can’t anything see relevant besides the call to Topfind.load_deeply. Would anyone have an idea what I should set to make it work?

1 Like

Of course, it’s right after I send the post that I see the problem… I forgot calling

  Topdirs.dir_use Format.std_formatter "topfind"

It seems the line:

#directory "@SITELIB@/findlib";;
  (* OCaml-4.00 requires to have #directory before we load anything *)

is important here. Well, sorry for the noise.

1 Like

This:

  Topfind.add_predicates [ "byte"; "toploop" ];

is the bit I was missing more specifically in my code. I should have the comments in Topfind more carefully:

  * The [Topfind] module needs some initialization, in particular the 
 * [predicates] variable needs to be
 * set, and the packages already compiled into the toploop needs to be
 * declared by the [don't_load]
 * function.
2 Likes

It seems i’m still missing something. The program:

let () =
  Toploop.initialize_toplevel_env () ;
  Findlib.init () ;
  Topdirs.dir_directory (Findlib.ocaml_stdlib () ^ "/../findlib") ;
  Topfind.add_predicates [ "byte"; "toploop" ];
  (
    try Topfind.load_deeply ["unix"]
    with Symtable.Error e as exn ->
      Symtable.report_error Format.err_formatter e ;
      raise exn
  )

fails saying this:

/home/pveber/.opam/4.11.1/lib/ocaml/unix.cma: loaded
Reference to undefined global `Stdlib__callback'Fatal error: exception Symtable.Error(_)

Here’s the corresponding dune file:

(executable
  (name test)
  (modes byte)
  (libraries
    compiler-libs.toplevel findlib.top))
1 Like

Just compile it with -linkall. ((link_flags .. ))

:exploding_head:

Thanks a lot! That one I could have stayed hopelessly looking for it for a long, long time. But of course it makes a lot of sense: not being able to find symbols meant I had a linking issue. Now it works perfectly, thanks a bunch!

1 Like