Interoperability between Boost and C++11 - c++

What is the extent of interoperability between C++11 and a recent version of Boost (say 1.55) built with a C++11 compiler.
Does the behavior of any library feature change depending on whether I built the libraries with c++11 flags enabled or not?
How do language features like lambda functions cooperate with Boost's lambdas?

You cannot use objects built with gcc with and without -std=c++11 together. You will get link errors or even runtime crashes. I cannot vouch for other C++ implementations. So at least with gcc, you do need to build a separate version of Boost with c++11 mode enabled.
They are pretty much independent. They don't cooperate and don't interfere with each other.
EDIT I see people are still reading (and upvoting!) this answer. Point 1 is no longer true (or perhaps never was true). Versions of gcc from I think 5.1 upwards use an ABI compatible with -std=<anything> by default.

No behaviours change: at the code level Boost is compatible with both C++03 and C++11.
However, at the object level you won't be able to mix and match: if your program is compiled as C++11, and you're using some non-header Boost libraries, you will have to build those Boost libraries as C++11 as well. This is because the respective C++ runtimes of your toolchain for each version of the language cannot be guaranteed to have ABI compatibility.

Related

Please explain the C++ ABI

The common explanation for not fixing some issues with C++ is that it would break the ABI and require recompilation, but on the other hand I encounter statements like this:
Honestly, this is true for pretty much all C++ non-POD types, not just exceptions. It is possible to use C++ objects across library boundaries but generally only so long as all of the code is compiled and linked using the same tools and standard libraries. This is why, for example, there are boost binaries for all of the major versions of MSVC.
(from this SO answer)
So does C++ have a stable ABI or not?
If it does, can I mix and match executables and libraries compiled with different toolsets on the same platform (for example VC++ and GCC on Windows)? And if it does not, is there any way to do that?
And more importantly, if there is no stable ABI in C++, why are people so concerned about breaking it?
Although the C++ Standard doesn't prescribe any ABI, some actual implementations try hard to preserve ABI compatibility between versions of the toolchain. E.g. with GCC 4.x, it was possible to use a library linked against an older version of libstdc++, from a program that's compiled by a newer toolchain with a newer libstdc++. The older versions of the symbols expected by the library are provided by the newer libstdc++.so, and layouts of the classes defined in the C++ Standard Library are the same.
But when C++11 introduced the new requirements to std::string and std::list, these couldn't be implemented in libstdc++ without changing the layout of these classes. This means that, if you don't use the _GLIBCXX_USE_CXX11_ABI=0 kludge with GCC 5 and higher, you can't pass e.g. std::string objects between a GCC4-compiled library and a GCC5-compiled program. So the ABI was broken.
Some C++ implementations don't try that hard to have compatible ABI: e.g. MSVC++ doesn't provide such compatibility between major compiler releases (see this question), so one has to provide different versions of library to use with different versions of MSVC++.
So, in general, you can't mix and match libraries and executables compiled with different versions even of the same toolchain.
C++ does not have an ABI standard as of yet. They are attempts to have it in the standard; You can read following it explains it in details:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2028r0.pdf

How do I make a C++ (shared) library compatible with clang and GCC?

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?
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.
Compile two separate libraries - always working solution.
Remove incompatible containers from your interface (eg. std::string) - but this might be lot of work and sometimes not a good idea.
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.
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.
There are several options:
Don't distribute it in binary form. Instead, make it easy to build everywhere (e.g. by using CMake, or autotools or ...)
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.
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.
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.

Using a C++11 shared library in a C++03 application that was compiled with gcc 4.1 in Linux?

