# Linker does not link libc.a

**URL:** https://discourse.cmake.org/t/linker-does-not-link-libc-a/8711
**Category:** Usage
**Tags:** os:linux
**Created:** [August 10, 2023, 9:15am UTC](https://discourse.cmake.org/t/linker-does-not-link-libc-a/8711 "2023-08-10T09:15:21Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![everedero](https://discourse.cmake.org/user_avatar/discourse.cmake.org/everedero/32/3699_2.png) [@everedero](https://discourse.cmake.org/u/everedero)
#### Post date: [August 10, 2023, 9:15am UTC](https://discourse.cmake.org/t/linker-does-not-link-libc-a/8711/1 "2023-08-10T09:15:21Z")

</div>

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:

```auto
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:

```auto
/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?

Some similar topics I read:

> [@Is CMakeCCompilerId.c used on the target or host system? How to tell Cmake which build system to use?](https://discourse.cmake.org/t/is-cmakeccompilerid-c-used-on-the-target-or-host-system-how-to-tell-cmake-which-build-system-to-use/6731):
>
> Newbie here. My question appears to be a variant of: [Cross compiling a Qt application for arm but the target rcc and moc executables are used instead of the host versions](https://discourse.cmake.org/t/cross-compiling-a-qt-application-for-arm-but-the-target-rcc-and-moc-executables-are-used-instead-of-the-host-versions/6240) My question is about specific operation of the Cmake operational process which I think is a narrower version of the same operational issue. The description of [Tool Chains](https://cmake.org/cmake/help/book/mastering-cmake/chapter/Cross%20Compiling%20With%20CMake.html) is explicit about using it to describe the Target environment but says little ( that I could glean ) about the use or settings for the Host environment…

> <https://stackoverflow.com/questions/38299841/makefile-linking-undefined-reference-to-exit>

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [August 10, 2023, 12:53pm UTC](https://discourse.cmake.org/t/linker-does-not-link-libc-a/8711/2 "2023-08-10T12:53:29Z")

</div>

> [@everedero](#):
>
> 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.

Is it possible to get the command line that STM IDE is using?

---

<div class="post-metadata">

### Author: ![everedero](https://discourse.cmake.org/user_avatar/discourse.cmake.org/everedero/32/3699_2.png) [@everedero](https://discourse.cmake.org/u/everedero)
#### Post date: [August 10, 2023, 1:12pm UTC](https://discourse.cmake.org/t/linker-does-not-link-libc-a/8711/3 "2023-08-10T13:12:54Z")

</div>

For linking, it’s using:  
`arm-none-eabi-gcc -o "lunii_firmware.elf" @"objects.list" -mcpu=cortex-m7 -T"STM32F730V8TX_FLASH.ld" --specs=nosys.specs -Wl,-Map="firmware.map" -Wl,--gc-sections -static -Wl,--print-memory-usage -flto -mfpu=fpv5-sp-d16 -mfloat-abi=hard -mthumb -Wl,--start-group -lc -lm -Wl,--end-group`

Here is what the STMCube-generated makefiles invoke:

```auto
Startup/%.o: ../Startup/%.s Startup/subdir.mk
    arm-none-eabi-gcc -mcpu=cortex-m7 -g3 -c -x assembler-with-cpp -MMD -MP -MF"$(@:%.o=%.d)" -MT"$@" -mfpu=fpv5-sp-d16 -mfloat-abi=hard -mthumb -o "$@" "$<"

Src/%.o Src/%.su: ../Src/%.c Src/subdir.mk
        arm-none-eabi-gcc -fstack-usage "$<" -mcpu=cortex-m7 -std=gnu11 -g3 -DUSE_HAL_DRIVER -D[CUSTOM_FLAGS] -DSTM32F730xx -DDEBUG -c -I../Middlewares/Third_Party/FreeRTOS/Source/include -I../Drivers/CMSIS/Include -I../Drivers/CMSIS/Device/ST/STM32F7xx/Include -I../Drivers/STM32F7xx_HAL_Driver/Inc -I../Middlewares/Third_Party/FreeRTOS/Source/portable/GCC/ARM_CM7/r0p1 -I../Middlewares/ST/STM32_USB_Device_Library/Class/MSC/Inc -I../Middlewares/ST/STM32_USB_Device_Library/Core/Inc -I../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS -I../Drivers/STM32F7xx_HAL_Driver/Inc/Legacy -I../Middlewares/Third_Party/FatFs/src -I../Middlewares/Third_Party/Helix -I../Middlewares/Third_Party/Helix/pub -I../Middlewares/Third_Party/Helix/real -I../Middlewares/Third_Party/FreeRTOS/coreJSON/include -I../Middlewares/Third_Party/microtar/src -I[my_source_paths] -Og -ffunction-sections -fdata-sections -mslow-flash-data -Wall -fstack-usage -MMD -MP -MF"$(@:%.o=%.d)" -MT"$@" -mfpu=fpv5-sp-d16 -mfloat-abi=hard -mthumb -o "$@"

firmware.elf firmware.map: $(OBJS) $(USER_OBJS) STM32F730V8TX_FLASH.ld makefile objects.list $(OPTIONAL_TOOL_DEPS)
        arm-none-eabi-gcc -o "firmware.elf" @"objects.list" $(USER_OBJS) $(LIBS) -mcpu=cortex-m7 -T"STM32F730V8TX_FLASH.ld" --specs=nosys.specs -Wl,-Map="firmware.map" -Wl,--gc-sections -static -Wl,--print-memory-usage -flto -mfpu=fpv5-sp-d16 -mfloat-abi=hard -mthumb -Wl,--start-group -lc -lm -Wl,--end-group

```

---

<div class="post-metadata">

### Author: ![hsattler](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/h/59ef9b/32.png) [@hsattler](https://discourse.cmake.org/u/hsattler)
#### Post date: [August 10, 2023, 2:37pm UTC](https://discourse.cmake.org/t/linker-does-not-link-libc-a/8711/4 "2023-08-10T14:37:54Z")

</div>

I assume it provides an object with those symbols in the objects.list file

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [August 10, 2023, 6:24pm UTC](https://discourse.cmake.org/t/linker-does-not-link-libc-a/8711/5 "2023-08-10T18:24:20Z")

</div>

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?

---

<div class="post-metadata">

### Author: ![everedero](https://discourse.cmake.org/user_avatar/discourse.cmake.org/everedero/32/3699_2.png) [@everedero](https://discourse.cmake.org/u/everedero)
#### Post date: [August 11, 2023, 8:52am UTC](https://discourse.cmake.org/t/linker-does-not-link-libc-a/8711/6 "2023-08-11T08:52:31Z")

</div>

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 🙂

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [August 11, 2023, 11:15am UTC](https://discourse.cmake.org/t/linker-does-not-link-libc-a/8711/7 "2023-08-11T11:15:30Z")

</div>

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).

---

<div class="post-metadata">

### Author: ![everedero](https://discourse.cmake.org/user_avatar/discourse.cmake.org/everedero/32/3699_2.png) [@everedero](https://discourse.cmake.org/u/everedero)
#### Post date: [August 11, 2023, 11:39am UTC](https://discourse.cmake.org/t/linker-does-not-link-libc-a/8711/8 "2023-08-11T11:39:29Z")

</div>

CMakeOutput.log tells me:

```auto
COLLECT_GCC=/opt/st/stm32cubeide_1.11.2/plugins/com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.10.3-2021.10.linux64_1.0.100.202210260954/tools/bin/arm-none-eabi-gcc
COLLECT_GCC_OPTIONS='-v' '-o' 'CMakeFiles/cmTC_44ac2.dir/CMakeCCompilerABI.c.obj' '-c' '-mcpu=arm7tdmi' '-mfloat-abi=soft' '-marm' '-mlibarch=armv4t' '-march=armv4t'

```

If I try to retrieve the compilation calls from CMakeOutput.log:

```auto
/opt/st/stm32cubeide_1.11.2/plugins/com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.10.3-2021.10.linux64_1.0.100.202210260954/tools/bin/arm-none-eabi-gcc -v -o CMakeFiles/cmTC_44ac2.dir/CMakeCCompilerABI.c.obj -c /usr/share/cmake-3.22/Modules/CMakeCCompilerABI.c
/opt/st/stm32cubeide_1.11.2/plugins/com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.10.3-2021.10.linux64_1.0.100.202210260954/tools/bin/../lib/gcc/arm-none-eabi/10.3.1/cc1 -quiet -v -iprefix /opt/st/stm32cubeide_1.11.2/plugins/com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.10.3-2021.10.linux64_1.0.100.202210260954/tools/bin/../lib/gcc/arm-none-eabi/10.3.1/ -isysroot /opt/st/stm32cubeide_1.11.2/plugins/com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.10.3-2021.10.linux64_1.0.100.202210260954/tools/bin/../arm-none-eabi -D __USES_INITFINI__ /usr/share/cmake-3.22/Modules/CMakeCCompilerABI.c -quiet -dumpbase CMakeCCompilerABI.c -mcpu=arm7tdmi -mfloat-abi=soft -marm -mlibarch=armv4t -march=armv4t -auxbase-strip CMakeFiles/cmTC_44ac2.dir/CMakeCCompilerABI.c.obj -version -o /tmp/cco6dRVU.s
/opt/st/stm32cubeide_1.11.2/plugins/com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.10.3-2021.10.linux64_1.0.100.202210260954/tools/bin/../lib/gcc/arm-none-eabi/10.3.1/../../../../arm-none-eabi/bin/as -v -march=armv4t -mfloat-abi=soft -meabi=5 -o CMakeFiles/cmTC_44ac2.dir/CMakeCCompilerABI.c.obj /tmp/cco6dRVU.s
/opt/st/stm32cubeide_1.11.2/plugins/com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.10.3-2021.10.linux64_1.0.100.202210260954/tools/bin/arm-none-eabi-ar qc libcmTC_44ac2.a CMakeFiles/cmTC_44ac2.dir/CMakeCCompilerABI.c.obj
/opt/st/stm32cubeide_1.11.2/plugins/com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.10.3-2021.10.linux64_1.0.100.202210260954/tools/bin/arm-none-eabi-ranlib libcmTC_44ac2.a

```

The CMake link.txt files says my final linker command is:  
` /opt/st/stm32cubeide_1.11.2/plugins/com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.10.3-2021.10.linux64_1.0.100.202210260954/tools/bin/arm-none-eabi-gcc -mthumb -mcpu=cortex-m7 -mfpu=fpv5-sp-d16 -mfloat-abi=hard -Wall -fs tack-usage -ffunction-sections -fdata-sections -mslow-flash-data -std=gnu11 -Og -g3 -g2 -Wl,--gc-sections -static --specs=nosys.specs -mthumb -T./STM32F730V8TX_FLASH.ld -Wl,-Map=firmware_mvp.map -mcpu=cortex-m7 -mfpu=fpv5-sp-d16 -mfloat-abi=hard -Wl,--start-group -lc -lm -Wl,--end-group -Wl,--print-memory-usage -flto OBJECTS.c.obj -o firmware.elf`

---

<div class="post-metadata">

### Author: ![everedero](https://discourse.cmake.org/user_avatar/discourse.cmake.org/everedero/32/3699_2.png) [@everedero](https://discourse.cmake.org/u/everedero)
#### Post date: [August 11, 2023, 12:03pm UTC](https://discourse.cmake.org/t/linker-does-not-link-libc-a/8711/9 "2023-08-11T12:03:46Z")

</div>

I checked that the object files linked in the STM32Cube IDE “objects.list” and in the CMake “link.txt” command are exactly the same.

I scraped the contents of the “objects.list” files with arm-none-eabi-nm, but \_init and \_fini are nowhere to be found.

\_exit is defined in a syscalls.c source file, but it is not in any include path, maybe I should add a matching header file?

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [August 12, 2023, 8:28pm UTC](https://discourse.cmake.org/t/linker-does-not-link-libc-a/8711/10 "2023-08-12T20:28:13Z")

</div>

> [@everedero](#):
>
> \_exit is defined in a syscalls.c source file, but it is not in any include path, maybe I should add a matching header file?

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…).

---

<div class="post-metadata">

### Author: ![everedero](https://discourse.cmake.org/user_avatar/discourse.cmake.org/everedero/32/3699_2.png) [@everedero](https://discourse.cmake.org/u/everedero)
#### Post date: [August 21, 2023, 1:07pm UTC](https://discourse.cmake.org/t/linker-does-not-link-libc-a/8711/11 "2023-08-21T13:07:24Z")

</div>

I ran out of time to spend on this topic, so I will keep my additional \_init and \_fini definitions for now:

```auto
/* Empty init definition to avoid errors linking libc.a */
__attribute__ ((weak)) void _init(void){}
__attribute__ ((weak)) void _fini(void){}

```
