首页 > 解决方案 > 未定义的 _write 引用,在库中实现

问题描述

在我的嵌入式项目中,我得到了 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

标签: cgccarm

解决方案


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

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. 先包括-lc自己uart.a
  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

推荐阅读