I am migrating a project from STM32CubeIDE to CMake. It is a cross-compiled ARM project using the standard libraries (not nanolib). With CMake, it fails to link libc.a and links libg.a instead, with an error in CMakeError.log:
Compiling the C compiler identification source file "CMakeCCompilerId.c" failed.
Compiler: /usr/bin/arm-none-eabi-gcc
Build flags:
Id flags:
The output was:
1
/usr/lib/gcc/arm-none-eabi/10.3.1/../../../arm-none-eabi/bin/ld: /usr/lib/gcc/arm-none-eabi/10.3.1/../../../arm-none-eabi/lib/libc.a(lib_a-exit.o): in function `exit':
/build/newlib-pB30de/newlib-3.3.0/build/arm-none-eabi/newlib/libc/stdlib/../../../../../newlib/libc/stdlib/exit.c:64: undefined reference to `_exit'
collect2: error: ld returned 1 exit status
I checked my options, I do have: set(CMAKE_TRY_COMPILE_TARGET_TYPE "STATIC_LIBRARY")
My linker flags include: --specs=nosys.specs -flto
Now, following a forum suggestion, if I add -ffreestanding -nostdlib
it now tries to link libc.a, but I get a linker error:
/usr/lib/gcc/arm-none-eabi/10.3.1/../../../arm-none-eabi/bin/ld: /usr/lib/gcc/arm-none-eabi/10.3.1/../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-init.o): in function `__libc_init_array':
/build/newlib-pB30de/newlib-3.3.0/build/arm-none-eabi/thumb/v7e-m+fp/hard/newlib/libc/misc/../../../../../../../../newlib/libc/misc/init.c:40: undefined reference to `_init'
I fixed the issue by adding a weak and empty definition for _init (and _fini, while at it), but it still puzzles me that the STM IDE manages to link libc.a without any workaround, and I cannot, even if I am using the exact same toolchain.
Has anyone a guess on what could be happening?
Hmm. I see that CMake’s command line is missing (it’s just error messages). Can you get that from the internal project that it uses to detect this stuff?
I don’t get what info I should be looking for, should I check the options it used to compile “CMakeCCompilerId.c”? Or the generated makefile linker calls? I am not very fluent in CMake
The generated linker call for sure, but the command line could be helpful too while you’re in there (to make sure any other intended flags are getting through).
A header file problem would be detected at compile time. Something needs to provide the implementation of the symbols from syscalls.c in one of the object files or something you link to (probably libc.a, but why that’s not being found…).