What is a good way to handle ABI differences between libc ++ and the old libstdc ++?

advertisements

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?


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