Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.Sign up
Undocumented ocamlc and ocamlopt link behaviour difference #7271
Original bug ID: 7271
I wrote a code like the following to enforce a compilation unit M linked. In bytecode, it works fine:
if false then M.f () (* dummy code to make sure M is linked. *)
However, ocamlopt seems to erase the entire expression. As a result the reference to M is lost and M is never linked together. The intention of linking of M is to execute an initialization side effect in M.
This is very confusing behaviour difference between ocamlc and ocamlopt. If it is not a bug, it should be noted in OCaml reference manual 11.5: "Compatibility with the bytecode compiler".
Comment author: furuse
You can reproduce the problem with the following code:
(* a.ml *)
let f = ref (fun () -> assert false : unit -> unit)
(* b.ml *)
let () = A.f := (fun () -> prerr_endline ":-)")
(* c.ml *)
let () = if false then ignore (B.g 1 2)
$ ocamlopt -c a.ml
I found this when I was playing with compiler-libs.common of 4.03.0. Env.scrape_alias failed since Env.strengthen was not initialized by Mtype. I tried to link Mtype by inserting a dummy expression like if false then Mtype.scrape Env.empty (Mty_signature ) , but it did not make ocamlopt link Mtype.
Currently I use the following instead to avoid the issue:
let () = ignore (Mtype.strengthen == Mtype.strengthen)
Comment author: @gasche
The particular case of compiler-libs.common is related to #6509 , see in particular the discussion in
I still think that relying on module linking to initialize back-patched functions in this case is fragile and that we should have a more explicit API for compiler-libs users to explicitly request their initialization -- and thus force their linking.
Comment author: @xavierleroy
My recommendation is to apply -linkall to the libraries or compilation units that have initialization code with important effects. Note that in 4.05 and up -linkall can be applied to a single compilation unit.
I'm not sure what needs to be done / can be done for release 4.05 and even for future releases.