ST STM32@7.0.0 w/ libopencm3: Update causes Linker Error

Hi PlatformIO-Experts,

I have a project for a bluepill board based on libopencm3. My project was building fine with the previous release of ststm32/libopencm3 used in PlatformIO.

After updating my PlatformIO packages today, I received a bunch of build errors. A first batch of errors related to the updated APIs of libopencm3 was easy to fix. However, I am now stuck on the following linker errors:

Linking .pio\build\bluepill\firmware.elf
c:/users/damian/.platformio/packages/toolchain-gccarmnoneeabi/bin/../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/lib/thumb/v7-m\libc.a(lib_a-sbrkr.o): In function `_sbrk_r':
sbrkr.c:(.text._sbrk_r+0xc): undefined reference to `_sbrk'
c:/users/damian/.platformio/packages/toolchain-gccarmnoneeabi/bin/../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/lib/thumb/v7-m\libc.a(lib_a-closer.o): In function `_close_r':
closer.c:(.text._close_r+0xc): undefined reference to `_close'
c:/users/damian/.platformio/packages/toolchain-gccarmnoneeabi/bin/../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/lib/thumb/v7-m\libc.a(lib_a-lseekr.o): In function `_lseek_r':
lseekr.c:(.text._lseek_r+0x12): undefined reference to `_lseek'
c:/users/damian/.platformio/packages/toolchain-gccarmnoneeabi/bin/../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/lib/thumb/v7-m\libc.a(lib_a-readr.o): In function `_read_r':
readr.c:(.text._read_r+0x12): undefined reference to `_read'
c:/users/damian/.platformio/packages/toolchain-gccarmnoneeabi/bin/../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/lib/thumb/v7-m\libc.a(lib_a-fstatr.o): In function `_fstat_r':
fstatr.c:(.text._fstat_r+0x10): undefined reference to `_fstat'
c:/users/damian/.platformio/packages/toolchain-gccarmnoneeabi/bin/../lib/gcc/arm-none-eabi/7.2.1/../../../../arm-none-eabi/lib/thumb/v7-m\libc.a(lib_a-isattyr.o): In function `_isatty_r':
isattyr.c:(.text._isatty_r+0xc): undefined reference to `_isatty'
collect2.exe: error: ld returned 1 exit status
*** [.pio\build\bluepill\firmware.elf] Error 1

I can reliably “fix” these errors by explicitly reverting to platform = ststm32@~6.1.1 in my platformio.ini. Similarly, I can reliably reproduce the error by switching to the latest ststm32 platform version.

I have tried to find a solution using google. However, the only information I found pointed towards the use of newlib. Looking through the PlatformIO documentation, I can see a use of newlib only with STM32Duino - which I am not using in the given environment.

In case source code is relevant, you can find my project at https://github.com/deltaphi/c6021light/tree/master/c6021light. For more details, Commit 9266ccc9 is fixed to use ststm32@~6.1.1. Commit e16df5f3 is updated for ststm32@7.0.0 and can be used to reproduce the issue.

I would like to use the newer release of libopencm3 for my project, as it contains a number of fixes for problems I had to work around in the past. How can I fix these linker errors?

Regards
Damian

Seems like some internal C library functions have started to go missing… @valeros can you have a look at this?

Hi @deltaphi! Could you please add -lc flag to your build flags, e.g.:

build_flags = ${env.build_flags} -D PLATFORMIO_FRAMEWORK_$PIOFRAMEWORK -lc

Hi @valeros,

this fixes the linker errors, thank you! Is this a bug that will be fixed in PlatformIO or is this something I overlooked in the documentation?

Regards
Damian

There is no documentation for such cases because they’re project specific. I suppose you’re using pritnf-like functions in your project? The default linker flags for libopencm3 framework doesn’t include any implementation for syscalls, so we didn’t add them to our build script. It think we can link stubs from newlib-nano to handle this issue in the future releases.

Indeed, my usecase is printf(). Looking through my code, I always had to provide an implementation of _write(), which is totally fine for me. I get why you wouldn’t want to enable -lc globally, if it causes linker errors for people not providing _write().

I just find it confusing that:

  • Most of the cstdlib is available without the linker flag,
  • This used to work in a past release,
  • Now it suddenly broke.

Given that it is hard to find out what PlatformIO is really doing under the hood (e.g., effective compiler/linker flags being used), I would appreciate a hint in the documentation what needs doing to enable the stdio portions of the cstdlib when a project requires it.