I have a large project with a custom Makefile building everything. This is for an ARM Cortex-M0.
One of the steps is to compile a Newlib syscalls.c
into syscalls.c.o
. That gets dumped into an archive file newlib.a
which in turn is linked to the final output.elf
for loading onto my device's flash.
$ arm-none-eabi-gcc -o output.elf .bld/*.c.o .bld/*.cpp.o .bld/libs/*.a -nostartfiles -mcpu=cortex-m0 -mthumb -Tlinker.ld -Wl,-Map=output.map --specs=nano.specs
If I follow the above procedure, sometimes the "Archive has no index":
.bld/libs/newlib.a: error adding symbols: Archive has no index; run ranlib to add one
And sometimes (I have not figured out how to deterministically make one or the other happen) I get an undefined reference even though _init()
is defined, as an empty function, in syscalls.c
.
c:/progra~2/gnutoo~1/50a5a~1.420/bin/../lib/gcc/arm-none-eabi/5.4.1/../../../../arm-none-eabi/lib/armv6-m\libc_nano.a(lib_a-init.o): In function `__libc_init_array':
init.c:(.text.__libc_init_array+0x1c): undefined reference to `_init'
However, if I skip the newlib.a
file and just directly link syscalls.c.o
into the final .elf
, it works as expected.
What about using an archive could be causing this issue? I've also tried reordering the arguments to the linker to no avail.
Note (edit)
I did notice the run ranlib to add one
instruction. However, this does not apply because:
- This is not necessary on other archives that I'm building, why is it needed here?
- That error doesn't happen anymore (after some fiddling. not sure what changed). The main issue is that
_init
is undefined.
Reference
I'm compiling other archive files in this build with no issues. The unique things here are that this archive only has one file in it and it's the only C-only archive. However, I don't see how this could affect things.
This is basically how I'm compiling
syscalls.c
and archiving the.o
file:$ arm-none-eabi-gcc newlib/syscalls.c -o .bld/newlib/syscalls.c.o -c -std=gnu11 -Wstrict-prototypes -nostartfiles -mcpu=cortex-m0 -mthumb -O2 -pipe -ffreestanding -funsigned-bitfields -Wall -Wfatal-errors -ffunction-sections -fdata-sections -MMD -MP -MF .bld/.dep/newlib/syscalls.c.o.d $ arm-none-eabi-ar rcs .bld/libs/newlib.a .bld/newlib/syscalls.c.o
gcc
versionarm-none-eabi-g++ (GNU Tools for ARM Embedded Processors) 5.4.1 20160919 (release) [ARM/embedded-5-branch revision 240496]
Simplified
syscalls.c
caddr_t _sbrk(int nbytes) __attribute__((externally_visible)); void _init(void) __attribute__((externally_visible)); /* c++ destructor dynamic shared object needed if -fuse-cxa-atexit is used*/ void *__dso_handle __attribute__ ((weak)); // defined in linker script extern caddr_t Heap_Bank1_Start; extern caddr_t Heap_Bank1_End; caddr_t _sbrk(int nbytes) { /* ... */ } void _init(void) {}