Linker error on a C project using Eclipse

75,738

Solution 1

I've looked at the toolkit you linked, just to read the following in the readme.txt:

This toolchain is built and optimized for Cortex-R/M bare metal development.

In other words, this toolchain is specifically configured for embedded systems, perhaps with no operating system running at all. In such case, there's no system to provide e.g. standard output where printf() is supposed to write, there's no file system, etc. - you have to link against some library providing these basic services, if you want to use them.

That said, your toolkit provides librdimon.a library which provides all those basic services. This library is actually a part of libgloss compilation. If you want to link against it, try the following command:

arm-none-eabi-gcc --specs=rdimon.specs   -Wl,--start-group -lgcc -lc -lm -lrdimon -Wl,--end-group -o test test.c

This links fine on my PC, but whether it's what you really want is another story (where do you expect to see printf() output, anyway?).

For you chip you should probably look for a library which redirects the standard output to serial port or provides debug output over JTAG. Alternatively, you can use your custom function e.g. sending debug output to serial console instead of printf() - it's up to you. If you decide on using printf() I suggest reading libgloss documentation.

Also, I suggest looking around for a toolchain which is specifically bundled for STM32 family. Properly configuring all this basic stuff (C library, linker script, etc.) requires a bit of experience.

Edit: Many embedded systems doesn't really use standard C library, starting pretty much from scratch. If you want to go this way, you should pass -nostdlib to your gcc invocation. Of course, you'll no longer have things like printf() available.

Edit 2: Another way is to use standard library (newlib, I mean) without libgloss and provide appropriate stubs for things you do not need. You might want to follow this tutorial, where _read and _write is implemented over the serial port, and everything else is stubbed. This is most likely what you really want.

Solution 2

I know this is an old question, but I ran into this today when trying to build for an STM32 board. The project I have has some linker scripts (specifically libs.ld). Adding an entry for libnosys.a in this satisfied the linker and I was able to continue.

libs.ld:

 GROUP(
   libgcc.a
   libg.a
   libc.a
   libm.a
   libnosys.a
 )

Solution 3

Saving your C program as "myprint.c", I compile it as follows:

arm-none-eabi-gcc myprint.c -lc -specs=nosys.specs

No errors and output is fine.

Solution 4

There also was such a problem with malloc() and free() function calls in the Eclipse project. I have written firmware for an STM32 microcontroller using Eclipse + GNU for ARM embedded GCC cross compiler + STM32CubeMX for microcontroller periphery initialization and linker script making.

When I have added missing strings libg.a ( * ) and libnosys.a ( * ) in the DISCARD section of .ld script, my project was build successfully.

Share:
75,738
damien
Author by

damien

Updated on September 03, 2021

