I'm getting undefined reference to _write, required by a printf statement, in my embedded project. Using arm-none-eabi-gcc 9.3.1.
uart.c implements _write, as shown below:
int _write(int file, char* ptr, int len) __atribute__ ((used));
int _write(int file, char* ptr, int len)
{
...
}
void foo()
{
nop();
}
uart.c is compiled into a static library, which is linked while compiling the executable.
Here is main.c:
int main()
{
//foo();
printf("Hello world!");
}
With foo();
commented out, I get undefined reference to '_write'
. With foo();
uncommented, the project builds as expected. How can I get it to build without including a dummy function?
Build steps:
arm-none-eabi-gcc -c uart.c
ar rvs uart.a uart.o
arm-none-eabi-gcc main.c uart.a
The problem is that the standard library is linked after your library:
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
which makes sense, but then -lc
can't find stuff from uart.a
. You can:
-lc
yourself first before uart.a
--whole-archive
and include uart.a
.Tested with:
// 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