1

I designed a static library for use in my AVR projects, but I'm having trouble linking it to an application. It reports this error:

libteleobjects/libteleobjects.a(telesignals.c.obj): In function `telesignal_get_event_data':                                                               
/home/claudio/git/ucp-usc64/libteleobjects/telesignals.c:559: undefined reference to `__mulhi3'
/home/claudio/git/ucp-usc64/libteleobjects/telesignals.c:561: undefined reference to `__mulhi3'
/home/claudio/git/ucp-usc64/libteleobjects/telesignals.c:561: undefined reference to `__mulhi3'
/home/claudio/git/ucp-usc64/libteleobjects/telesignals.c:561: undefined reference to `__mulhi3'

I found an interesting investigation to the same problem here, but since his solution is all about ADA I have no idea how to fix it in my case, which is a C application. It gave me nice tips though, like using avr-nm to search for this symbol in the system libraries. Unlike in his case, here the symbol __mulhi3 displays as U (undefined) even in the avr system libs where it was supposed to be found (libgcc.a for his libs from AVR-GCC 4.7.2 - mine is 4.8.0), so I guess the __mulhi3 is not defined at all(!?). I would expect it should appear as T (defined in the text section) in the system libs (.a files in /usr/avr/lib and subdirs). Any tips? As a sidenote, I'm using CMake as the build system.

EDIT:

Like suggested here and in the answer below, adding the math library to the end of linking would supposedly solve the problem, but CMake is already doing it and it didn't work yet:

Linking C executable ucp-usc64.elf
/usr/bin/cmake -E cmake_link_script CMakeFiles/ucp-usc64.dir/link.txt --verbose=1
/usr/bin/avr-gcc  -g -Os       -mcall-prologues -ffunction-sections -fdata-sections -Os -DNDEBUG -w -mcall-prologues -ffunction-sections -fdata-sections  -Wl,--gc-sections -lm -Wl,--gc-sections -lm -mmcu=atmega644p  CMakeFiles/ucp-usc64.dir/main.c.obj CMakeFiles/ucp-usc64.dir/modutr_callbacks.c.obj  -o ucp-usc64.elf  -lc -lm avr-drivers/libavr_drivers.a modutr-slave/lib/libmodutr_slave.a libteleobjects/libteleobjects.a -lc -lm 
libteleobjects/libteleobjects.a(telesignals.c.obj): In function `telesignal_get_event_data':
/home/claudio/git/ucp-usc64/libteleobjects/telesignals.c:559: undefined reference to `__mulhi3'
/home/claudio/git/ucp-usc64/libteleobjects/telesignals.c:561: undefined reference to `__mulhi3'
/home/claudio/git/ucp-usc64/libteleobjects/telesignals.c:561: undefined reference to `__mulhi3'
/home/claudio/git/ucp-usc64/libteleobjects/telesignals.c:561: undefined reference to `__mulhi3'
collect2: error: ld returned 1 exit status
Claudio
  • 2,191
  • 24
  • 49
  • can I see your build script? – washcloth Feb 12 '14 at 17:54
  • 2nded. Post you CMakesists.txt plz – Joshua Clayton Feb 12 '14 at 17:58
  • @ExcelledProducts, since I'm using CMake, it makes up the linking "under the hood", so I guess this would be the build script for the linking part (`link.txt` file): `/usr/bin/avr-gcc -g -Os -mcall-prologues -ffunction-sections -fdata-sections -Os -DNDEBUG -w -mcall-prologues -ffunction-sections -fdata-sections -Wl,--gc-sections -lm -Wl,--gc-sections -lm -mmcu=atmega644p CMakeFiles/ucp-usc64.dir/main.c.obj CMakeFiles/ucp-usc64.dir/modutr_callbacks.c.obj -o ucp-usc64.elf -lc -lm avr-drivers/libavr_drivers.a libteleobjects/libteleobjects.a modutr-slave/lib/libmodutr_slave.a -lc -lm` – Claudio Feb 12 '14 at 18:06
  • You may want to try with a g++ or gcc compiler with the -l linking all the libraries. That is what your error means. That you are not linking a library. – washcloth Feb 12 '14 at 18:09

2 Answers2

1

What does your CMake target_link_libraries argument look like?

My guess is you need to add "m" (lower case m) to pull in the math library.

