Fedora 22 will ship with GCC 5, which brings a whole host of enhancements, among which is a new default C++ ABI. In this article, we’ll cover how that ABI transition will work in Fedora.
Background – what’s an ABI, why is it changing, and what does this mean for developers?
Put simply, binary compatibility means applications that are compiled on a combination of an operating system and a particular hardware architecture will load and run similarly across different instances of the operating environment. Application binaries consist of executable files and Dynamic Shared Objects (DSOs – the formal name for shared libraries), and the level of compatibility is defined by a specific application binary interface (ABI).
The development of new features in compilers, libraries and related tools – and notably any new language standard those tools support – can result in changes to the ABI, requiring that certain binaries need to be re-built, or that newly built binaries are not directly compatible with existing binaries.
GCC 5 implements such an ABI change when the compiler is built with default options from the upstream community sources. It does this order to implement the new C++11 language standard. That provides new features to developers at the cost of binary compatibility – the C++11 requirements on certain C++ core classes requires an ABI change.
GCC 5 also provides, out of the box, a compiler switch to switch back to using the older ABI by default, at the cost of some C++11 conformance. Whichever ABI GCC is configured to use by default, developers can use the other one on a per-file basis by defining a macro to override the default.
FESCo’s decision and rationale around GCC 5 and Fedora 22
In mid-January, the maintainer of GCC in Fedora made a proposal for GCC 5 to be included in Fedora 22. That proposal was made to FESCo,the body that has overall authority to determine what major features get into each release of Fedora.
The issue was debated during the recent FESCo meetings, which the maintainer attended, and ultimately the decision was made to ship GCC 5, but with
the old ABI enabled by default.
At the heart of this decision was the priority placed by FESCo on the Fedora 22 schedule. A mass rebuild of all Fedora packages would not be possible if Fedora 22 is to ship on time. A “mini-mass-rebuild” was considered, where only C++ packages would be rebuilt (so Fedora could move to using C++11 and the new ABI). The idea here would be to reduce the number of packages that must be rebuilt to save time. That proposal was also rejected, however, as FESCo felt even the mini-mass-rebuild would impact the Fedora 22 schedule.
That left FESCO with two options. Either to remain with GCC 4.9 through the Fedora 22 cycle, then upgrade to GCC 5 in Fedora 23, or to use GCC 5, but with the old C++ ABI in Fedora 22, then step forward with the new ABI in Fedora 23.
Staying with GCC 4.9 would have minimized the work required for Fedora 22 GCC packaging, Fedora 22. The Fedora and GCC development cycles are mutually beneficial, however, and so removing GCC 5 from Fedora has side effects in terms of GCC 5’s development upstream.
Staying with GCC 4.9 would also leave Fedora users without easy access to all the other benefits GCC 5 brings. The removal of GCC 5 could even be misconstrued as signalling that GCC 5 wasn’t ready for production use.
Finally, staying with GCC 4.9 would also impact developers using Red Hat’s tools for RHEL, such as Red Hat Developer Toolset – GCC 5 wouldn’t have the widespread Fedora testing Red Hat desires before addition to Red Hat’s product portfolio.
The option to use GCC 5, but with the old ABI, allows developers to benefit from all the upstream community’s work on features and bugfixes. Those active users in turn benefit both the GCC and Fedora projects directly. Fedora will not enable the new C++11 ABI by default, but that will also allow developers to handle the general upgrade to GCC 5 separately to the new ABI, which is expected to be enabled in Fedora 23.
So what do I need to know about Fedora 22 and Fedora 23 as a developer?
One consequence of this decision will be that Fedora 22 and Fedora 23 will both have GCC 5, but they’ll be fundamentally different. The C++ library (libstdc++.so) will be
compatible between F22 and F23 (in fact, it will be almost exactly the same,
modulo some extra patches from upstream that might be pulled into the later F23 build). The difference will be all the other DSOs that link to it. That’s important for Fedora developers to note.
Specifically, FESCo’s decision means the C++ standard library headers installed by the
libstdc++-devel RPM will have a different default value for the _GLIBCXX_USE_CXX11_ABI macro (0 in F22 and 1 in F23) but the libstdc++.so library will be largely the same in F22 and F23, because that library contains all the symbol definitions for both the old ABI and the new ABI, so that the same library works for both cases.
However, when another DSO such as libboost_filesystem.so is compiled with GCC 5 it will be compiled using either the old ABI or the new one, but not both, and programs linking to that DSO will usually need to use the same ABI to avoid linker errors. The C++ libraries that are part of Fedora 22 will be built using the old ABI, but they will be built using the new ABI in Fedora 23. Developers might need to recompile their programs using the new ABI in order to link to C++ libraries in Fedora 23. Similarly, developers who use the _GLIBCXX_USE_CXX11_ABI macro to override the default might need to rebuild other libraries they depend on to ensure those libraries are also built with the non-default ABI.
If you happen to maintain a package in Fedora that provides a library for consumption by other packages, you might even consider doing something similar to libstdc++ for Fedora 22/23, i.e. provide two sets of your public symbols – one for the old ABI and one for the new ABI. Whether that would be worth the effort to implement depends largely on the number of consumers of your library, the number of symbols your library contains, and how sensitive your users are to ABI changes. Essentially, you need to work out which symbols are affected. One way to do this is to build for C++98 [gcc -D_GLIBCXX_USE_CXX11_ABI=0 -Wabi-tags in your rpmbuild], then separately for C++11 [gcc -D_GLIBCXX_USE_CXX11_ABI=1 -Wabi-tags in your rpmbuild], and then compare the two DSOs with abidiff (part of libabigail) [abidiff old-abi/libfoo.so new-abi/libfoo.so]. Having identified the symbols affected, make sure those symbols are compiled in their own files separately from unaffected symbols, so you can compile them twice (without duplicates of the unaffected symbols). It’s non-trivial, but something to consider.
Overall, there are three key things to keep in mind about GCC 5 in Fedora 22. Firstly, the Fedora 22 GCC component will still be from a full upstream release. Secondly, selection of the ABI is done by way of a standard configure time flag – the option is there to rebuild with that switch reversed. Thirdly, ABI compatibility with F21 is actually maintained in Fedora 22 (though developers will have the option to enable the newer C++11 ABI via -D_GLIBCXX_USE_CXX11_ABI=1).
What does this mean for RHEL developers?
Developers building applications for Red Hat Enterprise Linux, using Red Hat tools to build binaries and shared libraries, are unaffected by these changes.
Hopefully this article has been useful in explaining what the plan is for GCC 5’s release in Fedora, how FESCo arrived at their decision, and what it means for Fedora and Red Hat Enterprise Linux developers.
Feel free to ask questions or provide feedback.