Opened 7 years ago
Closed 6 years ago
#11756 closed Patches (fixed)
boost.Test: non standards compliant use of FE_* macros (unable to compile boost test library on FPU-less arches)
Reported by: | Owned by: | Raffi Enficiaud | |
---|---|---|---|
Milestone: | Boost 1.64.0 | Component: | test |
Version: | Boost 1.59.0 | Severity: | Problem |
Keywords: | Cc: |
Description
In file included from ./boost/test/unit_test_monitor.hpp:18:0,
from ./boost/test/impl/unit_test_monitor.ipp:20, from libs/test/src/unit_test_monitor.cpp:16:
./boost/test/execution_monitor.hpp:492:27: error: 'FE_DIVBYZERO' was not declared in this scope ./boost/test/execution_monitor.hpp:493:27: error: 'FE_INEXACT' was not declared in this scope ./boost/test/execution_monitor.hpp:494:27: error: 'FE_INVALID' was not declared in this scope ./boost/test/execution_monitor.hpp:495:27: error: 'FE_OVERFLOW' was not declared in this scope ./boost/test/execution_monitor.hpp:496:27: error: 'FE_UNDERFLOW' was not declared in this scope ./boost/test/execution_monitor.hpp:498:27: error: 'FE_ALL_EXCEPT' was not declared in this scope
these constants are not defined in fenv.h version 1.58 was compiled successfully
bartek@homesrv:~/builds/boost_1_59_0$ mips-openwrt-linux-g++ -v Reading specs from /work/openwrt-sdk/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/bin/../lib/gcc/mips-openwrt-linux-uclibc/4.6.3/specs COLLECT_GCC=mips-openwrt-linux-g++ COLLECT_LTO_WRAPPER=/work/openwrt-sdk/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/bin/../libexec/gcc/mips-openwrt-linux-uclibc/4.6.3/lto-wrapper Target: mips-openwrt-linux-uclibc Configured with: /work/openwrt/build_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/gcc-linaro-4.6-2012.02/configure --prefix=/work/openwrt/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2 --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=mips-openwrt-linux-uclibc --with-gnu-ld --enable-target-optspace --disable-libgomp --disable-libmudflap --disable-multilib --disable-nls --with-host-libstdcxx=-lstdc++ --with-float=soft --with-gmp=/work/openwrt/staging_dir/host --with-mpfr=/work/openwrt/staging_dir/host --disable-decimal-float --with-mips-plt --with-mpc=/work/openwrt/staging_dir/host --disable-libssp --disable-cxa_atexit --with-headers=/work/openwrt/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/include --enable-languages=c,c++ --enable-shared --enable-threads --with-slibdir=/work/openwrt/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/lib --enable-lto --with-libelf=/work/openwrt/staging_dir/host --disable-tls Thread model: posix gcc version 4.6.3 20120201 (prerelease) (Linaro GCC 4.6-2012.02)
Attachments (3)
Change History (67)
comment:1 by , 7 years ago
Component: | None → test |
---|---|
Owner: | set to |
comment:2 by , 7 years ago
comment:3 by , 7 years ago
I do not have access to those platforms. Do you know by chance if those "deficiencies" are described in the boost.config project?
especially the macro
BOOST_NO_FENV_H
comment:4 by , 7 years ago
Hi
here is search result:
bartek@homesrv:~/builds/boost_1_59_0$ grep -rnw . -e "BOOST_NO_FENV_H" ./libs/config/test/all/Jamfile.v2:394:test-suite "BOOST_NO_FENV_H" : ./libs/config/test/config_info.cpp:1073: PRINT_MACRO(BOOST_NO_FENV_H); ./libs/config/test/boost_no_fenv_h.ipp:9:// MACRO: BOOST_NO_FENV_H ./libs/config/test/no_fenv_h_pass.cpp:9:// Test file for macro BOOST_NO_FENV_H ./libs/config/test/no_fenv_h_pass.cpp:11:// BOOST_NO_FENV_H should be defined. ./libs/config/test/no_fenv_h_pass.cpp:23:#ifndef BOOST_NO_FENV_H ./libs/config/test/config_test.cpp:380:#ifndef BOOST_NO_FENV_H ./libs/config/test/config_test.cpp:1611: std::cerr << "Failed test for BOOST_NO_FENV_H at: " << FILE << ":" << LINE << std::endl; ./libs/config/test/no_fenv_h_fail.cpp:9:// Test file for macro BOOST_NO_FENV_H ./libs/config/test/no_fenv_h_fail.cpp:11:// BOOST_NO_FENV_H should not be defined. ./libs/config/test/no_fenv_h_fail.cpp:23:#ifdef BOOST_NO_FENV_H ./libs/config/doc/html/boost_config/boost_macro_reference.html:293: <code class="computeroutput"><span class="identifier">BOOST_NO_FENV_H</span></code> ./libs/config/doc/macro_reference.qbk:74:[[`BOOST_NO_FENV_H`][Platform, Standard library][
defined(QNX) | defined(IBMCPP)) && !defined(BOOST_NO_FENV_H) |
./boost/test/execution_monitor.hpp:63:#if !defined(BOOST_NO_FENV_H)
defined(BOOST_CLANG) |
./boost/test/impl/execution_monitor.ipp:1382:#elif defined(GLIBC) && defined(USE_GNU) && !defined(BOOST_CLANG) && !defined(BOOST_NO_FENV_H) ./boost/test/impl/execution_monitor.ipp:1419:#elif defined(GLIBC) && defined(USE_GNU) && !defined(BOOST_CLANG) && !defined(BOOST_NO_FENV_H) ./boost/detail/fenv.hpp:10:#if defined(BOOST_NO_FENV_H) ./boost/config/platform/cygwin.hpp:43:#define BOOST_NO_FENV_H ./boost/config/compiler/intel.hpp:497:# define BOOST_NO_FENV_H ./boost/config/compiler/visualc.hpp:47:# define BOOST_NO_FENV_H
when i added mentioned macro: BOOST_NO_FENV_H to the boost/config/user.hpp header then i successfully built following libraries (in comparision to the previous build - without this macro):
libbost_unit_test_framework.a libbost_test_exec_monitor.a libbost_prge_xec_monitor.a
of course for openwrt-linux-mips platform
thanks for clue
comment:5 by , 7 years ago
Thank you for your feedback,
Boost.Test relies on Boost.Config for the proper configuration of the BOOST_NO_FENV_H
macro. From your message, it looks like this macro is not properly defined for your platform openwrt-linux-mips
, and if you define it manually, Boost.Test properly compiles.
Have I understood properly?
comment:6 by , 7 years ago
Yes, exactly
It is because, i guess, first of all i build bootstrap in x86_64.
./bootstrap.sh
next i build boost for x86_64 and x86 platforms (debian)
./b2 link=static variant=release --prefix=/work/libextern/boost-x86 address-model=32 cxxflags=-fPIC install
once again, thanks bartek
./b2 link=static variant=release --prefix=/work/libextern/boost-x64 address-model=64 cxxflags=-fPIC install
finally i create boost.config.jam file, in which i place:
using gcc : mips : "mips-openwrt-linux-g++" ;
and i build boost for mips:
./b2 toolset=gcc-mips link=static variant=release --prefix=/work/libextern/boost-mips cxxflags=-fPIC --user-config=user.config.jam install
maybe I missed something that boost build system did not recognized correctly mips platform but now i will add manually mentioned macro and it is enough for me.
comment:8 by , 7 years ago
Component: | test → config |
---|---|
Owner: | changed from | to
comment:9 by , 7 years ago
Boost detects a fenv.h system header and assumes it defines FE_DIVBYZERO and friends. The involved toolchains does have this system header, but they do not define these macros, e.g. the mipsel toolchain from Buildroot (fenv.h includes tr1/cfenv):
/** @file tr1/cfenv * This is a TR1 C++ Library header. */ #ifndef _GLIBCXX_TR1_CFENV #define _GLIBCXX_TR1_CFENV 1 #pragma GCC system_header #include <bits/c++config.h> #if _GLIBCXX_HAVE_FENV_H # include <fenv.h> #endif #ifdef _GLIBCXX_USE_C99_FENV_TR1 #undef feclearexcept #undef fegetexceptflag #undef feraiseexcept #undef fesetexceptflag #undef fetestexcept #undef fegetround #undef fesetround #undef fegetenv #undef feholdexcept #undef fesetenv #undef feupdateenv namespace std _GLIBCXX_VISIBILITY(default) { namespace tr1 { // types using ::fenv_t; using ::fexcept_t; // functions using ::feclearexcept; using ::fegetexceptflag; using ::feraiseexcept; using ::fesetexceptflag; using ::fetestexcept; using ::fegetround; using ::fesetround; using ::fegetenv; using ::feholdexcept; using ::fesetenv; using ::feupdateenv; } } #endif // _GLIBCXX_USE_C99_FENV_TR1 #endif // _GLIBCXX_TR1_CFENV
by , 6 years ago
Attachment: | 0001-config-BOOST_NO_FENV_H.patch added |
---|
gcc: #define BOOST_NO_FENV_H on FPU-less arches
comment:10 by , 6 years ago
Summary: | Unable to compile boost test library on openwrt - mips → boost.Config doesn't detect FPU-less arches (Unable to compile boost test library on FPU-less arches) |
---|
comment:11 by , 6 years ago
Type: | Support Requests → Patches |
---|
follow-up: 57 comment:12 by , 6 years ago
Component: | config → test |
---|---|
Owner: | changed from | to
Sorry to ping this back to Boost.Test, but I believe this is a misunderstanding of how fenv.h works. The key point is:
A fully standards conforming fenv.h does not have to define any FE_* macros, and if it does define them, then it defines macros only for the FP exceptions it actually supports.
So correct usage requires a triple check:
1) Check BOOST_NO_FENV_H to see if the header is supported.
2) Include the header and then check FE_ALL_EXCEPT to see if any FP exceptions are supported.
3) Before using the individual FE_* macros, you need to check for their existence too as not all may be supported.
And finally.... the standard also permits other FE_* macros if there are exceptions supported other than the standard set. There's no standard way to tell what these might be, but their presence can be inferred by checking FE_ALL_EXCEPT against the bitwise or of the other FE_* macros.
by , 6 years ago
Attachment: | 0001-execution_monitor-fix-soft-float-issues.patch added |
---|
fix FE_* usage in test (based on previous comment)
comment:13 by , 6 years ago
Summary: | boost.Config doesn't detect FPU-less arches (Unable to compile boost test library on FPU-less arches) → boost.Test: non standards compliant use of FE_* macros (unable to compile boost test library on FPU-less arches) |
---|
comment:14 by , 6 years ago
That doesn't quite get it: if fenv.h is available, but FE_DIVBYZERO is unset then BOOST_FPE_DIVBYZERO is also left unset (for example), where as it should be set to a stub value I guess (1 or 0).... except a quick grep of the source suggests these are unused anyway? Which just leaves BOOST_FPE_ALL which definitely needs to be in #if...#else block, so I suggest something more like:
#ifdef FE_DIVBYZERO BOOST_FPE_DIVBYZERO = FE_DIVBYZERO, #else BOOST_FPE_DIVBYZERO = 0, #endif #ifdef FE_INEXACT BOOST_FPE_INEXACT = FE_INEXACT, #else BOOST_FPE_INEXACT = 0, #endif #ifdef FE_INVALID BOOST_FPE_INVALID = FE_INVALID, #else BOOST_FPE_INVALID = 0, #endif #ifdef FE_OVERFLOW BOOST_FPE_OVERFLOW = FE_OVERFLOW, #else BOOST_FPE_OVERFLOW = 0, #endif #ifdef FE_UNDERFLOW BOOST_FPE_UNDERFLOW = FE_UNDERFLOW, #else BOOST_FPE_UNDERFLOW = 0, #endif #ifdef FE_ALL_EXCEPT BOOST_FPE_ALL = FE_ALL_EXCEPT, #else BOOST_FPE_ALL = 1, #endif
comment:15 by , 6 years ago
Based on your previous comment:
Include the header and then check FE_ALL_EXCEPT to see if any FP exceptions are supported
I understood that if fenv.h is available, then FE_ALL_EXCEPT can have *any* value. In my case, it is defined, but it's defined to 0, since no exceptions are supported. Hence I had a check for this. This is now gone, and with this version BOOST_FPE_ALL would be == 0, too.
Hence I think it should be checking
#ifdef FE_ALL_EXCEPT && (FE_ALL_EXCEPT != 0)
BOOST_FPE_ALL = FE_ALL_EXCEPT,
#else
BOOST_FPE_ALL = 1,
#endif
instead ?
comment:16 by , 6 years ago
On the other hand, does it really make sense to set BOOST_FPE_ALL to 1 if exceptions are not supported in the implementation? Wouldn't this be better?
#ifdef FE_ALL_EXCEPT BOOST_FPE_ALL = FE_ALL_EXCEPT, #else BOOST_FPE_ALL = 0, #endif
comment:17 by , 6 years ago
Yes it does make more sense for BOOST_FPE_ALL to be 0 in that case - I just followed existing practice for the case where there is no fenv.h as I wasn't sure what effect a zero value might have in the code's assumptions. I think the library authors will have to figure that one out.
by , 6 years ago
Attachment: | 0001-execution_monitor-fix-soft-float-issues.2.patch added |
---|
fix FE_* usage in test (updated again based on johnmaddock's tips)
comment:18 by , 6 years ago
Thanks!
I've had another look and I think this is a good version now. This works well for me on my target device as well as on my host machine.
comment:19 by , 6 years ago
Milestone: | To Be Determined → Boost 1.63.0 |
---|---|
Owner: | changed from | to
comment:20 by , 6 years ago
I am looking at this right now, and it is running fine on branch origin/topic/11756-floatingpoint-exception-macros
. However, I am just thinking:
- In case
fenv.h
is not found, does it mean that floating point exception is just not supported? - Does this mean the same as
FE_ALL_EXCEPT
not defined?
I am just thinking of making this distinction together with the use of BOOST_FPE_OFF
.
I also would like to have a better coverage of this. On your platform, what happens when you divide by 0 with and without your patch applied?
Thanks,
comment:21 by , 6 years ago
Thanks. I can't really answer your questions regarding missing fenv.h / FE_ALL_EXCEPT and BOOST_FPE_OFF. A standards compliant env should provide both, but of course FE_ALL_EXCEPT may be 0.
http://pubs.opengroup.org/onlinepubs/009695399/basedefs/fenv.h.html http://en.cppreference.com/w/cpp/numeric/fenv/FE_exceptions
I am not an expert on boost so I need some more information on what you want me to test please. Without my patch it doesn't compile on my platform.
comment:23 by , 6 years ago
Status: | new → assigned |
---|
comment:25 by , 6 years ago
Resolution: | → fixed |
---|---|
Status: | assigned → closed |
comment:26 by , 6 years ago
Hi, this modification generates a buid error for Intel compilers (version 11.0 in my case).
Indeed, for Intel compilers BOOST_NO_FENV_H is set as true, and compiler will not find fe* functions in execution_monitor.ipp lines 1382 and 1422.
comment:27 by , 6 years ago
Resolution: | fixed |
---|---|
Status: | closed → reopened |
follow-up: 30 comment:28 by , 6 years ago
Hi smetz,
Is this visible now on the regression board? I have no access to neither the Intel nor the "FPU-less" machines.
comment:29 by , 6 years ago
It doesn't appear in the regression board for the moment. This regression appeared in the boost 1.63 version.
comment:30 by , 6 years ago
Maybe you just have to come back on some modifications:
in boost/test/impl/execution_monitor.ipp lines 1378 and 1418, change:
#elif defined(__GLIBC__) && defined(__USE_GNU)
by
#elif defined(__GLIBC__) && defined(__USE_GNU) && !defined(BOOST_CLANG) && !defined(BOOST_NO_FENV_H)
This works on my side with the Intel compiler. But I'm not sure that this will not introduce a new regression for the CLang compiler, I don't know if CLang support floatingpoint exceptions.
comment:31 by , 6 years ago
Hi there,
It would be handy if you can give a try to branch topic/11756-non-standards-fpexception-intel
. Thanks!
comment:32 by , 6 years ago
Milestone: | Boost 1.63.0 → Boost 1.64.0 |
---|
comment:34 by , 6 years ago
The suggested fix in topic/11756-non-standards-fpexception-intel breaks non-glibc builds (musl-libc in my case):
gcc.compile.c++ [...]/mipsel-poky-linux-musl/boost/bin.v2/libs/test/build/gcc-4.3.1/release/threading-multi/execution_monitor.o "mipsel-poky-linux-musl-g++" "-mel" "-mabi=32" "-msoft-float" "-march=mips32r2" "-mips16" "-minterlink-compressed" "-mtune=24kec" "-mdsp" "-Wl,-O1" "-Wl,--as-needed" "-fstack-protector-strong" "-Wl,-z,relro,-z,now" "--sysroot=[...sysroot...]" -ftemplate-depth-128 -O2 -pipe -g -feliminate-unused-debug-types -fstack-protector-strong -pie -fpie -D_FORTIFY_SOURCE=2 -Wformat -Wformat-security -Werror=format-security -fvisibility-inlines-hidden -O3 -finline-functions -Wno-inline -Wall -pedantic -pthread -fPIC -Wno-variadic-macros -DBOOST_ALL_NO_LIB=1 -DBOOST_CHRONO_DYN_LINK=1 -DBOOST_SYSTEM_DYN_LINK=1 -DBOOST_SYSTEM_NO_DEPRECATED -DBOOST_TEST_DYN_LINK=1 -DBOOST_TIMER_DYN_LINK=1 -DNDEBUG -I"." -c -o "[...]/mipsel-poky-linux-musl/boost/bin.v2/libs/test/build/gcc-4.3.1/release/threading-multi/execution_monitor.o" "libs/test/src/execution_monitor.cpp" In file included from libs/test/src/execution_monitor.cpp:16:0: ./boost/test/impl/execution_monitor.ipp: In function 'unsigned int boost::fpe::enable(unsigned int)': ./boost/test/impl/execution_monitor.ipp:1387:36: error: 'feenableexcept' was not declared in this scope ./boost/test/impl/execution_monitor.ipp: In function 'unsigned int boost::fpe::disable(unsigned int)': ./boost/test/impl/execution_monitor.ipp:1428:37: error: 'fedisableexcept' was not declared in this scope
Those two #ifdefs can not be made the same as as in execution_monitor.hpp, as the header file only does standard posix stuff, wheres the implementation uses the non-POSIX, non-standard-C APIs feenableexcept() and fedisableexcept(), which are only available when using glibc.
IOW, the test for __GLIBC__ and __USE_GNU must remain, and I think the two tests should go back to the original version:
-#elif defined(__GLIBC__) && defined(__USE_GNU) +#elif defined(__GLIBC__) && defined(__USE_GNU) && !(defined(BOOST_NO_FENV_H) || defined(BOOST_CLANG))
sorry for that.
comment:35 by , 6 years ago
Thanks for the quick feedback. Ok for the report, but to me the good solution is to be coherent with whatever is done to define the enum:
namespace fpe { enum masks { BOOST_FPE_OFF = 0, #ifdef BOOST_SEH_BASED_SIGNAL_HANDLING /* *** */ BOOST_FPE_DIVBYZERO = EM_ZERODIVIDE, BOOST_FPE_INEXACT = EM_INEXACT, BOOST_FPE_INVALID = EM_INVALID, BOOST_FPE_OVERFLOW = EM_OVERFLOW, BOOST_FPE_UNDERFLOW = EM_UNDERFLOW|EM_DENORMAL, BOOST_FPE_ALL = MCW_EM, #elif defined(BOOST_NO_FENV_H) || defined(BOOST_CLANG) /* *** */ BOOST_FPE_ALL = BOOST_FPE_OFF, #else /* *** */ // ...
So maybe a proper macro that says if there is nothing available and gathering the scenario where any of the BOOST_NO_FENV_H
, BOOST_CLANG
, __USE_GNU
etc is defined (or not).
What do you think?
comment:36 by , 6 years ago
Hm, not sure. On one hand I agree being coherent would be nice, but on the other hand it already isn't (and probably can't be) when you also take Windows & Visual Studio into account in the implementation. It would seem that there are always going to be different implementations based on the compilation environment (Windows CE / MSVC / Posix / Non-Posix Unices / gcc / clang / fenv / no-fenv).
Maybe I'm wrong. It does appear that the whole floating point support is a bit of a mess and hard to get right in a portable way, though.
Happy to test a patch :-)
follow-up: 40 comment:37 by , 6 years ago
Hi there again,
I moved the FPE logic in the macro BOOST_TEST_FPE_SUPPORT_WITHOUT_SEH__
. It would be cool if you can test the branch again.
The way I see this is that there is only 3 options in the code that should be handled:
- no fpe
- seh based fpe
- implementation based on fenv (and in that case, not all platforms support all signals)
All in all, I think that moving this switch to 2 configuration macros make the code easier to understand and to maintain.
Let me know the result of your tests. 1.64 will be closing soon, it would be good to have your feedback asap :)
Thanks, Raffi
comment:39 by , 6 years ago
This still doesn't work (same as in comment 34):
In file included from libs/test/src/execution_monitor.cpp:16:0: ./boost/test/impl/execution_monitor.ipp: In function 'unsigned int boost::fpe::enable(unsigned int)': ./boost/test/impl/execution_monitor.ipp:1384:36: error: 'feenableexcept' was not declared in this scope int res = feenableexcept( mask ); ^ ./boost/test/impl/execution_monitor.ipp: In function 'unsigned int boost::fpe::disable(unsigned int)': ./boost/test/impl/execution_monitor.ipp:1419:37: error: 'fedisableexcept' was not declared in this scope int res = fedisableexcept( mask );
This still goes into the wrong branch when not using glibc - we use the musl C library and gcc, so GLIBC is *not* defined (and therefore the non-posix, non-standard GNU APIs feenableexcept() and fedisableexcept() are not available), but at the same BOOST_NO_FENV_H and BOOST_CLANG are not defined, either. Hence the test in execution_monitor.hpp doesn't work:
#if !defined(BOOST_NO_FENV_H) && !defined(BOOST_CLANG) || \ (defined(__GLIBC__) && defined(__USE_GNU))
comment:40 by , 6 years ago
Replying to comment 37:
The way I see this is that there is only 3 options in the code that should be handled:
- no fpe
- seh based fpe
- implementation based on fenv (and in that case, not all platforms support all signals)
Basically, there should be 3 options for defining the interface in .hpp, but 4 options based on the compilation environment for the .ipp:
- no fpe
- seh based fpe
- implementation based on fenv (and in that case, not all platforms support all signals)
- using standard C/C++ APIs
- using non-standard glibc extensions (feenableexcept() etc.)
Which is what I meant in comment 34
comment:41 by , 6 years ago
Ok, now I think I understood the problem:
- the
feenableexcept/fedisableexcept
are not standard, those are
GLIBC
extensions
- having fenv does not ensure that those 2 functions are in there, for having those function, we should be ensured that we are indeed compiling with GLIBC
- however, for anything outside this and SEH based extensions, there is no easy way to mask floating point exceptions
So, I suggest the following:
- The macro indicating that the floating point exception settings is supported becomes
BOOST_TEST_FPE_SUPPORT_WITH_GLIBC_EXTENSIONS__
and is defined like this:
#if defined(BOOST_SEH_BASED_SIGNAL_HANDLING) && !defined(UNDER_CE) //! Indicates tha the floating point exception handling is supported //! through SEH #define BOOST_TEST_FPE_SUPPORT_WITH_SEH__ #elif !defined(BOOST_SEH_BASED_SIGNAL_HANDLING) && !defined(UNDER_CE) #if !defined(BOOST_NO_FENV_H) && !defined(BOOST_CLANG) && \ (defined(__GLIBC__) && defined(__USE_GNU)) //! Indicates that floating point exception handling is supported for the //! non SEH version of it, for the GLIBC extensions only #define BOOST_TEST_FPE_SUPPORT_WITH_GLIBC_EXTENSIONS__ #endif #endif
- the branch taking the
feenableexcept/fedisableexcept
is guarded by this macro
- the branch taking the SEH extension is not affected
- all the rest is falls back to the "unsupported" branch (returning
BOOST_FPE_OFF/BOOST_FPE_INV
). In particular, I do not see how to support 3.a from your comment.
Does this sound correct?
comment:42 by , 6 years ago
Yes, looks right.
As for 3.a from my comment, I don't think there's an easy way to support it either. Googling a little bit it probably is possible, but that's out of scope for this issue here.
comment:43 by , 6 years ago
Good, can you then please test again the branch topic/11756-non-standards-fpexception-intel
?
Many thanks!
comment:44 by , 6 years ago
That seems to work, at least it compiles in all cases I care about :-)
Thanks!
comment:45 by , 6 years ago
We recently bumped the boost version from 1.61.0 to 1.63.0 in Buildroot. Now, we get build errors for two architectures which were compiling successfully before: SH4 and OR1K. Both use a uclibc-toolchain.
In file included from libs/test/src/execution_monitor.cpp:16:0: ./boost/test/impl/execution_monitor.ipp: In function 'unsigned int boost::fpe::enable(unsigned int)': ./boost/test/impl/execution_monitor.ipp:1382:32: error: 'feclearexcept' was not declared in this scope feclearexcept(BOOST_FPE_ALL); ^ ./boost/test/impl/execution_monitor.ipp:1383:36: error: 'feenableexcept' was not declared in this scope int res = feenableexcept( mask ); ^ ./boost/test/impl/execution_monitor.ipp: In function 'unsigned int boost::fpe::disable(unsigned int)': ./boost/test/impl/execution_monitor.ipp:1422:32: error: 'feclearexcept' was not declared in this scope feclearexcept(BOOST_FPE_ALL); ^ ./boost/test/impl/execution_monitor.ipp:1423:37: error: 'fedisableexcept' was not declared in this scope int res = fedisableexcept( mask );
I've checked out the branch topic/11756-non-standards-fpexception-intel
of the test module, it does not build either.
At least, the SH4 toolchain does not have fenv.h. I did not checked to OR1K toolchain, yet.
Here are some macros I've checked using the branch 11756:
BOOST_NO_FENV_H
is definedBOOST_SEH_BASED_SIGNAL_HANDLING
is not definedBOOST_TEST_FPE_SUPPORT_WITH_GLIBC_EXTENSIONS__
is defined
comment:46 by , 6 years ago
Hi Jörg,
Thanks for looking at this as well! The macro definitions you report are weird:
#if !defined(BOOST_NO_FENV_H) && !defined(BOOST_CLANG) && \ (defined(__GLIBC__) && defined(__USE_GNU)) //! Indicates that floating point exception handling is supported for the //! non SEH version of it, for the GLIBC extensions only #define BOOST_TEST_FPE_SUPPORT_WITH_GLIBC_EXTENSIONS__ #endif
this means that if BOOST_NO_FENV_H
is defined, then
BOOST_TEST_FPE_SUPPORT_WITH_GLIBC_EXTENSIONS__
cannot be defined. Are you on revision
6f0d88ca9db00b449a795afa3218b815fe8c01b0
? (I forced pushed like 1 hour ago)
comment:47 by , 6 years ago
No, I am on revision c0fb4b1c21865d2096fbee2f3c77026f5a743180
.
Sorry, the macro definitions I posted are wrong. This is the correct ones:
BOOST_NO_FENV_H
is not definedBOOST_TEST_FPE_SUPPORT_WITH_GLIBC_EXTENSIONS__
is defined
Note, this is the content of output/host/opt/ext-toolchain/sh4-buildroot-linux-uclibc/include/c++/5.4.0/fenv.h:
#ifndef _GLIBCXX_FENV_H #define _GLIBCXX_FENV_H 1 #pragma GCC system_header #include <bits/c++config.h> #if _GLIBCXX_HAVE_FENV_H # include_next <fenv.h> #endif #if __cplusplus >= 201103L #if _GLIBCXX_USE_C99_FENV_TR1 #undef feclearexcept #undef fegetexceptflag #undef feraiseexcept #undef fesetexceptflag #undef fetestexcept #undef fegetround #undef fesetround #undef fegetenv #undef feholdexcept #undef fesetenv #undef feupdateenv namespace std { // types using ::fenv_t; using ::fexcept_t; // functions using ::feclearexcept; using ::fegetexceptflag; using ::feraiseexcept; using ::fesetexceptflag; using ::fetestexcept; using ::fegetround; using ::fesetround; using ::fegetenv; using ::feholdexcept; using ::fesetenv; using ::feupdateenv; } // namespace #endif // _GLIBCXX_USE_C99_FENV_TR1 #endif // C++11 #endif // _GLIBCXX_FENV_H
comment:48 by , 6 years ago
Hi,
Thanks for the update.
You said in comment 45 that SH4 does not have fenv. Does that still hold true? If yes, then BOOST_NO_FENV_H
should be defined.
I would kindly ask to test the following 2 revisions:
02f9a561bc8003cb38fcc5b0863482459a38ea4f
(18 October 2016)
eec86d1fbe68aea190ce05a080d20e1569fb82a9
(24 August 2016)
It looks to me that BOOST_NO_FENV_H
is not properly set.
Also, what are the status of the following two defines, for those two architectures:
__GLIBC__
__USE_GNU
Thanks!
comment:49 by , 6 years ago
Sorry about by confusion about fenv.h. The toolchain tarball include the C++ Library header file fenv.h in sh4-buildroot-linux-uclibc/include/c++/5.4.0/, but it does not have a fenv.h in sysroot. I guess the later is generated somehow, right? (I've compared with another arm musl-toolchain which does have fenv.h in sysroot).
I've compiled the following example with the SH4 C++ compiler:
#include <iostream> #include <cfenv> #include <cmath> #pragma STDC FENV_ACCESS ON volatile double zero = 0.0; // volatile not needed where FENV_ACCESS is supported volatile double one = 1.0; // volatile not needed where FENV_ACCESS is supported int main() { std::feclearexcept(FE_ALL_EXCEPT); std::cout << "1.0/0.0 = " << 1.0 / zero << '\n'; if(std::fetestexcept(FE_DIVBYZERO)) { std::cout << "division by zero reported\n"; } else { std::cout << "divsion by zero not reported\n"; } std::feclearexcept(FE_ALL_EXCEPT); std::cout << "1.0/10 = " << one/10 << '\n'; if(std::fetestexcept(FE_INEXACT)) { std::cout << "inexact result reported\n"; } else { std::cout << "inexact result not reported\n"; } std::feclearexcept(FE_ALL_EXCEPT); std::cout << "sqrt(-1) = " << std::sqrt(-1) << '\n'; if(std::fetestexcept(FE_INVALID)) { std::cout << "invalid result reported\n"; } else { std::cout << "invalid result not reported\n"; } }
Invoking the cross-compiler:
buildroot ) output/host/usr/bin/sh4-linux-g++ -std=c++11 main.cc main.cc: In function ‘int main()’: main.cc:12:5: error: ‘feclearexcept’ is not a member of ‘std’ std::feclearexcept(FE_ALL_EXCEPT); ^ main.cc:12:24: error: ‘FE_ALL_EXCEPT’ was not declared in this scope std::feclearexcept(FE_ALL_EXCEPT); ^ main.cc:14:8: error: ‘fetestexcept’ is not a member of ‘std’ if(std::fetestexcept(FE_DIVBYZERO)) { ^ main.cc:14:26: error: ‘FE_DIVBYZERO’ was not declared in this scope if(std::fetestexcept(FE_DIVBYZERO)) { ^ main.cc:20:5: error: ‘feclearexcept’ is not a member of ‘std’ std::feclearexcept(FE_ALL_EXCEPT); ^ main.cc:22:8: error: ‘fetestexcept’ is not a member of ‘std’ if(std::fetestexcept(FE_INEXACT)) { ^ main.cc:22:26: error: ‘FE_INEXACT’ was not declared in this scope if(std::fetestexcept(FE_INEXACT)) { ^ main.cc:28:5: error: ‘feclearexcept’ is not a member of ‘std’ std::feclearexcept(FE_ALL_EXCEPT); ^ main.cc:30:8: error: ‘fetestexcept’ is not a member of ‘std’ if(std::fetestexcept(FE_INVALID)) { ^ main.cc:30:26: error: ‘FE_INVALID’ was not declared in this scope if(std::fetestexcept(FE_INVALID)) {
Commit 02f9a561bc8003cb38fcc5b0863482459a38ea4f (18 October 2016) produces the following error:
from libs/test/src/execution_monitor.cpp:16: ./boost/test/execution_monitor.hpp:503:27: error: ‘FE_DIVBYZERO’ was not declared in this scope BOOST_FPE_DIVBYZERO = FE_DIVBYZERO, ^ ./boost/test/execution_monitor.hpp:504:27: error: ‘FE_INEXACT’ was not declared in this scope BOOST_FPE_INEXACT = FE_INEXACT, ^ ./boost/test/execution_monitor.hpp:505:27: error: ‘FE_INVALID’ was not declared in this scope BOOST_FPE_INVALID = FE_INVALID, ^ ./boost/test/execution_monitor.hpp:506:27: error: ‘FE_OVERFLOW’ was not declared in this scope BOOST_FPE_OVERFLOW = FE_OVERFLOW, ^ ./boost/test/execution_monitor.hpp:507:27: error: ‘FE_UNDERFLOW’ was not declared in this scope BOOST_FPE_UNDERFLOW = FE_UNDERFLOW, ^ ./boost/test/execution_monitor.hpp:509:27: error: ‘FE_ALL_EXCEPT’ was not declared in this scope BOOST_FPE_ALL = FE_ALL_EXCEPT,
Whereas commit eec86d1fbe68aea190ce05a080d20e1569fb82a9 (24 August 2016) produces the same error as reported in comment 45.
For SH4:
__GLIBC__
is defined__USE_GNU
is defined
comment:50 by , 6 years ago
Thanks for the quick reply.
Something troubles me a bit: you said earlier that things were working fine with boost 1.61. Since then, all the changes to the FPE were the following:
- the macros
FE_DIVBYZERO
... are not something that are necessarily defined, this is why their use has been protected if
ifdefs
and you are having the compilation error on
02f9a561bc8003cb38fcc5b0863482459a38ea4f
feenableexcept/fedisableexcept
are GNU extensions, this is why the latest status on this is to check for the macros
__GLIBC__
and
__USE_GNU
and restrict the code to that case.
So I have 2 hypothesis in mind:
- you are not compiling the code with the same options as you did before: the rationale behind is that C++11 is now defining
<cfenv>
which automatically would avoid the definition of
BOOST_NO_FENV_H
, while it was defined before
- for the cross compilation, more restrictions should be applied on how to check for the existence of
feenableexcept/fedisableexcept
(which means additional/other macros than
__GLIBC__
and
__USE_GNU
), but in that case I do not understand why it would have been working with boost 1.61
So ... would you check again with boost 1.61? Sorry to ask you that, but I am really lost there :-)
To nail down further the cause of those issues, it would be even better if you could (still based on the assumption that it was working with boost 1.61):
- check with the entire boost 1.61
- check with the latest boost develop but with boost.test 1.61
Thanks!
comment:51 by , 6 years ago
We can also iterate further:
- you may tell me how to set up this environment from eg. Ubuntu or a docker image
- you may also tell me the values of those macros: BOOST_LIB_C_GNU as well as BOOST_GCC
Thanks again, Raffi
comment:52 by , 6 years ago
I figured something out!
It is working for version 1.61.0 (and 1.62.0) for this toolchain because Buildroot is patching config/platform/linux.hpp:
+// uClibc has no support for fenv.h, and also a few architectures +// don't have fenv.h support at all (or incomplete support) even with +// glibc. + +// +#if defined(__UCLIBC__) || defined(__nios2__) || defined(__microblaze__) +# define BOOST_NO_FENV_H +#endif
Now let me explain my confusion about BOOST_NO_FENV_H
:
When I wrote BOOST_NO_FENV_H
is defined it was because of I was building a patched "in-tree" boost. When I wrote BOOST_NO_FENV_H
is not defined it was because of I was building an unpatched "out-of-tree" version of boost. Note, Buildroot applies patches to in-tree packages, but does not apply the patches to out-of-tree packages. In this case, I was using the git clone for an out-of-tree build. Therefore, the git clone does not had the patch applied, and BOOST_NO_FENV_H
was not set by the patch. May bad, sorry!
In short, for an unpatched boost BOOST_NO_FENV_H
is not defined for that toolchain.
Nevertheless, I did a git bisect (with the patch applied) for the test submodule: bisect says that eec86d1fbe68aea190ce05a080d20e1569fb82a9 (trac 11756: fix usage of floating point exception macros) is the bad commit. That means: when BOOST_NO_FENV_H
is set because of the patch, boost compiles before this commit, but not after.
comment:53 by , 6 years ago
Thanks again for the quick feedback. So the problem does not seem to be totally related to boost.test :)
I believe that the last version of the branch topic/11756-non-standards-fpexception-intel
should work fine with
BOOST_NO_FENV_H
. I kindly ask you to checkout this version (
6f0d88ca9db00b449a795afa3218b815fe8c01b0
) and test with
BOOST_NO_FENV_H
set.
For the definition of BOOST_NO_FENV_H
, we can
- ask to boost.build
- and/or mimic the behaviour of the patching inside boost.test directly, not directly by setting the
BOOST_NO_FENV_H
but by indicating the lack of those GNU extensions via the non definition of the macro
BOOST_TEST_FPE_SUPPORT_WITH_GLIBC_EXTENSIONS__
comment:54 by , 6 years ago
Yes, with BOOST_NO_FENV_H
set by the patch, version 1.63.0 of boost and the test module updated to commit 6f0d88ca9db00b449a795afa3218b815fe8c01b0 compiles for that toolchain.
I would say it is best to check for fenv.h, instead of depending on macro definition. But I do not know the boost build system...
comment:54 by , 6 years ago
Yes, with BOOST_NO_FENV_H
set by the patch, version 1.63.0 of boost and the test module updated to commit 6f0d88ca9db00b449a795afa3218b815fe8c01b0 compiles for that toolchain.
I would say it is best to check for fenv.h, instead of depending on macro definition. But I do not know the boost build system...
comment:55 by , 6 years ago
The thing is that fenv.h
is there, and hence this is normal that
BOOST_NO_FENV_H
is not defined. What is not normal is that
__GLIBC__
and
__USE_GNU
are also defined, which should not be the case (this is ulibC after all).
So my suggestion is not to define BOOST_NO_FENV_H
, but to not define
BOOST_TEST_FPE_SUPPORT_WITH_GLIBC_EXTENSIONS__
for the ulibC (this is the purpose of the macro).
I wanted to know if something outside of boost.test has changed, and this is indeed the case (boost.build or config).
But maybe I am missing sthg?
comment:56 by , 6 years ago
For whatever reasons uclibc defines both __UCLIBC__
and __GLIBC__
, whereas musl does not define any such macro, e.g. there is no __MUSL__
and will never be.
This is the commit log from the fenv.h patch used in Buildroot (I cannot add links here):
The boost build system does not properly test whether fenv.h is available, and if it is, if it supports all the features used by Boost. This causes build failures with uClibc (reported upstream at https://svn.boost.org/trac/boost/ticket/11756) but also with glibc on specific architectures that don't have a full fenv implementation, such as NIOSII or Microblaze. To address this, we forcefully disable the use of fenv support in the affected configurations.
I am afraid I am not much of help here. From my point of view, it should be checked if fenv.h is available, and then check for the GLIBC extensions.
comment:57 by , 6 years ago
I think it all makes sense, just re-iterating comment 12:
A fully standards conforming fenv.h does not have to define any FE_* macros, and if it does define them, then it defines macros only for the FP exceptions it actually supports.
So correct usage requires a triple check:
1) Check BOOST_NO_FENV_H to see if the header is supported. 2) Include the header and then check FE_ALL_EXCEPT to see if any FP exceptions are supported. 3) Before using the individual FE_* macros, you need to check for their existence too as not all may be supported. [...]
From my point of view, it should be checked if fenv.h is available, and then check for the GLIBC extensions.
So this is what is being done now. The fact that uclibc defines __GLIBC__
and __USE_GNU
without implementing the glibc extensions (on all arches it supports?) is the problem here.
Just adding a check for __UCLIBC__
into boost.test to guard usage of feenableexcept() etc. would be right if uclibc didn't implement them at all. I don't know if it does or not. I think it might for some arches?
comment:58 by , 6 years ago
I also agree that the problem seems to rather be on the side of uLibC right now. So what I suggest is to mimic the behavior of #comment:52 by adding this
// ... #if !defined(BOOST_NO_FENV_H) && !defined(BOOST_CLANG) && \ defined(__GLIBC__) && defined(__USE_GNU) && \ !(defined(__UCLIBC__) || defined(__nios2__) || defined(__microblaze__)) #define BOOST_TEST_FPE_SUPPORT_WITH_GLIBC_EXTENSIONS__ #endif // ...
like it was done for boost 1.61. This has the advantage to not define BOOST_NO_FENV_H
and focus the macro on the glibC extensions availability.
Can you quickly test the branch topic/11756-ulibc-disabling
?
Thanks
comment:59 by , 6 years ago
Unfortunately, trac does not accept my posting because it thinks it is spam. Now, my comment is lost...
So, I rewrite...
uClibc does have a fenv.h in the system directory path. It installs fenv.h to the sysroot path if it was configured with UCLIBC_HAS_FENV. However, this feature is only implemented for i386.
So, uClibc does have fenv.h, but does not necessarily implements and installs it. Furthermore, the following macros are defined:
BOOST_NO_FENV_H
is not defined__UCLIBC__
is defined__USE_GNU
is defined__GLIBC__
is defined
However, I think it is better to check with a test program if certain features are available, instead of relying on a bunch of macros:
1) check if feclearexcept()
is available => HAS_FENV
2) check for the macros => HAS_FENV_FE_xxx
3) check for the GNU extension => HAS_FENV_GNU
However, I am not familiar with the Boost build system.
comment:60 by , 6 years ago
Would you please quickly try the branch topic/11756-ulibc-disabling
and let me know if that works for you?
Again, uclibC should not define __USE_GNU
and/or
__GLIBC__
from my understanding. But it is more the level of the workaround what we are doing now.
comment:61 by , 6 years ago
Sorry, that part got lost because I had to rewrite: I've checked the branch without any patches from Buildroot and it compiles successfully.
comment:63 by , 6 years ago
Resolution: | → fixed |
---|---|
Status: | reopened → closed |
Merged to master, rev af78890325948bed598361966fa7f5fc9560c41d
. Closing as fixed, until next time :)
Same with Buildroot, e.g. http://autobuild.buildroot.net/results/28d/28db2fc2d6bffeb7c842fbcce2eeaf89ae5f8b01/build-end.log.
The problem is, that some architectures, currently do not implement FE_DIVBYZERO, even though they have <fenv.h> and feenableexcept().