Joshua Clayton
  • 1,669
  • 18
  • 29
  • Does the line above hint anything to you Joshua? I see the `-lm` in many places, although I really didn't specify it in LDFLAGS or anything like that (I guess CMake included it by itself). – Claudio Feb 12 '14 at 18:08
  • My `target_link_libraries` looks like this: `target_link_libraries(ucp-usc64 avr_drivers teleobjects_static lib_modutr_slave_static)`. I'll append the `-lm` in the end to check it out, but I guess CMake already did it, like shown above - `teleobjects_static` is CMake's target name for `libteleobjects.a` lib. – Claudio Feb 12 '14 at 18:13
  • @Claudio I edited my reply, I remembered after I posted that Cmake wants just "m" in the target_link_libraries for "-lm" – Joshua Clayton Feb 12 '14 at 18:17
  • Joshua, if I add either `-lm` or `m` the result is the same, it just adds another `-lm` by the end of the linker line (it even ends up duplicated, because CMake already put the first one), but it still doesn't work. – Claudio Feb 12 '14 at 18:24
  • The ada related link seemed to think the missing define was in libgcc.a, perhaps you should try adding "gcc" or "static-libgcc.a"? – Joshua Clayton Feb 12 '14 at 19:28
  • Unfortunately adding `-lgcc` doesn't work either. And it is really funny that symbol `__mulhi3` shows as `U` (undefined?) by `avr-nm` in any of the gcc static libs (those found at /usr/avr/lib and its subdirs). – Claudio Feb 13 '14 at 13:18
  • Maybe your library paths have something getting the wrong library version for your MCU, or generic libraries taking precedence? Seehttp://www.avrfreaks.net/index.php?name=PNphpBB2&file=printview&t=76720&start=0 – Joshua Clayton Feb 13 '14 at 19:16
  • Joshua, I found I was misled by not finding the symbol in /usr/avr/lib, in my system the symbol `__mulhi3` is really defined in /usr/lib/gcc/avr/4.8.0/libgcc.a, I just didn't post the solution yet because I'm very busy right now.. but thanks for the help and suggestions anyway! – Claudio Feb 13 '14 at 20:11
1

The symbol __mulhi3 is indeed defined by libgcc.a, like previously hinted by this link. The problem was that, when CMake's variable CMAKE_BUILD_TYPE was set to Release, the following flags are used (set through CMAKE_CXX_FLAGS_RELEASE):

-Os -DNDEBUG -mcall-prologues -ffunction-sections -fdata-sections -fno-exceptions

and it appears the use of optimization -Os causes the internal GCC function __mulhi3 to be used. In that situation, somehow CMake wasn't looking for libgcc.a in the place where it is in my system, which is /usr/lib/avr/gcc/4.8.0/libgcc.a.

I already knew beforehand undefined reference errors always happen when a library or object file defining a symbol is not linked in, and everybody helping me here were pointing in the right direction too, but I was really misled by the fact I was looking for libgcc.a in the wrong place like this:

cd /usr/avr/lib
find -name "*.a" -exec avr-nm {} \; | grep "__mulhi3"

That was just returning loads of __mulhi3 marked as U, which meant it should be defined somewhere else. Just after checking up my package contents for avr-gcc I found libgcc.a was placed at /usr/lib/gcc/avr/4.8.0.

Turns out in the end the whole problem was more related to CMake not being pointed the right place to look for libgcc.a, which I got to work by adding the line:

set(CMAKE_EXE_LINKER_FLAGS "-L /usr/lib/gcc/avr/4.8.0")

to CMakeLists.txt, which causes the following and successful linker invocation:

/usr/bin/avr-gcc  -Wall -Os -DNDEBUG -w -mcall-prologues -ffunction-sections -fdata-sections  -L /usr/lib/gcc/avr/4.8.0 -Wl,--gc-sections -lm -mmcu=atmega644p  CMakeFiles/ucp-usc64.dir/main.c.obj CMakeFiles/ucp-usc64.dir/modutr_callbacks.c.obj  -o ucp-usc64.elf  -lc -lm avr-drivers/libavr_drivers.a libteleobjects/libteleobjects.a modutr-slave/lib/libmodutr_slave.a -lc -lm 
Claudio
  • 2,191
  • 24
  • 49