I will attach files "myocamlbuild.ml", "main.ml", and "wrapper.c". Together these form a very simple test program that calls into zlib from OCaml.
When I run "ocamlbuild main.native", I get the following output:
+ /usr/bin/ocamlopt.opt -verbose -cclib -lz main.cmx wrapper.o -o main.native
+ as -o /tmp/camlstartup95a47f.o /tmp/camlstartup289f49.s
+ gcc -Wl,--no-as-needed -o 'main.native' -I'/usr/lib64/ocaml' '/tmp/camlstartup95a47f.o' '/usr/lib64/ocaml/std_exit.o' 'main.o' '/usr/lib64/ocaml/stdlib.a' '-L/usr/lib64/ocaml' '-lz' 'wrapper.o' '/usr/lib64/ocaml/libasmrun.a' -lm -ldl
Finished, 5 targets (0 cached) in 00:00:00.
Here's the problem: the GCC line above shows that "-lz" appears *before* "wrapper.o"! This is technically incorrect (since libraries must appear after the objects whose references they resolve), and fails with undefined reference errros if one builds ocaml without "LDFLAGS=-Wl,--no-as-needed" since --as-needed is now the default.
I notice that if I run the ocamlopt line above directly but move "-cclib -lz" after "wrapper.o", then this change in ordering is reflected in the GCC line. Unfortunately, it seems impossible to force ocamlopt to do this, since "dep"s and "flag"s are treated separately (oh, and it also doesn't work to add both a "dep" and a "flag" for "wrapper.o", since then you get multiple symbol definition errors).
I don't know where the bug is: is it in ocamlopt in that a library file ought to be shifted to the end of the command line automatically? Or is it in ocamlbuild, in that it provides no way to force the -cclib -lz options to the end of the ocamlopt command? But I believe one of those two is the bug.
Steps to Reproduce:
Created attachment 241583 [details]
The main OCaml driver
Created attachment 241585 [details]
The C wrapper
Created attachment 241587 [details]
The OCamlBuild plugin
can you check if the same happens with 3.12.0 ?
the problem is probably in ocamlbuild to pass the -cclib option before the .o file
if this is still an issue with newer versions, you may want to report this upstream because having ocamlbuild call ocamlopt with -cclib always at the end of the command line will probably not hurt and fix this
Yes, 3.12.0 still has the problem. Also, changing the constructor from "A" (atom) to "P" (pathname) also doesn't help—using only flag still doesn't treat it as a dependency, using only dep puts the filename in the wrong place (after -lz), and using both gives multiple definition errors. Finally, using the new flag_and_dep command also gives multiple definition errors.
fixed with the patch I just added to ocaml-3.12.0, no revbump since its masked and is an as-needed problem