clinuxgccuclibcfloating-point-exceptions

How to solve undefined reference to functions in fenv.h when using uclibc?


I'm trying to test some of the functions in fenv.h, however, when I compile the below function ld fails with undefined reference to 'feclearexcept' and undefined reference to 'fetestexcept'. I'm running hardened gentoo compiled against uclibc, and I suspect that this is at least somewhat related

#include <stdio.h>      /* printf */
#include <math.h>       /* sqrt */
#include <fenv.h>      
#pragma STDC FENV_ACCESS on

int main ()
{
  feclearexcept (FE_ALL_EXCEPT);
  sqrt(-1);
  if (fetestexcept(FE_INVALID)) printf ("sqrt(-1) raises FE_INVALID\n");
  return 0;
}

fenv.h is in /usr/include. There are static and dynamic libraries (libm.a, libm.so) in /usr/lib. I am compiling with gcc -o test test.c -lm; does anyone have any ideas why the linker can't find the relevant functions. It seems like nothing in fenv.h has a corresponding library.

UPDATE: this decade old blog post seems to suggest that fenv is not supported by uclibc. I cannot determine if this is the case still, but if it were is there anything to be done. http://uclibc.10924.n7.nabble.com/missing-fenv-h-for-qemu-td2703.html


Solution

  • Libraries go last, try compiling with

    $ gcc -o test test.c -lm
    

    I tried your exact program on my x86_64 Linux system with the above compilation statement, it built and ran just fine:

    $ gcc -o fenv fenv.c -lm
    $ ./fenv
    sqrt(-1) raises FE_INVALID
    

    My resulting binary had the following dependencies:

    $ ldd ./fenv
        linux-vdso.so.1 =>  (0x00007ffd924b7000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fca457e8000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fca4541e000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fca45af0000)
    

    I also verified that the functions from fenv.h really do live in the math library:

    emil@synapse:~/data/src$ strings /lib/x86_64-linux-gnu/libm.so.6 | grep -E ^fe
    feclearexcept
    fegetexceptflag
    feraiseexcept
    fesetexceptflag
    fetestexcept
    fegetround
    fesetround
    fegetenv
    feholdexcept
    fesetenv
    feupdateenv
    fedisableexcept
    feenableexcept
    fegetexcept
    

    So perhaps there's something else wrong in your setup.