Ocamlopt has problem with '-cc' and '-I +dir' options when they're not in standard location

I found when using ‘-cc’ and ‘-I +dir’ options together, the ld cannot correctly find the libraries under ‘dir’.

Here’s my case:

I have a sysroot, containing ocaml and a toolchain.
I have OCAMLLIB exported as in env, pointing to the standard library location.
export OCAMLLIB=“/path/to/sysroot/usr/lib/ocaml”
And CC is also exported.
export CC=“x86_64-wrs-linux-gcc -m64 -fstack-protector-strong …”

Now if I use ocamlopt like below, the linking process fails.
ocamlopt -cc ‘${CC}’ -I +compiler-libs
Even if I use host gcc, I get the same failure.
ocamlopt -cc ‘gcc’ -I +compiler-libs
The error message is like below:
ld: :(.text+0xd56): undefined reference to `camlStdlib__Bytes__sub_303’

However, if I don’t use ‘-cc’ option, the build succeed.
ocamlopt -I +compiler-libs

I’m wondering if the ‘-cc’ option has some problem with ocamlopt. Why specifying it will cause problem at linking stage?

The fastest way to diagnose what is going on is to pass the -verbose flag to ocamlopt with and without -cc and comparing the invocation of external commands (the lines starting with +).

Cheers,
Nicolas

1 Like

The missing symbol (camlStdlib__Bytes__sub_303) comes from the standard library, so I think the -I flags should be irrelevant.

The C compiler specified by the -cc option is used for two things: compiling C files to objects files, and (in native mode only) for the linking steps.
If you pass the -verbose flag to ocamlopt (without -cc), you should be able to see which C compiler is used for linking, which might give you some hints on why the other C compilers don’t work.

The (native) compiler has command line stuff baked in (grep ‘mkexe’). Passing -cc overrides this, so if you do that you must also pass all required compile/link options using -ccopt and -cclib. I’m guessing that includes stdlib info.

@nojb @vlaviron
After adding ‘-verbose’ option and comparing the building results, I found that the biggest different is about the ‘-shared’ option.
When ‘-cc’ option is specified, the ‘-shared’ option does not have effect on ocamlopt, that is, ocamlopt is not adding ‘-shared’ to underlying compiler invocation.

Here’s the Makefile: ocamlfind/src/findlib/Makefile at master · ocaml/ocamlfind (github.com)

The error happens at compiling .cmxs file.
e.g.,
$(OCAMLOPT) -shared -o findlib_dynload.cmxs $(DYNLOAD_XOBJECTS);

When I set OCAMLOPT like below, the ‘-shared’ is not passed to gcc.
OCAMLOPT = “ocamlopt -verbose -cc ‘${CC}’ -ccopt ‘–sysroot=${STAGING_DIR_TARGET} ${CFLAGS}’ -ccl
ib ‘${LDFLAGS}’ -I +compiler-libs”

If I don’t pass the ‘-cc’ option, things work.
OCAMLOPT:class-target = “ocamlopt -verbose -ccopt ‘–sysroot=${STAGING_DIR_TARGET} ${CFLAGS}’ -ccl
ib ‘${LDFLAGS}’ -I +compiler-libs”

Looking at the Makefile.build_config, there’s MKEXE_EXP and MKDLL_EXP.
It seems that by default MKDLL_EXP will be used when ‘-shared’ is supplied to ocamlopt. But when ‘-cc ${CC}’ is also supplied, it switches to use ${CC}, which does not have ‘-shared’ option.

I made some progress. I can’t mention more than 2 users in the reply. Please see my reply.

P.S.
I’m using ocaml 5.0.0. But I briefly checked ‘git log 5.0.0…HEAD’ in ocaml repo, I don’t see ‘-shared’ option related fix. So I assume this problem also applies to latest ocaml.

The workaround I currently use:
Add OCAMLOPT_SHARED.
See add OCAMLOPT_SHARED for genenrating .cmxs files by ChenQi1989 · Pull Request #69 · ocaml/ocamlfind (github.com)

Someone already reported this issue actually, but it seems no progress has been made since then: https://github.com/ocaml/ocaml/issues/12284

Thanks for the info.