ocaml / dune

A composable build system for OCaml.
https://dune.build/
MIT License
1.63k stars 409 forks source link

ld: Error: unable to disambiguate: -shared-libgcc #7073

Open emchristiansen opened 1 year ago

emchristiansen commented 1 year ago

I'm getting the linker error ld: Error: unable to disambiguate: -shared-libgcc when trying to create a .o file with (modes object). I'm not sure that the issue is with Dune, but I'm hoping you can shed some light.

To replicate, create a new project with dune init project broken, run opam install class_group_vdf, and finally change bin/dune to:

(executable
 (public_name broken)
 (name main)
 (libraries broken class_group_vdf)
 (modes exe object))

Then, dune build should fail with ld: Error: unable to disambiguate: -shared-libgcc.

Do you have any idea what might be causing this? It seems odd that a single library would use conflicting versions of another library, so perhaps a flag Dune is passing is introducing the conflict? I'm also confused as to why an apparently shared library is coming up when doing static linking.

Specifications

dune 3.6.2, ocaml 4.14.1, Ubuntu 22.04.

Additional information

https://gist.github.com/emchristiansen/da7584036fcbe7a3373f8298dbeaf84a

https://github.com/zshipko/rust-ocaml-starter/issues/4

nojb commented 1 year ago

To debug, I suggest you pass -verbose to the compilation and linking command (ie in the (flags ...) and (link_flags ...) fields of the executable stanza).

emchristiansen commented 1 year ago

@nojb thanks for the tip!

When I pass -verbose I get this output, which shows that ld is being passed -shared-libgcc. This is apparently the default behavior when linking executables, which I guess means that (modes object) doesn't produce fully-linked object files (?).

Relatedly, I found this problem goes away (at least at this stage) if I edit the ocamlopt.opt invocation constructed by Dune so that -output-complete-obj is replaced with -output-obj. Is it possible to tell Dune to use -output-obj and not -output-complete-obj when creating an object file with (modes object)?

emchristiansen commented 1 year ago

I think it might just be that ld is getting passed an invalid argument:

Screenshot 2023-02-14 at 6 43 28 PM

It appears ld doesn't have anything like a -shared-libgcc argument (but gcc does):

Screenshot 2023-02-14 at 6 46 43 PM

So, it seems to me like this is a bug in either Dune or ocamlopt.opt (whichever is passing ld the erroneous flag).

nojb commented 1 year ago

So, it seems to me like this is a bug in either Dune or ocamlopt.opt (whichever is passing ld the erroneous flag).

Do you have C++ stubs in your project? Pinging our C/C++ flag expert @voodoos.

emchristiansen commented 1 year ago

I don't have any stubs - I just did dune init project broken, installed class_group_vdf version 0.0.4 with opam install class_group_vdf, and then added class_group_vdf to the (libraries ...) stanza in bin/dune.

Here's the source for class_group_vdf. Perhaps it's something about that package?

voodoos commented 1 year ago

C/C++ flag expert @voodoos.

Ah, the git-blame curse :-) I am sadly not yet a flag expert, but I will have a look ! I tried to reproduce on my mac machine and I get a different error message but still an error. Not sure if it is an issue in Dune or with the package, but I will try to investigate.

emchristiansen commented 1 year ago

Thank you!

emillon commented 1 year ago

ocamlobjinfo class_group_vdf.cmxa returns:

Extra C object files: -lclass_group_vdf_stubs -lstdc++ -shared-libgcc -lgmpxx -lgmp
Extra C options: -lpthread

Looks like the flags computed in Cxx_flags all get prepended with -cclib in Lib_rules.build_lib ; some of these should get prepended with -ccopt instead.

emchristiansen commented 1 year ago

Any ideas for a workaround while we're waiting for a patch?

voodoos commented 1 year ago

Looks like the flags computed in Cxx_flags all get prepended with -cclib in Lib_rules.build_lib ; some of these should get prepended with -ccopt instead.

According to the manual -ccopt flags are also passed to the linker, so I am not sure this would work ?

-cclib -llibname
    Pass the -llibname option to the C linker when linking in “custom runtime” mode (see the -custom option). This causes the given C library to be linked with the program. 
-ccopt option
    Pass the given option to the C compiler and linker. When linking in “custom runtime” mode, for instance -ccopt -Ldir causes the C linker to search for C libraries in directory dir. (See the -custom option.) 
voodoos commented 1 year ago

Any ideas for a workaround while we're waiting for a patch?

I don't know if that would be useful for you but building in shared_object mode works on my setup.

emchristiansen commented 1 year ago

Any ideas for a workaround while we're waiting for a patch?

I don't know if that would be useful for you but building in shared_object mode works on my setup.

Unfortunately shared_object doesn't appear to be an option for me (though it does build).

emillon commented 1 year ago

passing -shared-libgcc as a -ccopt makes the error go away, but then ld is confused about -lstdc++. I suspect that the right fix is to invoke cc rather than ld by hand.

voodoos commented 1 year ago

Any ideas for a workaround while we're waiting for a patch?

A shot in the dark: could you try to add (use_standard_c_and_cxx_flags false) to your dune project file ?