Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
Bug 587012 - dev-libs/boost-1.61: Add ability to control c++11 building.
Summary: dev-libs/boost-1.61: Add ability to control c++11 building.
Status: RESOLVED FIXED
Alias: None
Product: Gentoo Linux
Classification: Unclassified
Component: Current packages (show other bugs)
Hardware: All Linux
: Normal normal (vote)
Assignee: C++ Team [disbanded]
URL:
Whiteboard:
Keywords: PATCH
Depends on:
Blocks: 582696
  Show dependency tree
 
Reported: 2016-06-25 07:52 UTC by Jonathan Scruggs (RETIRED)
Modified: 2016-10-26 12:13 UTC (History)
4 users (show)

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


Attachments
Diff for boost-1.61-r1 against boost-1.61 ebuild. (boost-1.61.diff,1.22 KB, patch)
2016-06-25 07:52 UTC, Jonathan Scruggs (RETIRED)
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Jonathan Scruggs (RETIRED) gentoo-dev 2016-06-25 07:52:58 UTC
Created attachment 438700 [details, diff]
Diff for boost-1.61-r1 against boost-1.61 ebuild.

Hi,

I don't know if this in the pipeline or how close to being released it is as I've seen no reports here after searching.

Boost 1.61 was made completely c++11 compatible. However, the current ebuilds explicitly enable c++98 standards no matter the compiler. GCC 5.x enables c++11 explicitly unless told not to. This breaks some packages as some will be compiled with c++11 standards, because they may have a compile setting to disable c++11 and there's no use flag for it, or the configure script does automagic to determine the compiler and sets c++11, or there is no mechanism and GCC just uses it.

Boost 1.60 has this in file: boost_1_60_0/boost/pool/detail/mutex.hpp
#if !defined(BOOST_HAS_THREADS) || defined(BOOST_NO_MT) || defined(BOOST_POOL_NO_MT)
typedef null_mutex default_mutex;
#else
typedef boost::mutex default_mutex;
#endif

However, Boost 1.61 has this in the same file: boost_1_61_0/boost/pool/detail/mutex.hpp
#if !defined(BOOST_HAS_THREADS) || defined(BOOST_NO_MT) || defined(BOOST_POOL_NO_MT)
typedef null_mutex default_mutex;
#else
#if defined (BOOST_NO_CXX11_HDR_MUTEX)
typedef boost::mutex default_mutex;
#else
typedef std::mutex default_mutex;
#endif
#endif

The functions of Boost call default_mutex. If Boost is compiled with C++98, it's internals are one thing, but when a program includes one of boosts .hpp files and is compiled with c++11, it will fail because it's trying to use std::mutex, which exists in '11 but not '98. This is what causes build failures such as the one in this bug report: https://bugs.gentoo.org/show_bug.cgi?id=582696
If doesn't look like a mutex error until you dig really deep into the issue.

There is a way around it:
Usually there is a single header file in a program that all the other files include, so this line can be added to that header file:
#define BOOST_NO_CXX11_HDR_MUTEX 1
Which forces the use of boost::mutex instead of std::mutex. It's cheap and dirty trick and all programs would need that until Boost is compiled with '11 standards.

I have tried this with several programs. Boost with '11 standards is able to compile other programs that fail otherwise. I have debated whether to have gcc detected and use c++11 by default or a use flag or both. I decided to include a patch with a use flag version. It's the simple way and allows users to explicitly disable. Also, it allows packages to depend on it: dev-libs/boost[c++11=]. Must be'=' as if boost is not compiled with '11 then the package depending on it cannot be compiled with '11.

I hope I fully explained my investigations on this issue. If not, let me know. :)
Comment 1 David Seifert gentoo-dev 2016-06-26 09:19:27 UTC
We're at a crossroads here. While I understand the desire to move to C++11 (of which I am a great fan), switching to C++11 in boost will cause a massive cascade of possible failures, and will most definitely require a rebuild of a myriad of packages. In addition, it will likely make all older GCC versions useless in Gentoo, as C++11 before GCC 5.1 does not have a stable ABI, and compiling with GCC below 5.1 against a libstdc++ from GCC 5.1 and above causes cataclysmic failure.

We have to discuss this in a wider context with the toolchain team. Switching to C++11 in boost will open the floodgates, and there will be no turning back. You will not be able to use Clang anymore, as it currently doesn't understand the GCC 5 dual-ABI thing.

