iarsystems / cmake-tutorial

Build and test embedded software using the IAR C/C++ Compiler alongside CMake
https://iar.com
MIT License
76 stars 14 forks source link

Release build optimizations #29

Closed Servomex-ivisser closed 1 year ago

Servomex-ivisser commented 1 year ago

I have the toolchain working for some time now, so thanks for this. One issue I am not able to resolve just yet has to do with optimizations in release builds.

In debug I have no issue whatsoever to include

$<$<COMPILE_LANGUAGE:C,CXX>:$<$<CONFIG:Debug>:-On>>

The -O switch appears only once in the output to iccarm.exe In release mode however if I add to my c make file:

$<$<COMPILE_LANGUAGE:C,CXX>:$<$<CONFIG:Release>:-Ohz>>

Then iccarm (rightfully) complains that I specify this -O switch twice

-Oh -DNDEBUG --cpu Cortex-M4 --fpu VFPv4_sp -e --endian=little --guard_calls --no_path_in_file_macros "--dlib_config=C:/Program Files (x86)/IAR Systems/Embedded Workbench 8.5/arm/inc/c/DLib_Config_Normal.h" -Ohz --dependencies=ns ...

(note: both -Oh and -Ohz are provided)

I am not knowingly providing the first optimization switch -Oh. How does this switch get added to the command line instruction? How can I prevent that from happening? Or how can I override that value to my preferred merit of optimization?

felipe-iar commented 1 year ago

Hi and thanks for your feedback and question.

Conveniently, the Modules/Compiler/IAR.cmake driver that ships with CMake already initializes CMAKE_<LANG>_FLAGS_<CONFIG> with the compiler's optimization flags suitable for each of the CMake's default build configurations:

    string(APPEND CMAKE_${lang}_FLAGS_INIT " ")
    string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT " -r")
    string(APPEND CMAKE_${lang}_FLAGS_RELEASE_INIT " -Oh -DNDEBUG")
    string(APPEND CMAKE_${lang}_FLAGS_MINSIZEREL_INIT " -Ohz -DNDEBUG")
    string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT " -Oh -r -DNDEBUG")

For Debug/Release, these flags are mostly what one would get from the IDE itself. That's the reason why we, in the tutorial, simply suggested using the "Ninja Multi-Config" generator: you get (almost) all of them at once!

MinSizeRel/RelWithDebInfo are CMake-specific, but can be useful in some situations

cmake --build build-dir --config MinSizeRel cmake --build build-dir --config RelWithDebInfo


## MinSizeRel specifics
There is one catch for `MinSizeRel` tough: [Ninja Multi-Config docs](https://cmake.org/cmake/help/v3.26/generator/Ninja%20Multi-Config.html) specifies the configurations types listed in `CMAKE_CONFIGURATION_TYPES` for the "Ninja Multi-Config" generator. The default value for `CMAKE_CONFIGURATION_TYPES` is `Debug;Release;RelWithDebInfo`, which does not include `MinSizeRel`.

The `MinSizeRel` build configuration was intentionally left out as, from the CMake's developers perspective, such option is rarely used (within their broader scope, e.g., Desktop, etc.). Because of Ninja Multi-Config's cross-config capabilities, when cross-config is enabled, it has a generation time of `O(n*m)`, where `n` is the number of configurations and `m` is the number of cross-configurations (in practice this is usually `O(n^2)`). MinSizeRel is rarely used, and taking it out reduced the default `O(n^2)` from `16` to `9`.

### Remediation 1: via command line
At configure stage, use `-DCMAKE_CONFIGURATION_TYPES="Debug;Release;RelWithDebInfo;MinSizeRel"` to get the configuration included.

### Remediation 2: via CMakeLists.txt
```cmake
list(APPEND CMAKE_CONFIGURATION_TYPES MinSizeRel) 

I hope it helps. Let me know if you have further related questions otherwise feel free to close.

Servomex-ivisser commented 1 year ago

@felipe-iar Thanks for the prompt answer. There's a lot of information there, so bear with me.

Servomex-ivisser commented 1 year ago

Yep, I did not know about this IAR.cmake file, which I do have on my filesystem. Thanks for pointing this out. I suppose it's perfectly fine then for debug builds to override the optimization setting. It's not set explicitly, and in its absence will default to "low optimization" (on EWARM 8.5).