raspberry-piarmcross-compilinglibclibm

no implementation of __fpclassify in armhf


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?


Solution

  • 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:

    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.