In slightly different news, from where do you take it that "GCC 5.x enables c++11 explicitly unless told not to"? GCC 5 only switched the ABI of some STL types (std::string and std::list) but did not change the standard -std=gnu++98 setting (that only happened in GCC 6, which is not in the tree as of yet).
Comment 2 Jonathan Scruggs (RETIRED) gentoo-dev 2016-06-27 07:55:04 UTC
(In reply to David Seifert from comment #1)
> We're at a crossroads here. While I understand the desire to move to C++11
> (of which I am a great fan), switching to C++11 in boost will cause a
> massive cascade of possible failures, and will most definitely require a
> rebuild of a myriad of packages. In addition, it will likely make all older
> GCC versions useless in Gentoo, as C++11 before GCC 5.1 does not have a
> stable ABI, and compiling with GCC below 5.1 against a libstdc++ from GCC
> 5.1 and above causes cataclysmic failure.
> 
> We have to discuss this in a wider context with the toolchain team.
> Switching to C++11 in boost will open the floodgates, and there will be no
> turning back. You will not be able to use Clang anymore, as it currently
> doesn't understand the GCC 5 dual-ABI thing.

This is why I was mentioning in the first that I was debating posting an ebuild with GCC detection or a use flag. I understand that there is no easy way to do this. And maybe you will agree with me that Boost 1.61 can't be made stable until this is fully implemented, as in the first post, it has code it in now that _causes_ build failures when Boost is compiled with '98 and a program using Boost is trying to compile with '11 or '14 standards.

In this instance, there is the one hack that I mentioned, but there are several other instances that can cause build failures, but fortunately there are similar macros that can be used.

The original suggestion I was thinking about is something like this:
if $(gcc-version) < 5.1; then
    Steps to enable c++98
else
    Steps to enable c++11 and not '14 as it breaks things.
fi

System wide rule for this as see below. Because as I mentioned before, a lot of newer versions of programs are enabling '11 by default of GCC 5 is detected, and some don't detect GCC version and just hard enable it. This is why it's really important. The above test logic can be made compatible with Clang, as some programs that offer to enable '11 standards, will also be clang friendly with it when they have the build option to select Clang. A lot of programs I have been working with have a USE_CPP11 build option and some a USE_LLVM with logic to be compatible. It's the programs that 

> In slightly different news, from where do you take it that "GCC 5.x enables
> c++11 explicitly unless told not to"? GCC 5 only switched the ABI of some
> STL types (std::string and std::list) but did not change the standard
> -std=gnu++98 setting (that only happened in GCC 6, which is not in the tree
> as of yet).

I may have read this wrong: https://gcc.gnu.org/gcc-5/changes.html
But I took the first line to mean that they want and enable '11 by default. If that is a wrong interpretation, I stand corrected and eat my words. :) I learn something new.

Personal experience:
If it helps in discussions, I have Boost compiled as '11, so ask me anything about that including packages. The toolchain team can ask me anything as well, you can point them to this report and I will answer. I will compile anything you have a question on and report it. Also, I actually didn't need to recompile many programs. In fact, most just still worked completely. I only needed to do two and I have a ton of Boost enabled packages installed. I have that use flag set system wide. Some of those programs use Clang to compile and they link against it just fine. It's actually not as disastrous as it may seem at first. I've done several reboots as well.

I had to delve deeply into this issue to find out why something wasn't compiling, and even talked with upstream to get ideas.

Cheers.
Comment 3 David Seifert gentoo-dev 2016-06-27 08:07:20 UTC
The GCC version detection business is way too wobbly. Here's the preliminary plan as discussed on IRC:

1) Move from building with C++98 to C++11 in boost
2) Depend on GCC 5 set during boost. This keeps the whole ABI breakage to a minimum, as it avoids double breakage with the libstdc++ ABI breakage
3) At the same time, revbump ALL reverse dependencies of boost in lockstep. Additionally, depend only on the boost version enabling C++11.
4) Also add "append-cxxflags -std=c++11" in all revdeps.

The main issue here is that going to C++11 (which will be unavoidable) requires a lockstep upgrade, as all consumers of boost have to use the same C++ standard for compiling, as boost does a ton of macro magic behind the scenes, changing the ABI etc.

