使用Eclipse的C项目上的链接器错误

时间:2012-11-05 15:59:36

标签: eclipse gcc linker arm gnu

我想为STM32F217IG微控制器创建一个项目。

然后我安装了Eclipse和GNU for ARM embedded GCC cross compiler。我不认为这是Code Sourcery。我使用它,因为它支持浮点,而Code Sourcery则不支持。

一旦我这样做了,我尝试创建一个只有两个源文件的小项目:test.c和main.c,只用两个文件编写:

#include <stdlib.h>
#include <stdio.h>

int main (void)
{
    printf("Hello, World!");
    return 0;
}

我更改了项目属性中的line命令,用arm-none-eabi-gcc替换GCC,然后尝试编译项目。

我自己没有创建任何make文件;我在Eclipse中使用了自动创建。

该建筑看起来很好,但是当谈到链接器时,我在控制台中遇到以下错误:

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

我在网上看了一下,发现这可能是一个系统调用问题。但我不知道如何在Linux上将这个库添加到我的项目中。

真的吗?如果是,我该如何解决?如果没有,那会是从哪里来的?

正如有人建议的那样,我尝试“链接”C运行时库。在Eclipse上,似乎我有两个解决方案:

首先在项目属性→ C / C ++ 构建设置交叉链接器文库。我只是添加了字母c,然后错误没有改变,但命令行末尾有-lc

 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

但我不知道它是否真的意味着添加C运行时库。

其次,我在项目属性→ C / C ++ general 路径和符号中添加了libc.a库,并且这是我得到的(完全不同的):

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

然后它仍然不起作用,但它是搜索的好方法吗?

哦,这是一个非常有趣的事实:

我只在调试模式下得到错误。如果我处于发布模式,一切都没问题,我没有任何错误(除非我添加了libc.a然后我认为这不是好事)。这是否意味着问题是.elf文件创建?

5 个答案:

答案 0 :(得分:28)

我查看了您链接的工具包,只是为了阅读readme.txt中的以下内容:

  

此工具链针对Cortex-R / M裸机开发而构建和优化。

换句话说,此工具链专门为嵌入式系统配置,可能根本没有运行任何操作系统。在这种情况下,没有系统可以提供例如printf()应该写的标准输出,没有文件系统等等 - 如果你想使用它们,你必须链接到提供这些基本服务的某个库。

也就是说,您的工具包提供了librdimon.a库,它提供了所有这些基本服务。该库实际上是libgloss编译的一部分。如果要链接它,请尝试以下命令:

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

这在我的电脑上链接得很好,但是你真正想要的是另一个故事(你希望在哪里看到printf()输出?)。

对于你的芯片你应该寻找一个库,它将标准输出重定向到串口或通过JTAG提供调试输出。或者,您也可以使用自定义功能,例如将调试输出发送到串行控制台而不是printf() - 这取决于您。 如果您决定使用printf(),建议您阅读libgloss文档。

另外,我建议四处寻找专为STM32系列捆绑的工具链。正确配置所有这些基本内容(C库,链接器脚本等)需要一些经验。

编辑:许多嵌入式系统并不真正使用标准C库,从头开始。如果您想这样做,则应将-nostdlib传递给gcc调用。当然,你将不再拥有像printf()这样的东西。

编辑2:另一种方法是使用不带newlib的标准库(libgloss),并为不需要的东西提供适当的存根。您可能需要关注this tutorial,其中_read_write是通过串口实现的,其他所有内容都是存根的。这很可能是你真正想要的。

答案 1 :(得分:9)

我知道这是一个古老的问题,但今天我在尝试构建STM32主板时遇到了这个问题。我的项目有一些链接器脚本(特别是libs.ld)。在libnosys.a中添加一个条目就满足了链接器,我能够继续。

libs.ld:

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

答案 2 :(得分:6)

将您的C程序保存为&#34; myprint.c&#34;,我将其编译如下:

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

没有错误,输出也没问题。

答案 3 :(得分:3)

Eclipse项目中的malloc()free()函数调用也存在这样的问题。我为STM32微控制器编写了固件,使用Eclipse + GNU for ARM嵌入式GCC交叉编译器+ STM32CubeMX进行微控制器外围初始化和链接器脚本制作。

当我在libg.a脚本的 DISCARD 部分添加了缺少的字符串libnosys.a(*)和.ld(*)时,我的项目已成功构建

答案 4 :(得分:0)

我使用CubeMX创建了一个RTOS项目并添加了一个printf,并在使用OpenOCD进行调试时遇到了相同的链接问题。

我用trace_puts替换了printf(“Hello ARM World!”)(“Hello ARM World!”);和 将消息显示在调试控制台中。