Comments

  • damien
    damien over 2 years

    I want create a project for the STM32F217IG microcontroller.

    So I installed Eclipse and the GNU for ARM embedded GCC cross compiler. I don't think it is the Code Sourcery one. I used it, because it supports floating point and Code Sourcery does not.

    Once I did that I tried creating a really small project with only two sources files: test.c and main.c with only the following Code written in both of them:

    #include <stdlib.h>
    #include <stdio.h>
    
    int main (void)
    {
        printf("Hello, World!");
        return 0;
    }
    

    I changed the line command in the project property to replace GCC with arm-none-eabi-gcc and then tried to compile the project.

    I did not create any makefile myself; I used the automatic creation in Eclipse.

    The building seems to be fine, but when it comes to the linker I got the following errors in the console:

    make all
    'Building target: test3'
    'Invoking: Cross GCC Linker'
    arm-none-eabi-gcc  -o"test3"  ./main.o ./test3.o
    
    c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libc.a(lib_a-exit.o): In function `exit':
    exit.c:(.text.exit+0x2c): undefined reference to `_exit'
    
    c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libc.a(lib_a-sbrkr.o): In function `_sbrk_r':
    sbrkr.c:(.text._sbrk_r+0x18): undefined reference to `_sbrk'
    
    c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libc.a(lib_a-writer.o): In function `_write_r':
    writer.c:(.text._write_r+0x20): undefined reference to `_write'
    
    c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libc.a(lib_a-closer.o): In function `_close_r':
    closer.c:(.text._close_r+0x18): undefined reference to `_close'
    
    c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libc.a(lib_a-fstatr.o): In function `_fstat_r':
    fstatr.c:(.text._fstat_r+0x1c): undefined reference to `_fstat'
    
    c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libc.a(lib_a-isattyr.o): In function `_isatty_r':
    isattyr.c:(.text._isatty_r+0x18): undefined reference to `_isatty'
    
    c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libc.a(lib_a-lseekr.o): In function `_lseek_r':
    lseekr.c:(.text._lseek_r+0x20): undefined reference to `_lseek'
    
    c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libc.a(lib_a-readr.o): In function `_read_r':
    readr.c:(.text._read_r+0x20): undefined reference to `_read'
    
    collect2: ld returned 1 exit status
    
    make: *** [test3] Erreur 1
    

    I looked on the Internet, and I found that it may be a syscall problem. But I don't know how I add this library to my project on Linux.

    Is that really the problem? If yes, how do I fix it? And if not, where is the error coming from?

    As someone suggested, I tried "linking" the C runtime library. In Eclipse it seems I have two solutions to do it:

    First on the project properties → C/C++BuildSettingsCross linkerlibraries. I just add the letter c and then the error does not change, but there is -lc at the end of the command line:

     make all
    'Building target: test3'
    'Invoking: Cross GCC Linker'
    arm-none-eabi-gcc  -o"test3"  ./main.o ./test3.o   -lc
    
    c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libc.a(lib_a-exit.o): In function `exit':
    exit.c:(.text.exit+0x2c): undefined reference to `_exit'
    
    c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libc.a(lib_a-sbrkr.o): In function `_sbrk_r':
    sbrkr.c:(.text._sbrk_r+0x18): undefined reference to `_sbrk'
    
    c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libc.a(lib_a-writer.o): In function `_write_r':
    writer.c:(.text._write_r+0x20): undefined reference to `_write'
    
    c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libc.a(lib_a-closer.o): In function `_close_r':
    closer.c:(.text._close_r+0x18): undefined reference to `_close'
    
    c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libc.a(lib_a-fstatr.o): In function `_fstat_r':
    fstatr.c:(.text._fstat_r+0x1c): undefined reference to `_fstat'
    
    c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libc.a(lib_a-isattyr.o): In function `_isatty_r':
    isattyr.c:(.text._isatty_r+0x18): undefined reference to `_isatty'
    
    c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libc.a(lib_a-lseekr.o): In function `_lseek_r':
    lseekr.c:(.text._lseek_r+0x20): undefined reference to `_lseek'
    
    c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib\libc.a(lib_a-readr.o): In function `_read_r':
    readr.c:(.text._read_r+0x20): undefined reference to `_read'
    
    collect2: ld returned 1 exit status
    make: *** [test3] Erreur 1
    

    But I don't know if it is really means to add the C runtime library.

    Second, I added the libc.a library in the project properties → C/C++ generalPath and symbolsLibraries, and here is what I get (completely different):

    make all
    'Building target: test3'
    'Invoking: Cross GCC Linker'
    arm-none-eabi-gcc  -o"test3"  ./main.o ./test3.o   -l"C:/Program\ Files/GNU\ Tools\ ARM\ Embedded/4.6\ 2012q4/arm-none-eabi/lib/armv7-m/libc.a"
    
    c:/program files/gnu tools arm embedded/4.6 2012q4/bin/../lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/bin/ld.exe: cannot find -lC:/Program\ Files/GNU\ Tools\ ARM\ Embedded/4.6\ 2012q4/arm-none-eabi/lib/armv7-m/libc.a
    
    collect2: ld returned 1 exit status
    make: *** [test3] Erreur 1
    

    Then it still does not work, but is it the good way to search on?

    Oh and a very interesting fact:

    I got the errors only in debug mode. If I am in release mode everything is okay, and I don't have any errors (except if I add the libc.a then I think this is not the best thing to do). Does that mean the problem is the .elf file creation?