Archive step breaks output elf file

The upgrade from PIO-Core 4.1.0 to 4.2.0 breaks my generated elf file (on atmelSam platform). I figured out the difference is in the addition of an archive step:

  • on PIO-Core 4.1.0: the recipe was:
  1. arm-none-eabi-gcc: compile all .c files to .o files
  2. arm-none-eabi-gcc: link all .o files together (in 1 command) into .elf file
  • on PIO-Core 4.2.0: this recipe changed (without upgrading any platforms or libraries) into
  1. arm-none-eabi-gcc: compile all .c files to .o files
  2. arm-none-eabi-ar: create an archive of all .o files to .a file
  3. arm-none-eabi-ranlib: create index
    4.arm-none-eabi-gcc: link main.o file with .a file into .elf file

=> The latter returns a different (non working) elf file than the former recipe. Not any warning or error is thrown by the linker, but it seems it wasn’t able to link in symbols from the .a file, since the .hex/.bin file is almost empty…

2 Questions:

  • can someone point me to the code change between 4.1.0 and 4.2.0 that might have changed this behaviour?
  • anybody an idea why the latter recipe is not working anymore? All commands seems valid to me and it should actually not make a difference if some .o files are first tied together into .a file before passed to the linker… or am i missing something.

Some more details:

  • I’m using a custom library that modifies the build recipe from the atmelsam platform a bit: it adds a custom linker script (maybe that might have some influence on the behaviour of .a files for the linker)
  • If you want to reproduce my issue, you can compile and execute the ArduinoZero example in GitHub - JelleRoets/AtmelStart_PlatformIO: PlatformIO library that automatically downloads Atmel Start generated code. If you do that with pio core 4.1.0 everything runs smooth, in 4.2.0 the extra archive step still runs without any errors but the elf file is not working (and almost empty)

I found some clues and a workaround:

The problem in my case is that the library contains a startup.c file that calls the main function from the src/main.cpp file in a function that is set to the reset interrupt script of the mcu. If this startup.c file is included in the archive and only added as a library to the linker, the linking doesn’t happen correctly and the program doesn’t startup at all. If that (compiled) file is directly added to the linker it does work.
This probably has something to do with how the linker adds symbols from libraries, while it entirely includes symbols from passed object files, but I don’t know the details…

Anyway the workaround in my case (using the ASF library package) was to exclude that startup script from the archived library and manually copy paste it into the project source dir. Which works, but is not very clean and nice for other users of the library.
Any hints on how to automate this: AtmelStart_PlatformIO/library.py at master · JelleRoets/AtmelStart_PlatformIO · GitHub?

Can you just try to add lib_archive = no in the platformio.ini? This links all object files together without archiving them first so maybe it works.

1 Like

That is an excellent hint! Many thanks.

Setting lib_archive = no in the platformio.ini indeed prevents the archive step (for all libraries) and solves my problem.

Actually the library.json already seems to contain build.libArchive = false, but this flag might be broken in the 4.2 release

I observed similiar things, see libArchive option in library.json does not overwrites global `lib_archive` option · Issue #3398 · platformio/platformio-core · GitHub. I’m not 100% what the behavior was before though…

I too experienced this issue, and disabling library archiving fixed it for me.