Hello. I am working on a binding of Allegro 5, a C library similar to SDL, aimed at video games.
It compiles well with my default switch which uses OCaml 5.2, but I can’t have it to compile with OCaml 4 compilers. I discovered this problem because I want to publish my package in opam-repository. You can see here the compilation errors. There is also a failure for OCaml 5.3 on Fedora. I require ocaml>=4.12 because previous compilers apparently don’t have Val_none. The repository of my binding is here.
I am able to reproduce the problem locally with an opam switch with OCaml 4.14.2. The error message is:
File "lib/dune", lines 19-26, characters 0-277:
19 | (library
20 | (name al5)
21 | (public_name allegro5)
22 | (foreign_stubs
23 | (language c)
24 | (names al5 display events graphics keyboard mouse system time timer font image primitives)
25 | (flags -std=c11 -Wall -O2 -I -fPIC (:include c_flags.sexp)))
26 | (c_library_flags (:include lib_flags.sexp)))
/usr/bin/ld: lib/display.o: warning: relocation against `Caml_state' in read-only section `.text'
/usr/bin/ld: lib/timer.o: relocation R_X86_64_PC32 against undefined symbol `Caml_state' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: bad value
collect2: error: ld returned 1 exit status
This is not particularly related to the display and timer modules, because if I remove them, I get the same error messages on the remaining modules.
Yes, I think I already tried it. I’ve just tried again and it changes nothing.
I think the error message talks about compiling the .o, not the C library, actually. But they are already compiled with -fPIC (I require it to use stderr in my source files).
Yes, I could restrict this package to OCaml 5, but unfortunately there’s also a problem with OCaml 5.3 with Fedora. The message is not exactly the same; it is:
File "lib/dune", lines 19-26, characters 0-277:
19 | (library
20 | (name al5)
21 | (public_name allegro5)
22 | (foreign_stubs
23 | (language c)
24 | (names al5 display events graphics keyboard mouse system time timer font image primitives)
25 | (flags -std=c11 -Wall -O2 -I -fPIC (:include c_flags.sexp)))
26 | (c_library_flags (:include lib_flags.sexp)))
(cd _build/default && /home/opam/.opam/5.3/bin/ocamlmklib -g -o lib/al5_stubs lib/timer.o lib/time.o lib/system.o lib/primitives.o lib/mouse.o lib/keyboard.o lib/image.o lib/graphics.o lib/font.o lib/events.o lib/display.o lib/al5.o -ldopt -lallegro_image -ldopt -lallegro_primitives -ldopt -lallegro_ttf -ldopt -lallegro_font -ldopt -lallegro)
/usr/bin/ld: lib/timer.o: relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: failed to set dynamic section sizes: bad value
collect2: error: ld returned 1 exit status
Does it help if you include :standard at the beginning of the flags field of the foreign_stubs stanza? (As it happens I don’t normally bother with specifying -fPIC in the flags field because I have assumed that the standard flags will deal with things like that.) The documentation says “[The flags] field is specified using the Ordered Set Language, where the :standard value comes from the environment settings c_flags and cxx_flags, respectively.”
Does that make any difference? It is rather perplexing, but it looks as if there is some incompatible use of flags here, either in your code or in the libraries you are linking to.
Edlt: Also try adding or removinig “use_standard_c_and_cxx_flags” in your dune-project file. That might change the way ocamlc_cflags and ocamlc_cppflags are added to the compiler command line. (I don’t understand the documentation on this option.)
Oh, shame on me, I’ve just figured out what the problem was: I left -I just before -fPIC (I used the -I flag before I decided to use pkg-config), so -fPIC was taken as an include directory instead of a flag.
Everything is fine once I’ve removed -I. Build works. Using :standard instead of -fPIC works too, so I’m using :standard at the end.
Thank you for your help.
I also encountered a problem when installing packages on my opam switch, I will open another post for it.
The documentation I have traced is in two places, first for the flags field of the foreign stubs dune stanza and secondly for dune-project’s use standard c and cxx flags option, which are difficult to reconcile.
The first says
… the :standard value comes from the environment settings c_flags and cxx_flags, respectively. Note that, for C stubs, Dune unconditionally adds the flags present in the OCaml config fields ocamlc_cflags and ocamlc_cppflags to the compiler command line. This behavior can be disabled since Dune 2.8 via the dune-project option use_standard_c_and_cxx_flags
The second says about that option
Control how flags coming from ocamlc -config are passed to the C compiler command line.
Historically, they have been systematically prepended without a way to override them.
If the following is passed, the mechanism is slightly altered:
(use_standard_c_and_cxx_flags)
In this mode, Dune will populate the :standard set of C flags with the content of ocamlc_cflags and ocamlc_cppflags. These flags can be completed or overridden using the Ordered Set Language.
This is the default in the language version 3.0.
You can examine ocamlc_cflags and ocamlc_cppflags by greping the output of ocamlc -config. One possible reading of the somewhat obscure and contradictory wording above is that prior to dune 2.8, ocamlc_cflags and ocamlc_cppflags were always passed to the C compiler, from 2.8 to 3.0 dune optionally does this, and from 3.0 dune adds them to :standard flags instead.