13

I've written a fairly substantial C++11 library, and I'm planning to allow download of pre-compiled versions from my website.

So I've set up an automated build which compiles the library with clang and make it available for download, but this has exposed a problem: if I try to use the clang-compiled library with GCC I get undefined references (mainly related to std::string). I think this is related to the GCC dual-ABI changes in GCC 5.1 but I'm not sure how to fix it.

My question is, what flags should I set, or practices should I follow to make a C++ library compatible with both clang and GCC?

Or should I give up and compile two separate libraries?

Kazade
  • 1,297
  • 2
  • 15
  • 25
  • 8
    IMHO this can't be done. GNU libstdc++ and libc++ are incompatible. – rustyx Jan 03 '18 at 07:33
  • 3
    Two approaches: do what everyone else does and make it header only (joke), or give up and compile two separate libraries. – Alex Huszagh Jan 03 '18 at 10:38
  • If you think you are getting errors due to dual ABI, you probably need to show at least the text of the errors, your compilation flags, and versions of everything involved. – n. m. could be an AI Jan 03 '18 at 15:28

3 Answers3

5

As already mentioned in several places (eg. here) libc++ is not fully binary compatible with libstdc++. There are several options, but some of them are somewhat not-so-straightforward.

  1. Compile two separate libraries - always working solution.
  2. Remove incompatible containers from your interface (eg. std::string) - but this might be lot of work and sometimes not a good idea.
  3. Instruct your library GCC users that you link with libc++ and that they need to do the same, basic steps here. But I guess most GCC users do not want to do this.
  4. Use clang with libstdc++ using -stdlib=libstdc++ flag to be compatible with libstdc++ (as suggested in other answer). This solution might be harder to setup on some platforms though.

I would suggest as already mentioned in comments to go with option 1.

pe3k
  • 796
  • 5
  • 15
  • 1
    Maybe add "Don't distribute it in binary form. Instead, make it easy to build everywhere (e.g. by using CMake, or autotools or ...)"?? – Massa Jan 04 '18 at 16:27
3

There are several options:

  1. Don't distribute it in binary form. Instead, make it easy to build everywhere (e.g. by using CMake, or autotools or ...)

  2. Make it header only. This is by far the simplest solution but might not be what you want. It only really makes sense for templated code, and incurs a heavy impact on compile-time performance of your library.

  3. Tell people to link with libstdc++ when using Clang and your library. Suboptimal solution (I for one like to check my code against libc++ as well as libstdc++), but (virtually) every Linux user has libstdc++ installed anyway. Make sure to pick a slightly older version (the one shipped in the latest Debian Stable distro is a good choice), because newer versions might introduce new symbols olders versions are missing. New versions should be ABI compatible anyway.

Note the situation for Visual Studio users is even worse, where every single compiler release mandates a new binary because they guarantee absolutely nothing with respect to the C++ libraries' or compiler's ABI.

rubenvb
  • 74,642
  • 33
  • 187
  • 332
2

Another option is for your shared library to not expose any C++ standard library types in its interface. And have a header file supplied with your shared library that converts std::string to types consumed by your library, such as struct my_string_span { char const *begin, *end; }; and other standard containers as necessary.

Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271