I’m currently working on a rather big project where you can disable whole blocks/features to customize for the given task.
Right now I’m trying to port that project to the STM32. With the STM32 Nucelo32 series the Flash memory is quite restricted compared to SAMD or ESP32 and I have trouble getting everything to fit on it.
Therefore I looked closer into who diabeling features reduce Flash usage and I noticed that even completely unused code files increase flash usage.
I have for example a library to read out a Sensor. Over #ifdef i can disable the include of the header. therefore it is possible to delete the header and cpp file from my project. but leaving it in the src folder increases the flash usage by 3%.
compilation complete even if the file is not present. that shows it is not referenced by any code.
Why is the Flash size then increasing?
I tried using builf-flags -O3 -Os and others but it does not change the result.
I’m a little bit confused. can somebody give me an explanation of why this is happening? it this expected behaviour?
Edit: to be more clear I have a wrapper class in src folder for the sensor using a library in the lib folder. the wrapper class and library can be removed without breaking compilation. leaving it in increases flash usage by 3%. Also removing only the wrapper in my project src folder but leavin the library in lib does not cause the 3% increase. Are by change librarys in libs compiled into the code if they are just referenced in the code but not actually used? that would mean I would have to “#ifdef out” all references of libs to make sure they are not compiled into the result even if unused by the actual code
O3 and Os are contradicatory to each other, O3 will optimized for high-speed performance even at the expense of program / flash space, Os, which is already the default, will optimize for minimizinng space (which often also includes perfomance improvements).
If the PlatformIO library dependency finder (LDF) finds your library to be used, it will be included and linked. The linker has the ability to apply link-time-optimization (LTO) to optimize away unused stuff. (That is however also sometimes too aggressive and optimizes away interrupt handlers, leaving the firmware really broken). As far as I read the linker flags for the STM32 + Arduino scenario, the
-flto flag is not given, so it’s possible that the size increase is due to that.
If you remove the wrapper class you probably also thus remove the only reference to your library it doesn’t get compiled in, regardless of the wrapper class itself is used or not… (without LTO). You should be able to see if that happens by looking at the “Dependency Graph” at the start of the compilation output for these two scenarios (wrapper is present or not present).
The specifics of that depend on the used code.
You may try and do
build_flags = -flto and see if it works or destroys stuff.
Thanks for the Answer.
Hit the nail on the head.
First I of course did not use -O3 and -Os together. I tried them separately ;]
Out of interest if I use
build_flags = -O3 does it override -Os or is it just appended giving me again contradictory flags?
the library shows up in the dependency Graph as long as the wrapper file is present in my src code independent of if the wrapper is included anywhere. with makes sense considering what you explained.
-flto works as expected. got some 10% Flash back. I’m a little bit concerned about the aggressive optimization. I previously had trouble with the stm core while debugging and optimization and code just randomly stopping for no reason. couldn’t yet narrow down by what it is caused. do I get unoptimized code using
build_flags = -Og or is it overwritten by default -Os?
If you want different optimization levels you need to “undo” the
-Os option first with
build_unflags and then add your new option with
build_flags. You can also execute the project task “Advanced → Verbose Build” to check the complete compiler invocation with all flags to make sure only one
-Ox option is used.
If you want the complete debug build as it would be compiled and uploaded during a debug session, you can also set build_type = debug and a normal upload will then compile&upload the debug firmware. There, default or modified debug_build_flags apply.