【问题标题】:Undefined reference to _write, which is implemented in a library未定义的 _write 引用,在库中实现
【发布时间】:2021-09-07 02:26:54
【问题描述】:

在我的嵌入式项目中,我收到了 printf 语句所需的未定义的 _write 引用。使用 arm-none-eabi-gcc 9.3.1。

uart.c实现_write,如下图:

int _write(int file, char* ptr, int len) __atribute__ ((used));
int _write(int file, char* ptr, int len)
{
   ...
}
void foo()
{
   nop();
}

uart.c 被编译成静态库,在编译可执行文件时链接。

这里是 main.c:

int main()
{
   //foo();
   printf("Hello world!");
}

注释掉foo();,我得到undefined reference to '_write'。取消注释 foo(); 后,项目将按预期构建。如何在不包含虚拟函数的情况下构建它?

构建步骤:

arm-none-eabi-gcc -c uart.c
ar rvs uart.a uart.o
arm-none-eabi-gcc main.c uart.a

【问题讨论】:

  • @Someprogrammerdude 不,在这种情况下不是。库 grepping write 的 Objdump 返回:00000000 g F .text._write 00000018 _write
  • uart.c is compiled into a static library, which is linked while compiling the executable. 请显示编译命令。参数的顺序是什么?
  • @KamilCuk 我用我的构建步骤更新了问题
  • 能否请您逐字发布您收到的所有错误消息?你没有得到undefined reference to _lseekundefined reference to _exit等吗?也请s/__atribute__/__attribute__
  • @KamilCuk 我发布的文件只是我的大型 cmake 项目的简化。我在 cmake 项目中遇到的唯一错误是:writer.c:(.text._write_r+0x10): undefined reference to '_write'。是的,我也得到了对其他人的未定义引用,但在我的 cmake 项目中我没有,因为它们是在正确链接的其他文件中定义的。

标签: c gcc arm


【解决方案1】:

问题是标准库是在您的库之后链接的

arm-none-eabi-gcc -v main.c uart.a
...
/usr/lib/gcc/arm-none-eabi/11.1.0/collect2 ....
        uart.a
        --start-group -lgcc -lc --end-group
        /usr/lib/gcc/arm-none-eabi/11.1.0/crtend.o /usr/lib/gcc/arm-none-eabi/11.1.0/crtn.o

这是有道理的,但是-lc 找不到来自uart.a 的东西。你可以:

  1. uart.a之前先包含-lc你自己
  2. 或使用--whole-archive 并包含uart.a

测试:

// main.c
#include <stdio.h>
int main() {
    printf("Hello wolrd\n");
}

// uart.c
#define nop()  __asm__("nop")
void _exit(int a) { for(;;); }
int _sbrk() { return -1; }
int _close() { return -1; }
int _read() { return -1; }
int _fstat() { return -1; }
int _isatty() { return -1; }
int _lseek() { return -1; }

int _write(int file, char* ptr, int len)
{
   nop();
}
void foo()
{
   nop();
}

// Makefile
all:
    arm-none-eabi-gcc -c uart.c
    ar rvs uart.a uart.o
    arm-none-eabi-gcc main.c -lc uart.a
    arm-none-eabi-gcc main.c -Wl,--whole-archive uart.a -Wl,--no-whole-archive

【讨论】:

  • 啊,非常感谢这修复了它!对于非完整的最小可重现示例感到抱歉,我不确定 cmake 构建是如何工作的。
猜你喜欢
  • 2015-11-09
  • 2015-02-26
  • 1970-01-01
  • 2020-07-21
  • 2019-01-17
  • 1970-01-01
  • 1970-01-01
  • 2022-01-02
  • 1970-01-01
相关资源
最近更新 更多