Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
Bug 542482 (c++11-abi) - [TRACKER] c++11 abi incompatibility
Summary: [TRACKER] c++11 abi incompatibility
Status: RESOLVED OBSOLETE
Alias: c++11-abi
Product: Gentoo Linux
Classification: Unclassified
Component: Current packages (show other bugs)
Hardware: All Linux
: Normal normal with 1 vote (vote)
Assignee: Gentoo Toolchain Maintainers
URL:
Whiteboard:
Keywords: Tracker
: 570604 (view as bug list)
Depends on: 513386 550432 libsigc++-2.6 575198 582696
Blocks: gcc-5
  Show dependency tree
 
Reported: 2015-03-07 21:41 UTC by Anthony Basile
Modified: 2017-12-09 21:56 UTC (History)
15 users (show)

See Also:
Package list:
Runtime testing required: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Anthony Basile gentoo-dev 2015-03-07 21:41:58 UTC
This tracker is for packages which break due to C++11 abi incompatibility issues.  Incompatibility can occur for two reasons,

1) because C++ libraries compiled with C++11 are not necessarily abi compatible with objects compiled with C++98 or older.

2) because C++11 code compiled with gcc-4.X is not guaranteed to be ABI-compatible even with C++11 compiled with 4.Y if X != Y.

This problem will increase as more packages are written using C++11 syntax/semantics and excpect -std=c++11 (or -std=gnu++11).  The problem may also continue into C++14.

Let's only discuss strategies for dealing with this in the Tracker.  Individual instances of the problem should go into their own bugs.
Comment 1 Anthony Basile gentoo-dev 2015-03-07 22:34:39 UTC
gcc upstream's position on the question:  https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61758
Comment 2 Anthony Basile gentoo-dev 2015-03-10 16:24:21 UTC
There is some confusion about this bug.  It is subtle, so I wrote a blog post which illustrates it:

