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?
Related
Suppose we have a shared library which accepts or returns some kind of std class:
//lib.h
#include <vector>
std::vector<int> returnSomeInts();
//lib.cpp
#include "lib.cpp"
std::vector<int> returnSomeInts() {
return {1, 3, 5};
}
So, obviously, when compiling the shared library lib.so, this code had to be compiled against a particular version of the standard library, for instance with -std=c++11.
Now imagine we have an application which will be using our shared library, but it will be compiled against a newer std library, for example -std=c++2a
//app.cpp
#include <lib.h>
int main()
auto v = returnSomeInts();
//Process v
}
As the standard library defines inline classes, if the layout of the class members changes, ABI compatibility gets broken, so the code above would not work properly.
My questions are: Is there any guarantee for ABI stability with the common implementations of the the std library when compiling against the same header using different c++ standards? And when compiling against different header versions (libstdc++-8 and libstdc++-9 for example)?
PD: The code above is just an example, I am not referring specifically to std::vector
ABIs in practice are not linked to the standard, for example consider this following code compiled with gcc 4.9.4 and gcc 5.1
using the same flags:
-std=c++11 -O2
#include <string>
int main(){
return sizeof (std::string);
}
gcc 4.9.4 returns 8 from main, gcc 5.1 returns 32.
As for guarantees: it is complicated:
Nothing is guaranteed by the standard.
Practically MSVC used to break ABI compatability, they stopped (v140,v141,v142 use the same ABI), clang/gcc have a stable ABI for a long time.
For those interested in learning more:
For a broad discussion of ABI/C++ standard that is not directly related to this question you an look at this blog post.
Your example with std::vector is not a problem. As other answer points out compilers maintain compatibility and std::vector is quite old.
Problem can be new library features of newer C++ standard is used.
For example I have some product which uses C++17 languages features. My product supports MacOS 10.13. I can build my project using C++17 (language features), but I can't use for example std::optional since some methods are throwing std::bad_optional_access which is part dynamic library and this is not supported/present in MacOS 10.13. Clang warns me about that (reports an error).
Same applies on other system (clang nicely controls that). So when you use some library features you need make sure that libraries on deployed system supports that (on Linux package managers handle that nicely if system doesn't have access to required package version installation will fail). On Windows 10 AFAIK Windows update keeps newest version of msvc redistributable, older versions of Windows need manual updates.
Note that many templates are becoming part of your executable and do not have dependencies to shared standard library. Those will not create problems.
These are the kinds of question that the standard doesn't answer, it is down to individual implementers how long they keep compatibility for and which (if any) compiler flags affect compatibility.
In practice libstdc++ on Linux has tried very hard to keep a stable ABI for quite a long time now. The soversion has remained at 6 for around 15 years now.
However there have been some changes, most notable were those introduced with g++-5.1 related to std::list and std::string. New requirements in c++11 meant that to be compliant libstdc++ needed to make breaking changes to the ABI of those classes.
g++'s solution was to define two versions of those classes. To allow both types to coexist in the same shared library they are defined with different names, so the old std::list is defined as std::list while the new std::list is defined as std::__cxx11::list and then aliased as std::list. Which definition is used in a given source file is controlled by a preprocessor macro.
Note that the setting of said preprocessor macro is independent of the -std= setting, you can use the compiler in c++11 mode with the old string/list implementation (in which case it won't be fully compliant with the standard) or you can use the compiler in c++03 mode with the new string/list implementations.
The default value of the macro (if not set explicitly by the user) depends on compiler version and can also be overridden by distribution maintainers.
The trouble is while this solves the problem for libstdc++ it doesn't solve it for all the other libraries. If a program was built with the new implementations while a library was built with the old ones or vice-versa and the library used std::string or std::list in it's API, then the likely outcome was a link failure (it was also possible but less-likely for the linking to succeed but the program to be silently broken). In Debian at least this lead to a massive set of library transitions (it would not surprise me if it was the largest in the project's entire history).
I am working in a project based on C++17 and have to rely on a library built with C++11 (or older). Problems arise from the fact that several structs have been removed for good from std with C++17.
Note that I am building the legacy library from source!
The problems:
If I am building the library with C++11 and use it in the C++17 project, the linker won't find the correct implementations (e.g. string). That makes sense, since listing the library symbols I can see it references std::c++11::basic_string.
If I am trying to build the library with C++17, the compiler does not find the missing C++03 structs (e.g. ptr_fun). Again makes sense, as they are not part of the C++17 stdlib.
If I am trying to build the library with C++17 but include headers from C++11, everything explodes. Makes sense since the headers are not compatible.
Long story short, I do not see how to easily solve this. Technically, since I am able to build the library from source, there should be no definitive reason why I cannot use it with any other project. What's the best practice for this?
I am using Linux with clang for this. The question should be the same with any compiler and OS though.
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.
After much research and digging into the Boost libraries documentation, I cannot find answers or high-level advice on the following questions:
Which are the requirements of Boost regarding the C++ language version? C++03? C++11? How can I now which version of Boost requires which version of the C++ language?
Does it depends on the specific library (most of the times, the .hpp file included).
Do I have to check manually (as a last resort) with all the libraries I may need and all the versions of Boost, from the latest and then moving backwards in case I need a less strict dependency?
Which are the dependencies with the C++ Standard Library?
Context:
I am evaluating the use of Boost on an embedded platform (MCU with limited and no virtual memory, no underlying OS).
I have GCC 4.8.1 with C++11 support.
We do not have a complete C++ Standard Library for this platform.
I was hoping to use Boost as a complement and substitute of the C++ Standard Library, hence my research on the topics asked above.
I appreciate the high quality of the Boost project documentation, however, I could not find any reference to the above topics in the official documentation. Maybe I have missed something.
P.S.: A gente introduction to the historically complex topic of C++ language versions, Standard Library and Boost libraries,
http://news.dice.com/2013/03/15/comparing-the-c-standard-and-boost-2/
http://beta.boost.org/development/tests/master/developer/summary.html
This lists some of the platforms boost is tested against.
Every release, boost mentions which platforms it has been tested against.
It is expected to work on more platforms than those listed, but there are no guarantees.
The support and evolution of a boost library in terms of supporting new c++ features is not tightly related to the other libraries. Since boost has been living mainly in a mono standard world (c++03), it was implied that it works in c++03. But as boost people tend to do stuff in a smart way, for the libraries who now support c++11 features, they either use some feature emulation system to keep it working on c++03 or they test for your configuration and if you can't use some advanced stuff then they just disable it.
So basically there is no language standard requirements, it works on all c++03/C++11/C++14 with different features sets.
For other requirements (namely parts of the STL) it directly depends on the libraries you want. The best way is to test. You might find a way to launch their unit test on your plateforme to see how much is working.
You might also want to check Boost Config which is the library that all others use to check for features.
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.