Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Undocumented ocamlc and ocamlopt link behaviour difference #7271

Closed
vicuna opened this issue Jun 10, 2016 · 6 comments
Closed

Undocumented ocamlc and ocamlopt link behaviour difference #7271

vicuna opened this issue Jun 10, 2016 · 6 comments
Labels
Milestone

Comments

@vicuna
Copy link

vicuna commented Jun 10, 2016

Original bug ID: 7271
Reporter: furuse
Status: resolved (set by @xavierleroy on 2017-10-19T14:16:37Z)
Resolution: fixed
Priority: low
Severity: minor
Version: 4.03.0
Target version: 4.06.0 +dev/beta1/beta2/rc1
Fixed in version: 4.06.0 +dev/beta1/beta2/rc1
Category: misc
Related to: #6509
Monitored by: @gasche

Bug description

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".

@vicuna
Copy link
Author

vicuna commented Jun 10, 2016

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 ":-)")
let g x y = x + y


(* c.ml *)

let () = if false then ignore (B.g 1 2)
let () = !A.f ()


$ ocamlopt -c a.ml
$ ocamlopt -c b.ml
$ ocamlopt -o ab.cmxa -a a.cmx b.cmx
$ ocamlopt -o test ab.cmxa c.ml
$ ./test
Fatal error: exception Assert_failuire("a.ml", 1, 23)

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)

@vicuna
Copy link
Author

vicuna commented Sep 2, 2016

Comment author: @damiendoligez

I think the recommended way to force inclusion (under 4.03.0 or later) would be:

ignore (Sys.opaque_identity Mtype.scrape)

But I agree we need to (at least) document the difference between byte-code and native.

@vicuna
Copy link
Author

vicuna commented Sep 2, 2016

Comment author: @gasche

The particular case of compiler-libs.common is related to #6509 , see in particular the discussion in

#53

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.

@vicuna
Copy link
Author

vicuna commented Dec 12, 2016

Comment author: @mshinwell

I'm not sure the Sys.opaque_identity line that @doligez writes above will work except when using Flambda---we should check.

@vicuna
Copy link
Author

vicuna commented Feb 16, 2017

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.

@vicuna
Copy link
Author

vicuna commented Oct 19, 2017

Comment author: @xavierleroy

Mentioned this issue in section 11.5 of the manual (differences ocamlc/ocamlopt).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant