Is It Safe to Link C++17, C++14, and C++11 Objects

Is it safe to link C++17, C++14, and C++11 objects

Which combinations of these objects is it and isn't it safe to link into a single binary? Why?

For GCC it is safe to link together any combination of objects A, B, and C. If they are all built with the same version then they are ABI compatible, the standard version (i.e. the -std option) doesn't make any difference.

Why? Because that's an important property of our implementation which we work hard to ensure.

Where you have problems is if you link together objects compiled with different versions of GCC and you have used unstable features from a new C++ standard before GCC's support for that standard is complete. For example, if you compile an object using GCC 4.9 and -std=c++11 and another object with GCC 5 and -std=c++11 you will have problems. The C++11 support was experimental in GCC 4.x, and so there were incompatible changes between the GCC 4.9 and 5 versions of C++11 features. Similarly, if you compile one object with GCC 7 and -std=c++17 and another object with GCC 8 and -std=c++17 you will have problems, because C++17 support in GCC 7 and 8 is still experimental and evolving.

On the other hand, any combination of the following objects will work (although see note below about libstdc++.so version):

  • object D compiled with GCC 4.9 and -std=c++03
  • object E compiled with GCC 5 and -std=c++11
  • object F compiled with GCC 7 and -std=c++17

This is because C++03 support is stable in all three compiler versions used, and so the C++03 components are compatible between all the objects. C++11 support is stable since GCC 5, but object D doesn't use any C++11 features, and objects E and F both use versions where C++11 support is stable. C++17 support is not stable in any of the used compiler versions, but only object F uses C++17 features and so there is no compatibility issue with the other two objects (the only features they share come from C++03 or C++11, and the versions used make those parts OK). If you later wanted to compile a fourth object, G, using GCC 8 and -std=c++17 then you would need to recompile F with the same version (or not link to F) because the C++17 symbols in F and G are incompatible.

The only caveat for the compatibility described above between D, E and F is that your program must use the libstdc++.so shared library from GCC 7 (or later). Because object F was compiled with GCC 7, you need to use the shared library from that release, because compiling any part of the program with GCC 7 might introduce dependencies on symbols that are not present in the libstdc++.so from GCC 4.9 or GCC 5. Similarly, if you linked to object G, built with GCC 8, you would need to use the libstdc++.so from GCC 8 to ensure all symbols needed by G are found. The simple rule is to ensure the shared library the program uses at run-time is at least as new as the version used to compile any of the objects.

Another caveat when using GCC, already mentioned in the comments on your question, is that since GCC 5 there are two implementations of std::string available in libstdc++. The two implementations are not link-compatible (they have different mangled names, so can't be linked together) but can co-exist in the same binary (they have different mangled names, so don't conflict if one object uses std::string and the other uses std::__cxx11::string). If your objects use std::string then usually they should all be compiled with the same string implementation. Compile with -D_GLIBCXX_USE_CXX11_ABI=0 to select the original gcc4-compatible implementation, or -D_GLIBCXX_USE_CXX11_ABI=1 to select the new cxx11 implementation (don't be fooled by the name, it can be used in C++03 too, it's called cxx11 because it conforms to the C++11 requirements). Which implementation is the default depends on how GCC was configured, but the default can always be overridden at compile-time with the macro.

Can i safely mix libraries compiled with -std=c++11 and -std=c++14?

The mixup for gcc was a stdc++ decision (not even gcc). They are indeed incompatible when you set the macro in a different state, but you can mix C++98 with C++11 with libstdc++ if you set it consistently. For instance, on RedHat, the default gcc compiler is old and doesn't support C++11, so the devtools with newer compiler have the macro set to old ABI by default so that they are always compatible.

So if you are consistent with your stdc++ library, no problem. No problem on libc++, VS...

Can I link an object compiled with clang c++11 with another compiled with c++17

The answer posted here by Jonathan Wakely is correct for Clang as well.

Easy answer: if you're compiling both of the objects yourself, the -std option you choose won't affect the final outcome.

Most of a given C++ ABI is decided by the standard library. The rest is assorted runtime support such as exceptions, compiler builtins (which may actually dispatch to the standard library), and things like that. libstdc++ ABI compatibility is an explicit goal of for Clang, so you're ok here.

If you're using the same compiler version, the -std option will change which symbols get exposed to code when you compile. However, libstdc++'s ABI for stable features is forwards compatible, so you'd also be OK here too.

Harder answer: Your comments suggest you have the source, but if you only have object files and are just doing the final link, there's a good chance it will work unless the version of Clang used to build the std=c++11 object is very old. The g++ and libstdc++ authors went out of their way to version symbols, so the chances of you having something that links, but then fails in a hard to diagnose way is basically zero. (This is referred to in the second to last paragraph in Jonathan's answer).

Again, since Clang aims to keep compatibility with libstdc++'s ABI, you should be fine. There are other details, but the vast majority are addressed in Jonathan's answer, and he's in a better position to explain it than I am.

Can a C++14/17 project use binary libraries compiled using C++11 standard or does the source code need to be recompiled?

The C++ standard has nothing todo with the file format of the binary. That only depends on the compilers/linkers and the OS. So if the compiler vendor changes the ABI ( Application binary interface ), you can not simply link the parts together.

As you can read here, only relevant for gcc:

https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html

gcc introduces with gcc5.1 a new ABI. A history of versions of libraries from gcc and maybe comments to ABI changes can be found here:

https://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html

So changing from one C++ version to another did not change the ABI but changing the compiler can.



Related Topics



Leave a reply



Submit