Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is a good way of handling ABI-differences between libc++ and the older libstdc++?

What (if any) is a good way of handling the ABI inconsistency between libc++ and stdlibc++ on Mac?

The problem: Many c++11 features require the new libc++ implementation of the C++ standard library. But libc++ is not ABI-compatible with the old libstdc++, while currently most software typically links against the latter. For example the system compiler still uses stdlibc++ which means that all my libraries installed with macports have a different ABI for std-classes like string and are unlinkable with projects that make heavy use of c++11.

My current hack-of-a-solution: Keep two versions of libraries where this commonly leads to an issue (boost, opencv etc.) and link to the appropriate one.

I guess that one might suggest that if I really want to make use of libc++ I should purge my system of anything using stdlibc++, and make sure that anything from macports (or anywhere else) only links with libc++. You could see how daunting this task seems.

Has anyone worked out a nice way of relating to this "between-stdlib-limbo" that we are living in? :)

EDIT: I'm making an implied follow-up question more explicit: Apple ships both libc++ and libstdc++ with their systems. Assuming one attacks the underlying problem and tries to make a switch to libc++-only. What would be the recommended way of switching from libstdc++ to libc++ given that 100% of the libraries currently installed on your system (some shipped with the system, most of them via macports, a few via manual compilation) are linked to libstdc++ (if any)? Has anyone done this and survived?

like image 581
kamjagin Avatar asked Jul 03 '13 14:07

kamjagin


People also ask

What is ABI compatibility?

A complete ABI, such as the Intel Binary Compatibility Standard (iBCS), allows a program from one operating system supporting that ABI to run without modifications on any other such system, provided that necessary shared libraries are present, and similar prerequisites are fulfilled.

What is libc ++ ABI?

libc++abi is a new implementation of low level support for a standard C++ library. All of the code in libc++abi is dual licensed under the MIT license and the UIUC License (a BSD-like license).

What is ABI in GCC?

These details are defined as the compiler Application Binary Interface, or ABI. From GCC version 3 onwards the GNU C++ compiler uses an industry-standard C++ ABI, the Itanium C++ ABI. The GNU C++ compiler, g++, has a compiler command line option to switch between various different C++ ABIs.

Does C++ use libc?

Most implementations of libstdc++ depend on libc, so they require it. The C++ standard includes most of the C standard library. So it's kind of a dependency and technically it's part of the C++ standard library.


1 Answers

Barring 'hidden' uses of standard library types it is perfectly safe to mix libc++ and libstdc++ in a single program, where some TUs (or libraries, or modules) use libc++ and some use libstdc++. As long as the interfaces between TUs do not use the incompatible types there shouldn't be any problems.

libc++ uses inline namespaces to help ensure that ABI incompatible types cannot be mistaken for one another; if an interface uses libc++ std::string directly a library expecting libstdc++ std::string will not link to the interface, because the actual symbols are different: std::string vs. std::__1::string.

libc++ also ensures that low level features like exceptions and dynamic memory allocation are ABI compatible (assuming you build libstdc++ and libc++ using the same abi library), so it's safe to deallocate memory in a TU that uses, say, libc++ when the memory was allocated in a TU using libstdc++, or to throw an exception from code build on libc++ and catch it in code using libstdc++.

There can be a problem when types in interfaces hide standard library types; given an interface using struct S { std::string s; }; the definition of the type S will be different depending on what the TU thinks std::string is, thus violating the one definition rule.


However it sounds as if your real problem is with libraries that do use standard library types in interfaces.

I guess that one might suggest that if I really want to make use of libc++ I should purge my system of anything using stdlibc++, and make sure that anything from macports (or anywhere else) only links with libc++. You could see how daunting this task seems.

You only need to ensure that TUs that use the standard library in interfaces use libc++. You do not need to completely purge libstdc++. Libraries that don't use the standard library in their interface can still go on linking with libstdc++.

EDIT: I'm making an implied follow-up question more explicit: Apple ships both libc++ and libstdc++ with their systems. Assuming one attacks the underlying problem and tries to make a switch to libc++-only. What would be the recommended way of switching from libstdc++ to libc++ given that 100% of the libraries currently installed on your system (some shipped with the system, most of them via macports, a few via manual compilation) are linked to libstdc++ (if any)? Has anyone done this and survived?

Remember, it only matters when the standard library is being used in interfaces. Hopefully such libraries are already switching to libc++ on their own when they build for OS X. If not, perhaps they'll accept patches to do so.

Building your own binaries using the appropriate library is not a 'hack'; it is the correct thing to do absent the upstream project doing it for you. If you consistently use libc++ in your own code then you will not need to build multiple versions of any library; only libc++ versions.


reference for abi compatibility of libc++: http://lists.cs.uiuc.edu/pipermail/cfe-dev/2012-September/024594.html

like image 175
bames53 Avatar answered Nov 07 '22 06:11

bames53