2024A-SW/managed_components/espressif__cmake_utilities/docs/gcc.md
2025-01-25 14:04:42 -06:00

3.4 KiB

Link Time Optimization(LTO)

Link time optimization(LTO) improves the optimization effect of GCC, such as reducing binary size, increasing performance, and so on. For more details please refer to related GCC documents.

Use

To use this feature, you need to include the required CMake file in your project's CMakeLists.txt after project(XXXX).

include($ENV{IDF_PATH}/tools/cmake/project.cmake)

project(XXXX)

include(gcc)

The LTO feature is disabled by default. To use it, you should enable the option CU_GCC_LTO_ENABLE in menuconfig. Then specify target components or dependencies to be optimized by LTO after include(gcc) as follows:

include(gcc)

cu_gcc_lto_set(COMPONENTS component_a component_b
               DEPENDS dependence_a dependence_b)

cu_gcc_string_1byte_align(COMPONENTS component_c component_d
                          DEPENDS dependence_c dependence_d)

Based on your requirement, set compiling optimization level in the option COMPILER_OPTIMIZATION.

  • Note

    1. Reducing firmware size may decrease performance
    2. Increasing performance may increase firmware size
    3. Enable LTO cause compiling time cost increases a lot
    4. Enable LTO may increase task stack cost
    5. Enable string 1-byte align may decrease string process speed
    

Limitation

At the linking stage, the LTO generates new function indexes instead of the file path as follows:

  • LTO

    .text          0x00000000420016f4        0x6 /tmp/ccdjwYMH.ltrans51.ltrans.o
                   0x00000000420016f4                app_main
    
  • Without LTO

    .text.app_main 0x00000000420016f4        0x6 esp-idf/main/libmain.a(app_main.c.obj)
                   0x00000000420016f4                app_main
    

So tools used to relink functions between flash and IRAM can't affect these optimized components and dependencies again. It is recommended that users had better optimize application components and dependencies than kernel and hardware driver ones.

Example

The example applies LTO in light of esp-matter because its application code is much larger. Add LTO configuration into project script CMakeLists.txt as follows:


project(light)

include(gcc)

# Add
set(app_lto_components main chip esp_matter)
# Add
set(idf_lto_components lwip wpa_supplicant nvs_flash)
# Add
set(lto_depends mbedcrypto)

# Add
cu_gcc_lto_set(COMPONENTS ${app_lto_components} ${idf_lto_components} 
               DEPENDS ${lto_depends})

Configure ESP32-C2 as the target platform, enable CU_GCC_LTO_ENABLE and CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE, set COMPILER_OPTIMIZATION to be -Os. Increase the main task stack size to 5120 by option ESP_MAIN_TASK_STACK_SIZE. Compile the project, and then you can see the firmware size decrease a lot:

Option Firmware size Stask cost
-Os 1,113,376 2508
-Os + LTO 1,020,640 4204

Then add cu_gcc_string_1byte_align after cu_gcc_lto_set:

# Add
cu_gcc_lto_set(COMPONENTS ${app_lto_components} ${idf_lto_components} 
               DEPENDS ${lto_depends})

cu_gcc_string_1byte_align(COMPONENTS ${app_lto_components} ${idf_lto_components} 
                          DEPENDS ${lto_depends})

Build the project and the firmware size is:

Option Firmware size
-Os + LTO 1,020,640
-Os + LTO + string 1-byte align 1,018,340