I'm cross-compiling for Raspberry Pi 4B using ARM's 10.3-2021.07 GCC toolchain (specifically this file uncompressed into ARMGCC
). I'm also using the latest Raspberry OS image as sysroot (loop-mounted into RPISYSROOT
). The host is an Ubuntu Xenial VM on a Windows host.
When using this compilation line (edited for readability, CFLAGS
inspired by the Pi's /proc/cpuinfo
, gentoo and GNU):
${ARMGCC}/bin/arm-none-linux-gnueabihf-g++ -std=c++11 \
-v -w -fexceptions -fpermissive --sysroot=$RPISYSROOT \
-pipe -mcpu=cortex-a72 -mfpu=neon-vfpv4 -mfloat-abi=hard -g \
-I . -I .. -I libA/include -I libB/include \
-I ${ARMGCC}/arm-none-linux-gnueabihf/libc/usr/include \
-I ${RPISYSROOT}/usr/include/arm-linux-gnueabihf \
-c file.cpp -o obj/debug/file.o
I get the following error:
$ARMGCC/arm-none-linux-gnueabihf/libc/usr/include/bits/mathcalls-helper-functions.h:20:24: error: ‘__fpclassify’ has not been declared
20 | __MATHDECL_ALIAS (int, __fpclassify,, (_Mdouble_ __value), fpclassify)
| ^~~~~~~~~~~~
I see uses of __fpclassify
in ARMGCC
, RPISYSROOT
and Raspberry Pi's tools git repo and they seem to be all iterations of the same files:
usr/include/math.h
usr/include/bits/mathcalls-helper-functions.h
(paths may vary slightly). However, none of these provide declarations or implementations of __fpclassify
. This seems to come from libm
which, I think, has been a part of libc
for a while now. I've already installed libc onto RPISYSROOT
.
The only implementation I've found is from uCLibc but I don't think mixing libc implementations is a good idea.
Also, since the Raspberry Pi is armhf, should I be seeing these errors?
The issue here is a mixing of the two sets of headers, those of the build chain (ARMGCC
) and those of the specified system root (RPISYSROOT
). In particular, presuming a file.cpp
which looks something like:
#include <cmath>
void function(void) {}
your compilation command will perform the following nested includes:
${ARMGCC}/arm-none-linux-gnueabihf/include/c++/10.3.1/cmath
${RPISYSROOT}/usr/include/math.h
${ARMGCC}/arm-none-linux-gnueabihf/libc/usr/include/bits/mathcalls-helper-functions.h
The specific error you are receiving (mentioning __fpclassify
) is a bit misleading, because what is most relevantly undefined at that point is the __MATHDECL_ALIAS
function-like macro, which is defined in ${ARMGCC}/arm-none-linux-gnueabihf/libc/usr/include/math.h
.
If you look at the same file under RPISYSROOT
, you can see that it uses __MATHDECL_1
instead:
/* Classify given number. */
__MATHDECL_1 (int, __fpclassify,, (_Mdouble_ __value))
__attribute__ ((__const__));
which is defined in ${RPISYSROOT}/usr/include/math.h
.
So what you need to do is ensure that ${RPISYSROOT}/usr/include/arm-linux-gnueabihf/bits/mathcalls-helper-functions.h
is included instead of the ARMGCC
counterpart, which you can do by changing the order of includes in your compilation command. Reducing your command to its essentials, we have:
${ARMGCC}/bin/arm-none-linux-gnueabihf-g++ \
--sysroot=${RPISYSROOT} \
-I ${ARMGCC}/arm-none-linux-gnueabihf/libc/usr/include \
-I ${RPISYSROOT}/usr/include/arm-linux-gnueabihf \
-c file.cpp \
-o obj/debug/file.o
which fails as above. Changing this to:
${ARMGCC}/bin/arm-none-linux-gnueabihf-g++ \
--sysroot=${RPISYSROOT} \
-I ${RPISYSROOT}/usr/include/arm-linux-gnueabihf \
-I ${ARMGCC}/arm-none-linux-gnueabihf/libc/usr/include \
-c file.cpp \
-o obj/debug/file.o
compiles successfully.
In fact, for this case we can remove the explicit reference to any ARMGCC
includes, with the following:
${ARMGCC}/bin/arm-none-linux-gnueabihf-g++ \
--sysroot=${RPISYSROOT} \
-I ${RPISYSROOT}/usr/include/arm-linux-gnueabihf \
-c file.cpp \
-o obj/debug/file.o
which also compiles.