Linking requires to link two static libs that depend on each other: undefined reference

1k views Asked by At

I know, that was already asked a million of times... Unfortunately.

But however, I' working on metal builds for ARM Cortex M4 Processors. So there aren't any shared libs, just static ones. When linking my program with gcc, it throws the following error:

$ arm-none-eabi-gcc -Wall lots_of_code.o libFW.a
arm-none-eabi/4.7.4/../../../../arm-none-eabi/lib/armv7e-m/fpu/libg.a(lib_a-exit.o):
In function `exit':
exit.c:(.text.exit+0x16): undefined reference to `_exit'
collect2: error: ld returned 1 exit status

libFW.a is a lib I created containing a file called syscalls.o providing _exit():

$ arm-none-eabi-nm -s libFW.a | grep _exit
_exit in syscalls.o
00000018 T _exit

I seems to me that gcc tries to link libg.a and lots_of_code.o but doesn't know about _exit() yet. But the weird thing is the following: It works properly when linking directly to syscalls.o:

$ arm-none-eabi-gcc -Wall lots_of_code.o syscalls.o libFW.a

What could cause this?

1

There are 1 answers

2
Jonathan Leffler On

When you force link the object file by specifying it on the link command line, it is built into the program, regardless of whether it provides any needed symbols or not. When you link it from a library, it will only be included in the program if it satisfies at least one of the undefined symbols at the time the library is read.

It is a bad idea to have circular dependencies between static libraries. The workaround is to link libraries twice. It is also usually a bad idea to replace system-provided functions such as exit() with your own incarnation of it. It looks like the C library is picking up an exit() which calls _exit() but for some reason, there is no _exit() in the libraries linked after that. It is all a bit odd, quite frankly. Why do you think your syscalls.o is better than the facilities provided by the compiler (O/S)? If you need to force link your system calls, you need to have references to one of the symbols defined in syscalls.o before you link the main C library (where there are lots of such calls).