Yocto development with C++11 threads and gcc
The program below built on the target with the MACHINE=beaglebone gcc-4.9.1 compiler from Yocto/OpenEmbedded poky master produces this error:
beaglebone[52]$ g++ -std=c++1y -pthread test.cc && ./a.out starting
joining
pure virtual method called
terminate called without an active exception Aborted (core dumped)
When the program is recompiled with the defines for __GCC_HAVE_SYNC_COMPARE_AND_SWAP_X enabled as suggested at https://groups.google.com/d/msg/automatak-dnp3/Jisp_zGhd5I/ck_Cj6nO8joJ it works:
beaglebone[53]$ g++ -std=c++1y -pthread test.cc && ./a.out starting
joining
doit
done
Preliminary analysis confirms that the built-ins for those defines are not being added by the compiler because it thinks the target doesn't support those operations. Nonetheless, it doesn't use the substitutes that are obviously available.
Can anybody recall anything about the way GCC is built under OE that would explain this?
Peter
/* g++ -std=c++1y -pthread test.cc && ./a.out */
#if 0
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
#define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
#endif
#include <iostream>
#include <thread>
void
doit ()
{
std::cerr << "doit\n";
}
int main (int argc,
char * argv [])
{
std::cerr << "starting\n";
std::thread thr{doit};
std::cerr << "joining\n";
thr.join();
std::cerr << "done\n";
return 0;
}
Quoted 17 lines · Peter A. Bigot
The program below built on the target with the MACHINE=beaglebone gcc-4.9.1 compiler from Yocto/OpenEmbedded poky master produces this error:
beaglebone[52]$ g++ -std=c++1y -pthread test.cc && ./a.out starting
joining
pure virtual method called
terminate called without an active exception Aborted (core dumped)When the program is recompiled with the defines for
__GCC_HAVE_SYNC_COMPARE_AND_SWAP_Xenabled as suggested at https://groups.google.com/d/msg/automatak-dnp3/Jisp_zGhd5I/ck_Cj6nO8joJ it works:beaglebone[53]$ g++ -std=c++1y -pthread test.cc && ./a.out starting
joining
doit
done
Quoted 3 lines
Preliminary analysis confirms that the built-ins for those defines are not being added by the compiler because it thinks the target doesn't support those operations. Nonetheless, it doesn't use the substitutes that are obviously available.
Can anybody recall anything about the way GCC is built under OE that would explain this?
Not an OE problem. See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=62100
I'm testing a patch locally and awaiting GCC maintainer comment before proposing it for OE.
Peter
Quoted 31 lines
Peter
/* g++ -std=c++1y -pthread test.cc && ./a.out */
#if 0
#define__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
#define__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
#define__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
#define__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
#endif#include <iostream>
#include <thread>void
doit ()
{
std::cerr<< "doit\n";
}int main (int argc,
char * argv []){
std::cerr<< "starting\n";
std::threadthr{doit};
std::cerr<< "joining\n";
thr.join();
std::cerr<< "done\n";
return 0;
}
Quoted 18 lines · Peter A. Bigot
Quoted 17 lines · Peter A. Bigot
The program below built on the target with the MACHINE=beaglebone gcc-4.9.1 compiler from Yocto/OpenEmbedded poky master produces this error:
beaglebone[52]$ g++ -std=c++1y -pthread test.cc && ./a.out starting
joining
pure virtual method called
terminate called without an active exception Aborted (core dumped)When the program is recompiled with the defines for
__GCC_HAVE_SYNC_COMPARE_AND_SWAP_Xenabled as suggested at https://groups.google.com/d/msg/automatak-dnp3/Jisp_zGhd5I/ck_Cj6nO8joJ it works:beaglebone[53]$ g++ -std=c++1y -pthread test.cc && ./a.out starting
joining
doit
done
Quoted 7 lines
Quoted 3 lines
Preliminary analysis confirms that the built-ins for those defines are not being added by the compiler because it thinks the target doesn't support those operations. Nonetheless, it doesn't use the substitutes that are obviously available.
Can anybody recall anything about the way GCC is built under OE that would explain this?
Not an OE problem. See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=62100
I'm testing a patch locally and awaiting GCC maintainer comment before proposing it for OE.
The GNU folks objected to the workaround and suggested that the behavior is evidence that libstdc++ was not built with the same ABI flags as the compiler uses by default.
I built the release version of gcc 4.9.1 on the beaglebone and confirmed that it works fine.
This is indeed an OE-Core bug.
I've just sent a series of cleanup patches to gcc that may make it easier to detect differences. I've spent some time changing the "obvious" things and have been unable to figure out where the compilation is going wrong. I'm hoping somebody else can help out; as C++11 becomes more prevalent the workaround recommended on stackoverflow and other sites will continue to propagate, and it's not the right solution.
Peter
Quoted 21 lines · Peter A. Bigot
The program below built on the target with the MACHINE=beaglebone gcc-4.9.1 compiler from Yocto/OpenEmbedded poky master produces this error:
beaglebone[52]$ g++ -std=c++1y -pthread test.cc && ./a.out starting
joining
pure virtual method called
terminate called without an active exception Aborted (core dumped)When the program is recompiled with the defines for
__GCC_HAVE_SYNC_COMPARE_AND_SWAP_Xenabled as suggested at
https://groups.google.com/d/msg/automatak-dnp3/Jisp_zGhd5I/ck_Cj6nO8joJ it works:beaglebone[53]$ g++ -std=c++1y -pthread test.cc && ./a.out starting
joining
doit
done
Quoted 7 lines
Preliminary analysis confirms that the built-ins for those defines are not being added by the compiler because it thinks the target doesn't support those operations. Nonetheless, it doesn't use the substitutes that are obviously available.
Can anybody recall anything about the way GCC is built under OE that would explain this?
Can you add -mcpu=cortex-a8 to your cmdline and see if it solves the problem ?
Quoted 36 lines
Peter
/* g++ -std=c++1y -pthread test.cc && ./a.out */
#if 0
#define__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
#define__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
#define__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
#define__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
#endif#include <iostream>
#include <thread>void
doit ()
{
std::cerr<< "doit\n";
}int main (int argc,
char * argv []){
std::cerr<< "starting\n";
std::threadthr{doit};
std::cerr<< "joining\n";
thr.join();
std::cerr<< "done\n";
return 0;
}--
_______________________________________________
Openembedded-core mailing list
[email protected]
http://lists.openembedded.org/mailman/listinfo/openembedded-core
Quoted 22 lines · Khem Raj
Quoted 21 lines · Peter A. Bigot
The program below built on the target with the MACHINE=beaglebone gcc-4.9.1 compiler from Yocto/OpenEmbedded poky master produces this error:
beaglebone[52]$ g++ -std=c++1y -pthread test.cc && ./a.out starting
joining
pure virtual method called
terminate called without an active exception Aborted (core dumped)When the program is recompiled with the defines for
__GCC_HAVE_SYNC_COMPARE_AND_SWAP_Xenabled as suggested at
https://groups.google.com/d/msg/automatak-dnp3/Jisp_zGhd5I/ck_Cj6nO8joJ it works:beaglebone[53]$ g++ -std=c++1y -pthread test.cc && ./a.out starting
joining
doit
done
Quoted 8 lines
Quoted 7 lines
Preliminary analysis confirms that the built-ins for those defines are not being added by the compiler because it thinks the target doesn't support those operations. Nonetheless, it doesn't use the substitutes that are obviously available.
Can anybody recall anything about the way GCC is built under OE that would explain this?
Can you add -mcpu=cortex-a8 to your cmdline and see if it solves the problem ?
Yes, it does. That's a good clue.
Peter
Quoted 35 lines
Quoted 35 lines
Peter
/* g++ -std=c++1y -pthread test.cc && ./a.out */
#if 0
#define__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
#define__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
#define__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
#define__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
#endif#include <iostream>
#include <thread>void
doit (){ std::cerr << "doit\n"; }int main (int argc,
char * argv []) { std::cerr << "starting\n"; std::thread thr{doit}; std::cerr << "joining\n"; thr.join(); std::cerr << "done\n"; return 0; }--
_______________________________________________
Openembedded-core mailing list
[email protected]
http://lists.openembedded.org/mailman/listinfo/openembedded-core
Quoted 28 lines · Peter A. Bigot
Quoted 27 lines · Khem Raj
Quoted 26 lines · Peter A. Bigot
The program below built on the target with the MACHINE=beaglebone gcc-4.9.1 compiler from Yocto/OpenEmbedded poky master produces this error:
beaglebone[52]$ g++ -std=c++1y -pthread test.cc && ./a.out starting
joining
pure virtual method called
terminate called without an active exception Aborted (core dumped)When the program is recompiled with the defines for
__GCC_HAVE_SYNC_COMPARE_AND_SWAP_Xenabled as suggested at
https://groups.google.com/d/msg/automatak-dnp3/Jisp_zGhd5I/ck_Cj6nO8joJ it works:beaglebone[53]$ g++ -std=c++1y -pthread test.cc && ./a.out starting
joining
doit
donePreliminary analysis confirms that the built-ins for those defines are not being added by the compiler because it thinks the target doesn't support those operations. Nonetheless, it doesn't use the substitutes that are obviously available.
Quoted 5 lines
Quoted 3 lines
Quoted 2 lines
Can anybody recall anything about the way GCC is built under OE that would explain this?
Can you add -mcpu=cortex-a8 to your cmdline and see if it solves the problem ?
Yes, it does. That's a good clue.
More specifically, the build logs say gcc-runtime was built with:
arm-poky-linux-gnueabi-gcc -march=armv7-a -mthumb-interwork -mfloat-abi=hard -mfpu=neon -mtune=cortex-a8
and using those flags instead of -mcpu=cortex-a8 also solves the problem.
So either gcc-runtime needs to stop using those flags, or gcc itself needs to default to them. Or some other solution.
In any case, Khem can you run with this? It'd be fixed a lot better that way....
Peter
Quoted 39 lines
Peter
Quoted 35 lines
Quoted 35 lines
Peter
/* g++ -std=c++1y -pthread test.cc && ./a.out */
#if 0
#define__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
#define__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
#define__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
#define__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
#endif#include <iostream>
#include <thread>void
doit (){ std::cerr << "doit\n"; }int main (int argc,
char * argv []) { std::cerr << "starting\n"; std::thread thr{doit}; std::cerr << "joining\n"; thr.join(); std::cerr << "done\n"; return 0; }Signature · 4 lines
_______________________________________________ Openembedded-core mailing list [email protected] http://lists.openembedded.org/mailman/listinfo/openembedded-core
Quoted 2 lines · Peter A. Bigot
In any case, Khem can you run with this? It'd be fixed a lot better that way....
We do not configure target gcc with right matching cpu defaults, atomic instruction strex/ldrex are only added after armv6 but defaults for gcc if not specified is armv5t and hence it does not use the right set as expected by libstdc++ which has been cross compiled. so while you are at it and can reproduce it. Try to add
EXTRA_OECONF += '${@bb.utils.contains("TUNE_FEATURES", "armv7a", " --with-cpu=armv7-a", "", d)}'
to gcc-target.inc and see if resulting gcc is any better
Quoted 9 lines · Khem Raj
Quoted 2 lines · Peter A. Bigot
In any case, Khem can you run with this? It'd be fixed a lot better that way....
We do not configure target gcc with right matching cpu defaults, atomic instruction strex/ldrex are only added after armv6 but defaults for gcc if not specified is armv5t and hence it does not use the right set as expected by libstdc++ which has been cross compiled. so while you are at it and can reproduce it. Try to add
Quoted 4 lines
EXTRA_OECONF+= '${@bb.utils.contains("TUNE_FEATURES", "armv7a", " --with-cpu=armv7-a", "", d)}'to gcc-target.inc and see if resulting gcc is any better
I had to make it:
EXTRA_OECONF += '${@bb.utils.contains("TUNE_FEATURES", "armv7a", "--with-cpu=generic-armv7-a", "", d)}'
to get gcc to build but at runtime I then get:
beaglebone[16]$ g++ -std=c++11 -pthread test.cc && ./a.out Assembler messages:
Error: unknown cpu `generic-armv7-a'
Error: unrecognized option -mcpu=generic-armv7-a
which indicates the flag's being passed to the assembler which doesn't recognize it even though g++ is happy with it. I suppose we could hack binutils to substitute whatever spelling it wants to see.
(Also tried --with-cpu=arm7, but that generates assembler errors related to unsupported RM mode "bx lr").
The approach bothers me, though. Instead of explicitly changing gcc-target to match gcc-runtime, shouldn't it be a general rule that gcc-runtime not apply OE-specific target flags that aren't going to be used by direct invocations of the compiler outside of the OE build environment? That seems a little more robust, as the default target flags may be changed upstream or by bbappends within OE, and having to make them match in gcc-runtime as well would be a headache.
And would we need similar overrides for other architectures? There's something similar already in gcc-configure-common.inc for mips64.
Peter
Quoted 16 lines · Peter A. Bigot
Quoted 14 lines · Khem Raj
Quoted 3 lines · Peter A. Bigot
In any case, Khem can you run with this? It'd be fixed a lot better that way....
We do not configure target gcc with right matching cpu defaults, atomic instruction strex/ldrex are only added after armv6 but defaults for gcc if not specified is armv5t and hence it does not use the right set as expected by libstdc++ which has been cross compiled. so while you are at it and can reproduce it. Try to add
EXTRA_OECONF+= '${@bb.utils.contains("TUNE_FEATURES", "armv7a", " --with-cpu=armv7-a", "", d)}'
Quoted 9 lines
Quoted 2 lines
to gcc-target.inc and see if resulting gcc is any better
I had to make it:
EXTRA_OECONF+= '${@bb.utils.contains("TUNE_FEATURES", "armv7a", "--with-cpu=generic-armv7-a", "", d)}'
Sorry a typo there you need --with-arch
to get gcc to build but at runtime I then get:
Quoted 26 lines
beaglebone[16]$ g++ -std=c++11 -pthread test.cc && ./a.out Assembler messages:
Error: unknown cpu `generic-armv7-a'
Error: unrecognized option -mcpu=generic-armv7-awhich indicates the flag's being passed to the assembler which doesn't recognize it even though g++ is happy with it. I suppose we could hack binutils to substitute whatever spelling it wants to see.
(Also tried --with-cpu=arm7, but that generates assembler errors related to unsupported RM mode "bx lr").
The approach bothers me, though. Instead of explicitly changing gcc-target to match gcc-runtime, shouldn't it be a general rule that gcc-runtime not apply OE-specific target flags that aren't going to be used by direct invocations of the compiler outside of the OE build environment?
That seems a little more robust, as the default target flags may be
changed upstream or by bbappends within OE, and having to make them match in gcc-runtime as well would be a headache.And would we need similar overrides for other architectures? There's something similar already in gcc-configure-common.inc for mips64.
Peter
Quoted 28 lines · Khem Raj
On Wednesday, August 13, 2014, Peter A. Bigot <[email protected] <mailto:[email protected]>> wrote:
On 08/13/2014 05:05 PM, Khem Raj wrote:
On Wed, Aug 13, 2014 at 2:36 PM, Peter A. Bigot <[email protected]> wrote:
In any case, Khem can you run with this? It'd be fixed a lot better that
way....We do not configure target gcc with right matching cpu defaults, atomic instruction strex/ldrex are only added after armv6 but defaults
for gcc if not specified is armv5t and hence it does not use the right
set as expected by libstdc++ which has been cross compiled. so while
you are at it and can reproduce it. Try to add
EXTRA_OECONF+= '${@bb.utils.contains("TUNE_FEATURES", "armv7a", " --with-cpu=armv7-a", "", d)}'to gcc-target.inc and see if resulting gcc is any better
Quoted 7 lines
I had to make it:
EXTRA_OECONF+= '${@bb.utils.contains("TUNE_FEATURES", "armv7a", "--with-cpu=generic-armv7-a", "", d)}'Sorry a typo there you need --with-arch
OK, that works. So do we need to do the same thing for every TUNE_FEATURES element that ends up changing the value of -march= in TUNE_CCARGS which ends up getting passed into gcc-runtime?
If so would it be better to add a TUNE_ARCH setting to all the tune-foo.inc files and use that in both TUNE_CCARGS and the --with-arch= flag passed to gcc? Just to avoid having this stuff hidden inside gcc-target.inc where it's pretty obscure.
Quoted 17 lines
to get gcc to build but at runtime I then get:
beaglebone[16]$ g++ -std=c++11 -pthread test.cc && ./a.out Assembler messages:
Error: unknown cpu `generic-armv7-a'
Error: unrecognized option -mcpu=generic-armv7-awhich indicates the flag's being passed to the assembler which doesn't recognize it even though g++ is happy with it. I suppose we could hack binutils to substitute whatever spelling it wants to see.
(Also tried --with-cpu=arm7, but that generates assembler errors related to unsupported RM mode "bx lr").
Quoted 9 lines
The approach bothers me, though. Instead of explicitly changing gcc-target to match gcc-runtime, shouldn't it be a general rule that gcc-runtime not apply OE-specific target flags that aren't going to be used by direct invocations of the compiler outside of the OE build environment? That seems a little more robust, as the default target flags may be changed upstream or by bbappends within OE, and having to make them match in gcc-runtime as well would be a headache.
Just to record one reason why this isn't trivial: although it's possible to strip ${TARGET_CC_ARCH} from ${CXX}, doing so removes -mfloat-abi=hard which makes gcc-runtime try to build a library that supports soft float, and the compiler didn't generate the necessary gnu/stubs-soft.h header for that.
Quoted 7 lines
And would we need similar overrides for other architectures? There's something similar already in gcc-configure-common.inc for mips64.
Peter
Quoted 10 lines · Peter A. Bigot
Quoted 3 lines
EXTRA_OECONF+= '${@bb.utils.contains("TUNE_FEATURES", "armv7a", "--with-cpu=generic-armv7-a", "", d)}'Sorry a typo there you need --with-arch
OK, that works. So do we need to do the same thing for every
TUNE_FEATURESelement that ends up changing the value of -march= inTUNE_CCARGSwhich ends up getting passed into gcc-runtime?
Not really but arm v6+ is an exception here due to reasons explained earlier. gcc as a target package is a bit
different than rest of them since it has mind of its own when it comes to configuring it. It encodes certain
defaults into its driver etc. based on the configure parameters. Ideally when we pass the flags via CFLAGS
it does it for most of packages but not for gcc.
Quoted 5 lines
If so would it be better to add a
TUNE_ARCHsetting to all the tune-foo.inc files and use that in bothTUNE_CCARGSand the --with-arch= flag passed to gcc? Just to avoid having this stuff hidden inside gcc-target.inc where it's pretty obscure.
Quoted 10 lines · Khem Raj
Quoted 9 lines · Peter A. Bigot
Quoted 3 lines
EXTRA_OECONF+= '${@bb.utils.contains("TUNE_FEATURES", "armv7a", "--with-cpu=generic-armv7-a", "", d)}'Sorry a typo there you need --with-arch
OK, that works. So do we need to do the same thing for every
TUNE_FEATURESelement that ends up changing the value of -march= inTUNE_CCARGSwhich ends up getting passed into gcc-runtime?
Quoted 7 lines
Not really but arm v6+ is an exception here due to reasons explained earlier. gcc as a target package is a bit
different than rest of them since it has mind of its own when it comes to configuring it. It encodes certain
defaults into its driver etc. based on the configure parameters. Ideally when we pass the flags via CFLAGS
it does it for most of packages but not for gcc.
tl;dr: the proposed fix to gcc-target works for my example but I'm concerned it's a bandaid that doesn't address a more long-term risk.
I understand gcc-target is different. I frame the issue as: bitbake (via toolchain-scripts.bbclass) ensures OE builds its applications with TARGET_CC_ARCH flags such as -march=FOO, but building gcc itself requires EXTRA_OECONF to pass different flags such as --with-arch=FOO which set the default behavior for the target compiler.
There are actually a bunch of these gcc configuration options:
--with-schedule=cpu
--with-arch=cpu
--with-arch-32=cpu
--with-arch-64=cpu
--with-tune=cpu
--with-tune-32=cpu
--with-tune-64=cpu
--with-abi=abi
--with-fpu=type
--with-float=type
all of which affect the default for the corresponding -m flags, and any of which may affect each other within gcc's configure script.
It sounds like the intent is that the default behavior of the target gcc should match what bitbake is passing via TARGET_CC_ARCH. Of course, if that were guaranteed there wouldn't be any need for OE to apply TARGET_CC_ARCH at all, but I wouldn't suggest changing that.
My concern is that gcc-runtime invokes configure in subdirectories of gcc's source tree, bypassing the top-level configure where some of the translation from (e.g.) --with-arch=FOO to -march=FOO is done. It then builds the libraries with TARGET_CC_ARCH flags appended to CC, CXX, and CPP.
What this means is that the libraries built by gcc-runtime use TARGET_CC_ARCH settings that don't necessarily match the target compiler's defaults, and that ABI conflicts can result by linking in those libraries when the non-default settings were absent in non-OE application builds. ABI can only be "guaranteed" if every one of the -mFOO=BAR passed in TARGET_CC_ARCH (*or defaulted by the compiler*) has a corresponding -with-FOO=BAR option passed to (*or inferred by*) gcc's configure.
That's a pretty strong assumption to make.
It may be that this can be worked around for the specific case I raised by explicitly adding --with-arch=armv7-a to gcc-target's EXTRA_OECONF. I do have to wonder whether the same should be done for any of armv7 armv7-m armv7-r armv7e-m armv7ve armv8-a armv8-a+crc which are other -march options that are armv6+, and whether there are other ABI issues that might be hiding now or in the future because TARGET_CC_ARCH makes more assumptions than gcc-target does.
The solution I propose is to rework gcc-runtime's override of CC/CXX/CPP so the libraries are built the same way they would be if they had been built during gcc-target.
From initial attempts this won't be easy to do. I'd be happy to keep trying if this worries other people, but if I'm being too picky I'll just suck it up and move on.
Peter
Quoted 19 lines · Peter A. Bigot
What this means is that the libraries built by gcc-runtime use
TARGET_CC_ARCHsettings that don't necessarily match the target compiler's defaults, and that ABI conflicts can result by linking in those libraries when the non-default settings were absent in non-OE application builds. ABI can only be "guaranteed" if every one of the -mFOO=BAR passed inTARGET_CC_ARCH(*or defaulted by the compiler*) has a corresponding -with-FOO=BAR option passed to (*or inferred by*) gcc's configure.That's a pretty strong assumption to make.
It may be that this can be worked around for the specific case I raised by explicitly adding --with-arch=armv7-a to gcc-target's
EXTRA_OECONF. I do have to wonder whether the same should be done for any of armv7 armv7-m armv7-r armv7e-m armv7ve armv8-a armv8-a+crc which are other -march options that are armv6+, and whether there are other ABI issues that might be hiding now or in the future becauseTARGET_CC_ARCHmakes more assumptions than gcc-target does.
Quoted 7 lines
The solution I propose is to rework gcc-runtime's override of CC/CXX/CPP so the libraries are built the same way they would be if they had been built during gcc-target.
From initial attempts this won't be easy to do. I'd be happy to keep
trying if this worries other people, but if I'm being too picky I'll just suck it up and move on.
Its a valid concern, I just don't think anyone else has run into the kinds of issues you're seeing :/. We don't want to diverge too far from upstream gcc, equally, we need a working compiler...
Cheers,
Richard
Quoted 24 lines · Richard Purdie
Quoted 23 lines · Peter A. Bigot
What this means is that the libraries built by gcc-runtime use
TARGET_CC_ARCHsettings that don't necessarily match the target compiler's defaults, and that ABI conflicts can result by linking in those libraries when the non-default settings were absent in non-OE application builds. ABI can only be "guaranteed" if every one of the -mFOO=BAR passed inTARGET_CC_ARCH(*or defaulted by the compiler*) has a corresponding -with-FOO=BAR option passed to (*or inferred by*) gcc's configure.That's a pretty strong assumption to make.
It may be that this can be worked around for the specific case I raised by explicitly adding --with-arch=armv7-a to gcc-target's
EXTRA_OECONF. I do have to wonder whether the same should be done for any of armv7 armv7-m armv7-r armv7e-m armv7ve armv8-a armv8-a+crc which are other -march options that are armv6+, and whether there are other ABI issues that might be hiding now or in the future becauseTARGET_CC_ARCHmakes more assumptions than gcc-target does.The solution I propose is to rework gcc-runtime's override of CC/CXX/CPP so the libraries are built the same way they would be if they had been built during gcc-target.
Quoted 5 lines
Quoted 3 lines
From initial attempts this won't be easy to do. I'd be happy to keep
trying if this worries other people, but if I'm being too picky I'll just suck it up and move on.Its a valid concern, I just don't think anyone else has run into the kinds of issues you're seeing :/.
I think it's more that somebody found a workaround and posted it on stackoverflow so nobody reported back to OE. A potential client I talked to yesterday mentioned having run into this exact problem a month or so ago, and the earliest mention of it I've found was from a year ago [1]. As use of threading in C++11 becomes more common I'd expect it to have had increased visibility.
I'm content with the solution in my v2 gcc patch series, but I expect someday the underlying cause will re-appear as new processors have new features with ABI impacts due to gcc target optimization. Hopefully when that happens the discussion here will be of some help in identifying the problem.
Peter
[1] https://groups.google.com/forum/#!msg/automatak-dnp3/Jisp_zGhd5I/ck_Cj6nO8joJ
Quoted 5 lines · Peter A. Bigot
I'm content with the solution in my v2 gcc patch series, but I expect someday the underlying cause will re-appear as new processors have new features with ABI impacts due to gcc target optimization. Hopefully when that happens the discussion here will be of some help in identifying the problem.
general usecase on arm thus far is to use cross compilers and I think we are good there. target compilation is not a norm but this might change soon but then we can propose to change defaults in gcc to use armv6+, we build arm native gcc using canadian cross method, thats kind of different than usual known gcc compilation methods so there may be less favors for this use case.
Quoted 78 lines · Peter A. Bigot
Quoted 15 lines · Khem Raj
Quoted 4 lines · Peter A. Bigot
Quoted 4 lines
EXTRA_OECONF+= '${@bb.utils.contains("TUNE_FEATURES", "armv7a", "--with-cpu=generic-armv7-a", "", d)}'Quoted 8 lines
Sorry a typo there you need --with-arch
OK, that works. So do we need to do the same thing for every
TUNE_FEATURES
element that ends up changing the value of -march= inTUNE_CCARGSwhich ends
up getting passed into gcc-runtime?Quoted 7 lines
Not really but arm v6+ is an exception here due to reasons explained earlier. gcc as a target package is a bit
different than rest of them since it has mind of its own when it comes to configuring it. It encodes certain
defaults into its driver etc. based on the configure parameters. Ideally when we pass the flags via CFLAGS
it does it for most of packages but not for gcc.tl;dr: the proposed fix to gcc-target works for my example but I'm concerned it's a bandaid that doesn't address a more long-term risk.
I understand gcc-target is different. I frame the issue as: bitbake (via toolchain-scripts.bbclass) ensures OE builds its applications with
TARGET_CC_ARCHflags such as -march=FOO, but building gcc itself requiresEXTRA_OECONFto pass different flags such as --with-arch=FOO which set the default behavior for the target compiler.There are actually a bunch of these gcc configuration options:
--with-schedule=cpu
--with-arch=cpu
--with-arch-32=cpu
--with-arch-64=cpu
--with-tune=cpu
--with-tune-32=cpu
--with-tune-64=cpu
--with-abi=abi
--with-fpu=type
--with-float=typeall of which affect the default for the corresponding -m flags, and any of which may affect each other within gcc's configure script.
It sounds like the intent is that the default behavior of the target gcc should match what bitbake is passing via
TARGET_CC_ARCH. Of course, if that were guaranteed there wouldn't be any need for OE to applyTARGET_CC_ARCHat all, but I wouldn't suggest changing that.My concern is that gcc-runtime invokes configure in subdirectories of gcc's source tree, bypassing the top-level configure where some of the translation from (e.g.) --with-arch=FOO to -march=FOO is done. It then builds the libraries with
TARGET_CC_ARCHflags appended to CC, CXX, and CPP.What this means is that the libraries built by gcc-runtime use
TARGET_CC_ARCHsettings that don't necessarily match the target compiler's defaults, and that ABI conflicts can result by linking in those libraries when the non-default settings were absent in non-OE application builds. ABI can only be "guaranteed" if every one of the -mFOO=BAR passed inTARGET_CC_ARCH(*or defaulted by the compiler*) has a corresponding -with-FOO=BAR option passed to (*or inferred by*) gcc's configure.That's a pretty strong assumption to make.
It may be that this can be worked around for the specific case I raised by explicitly adding --with-arch=armv7-a to gcc-target's
EXTRA_OECONF. I do have to wonder whether the same should be done for any of armv7 armv7-m armv7-r armv7e-m armv7ve armv8-a armv8-a+crc which are other -march options that are armv6+, and whether there are other ABI issues that might be hiding now or in the future becauseTARGET_CC_ARCHmakes more assumptions than gcc-target does.
Quoted 4 lines
The solution I propose is to rework gcc-runtime's override of CC/CXX/CPP so the libraries are built the same way they would be if they had been built during gcc-target.
we are actually pulling out the target runtime out of gut of gcc-cross and then doing the match with target gcc
so as long as we make target gcc recipe confirm to this we are good. I dont feel like we need to engineer a general solution here. Since what we are addressing is an anamoly not norm. So lets keep it that way. meaning patch it for arm where needed.
one day all < armv5 architectures will die out and we will be a happy lot :) oh wait then aarch64-32 might spring another ABI concern who knows
Quoted 5 lines
From initial attempts this won't be easy to do. I'd be happy to keep trying if this worries other people, but if I'm being too picky I'll just suck it up and move on.
Peter