This atomic lockstep addition to the tree will be a nightmare, and I don't have a lot of time right now for doing the changes. If you're up for it, fork the repo on Github and implement the changes for the latest version of ALL revdeps (yes, they go well into the hundreds).

@toolchain I'd like to get your view on this too. Do you agree with this plan? I understand that it is open-heart surgery, but we're pretty much in the same situation here as with the libsigc++ breakage. We need to move the whole boost ecosystem to C++11 (which will make old GCC versions below 5.1 pretty much useless).
Comment 4 Anthony Basile gentoo-dev 2016-06-27 20:44:59 UTC
(In reply to David Seifert from comment #3)
> 
> @toolchain I'd like to get your view on this too. Do you agree with this
> plan? I understand that it is open-heart surgery, but we're pretty much in
> the same situation here as with the libsigc++ breakage. We need to move the
> whole boost ecosystem to C++11 (which will make old GCC versions below 5.1
> pretty much useless).

this seems like a sane path forward.  as long as everything is done lock in step so that you're either on c++98 or c++11 and not mixing abis, you'll be okay.
Comment 5 Jonathan Scruggs (RETIRED) gentoo-dev 2016-06-27 21:06:40 UTC
The main reason I was suggesting some kind of control mechanism to choose one about or the other is because a lot of packages that depend on Boost also use CUDA. The strange thing is that CUDA only works with GCC versions less than 5.0, so all the CUDA users would be stuck on older versions of Boost, so 1.60. Which would mean maintaining that version until nVidia makes CUDA work with new versions of GCC.

That's why, and I have no idea how, have GCC 5.1+ compile in '11 ABI and less than compile in '98. The only way I can think of doing that would be to have gcc-config initiate a recompile of the whole system in the correct ABI if switching from less than 5.1 to greater than or visa versa with a message saying this needs to be done to have an ABI correct system. Then detection of GCC version would work fine. This would keep GCC 4.x relevant with new packages. I use gcc-config as an example because that's how you switch compilers. It would mean a user could only choose one major branch of GCC, but to be fair, it makes for a stable system.

Is that a possibility?
Comment 6 David Seifert gentoo-dev 2016-06-27 21:55:28 UTC
I'm still generally opposed to adding a USE=cxx11 flag, as it only has an extremely specialized use case and will just lead to more obscure errors. If this is so important to you, why not maintain an ebuild with the little patch you proposed in a local overlay?

On GCC 4.9 being supported, I've spoken to toolchain. I understand the CUDA/nvcc predicament and am willing to support GCC 4.9 for a C++11-enabled boost. Do understand that you will be treading on thin ice, as an eventual upgrade to the GCC-5+ stable C++11 ABI will cause a MASSIVE fallout. Are you willing to accept these risks?
Comment 7 Ryan Hill (RETIRED) gentoo-dev 2016-06-29 01:16:11 UTC
There's really not much difference between 4.9 C++11 and 5.0 C++11.  Just don't mix em.
Comment 8 Sven Eden 2016-08-16 10:39:48 UTC
This patch saved my life!

I was constantly banging my head against the wall for a few days now, because libixion e.g.) could not be merged, failing with errors like:

undefined reference to `boost::program_options::arg[abi:cxx11]`

At least I now know what this means... ;-)

Locally I have adopted the USE flag strategy and am testing.

But there is one thing, I do not understand:

(In reply to Jon from comment #0)
GCC 5.x
> enables c++11 explicitly unless told not to. This breaks some packages as
> some will be compiled with c++11 standards, because they may have a compile
> setting to disable c++11 and there's no use flag for it, or the configure
> script does automagic to determine the compiler and sets c++11, or there is
> no mechanism and GCC just uses it.

Actually https://gcc.gnu.org/onlinedocs/gcc-5.4.0/gcc/Standards.html#Standards says:

1) C
"The default, if no C language dialect options are given, is -std=gnu11:"

2) C++
"The default, if no C++ language dialect options are given, is -std=gnu++98."

AFAIR it is gcc-7+ which default to gnu++14.

----------

