When is libm.a needed?

Go To Last Post
6 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In the AVR-libc documentation of the math functions ( http://www.nongnu.org/avr-libc/u... ) it says as follows:

"In order to access the functions delcared herein, it is usually also required to additionally link against the library libm.a. See also the related FAQ entry."

What determines this? I have compiled a program that uses the 'sqrt' function and it curiously works without including the library. Does this mean that my code will work on other computers as well, or will it fail on some?

Normally I would just be happy that it works, but I need to explain this to someone, so I am curious why this is.

Can anyone shed some light on this?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The compiler has a generic support library (libgcc.a) that it will bind the weak references to things like sqrt() to if no other lib can first provide a "better" implementation. But that lib has not been written/optimised for the AVR8 - it's generic and principally for the I386 version of GCC and while it may work it isn't optimised for 8 bit and may be slow and bloaty and some of the functions simply produce incorrect results.

libm.a meanwhile is hand crafted for the AVR8 so it would be very unwise not to link against it so that it, rather than libgcc.a will provide the implementation. In fact the Mfile template includes a -lm in the LDFLAGS so if you use that to build you always link against libm.a anyway (nothing used if nothing called so there's no harm in the -lm). Sadly Atmel forgot to link against libm.a by default in the avr-gcc plugin for Studio so in that it's pretty important to add libm.a to the list of libraries to be linked against to overcome Atmel's shortcoming.

It'd be interesting to hear how the size of your program changes when you switch to using libm.a (there's a fairly strong chance it's going to get smaller and faster executing)

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Small correction: libgcc.a doesn't contain stuff like sqrt(), that one
is only in libm.a. libgcc.a really only contains (mostly automatically
generated) helper functions for things like "add two floating point
numbers" which are then used by the compiler. For historical reasons,
some of these functions have been replaced/superseded by improved
(manual assembly implementation) counterparts by the same name in libm.a.
They come into effect since libm.a, when requested on the command-line,
will be queried before libgcc.a is (the latter is implicitly appended by
the compiler driver to the end of the linker command).

Jörg Wunsch

Please don't send me PMs, use email if you want to approach me personally.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the feedback guys.

Jörg:
Where is the sqrt located if it is not in the libgcc.a?

In earlier versions of avr-gcc I seem to remember that it did not compile/link unless I added libm...

I did a small test and without libm my codesize is 3442 and when I use libm I get 1084 bytes, so there is a significant difference.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Did you happen to pass a constant to the sqrt function? If so, then it is possible that AVR GCC optimized the call into a constant instead of actually calling any function. Take a look at the assembly and see.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

EW: I double checked by making the variable volatile and get the same size difference by adding libm and not.