http://blogs.gentoo.org/blueness/2015/03/10/the-c11-abi-incompatibility-problem-in-gentoo/
Comment 3 Ted Tanberry 2015-03-29 14:19:24 UTC
Without an ultimate solution in the near-term future, how should "-std=XYZ" hardcoded in build systems be worked around? Example: I have a package that hardcodes "-std=c++98" into CXXFLAGS in the configure.ac, likely an ABI disaster waiting to happen. Should I remove that? What about C++11? Surely a rule to remove -std= from the build system is only applicable to C++98/03, as for C++11 removing -std=c++11 will fail in those packages relying on it. Hence only remove "-std=c++98" but retain "-std=c++11"? Or should I leave -std=c++98 in the build system and keep my fingers crossed?
Comment 4 Anthony Basile gentoo-dev 2015-03-29 19:10:58 UTC
(In reply to Ted Tanberry from comment #3)
> Without an ultimate solution in the near-term future, how should "-std=XYZ"
> hardcoded in build systems be worked around? Example: I have a package that
> hardcodes "-std=c++98" into CXXFLAGS in the configure.ac, likely an ABI
> disaster waiting to happen. Should I remove that? What about C++11? Surely a
> rule to remove -std= from the build system is only applicable to C++98/03,
> as for C++11 removing -std=c++11 will fail in those packages relying on it.
> Hence only remove "-std=c++98" but retain "-std=c++11"? Or should I leave
> -std=c++98 in the build system and keep my fingers crossed?

So far this is hitting only a few packages.  We'll have to see if this number gets serious.  So I'm not sure how "disasterous" it'll be.  It'll certainly be annoying when some big ticket package, like chromium, insists on c++11 and the rest of your system is c++98.  Right now we just want to track this problem.

Also, you can't just go changing -std= in build scripts.  The underlying code might use c++11 standards in which case expect breakage if you force c++93/03.
Comment 5 Ted Tanberry 2015-03-29 20:01:16 UTC
(In reply to Anthony Basile from comment #4)
> Also, you can't just go changing -std= in build scripts.  The underlying
> code might use c++11 standards in which case expect breakage if you force
> c++93/03.

Hence my suggestion to strip all build systems ONLY of "-std=c++98" but never touch any build system setting "-std=c++11". In that case, C++98 code should compile anyway, given that its the default, and should the need arise, we can always set -std=c++11 globally then and have all old code switch to c++11 too. Does this make sense?
Comment 6 Anthony Basile gentoo-dev 2015-03-29 20:18:39 UTC
(In reply to Ted Tanberry from comment #5)
> (In reply to Anthony Basile from comment #4)
> > Also, you can't just go changing -std= in build scripts.  The underlying
> > code might use c++11 standards in which case expect breakage if you force
> > c++93/03.
> 
> Hence my suggestion to strip all build systems ONLY of "-std=c++98" but
> never touch any build system setting "-std=c++11". In that case, C++98 code
> should compile anyway, given that its the default, and should the need
> arise, we can always set -std=c++11 globally then and have all old code
> switch to c++11 too. Does this make sense?

1) some packages that build under c++98/03 may not build under c++11.  eg xapian-1.2.19 doesn't.  see bug #541470.  I don't know why since it is my understanding that they should.

2) if we force a system to be all c++11, we'll have abi incompatibility between different libstdc++ for different versions of gcc.  we might be able to address this by setting an rpath during build so that the right version of libstdc++ is always linked against.  or maybe/hopefully upstream's c++11 abi will stabilize and this problem will become obsolete.

So I'm still not sure your approach is the least painful going forward.
Comment 7 Nikos Chantziaras 2015-10-01 20:50:42 UTC
(In reply to Ted Tanberry from comment #5)
> (In reply to Anthony Basile from comment #4)
> > Also, you can't just go changing -std= in build scripts.  The underlying
> > code might use c++11 standards in which case expect breakage if you force
> > c++93/03.
> 
> Hence my suggestion to strip all build systems ONLY of "-std=c++98" but
> never touch any build system setting "-std=c++11". In that case, C++98 code
> should compile anyway, given that its the default

It's not the default. The default is "-std=gnu++98". Setting "-std=c++98" disables the GNU C++ language extensions. Some code needs this on order to compile (for example identifiers are used that are GNU keywords.)
Comment 8 SpanKY gentoo-dev 2015-10-01 22:03:40 UTC
(In reply to Nikos Chantziaras from comment #7)

not entirely sure what version you're referring to, so i'll clarify:
  <gcc-5: default is gnu89/gnu++98  (checked back to 3.3)
  =gcc-5: default is gnu11/gnu++98
  >=gcc-6: default is gnu11/gnu++14 (obviously might change before next release)

you can verify yourself:
  $ gcc -E -dD -x c - </dev/null |& grep STDC_VERSION
  $ g++ -E -dD -x c++ - </dev/null |& grep cplusplus

(In reply to Ted Tanberry from comment #5)

you can't blindly change the standard used.  it has to be on a per-package basis so things can be built/tested to verify things continue to work.  certainly going from a gnu-standard to a non-gnu-standard would easily break things as is a non-starter on our side.

the other big case is "static inline": it changed semantics between <=gnu89 and >=gnu99; when using newer versions, you need to specify -fgnu89-inline or use the gnu_inline attribute.  glibc def broke here, but i've seen a few others.
Comment 9 Ted Tanberry 2015-10-10 15:53:15 UTC
My ideas is anyway moot, as GCC 5 implements the new ABI when compiling for -std=c++98 as well. Thus code with std::string and std::list crossing interfaces compiled under -std=c++98 and -std=c++11 can be linked.
Comment 10 Michał Górny archtester Gentoo Infrastructure gentoo-dev Security 2015-11-29 09:04:10 UTC
So how many incompatible ABIs do we need to be concerned with? If I understand correctly, that would be:

1. gcc-4.x with c++98,

2. gcc-4.x with c++11,

3. gcc-5.x,

4. libcxx...

With each of them possibly having ABI changes between minor versions. Not really sure what would be the best solution here -- maybe library USE flags combined with := dependency on a stdlib tracking virtual? Nah, that won't work correctly with gcc multi-slotting.

USE dependencies alone are going to be a pain since users would have to set them to match the gcc version in question, which means along with gcc-config switching.
Comment 11 Anthony Basile gentoo-dev 2015-11-29 10:54:23 UTC
(In reply to Michał Górny from comment #10)
> So how many incompatible ABIs do we need to be concerned with? If I
> understand correctly, that would be:
> 
> 1. gcc-4.x with c++98,
> 
> 2. gcc-4.x with c++11,
> 
> 3. gcc-5.x,
> 
> 4. libcxx...
> 
> With each of them possibly having ABI changes between minor versions. Not
> really sure what would be the best solution here -- maybe library USE flags
> combined with := dependency on a stdlib tracking virtual? Nah, that won't
> work correctly with gcc multi-slotting.
> 
> USE dependencies alone are going to be a pain since users would have to set
> them to match the gcc version in question, which means along with gcc-config
> switching.

1) if a particular package needs gnu++11 or c++11 then the correct -std= needs to be passed in the build system.

2) we record in vdb which libstdc++.so.6 was used when building and track mismatches that way.  since gcc doesn't bump soname, we have to record that information for them and use that information to trigger rebuilds the way we do for :=  Zac Medico has some nice provider/consumer code in portage that can be used for this.

3) if a user has more than one gcc installed and continuously switches between them, then he's on his own :(  alternatively we shuffle the order of library paths in /etc/ld.so.conf.d/05gcc-<tuple>.conf when gcc-config is invoked.
Comment 12 Michał Górny archtester Gentoo Infrastructure gentoo-dev Security 2015-11-29 11:06:24 UTC
(In reply to Anthony Basile from comment #11)
> (In reply to Michał Górny from comment #10)
> > So how many incompatible ABIs do we need to be concerned with? If I
> > understand correctly, that would be:
> > 
> > 1. gcc-4.x with c++98,
> > 
> > 2. gcc-4.x with c++11,
> > 
> > 3. gcc-5.x,
> > 
> > 4. libcxx...
> > 
> > With each of them possibly having ABI changes between minor versions. Not
> > really sure what would be the best solution here -- maybe library USE flags
> > combined with := dependency on a stdlib tracking virtual? Nah, that won't
> > work correctly with gcc multi-slotting.
> > 
> > USE dependencies alone are going to be a pain since users would have to set
> > them to match the gcc version in question, which means along with gcc-config
> > switching.
> 
> 1) if a particular package needs gnu++11 or c++11 then the correct -std=
> needs to be passed in the build system.

Yes. Plus some build system auto-append random CXXFLAGS, often unnecessarily. As a result, some packages that could work well with c++98 go for c++11 automatically because it's available. Then we either need to limit the choice to c++11 (since it will forced anyway), or hack the build system.

> 2) we record in vdb which libstdc++.so.6 was used when building and track
> mismatches that way.  since gcc doesn't bump soname, we have to record that
> information for them and use that information to trigger rebuilds the way we
> do for :=  Zac Medico has some nice provider/consumer code in portage that
> can be used for this.

How do you distinguish them? Special code is of no help since we need to operate within bounds of PMS.

I'm currently working on an eclass to make things a bit cleaner. It's not an easy task though.
Comment 13 Anthony Basile gentoo-dev 2015-11-29 11:33:05 UTC
(In reply to Michał Górny from comment #12)
> (In reply to Anthony Basile from comment #11)
 to c++11 (since it will forced anyway), or hack the build system.
> 
> > 2) we record in vdb which libstdc++.so.6 was used when building and track
> > mismatches that way.  since gcc doesn't bump soname, we have to record that
> > information for them and use that information to trigger rebuilds the way we
> > do for :=  Zac Medico has some nice provider/consumer code in portage that
> > can be used for this.
> 
> How do you distinguish them? Special code is of no help since we need to
> operate within bounds of PMS.
> 

by path.  on my arm system

/usr/lib/gcc/armv7a-hardfloat-linux-gnueabi/<gcc-version>/libstdc++.so.6

where <gcc-version> = 4.7.4 4.8.5 4.9.3 in my particular case.

what is your eclass supposed to do?  i don't see how we can get this right without recording information at build time.
Comment 14 Michał Górny archtester Gentoo Infrastructure gentoo-dev Security 2015-11-29 15:40:27 UTC
Do you think __GXX_ABI_VERSION could be used for this purpose? I see it set to 1002 in gcc-4.[89], 1008 in 5.1 and 1009 in 5.2.

USE flags to select specific stdlibc++ ABI. Bail out if ABI doesn't match gcc version. Painful but the only really working way other than magically guessing something needs to be magically rebuilt.
Comment 15 Anthony Basile gentoo-dev 2015-11-29 16:06:40 UTC
(In reply to Michał Górny from comment #14)
> Do you think __GXX_ABI_VERSION could be used for this purpose? I see it set
> to 1002 in gcc-4.[89], 1008 in 5.1 and 1009 in 5.2.

it can't because there was certainly an abi change between 4.7 and 4.8 yet both 4.[78] have 1002.

> 
> USE flags to select specific stdlibc++ ABI. Bail out if ABI doesn't match
> gcc version. Painful but the only really working way other than magically
> guessing something needs to be magically rebuilt.

yes painful.  i know pms etc, but really, if we recorded the C++ abi in NEEDED.ELF.2 or similar, we'd have a better handle on this.  there'd be no guessing.
Comment 16 Michał Górny archtester Gentoo Infrastructure gentoo-dev Security 2015-11-29 17:01:10 UTC
(In reply to Anthony Basile from comment #15)
> (In reply to Michał Górny from comment #14)
> > 
> > USE flags to select specific stdlibc++ ABI. Bail out if ABI doesn't match
> > gcc version. Painful but the only really working way other than magically
> > guessing something needs to be magically rebuilt.
> 
> yes painful.  i know pms etc, but really, if we recorded the C++ abi in
> NEEDED.ELF.2 or similar, we'd have a better handle on this.  there'd be no
> guessing.

How does that help switching between C++98 and C++11 in gcc < 5.0? You'd be just rebuilding the same package indefinitely with no result.
Comment 17 Anthony Basile gentoo-dev 2015-11-30 00:56:09 UTC
(In reply to Michał Górny from comment #16)
> (In reply to Anthony Basile from comment #15)
> > (In reply to Michał Górny from comment #14)
> > > 
> > > USE flags to select specific stdlibc++ ABI. Bail out if ABI doesn't match
> > > gcc version. Painful but the only really working way other than magically
> > > guessing something needs to be magically rebuilt.
> > 
> > yes painful.  i know pms etc, but really, if we recorded the C++ abi in
> > NEEDED.ELF.2 or similar, we'd have a better handle on this.  there'd be no
> > guessing.
> 
> How does that help switching between C++98 and C++11 in gcc < 5.0? You'd be
> just rebuilding the same package indefinitely with no result.

i think we're solving different problems.  the one i'm thinking of is the one in my blog post above.  if you're talking about switching between building a given package with -std=c++98 and -std=c++11 we shouldn't support that.  packages should be built with the compiler default unless upstream adds -std= to their build system.  there are syntactic differences that might make the switch impossible for a given package anyhow.
Comment 18 Pacho Ramos gentoo-dev 2015-12-01 11:32:18 UTC
(In reply to Anthony Basile from comment #15)
> (In reply to Michał Górny from comment #14)
> > Do you think __GXX_ABI_VERSION could be used for this purpose? I see it set
> > to 1002 in gcc-4.[89], 1008 in 5.1 and 1009 in 5.2.
> 
> it can't because there was certainly an abi change between 4.7 and 4.8 yet
> both 4.[78] have 1002.
> 

Would patching of gcc to support something like an additional __GXX_ABI_VERSION_GENTOO to allow us to bump it when needed and be used by that mgorny's eclass be too hard to do?
Comment 19 Anthony Basile gentoo-dev 2015-12-01 12:10:31 UTC
(In reply to Anthony Basile from comment #17)

> if you're talking about switching between
> building a given package with -std=c++98 and -std=c++11 we shouldn't support
> that.  packages should be built with the compiler default unless upstream
> adds -std= to their build system.  

I'm beginning to wonder if we can't just make a switch to c++11 in gcc-4.[7,8,9] globally.  But, I don't know how we'd migrate existing systems.

> there are syntactic differences that
> might make the switch impossible for a given package anyhow.

C++98 is a subset of C++11 so we should be able to switch c++98 -> c+11 to build an entire system, but not vice versa.


(In reply to Pacho Ramos from comment #18)
> (In reply to Anthony Basile from comment #15)
> 
> Would patching of gcc to support something like an additional
> __GXX_ABI_VERSION_GENTOO to allow us to bump it when needed and be used by
> that mgorny's eclass be too hard to do?

This is going to get ugly.
Comment 20 Ulenrich 2015-12-07 19:49:01 UTC
Just my 2cent observing Debian-sid(unstable) transition:
Debian added many libs with the old name added 'v5' 
eg:
libgpgme++2v5-4:4.14.10
having had the old name lib for a transitional period also:
libgpgme++2v5-VERSION

What is ugly about that: After transition it ends up 
with system having many LIBNAMEv5 without a meaning 
of the suffix 'v5'
Comment 21 Ulenrich 2015-12-07 19:51:30 UTC
error with my writing: 
Debian had for a transitional period both, for example:
libgpgme++2v5-4:4.14.10
libgpgme++2-4:4.14.10
Comment 22 Zac Medico gentoo-dev 2015-12-21 02:21:36 UTC
(In reply to Anthony Basile from comment #19)
> (In reply to Anthony Basile from comment #17)
> 
> > if you're talking about switching between
> > building a given package with -std=c++98 and -std=c++11 we shouldn't support
> > that.  packages should be built with the compiler default unless upstream
> > adds -std= to their build system.  
> 
> I'm beginning to wonder if we can't just make a switch to c++11 in
> gcc-4.[7,8,9] globally.  But, I don't know how we'd migrate existing systems.

We could do it as a profile version bump, like default/linux/amd64/16.0 or something. Create a migration guide, and deprecate the 13.0 profiles.
Comment 23 Manuel Nickschas 2016-01-08 11:39:13 UTC
(In reply to Anthony Basile from comment #19)

> I'm beginning to wonder if we can't just make a switch to c++11 in
> gcc-4.[7,8,9] globally.  But, I don't know how we'd migrate existing systems.
> 
> > there are syntactic differences that
> > might make the switch impossible for a given package anyhow.
> 
> C++98 is a subset of C++11 so we should be able to switch c++98 -> c+11 to
> build an entire system, but not vice versa.

Just chiming in here. C++98 is not a pure subset of C++11, and I'm rather sure that there will be a plethora of packages that would not survive a global switch to C++11. Heck, there's enough software that breaks with newer compilers without even switching the language standard...

Here's the main issues I see:

* New keywords and other syntactic features introduced in C++11 may clash with existing (valid) older code
* Some things in the STL changed signature and/or behavior between the language standards (most notably the introduction of explicit bool conversions in lieu of implicit conversions from void* causes issues, although programs relying on the old behavior are non-conforming even in C++03...)
* The C++11 standard is much stricter and defines many things that were previously undefined. Consequently, code that (irresponsibly) relied on GCC's implementation for "undefined behavior" will break. This is a similar issue to what plagued code when going to newer (stricter) compiler versions in the past, but will be much more wide-spread due to the amount of changes

Most dangerously, there are subtle changes in template handling, SFINAE, user-defined ctors/dtors, containers, exception handling, integer conversions, and other areas, where code written for C++03 may still compile with C++11, but silently change behavior.

TL;DR: Blindly changing standards without it being a conscious decision (by upstream) will likely lead to compile failures, or (worse) let the program compile, but alter/break its behavior. Don't do this.
Comment 24 Pacho Ramos gentoo-dev 2016-01-08 15:02:12 UTC
*** Bug 570604 has been marked as a duplicate of this bug. ***
Comment 25 David Seifert gentoo-dev 2016-09-13 09:05:30 UTC
(In reply to Manuel Nickschas from comment #23)
> Just chiming in here. C++98 is not a pure subset of C++11, and I'm rather
> sure that there will be a plethora of packages that would not survive a
> global switch to C++11. Heck, there's enough software that breaks with newer
> compilers without even switching the language standard...
> 
> Here's the main issues I see:
> 
> * New keywords and other syntactic features introduced in C++11 may clash
> with existing (valid) older code
> * Some things in the STL changed signature and/or behavior between the
> language standards (most notably the introduction of explicit bool
> conversions in lieu of implicit conversions from void* causes issues,
> although programs relying on the old behavior are non-conforming even in
> C++03...)
> * The C++11 standard is much stricter and defines many things that were
> previously undefined. Consequently, code that (irresponsibly) relied on
> GCC's implementation for "undefined behavior" will break. This is a similar
> issue to what plagued code when going to newer (stricter) compiler versions
> in the past, but will be much more wide-spread due to the amount of changes
> 
> Most dangerously, there are subtle changes in template handling, SFINAE,
> user-defined ctors/dtors, containers, exception handling, integer
> conversions, and other areas, where code written for C++03 may still compile
> with C++11, but silently change behavior.
> 
> TL;DR: Blindly changing standards without it being a conscious decision (by
> upstream) will likely lead to compile failures, or (worse) let the program
> compile, but alter/break its behavior. Don't do this.

Manuel, I generally agree with you. C++98 is not a proper subset of C++11. My feeling is that 90% of C++98 code should build fine using -std=c++11, another 5-8% will likely need explicit casts (due to the aforementioned iostream_* operator void*() conversion functions being replaced by explicit operator bool()), and maybe a hardcore 1% will break due to the changed semantics of some code.

Given that we don't have the luxury that binary distros have of compiling some packages against C++11 libs and then rpath hacking stuff on, what do you see as a possible solution? I've documented the best solution I think is suitable for Gentoo (https://wiki.gentoo.org/wiki/Project:C%2B%2B/Maintaining_ABI), which is just the libsigc++ solution (adding -std=c++11 to all boost revdeps in my case), this time just doing it in lockstep with the boost C++11 switch. When performing the switch, I'll collect fallout from failing packages and fix them on the way. Keep in mind that this isn't just a boost/libsigc++ issue: Qt 5.7 will have a hard requirement on C++11 as well.
Comment 26 Pacho Ramos gentoo-dev 2016-11-07 15:06:30 UTC
(In reply to David Seifert from comment #25)
[...]
> Given that we don't have the luxury that binary distros have of compiling
> some packages against C++11 libs and then rpath hacking stuff on, what do
> you see as a possible solution? I've documented the best solution I think is
> suitable for Gentoo
> (https://wiki.gentoo.org/wiki/Project:C%2B%2B/Maintaining_ABI), which is
> just the libsigc++ solution (adding -std=c++11 to all boost revdeps in my
> case), this time just doing it in lockstep with the boost C++11 switch. When
> performing the switch, I'll collect fallout from failing packages and fix
> them on the way. Keep in mind that this isn't just a boost/libsigc++ issue:
> Qt 5.7 will have a hard requirement on C++11 as well.

Maybe we should consider trying to stabilize a newer gcc (that defaults to new standards) in the "near" future as more and more packages will start to need C++11 or newer and, hence, it will be harder to maintain them working with our (old) stable gcc-4.9 version :/
Comment 27 David Seifert gentoo-dev 2016-12-20 13:40:57 UTC
(In reply to Pacho Ramos from comment #26)

I completely support that. GCC 5 already supports C++14 fully, so we should start stabilising that.

@blueness, can we slowly initiate GCC 5 stabilisation?
Comment 28 Anthony Basile gentoo-dev 2016-12-20 17:34:10 UTC
(In reply to David Seifert from comment #27)
> (In reply to Pacho Ramos from comment #26)
> 
> I completely support that. GCC 5 already supports C++14 fully, so we should
> start stabilising that.
> 
> @blueness, can we slowly initiate GCC 5 stabilisation?

yeah let's start putting pressure on people fix their stuff.  there's a few remaining bugs, but nothing too critical.  a few even have fixes ready and just need to be applied.  go ahead and start a gcc-5.4.0 stabilization bug.
Comment 29 Andreas K. Hüttel gentoo-dev 2017-12-09 21:56:41 UTC
(In reply to David Seifert from comment #27)
> (In reply to Pacho Ramos from comment #26)
> 
> I completely support that. GCC 5 already supports C++14 fully, so we should
> start stabilising that.
> 
> @blueness, can we slowly initiate GCC 5 stabilisation?

It's been stable for a while now, so this is obsolete.