【问题标题】:Linker error on a C project using Eclipse使用 Eclipse 的 C 项目上的链接器错误
【发布时间】:2012-10-25 12:05:23
【问题描述】:

我想为 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;
}

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

我自己没有创建任何makefile;我在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++BuildSettingsCross linker图书馆。我只是添加了字母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++通用路径和符号中添加了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 文件的创建?

【问题讨论】:

  • 请将源代码格式化成可读的格式,拜托!提供链接器命令行,有关您的工具链的更多详细信息(我只能猜测它是 Code Sourcery/Mentor 工具链)等。
  • 我编辑了我的问题我对这一切都很陌生,所以我真的不知道你需要回答这个问题的信息,如果你需要更多告诉我,我会再次编辑
  • 如果引用文件名,空格不需要转义:所以它应该是... -l"C:/Program Files/GNU Tools ARM Embedded/4.6 2012q4/arm-none-eabi/lib/armv7-m/libc.a"... -lC:/Program\ Files/GNU\ Tools\ ARM\ Embedded/4.6\ 2012q4/arm-none-eabi/lib/armv7-m/libc.a
  • 好的,但我不知道如何更改它,无论如何,当我们阅读错误时,它是:ld.exe: cannot find -lC:/Program\ Files/GNU\ Tools\ ARM\ Embedded/4.6\ 2012q4/arm-none-eabi/lib/armv7-m/libc.a 这是你的第二个建议,那么我认为命令行有一个很好的语法,即使它不行吗?
  • 根据您的代码,您可能希望删除这些函数...它们是:extern "C" { void _exit( int status ) { while (1); } 无符号整数 _getpid() { 返回 0; } int _kill( int id, int sig ) { 返回 0; } void _sbrk( int id) {} int _fstat (int fd, void* buf) { return 0; } int _write( int fd, char *buf, int count ) { return 0; } int _read( int fd, char *buf, int count ) { return 0; } int _lseek( int fd, int count ) { 返回 0; } int _close( int fd ) { 返回 0; } int _isatty( int fd ) { 返回 0; } }

标签: eclipse gcc linker arm gnu


【解决方案1】:

我查看了您链接的工具包,只是为了阅读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

此链接在我的 PC 上很好,但是否是您真正想要的则是另一回事(无论如何,您希望在哪里看到 printf() 输出?)。

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

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

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

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

【讨论】:

  • 感谢您的回答,即使我不知道在 Eclipse 中应该在哪里执行此命令。碰巧有人知道是否有专门为 STM32 系列捆绑的工具链吗?
  • 为了回答你的问题,我没想到会在任何地方看到 printf()。我只是想做一个简单的项目并编译和链接它,以确保这个工具链以后可以用于我的项目。顺便说一句,如果是库问题,为什么我只会在调试模式下而不是在发布模式下收到错误?
  • 既然你提到了 printf,我只是评论了我项目中的所有 printf,这就是发生的事情:即使只是一个错误,我仍然有错误:'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' collect2: ld returned 1 exit status make: *** [test3] Erreur 1 这与错误完全相同我之前得到的第一个
  • 嗯,不完全是,我会说 - 它仍然抱怨例如_write()?无论如何,_exit() 也是libgloss 的一部分,引用自newlib,您需要提供一些实现,或者放弃标准库。让我更新我的答案。
  • 实际上我设法添加了 rdimon 库,并且链接正常。非常感谢。我现在需要能够生成一个elf文件,目前不是这样,我不知道为什么
【解决方案2】:

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

libs.ld:

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

【讨论】:

  • 重要的是要了解nosys stub 几乎所有内容 - 因此上面的HelloWorld 将编译和链接,但不会做任何事情,因为文件 I/O 也被存根。
【解决方案3】:

将你的C程序保存为“myprint.c”,我编译如下:

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

没有错误,输出很好。

【讨论】:

    【解决方案4】:

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

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

    【讨论】:

      【解决方案5】:

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

      我将 printf("Hello ARM World!") 替换为 trace_puts("Hello ARM World!");和 消息是否出现在调试控制台中。

      【讨论】:

        猜你喜欢
        • 2021-07-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-08
        • 1970-01-01
        • 2017-05-26
        • 2014-10-26
        相关资源
        最近更新 更多