Having gone through a number of similar questions (see below), I don't think any of them cover this case.
Problem
Is it possible to dlopen and use a C++11 shared library compiled using gcc 4.9 from a C++03 application compiled with gcc 4.1? Both the library and application use libstdc++, including on the API (but not std::list, which is apparently a problem). I can't change the way the application is compiled (sadly), and must be certain that existing code doesn't break (e.g. if it ends up dynamically linking to a new version of libstdc++.so).
As far as I understand it (which is not very), on Linux the dynamic linker uses a flat namespace, meaning that is not possible to have the same symbol defined in two libraries. Does statically linking the library against the newer libstdc++ help at all here, or is there perhaps some other way?
Some similar questions that don't seem to answer this
C++11 backwards compatibility
C++03 library with C++11 source code
C++11 compatibility with existing libraries/frameworks
Can a compiled C++11 library (lib,dll,etc.) be linked in older C++ compilers? [softwareengineering.stackexchange.com]
If you do that, you definitely need to use the newer libstdc++.so.6, which should be compatible with the system libstdc++.so.6 based on GCC 4.1 (in the sense that GCC upstream intends to preserve ABI compatibility for the library). It would be a very good idea to use the libstdc++.so.6 library that came with the GCC 4.9 compiler.
Once you do that, it is supposed to work, unless you hit the few of the compatibility gotchas you already listed, and as long as the C++ part of the library interface actually sticks to the C++98 subset and does not use any constructs which are not expressible in the language subset.
All this assumes that the library was actually compiled on the the system which uses GCC 4.1, which probably has something like glibc 2.5. If the library was compiled on a completely different, newer system, then you will likely run into library compatibility issues beyond libstdc++.so.6, and these libraries tend to be even harder to upgrade.
(There is also the possibility that the library was explicitly compiled for use with the 4.1-based system libstdc++.so.6 and everything just works, just as if by magic, but then you wouldn't be asking here, I suppose.)
If you still have problems there is the option to use a statically linked C-API library as border between the two, application and your library, see this post.
Also you may be able to explicitely demand an old version of a symbol, see this post

C++11 compatibility with existing libraries/frameworks

I am wondering something for which I have not found a convincing answer yet.
Situation:
A system with some libraries (e.g. gtkmm) compiled without c++11 enabled.
An application compiled with C++11 enabled.
Both are compiled and linked with the same GCC version/environment.
The application has some function calls to the library which use std::string and std::vector.
both std::string and std::vector support move semantics which most likely mean they are not binary compatible with wth non C++11 variants. However both the application and library are build with the same compiler and standard libraries, so it would not be so strange if the lib would recognize this and support it.
Is the above situation safe, or would it be really required to compile everything with the C++11 flag, even if the same build environment is used ?
This page is dedicated to g++ abi breaks with c++11 up to version 4.7.
The first sentence there is:
The C++98 language is ABI-compatible with the C++11 language, but several places in the library break compatibility. This makes it dangerous to link C++98 objects with C++11 objects.
Though there are examples, where enabling c++11 won't brake ABI compatibility: one example is Qt where you can freely mix c++11 enabled builds with c++03 builds.
You can consider each translation of C++ by a different compiler (even if the compiler is the same, but has a different (minor) version) incompatible. C++ has no common application binary interface (ABI).
In addition, a change of the dialect supported by the compiler is a change of the ABI, hence the resulting libraries are incompatible. An obvious example is a release build vs. debug build, where the debug data structures introduce additional members.
And moving structures (C++11) or not moving structures ( < C++11) is a radical change of the ABI.

Using Boost with C++14 compiler

When I am compiling my code with C++11 support (using the -std=c++11 flag) and use non-header-only Boost libraries, then I need to have Boost compiled with -std=c++11. This is because Boost has some interface differences in header files when C++11 is enabled, and some function signatures are different for the different C++ standards.
My question is whether the same is true with C++14 (using g++ 4.9, with the `-std=c++1y flag), or is it safe to use Boost compiled with C++11 for a program compiled with C++14?
This is a very broad question that is difficult to answer definitively, because
Boost is a federation of libraries, many of which are over decade old
there are quite a lot of backward compatibilities that could in principle happen, some detected by the compiler, and some only by unit tests
many Boost libraries are actually C++98 implementations of C++11/14 features (both library and compiler functionality), so that you would not need to use this in a C++11/14 project.
Boost itself is very much debating at which pace the library should be updated to C++11/14, whether V2 versions of libraries should be written that fully take advantage of C++11/14, and even whether new C++11/14 libraries should offer backward C++98 compatibility
You might want to closely read your compiler errors (if any) and compare them to the list of breaking changes listed below. Furthermore, I would recommend following the Boost test harness for finding suspect compiler/library combinations that apply to your system.
Some relevant Q&A's here:
What breaking changes are introduced in C++11?
What changes introduced in C++14 can potentially break a program written in C++11?
Relevant boost features vs C++11
How well does boost use c++11?