However, a USE flag, that is disabled by default, could help updating package dependencies like in libixion to something like boost[c++11].
Comment 9 David Seifert gentoo-dev 2016-08-16 11:37:05 UTC
(In reply to Sven Eden from comment #8)

As I have said earlier, we will move the Boost-dependent ecosystem to C++11 with the next release (1.62) of Boost. Providing a C++11 USE flag is imo too problematic, as it will lead to further obscure problems (what about packages building against C++98 explicitly and then linking to ones built against C++11?)

Also, GCC-6 switch to C++14 by default, not 7.
Comment 10 Sven Eden 2016-08-16 12:07:06 UTC
(In reply to David Seifert from comment #9)
> (In reply to Sven Eden from comment #8)
> 
> As I have said earlier, we will move the Boost-dependent ecosystem to C++11
> with the next release (1.62) of Boost. Providing a C++11 USE flag is imo too
> problematic, (...)

I did not say the a USE flag might be a good idea. I am just testing with it. ;-)

And I do it, because I need a specific library now which can not be built otherwise in the version I want.

> as it will lead to further obscure problems (what about
> packages building against C++98 explicitly and then linking to ones built
> against C++11?)

You might run into problems if you tried to link C++98 objects with C++11 objects. Yes. For that, the library must expose functions in its headers which take or return references to objects in the standard library.
And even then only a very limited number of parts in the standard library is subject to this potential breakage.

That's easy.

Not so easy are function and object templates which deal with libstdc++ object references in their template bodies, that will the be compiled by the customer of the library. And Boost is ... well... Boost.

So while the libraries internals have been compiled with -std=gnu++98, libixion compiles some external parts (the templated stuff) with -std=gnu++11, which then does no longer fit the libraries internals.

Actually I consider both boost, that allows to let this happen, and libixion, which is not careful about what it uses where and how, to be badly broken at this point.

(And pages like https://gcc.gnu.org/wiki/Cxx11AbiCompatibility aren't up since yesterday...)

( ( and it is a completely different matter. ) )

> Also, GCC-6 switch to C++14 by default, not 7.
Really? Wow! I haven't looked up GCC-6. I looked into the documentation of the most current in-tree version 5.4. ;-)
Comment 11 Jonathan Scruggs (RETIRED) gentoo-dev 2016-08-16 12:26:03 UTC
@Sven Eden, I initially proposed the Use Flag idea to try to accommodate everything, but after reading all the comments here, I am in line with just making everything c++11. It just makes more sense. Since nothing really needs gcc4.8.x, it should work fine. I have been using boost1.61 compiled with c++11 for awhile now and had zero issues.

@others, would modifying the base eclass (the one that's included with all ebuilds) to append c++11 to the compiler flags be good, so there is no mixed Ability at all, especially since gcc6 will default to '14? This would stop compiling in that ability?
Comment 12 David Seifert gentoo-dev 2016-10-01 17:03:36 UTC
(In reply to Jon from comment #11)
> @Sven Eden, I initially proposed the Use Flag idea to try to accommodate
> everything, but after reading all the comments here, I am in line with just
> making everything c++11. It just makes more sense. Since nothing really
> needs gcc4.8.x, it should work fine. I have been using boost1.61 compiled
> with c++11 for awhile now and had zero issues.
> 
> @others, would modifying the base eclass (the one that's included with all
> ebuilds) to append c++11 to the compiler flags be good, so there is no mixed
> Ability at all, especially since gcc6 will default to '14? This would stop
> compiling in that ability?

The base.eclass is deprecated and awful and has in large been replaced with features introduced by EAPI=6. Also, globally adding -std=c++{11,14} to CXXFLAGS is a disaster waiting to happen. This will require careful editing of a number of ebuilds to manually append -std=c++14 (which we have settled for now in accordance with toolchain and QA). I have added the 1.62 version, which is now built using -std=c++14. Give it a try and report back! You will have to KEYWORD dev-util/boost-build and dev-libs/boost.

commit 1367893b54c8ee3de72561e853c9f0f70089bd40
Author: David Seifert <soap@gentoo.org>
Date:   Sat Oct 1 15:54:42 2016 +0200

    dev-libs/boost: Version bump to 1.62.0
    
    * Various QA cleanups
    * Switch to building in ISO C++14 mode (-std=c++14)
Comment 13 David Seifert gentoo-dev 2016-10-08 18:50:25 UTC
I'm closing this, now that boost-1.62 is build using -std=c++14.
Comment 14 Sven Eden 2016-10-26 12:13:27 UTC
David, sorry for the late reply!

I have tested boost-1.62 on an x64 laptop and an ARM32 Raspberry PI 3, both compiling with gcc-5.4.0, and everything works like a charm!

Thank you very much!