mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 19:13:21 +00:00
c6c1293d0c
The __init_project_configuration() function in cmakev2's project.cmake unconditionally applied app-level compiler optimization flags based on CONFIG_COMPILER_OPTIMIZATION_* Kconfig options. When the bootloader subproject was built with cmakev2, these app-level flags leaked into the bootloader compile command alongside the correct bootloader-specific flags from CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_*. For example, with the default configuration (app: DEBUG, bootloader: SIZE), the bootloader received both "-Og -fno-shrink-wrap" (from app config) and "-Os -freorder-blocks" (from bootloader config). While GCC uses the last -O flag (-Os wins), the stray -fno-shrink-wrap persisted. Introduce a SET_COMPILER_OPTIMIZATION build property that defaults to YES when unset. Subprojects that manage their own optimization flags (like the bootloader) can set this to NO before calling idf_project_init() to prevent the default optimization flags from being applied. This keeps project.cmake generic without requiring it to know about specific subproject types. Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
841 lines
35 KiB
CMake
841 lines
35 KiB
CMake
# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
include_guard(GLOBAL)
|
|
|
|
#[[
|
|
__init_project_name()
|
|
|
|
Initialize the PROJECT_NAME build property, using CMAKE_PROJECT_NAME as a
|
|
fallback.
|
|
#]]
|
|
function(__init_project_name)
|
|
__get_default_value(VARIABLE PROJECT_NAME
|
|
DEFAULT "${CMAKE_PROJECT_NAME}"
|
|
OUTPUT project_name)
|
|
idf_build_set_property(PROJECT_NAME "${project_name}")
|
|
endfunction()
|
|
|
|
#[[
|
|
__init_project_version()
|
|
|
|
Initialize the PROJECT_VER build property based on the following
|
|
precedence.
|
|
|
|
1. The PROJECT_VER environment or CMake variable.
|
|
2. The version.txt file located in the top-level project directory.
|
|
3. The VERSION argument, if provided, in the project() macro.
|
|
4. The output of git describe if the project is within a Git repository.
|
|
5. Defaults to 1 if none of the above conditions are met.
|
|
|
|
The value of PROJECT_VER will be overridden later if
|
|
CONFIG_APP_PROJECT_VER_FROM_CONFIG is defined. For more details, refer to
|
|
components/esp_app_format/CMakeLists.txt.
|
|
#]]
|
|
function(__init_project_version)
|
|
idf_build_get_property(project_dir PROJECT_DIR)
|
|
|
|
# 1. The PROJECT_VER environment or CMake variable.
|
|
__get_default_value(VARIABLE PROJECT_VER
|
|
DEFAULT NOTFOUND
|
|
OUTPUT project_ver)
|
|
if(project_ver)
|
|
idf_build_set_property(PROJECT_VER "${project_ver}")
|
|
return()
|
|
endif()
|
|
|
|
# 2. The version.txt file located in the top-level project directory.
|
|
if(EXISTS "${project_dir}/version.txt")
|
|
file(STRINGS "${project_dir}/version.txt" project_ver)
|
|
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${project_dir}/version.txt")
|
|
idf_build_set_property(PROJECT_VER "${project_ver}")
|
|
return()
|
|
endif()
|
|
|
|
# 3. The VERSION argument, if provided, in the project() macro.
|
|
if(PROJECT_VERSION)
|
|
idf_build_set_property(PROJECT_VER "${PROJECT_VERSION}")
|
|
return()
|
|
endif()
|
|
|
|
# 4. The output of git describe if the project is within a Git repository.
|
|
git_describe(project_ver "${project_dir}")
|
|
if(project_ver)
|
|
idf_build_set_property(PROJECT_VER "${project_ver}")
|
|
return()
|
|
endif()
|
|
|
|
# 5. Defaults to 1 if none of the above conditions are met.
|
|
idf_build_set_property(PROJECT_VER 1)
|
|
endfunction()
|
|
|
|
#[[
|
|
__init_project_configuration()
|
|
|
|
Configure the build settings in one location, incorporating preset
|
|
compilation flags, definitions, and settings based on sdkconfig.
|
|
#]]
|
|
function(__init_project_configuration)
|
|
set(compile_definitions)
|
|
set(compile_options)
|
|
set(c_compile_options)
|
|
set(cxx_compile_options)
|
|
set(asm_compile_options)
|
|
set(link_options)
|
|
|
|
idf_build_get_property(idf_ver IDF_VER)
|
|
idf_build_get_property(idf_path IDF_PATH)
|
|
idf_build_get_property(idf_target IDF_TARGET)
|
|
idf_build_get_property(component_interfaces COMPONENT_INTERFACES)
|
|
idf_build_get_property(build_dir BUILD_DIR)
|
|
idf_build_get_property(project_dir PROJECT_DIR)
|
|
idf_build_get_property(project_name PROJECT_NAME)
|
|
|
|
# Set the LINKER_TYPE build property. Different linkers may have varying
|
|
# options, so it's important to identify the linker type to configure the
|
|
# options correctly. Currently, LINKER_TYPE is used to set the appropriate
|
|
# linker options for linking the entire archive, which differs between the
|
|
# GNU and Apple linkers when building on the host.
|
|
if(CONFIG_IDF_TARGET_LINUX AND CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin")
|
|
# Compiling for the host, and the host is macOS, so the linker is Darwin LD.
|
|
# Note, when adding support for Clang and LLD based toolchain this check will
|
|
# need to be modified.
|
|
set(linker_type "Darwin")
|
|
else()
|
|
set(linker_type "GNU")
|
|
endif()
|
|
idf_build_set_property(LINKER_TYPE "${linker_type}")
|
|
|
|
list(APPEND compile_definitions "_GLIBCXX_USE_POSIX_SEMAPHORE" # These two lines enable libstd++ to use
|
|
"_GLIBCXX_HAVE_POSIX_SEMAPHORE" # posix-semaphores from components/pthread
|
|
"_GNU_SOURCE")
|
|
|
|
list(APPEND compile_definitions "ESP_PLATFORM")
|
|
list(APPEND compile_definitions "IDF_VER=\"${idf_ver}\"")
|
|
|
|
list(APPEND compile_options "-ffunction-sections"
|
|
"-fdata-sections"
|
|
# warning-related flags
|
|
"-Wall"
|
|
"-Wno-error=unused-function"
|
|
"-Wno-error=unused-variable"
|
|
"-Wno-error=unused-but-set-variable"
|
|
"-Wno-error=deprecated-declarations"
|
|
"-Wextra"
|
|
"-Wno-error=extra"
|
|
"-Wno-unused-parameter"
|
|
"-Wno-sign-compare"
|
|
# ignore multiple enum conversion warnings since gcc 11
|
|
# TODO: IDF-5163
|
|
"-Wno-enum-conversion"
|
|
# Default is dwarf-5 since GCC 11, fallback to dwarf-4 because of binary size
|
|
# TODO: IDF-5160
|
|
"-gdwarf-4"
|
|
# always generate debug symbols (even in release mode, these don't
|
|
# go into the final binary so have no impact on size
|
|
"-ggdb")
|
|
|
|
if(CONFIG_COMPILER_DISABLE_DEFAULT_ERRORS AND NOT CMAKE_C_COMPILER_ID MATCHES "Clang")
|
|
list(APPEND compile_options "-Werror=all")
|
|
else()
|
|
list(APPEND compile_options "-Werror")
|
|
endif()
|
|
|
|
if(IDF_TARGET STREQUAL "linux")
|
|
# Building for Linux target, fall back to an older version of the standard
|
|
# if the preferred one is not supported by the compiler.
|
|
set(preferred_c_versions gnu23 gnu17 gnu11 gnu99)
|
|
set(ver_found FALSE)
|
|
foreach(c_version ${preferred_c_versions})
|
|
check_c_compiler_flag("-std=${c_version}" ver_${c_version}_supported)
|
|
if(ver_${c_version}_supported)
|
|
set(c_std ${c_version})
|
|
set(ver_found TRUE)
|
|
break()
|
|
endif()
|
|
endforeach()
|
|
if(NOT ver_found)
|
|
idf_die("Failed to set C language standard to one of the supported versions: "
|
|
"${preferred_c_versions}. Please upgrade the host compiler.")
|
|
endif()
|
|
|
|
set(preferred_cxx_versions gnu++26 gnu++2b gnu++20 gnu++2a gnu++17 gnu++14)
|
|
set(ver_found FALSE)
|
|
foreach(cxx_version ${preferred_cxx_versions})
|
|
check_cxx_compiler_flag("-std=${cxx_version}" ver_${cxx_version}_supported)
|
|
if(ver_${cxx_version}_supported)
|
|
set(cxx_std ${cxx_version})
|
|
set(ver_found TRUE)
|
|
break()
|
|
endif()
|
|
endforeach()
|
|
if(NOT ver_found)
|
|
idf_die("Failed to set C++ language standard to one of the supported versions: "
|
|
"${preferred_cxx_versions}. Please upgrade the host compiler.")
|
|
endif()
|
|
|
|
list(APPEND c_compile_options "-std=${c_std}")
|
|
list(APPEND cxx_compile_options "-std=${cxx_std}")
|
|
else()
|
|
# Building for chip targets: we use a known version of the toolchain.
|
|
# Use latest supported versions.
|
|
# For Linux target -std settings, refer to the __linux_build_set_lang_version
|
|
# function, which must be called after project().
|
|
# Please update docs/en/api-guides/c.rst, docs/en/api-guides/cplusplus.rst and
|
|
# tools/test_apps/system/cxx_build_test/main/test_cxx_standard.cpp when changing this.
|
|
list(APPEND c_compile_options "-std=gnu23")
|
|
list(APPEND cxx_compile_options "-std=gnu++26")
|
|
endif()
|
|
|
|
# Subprojects that handle their own compiler optimization flags can set the
|
|
# SET_COMPILER_OPTIMIZATION build property to NO before idf_project_init().
|
|
idf_build_get_property(set_compiler_optimization SET_COMPILER_OPTIMIZATION)
|
|
if(NOT set_compiler_optimization)
|
|
set(set_compiler_optimization YES)
|
|
endif()
|
|
if(set_compiler_optimization)
|
|
if(CONFIG_COMPILER_OPTIMIZATION_SIZE)
|
|
if(CMAKE_C_COMPILER_ID MATCHES "Clang")
|
|
list(APPEND compile_options "-Oz")
|
|
else()
|
|
list(APPEND compile_options "-Os")
|
|
endif()
|
|
if(CMAKE_C_COMPILER_ID MATCHES "GNU")
|
|
list(APPEND compile_options "-freorder-blocks")
|
|
endif()
|
|
elseif(CONFIG_COMPILER_OPTIMIZATION_DEBUG)
|
|
list(APPEND compile_options "-Og")
|
|
if(CMAKE_C_COMPILER_ID MATCHES "GNU" AND NOT CONFIG_IDF_TARGET_LINUX)
|
|
list(APPEND compile_options "-fno-shrink-wrap") # Disable shrink-wrapping to reduce binary size
|
|
endif()
|
|
elseif(CONFIG_COMPILER_OPTIMIZATION_NONE)
|
|
list(APPEND compile_options "-O0")
|
|
elseif(CONFIG_COMPILER_OPTIMIZATION_PERF)
|
|
list(APPEND compile_options "-O2")
|
|
endif()
|
|
endif()
|
|
|
|
if(CONFIG_COMPILER_CXX_EXCEPTIONS)
|
|
list(APPEND cxx_compile_options "-fexceptions")
|
|
else()
|
|
list(APPEND cxx_compile_options "-fno-exceptions")
|
|
endif()
|
|
|
|
if(CONFIG_COMPILER_CXX_RTTI)
|
|
list(APPEND cxx_compile_options "-frtti")
|
|
else()
|
|
list(APPEND cxx_compile_options "-fno-rtti")
|
|
list(APPEND link_options "-fno-rtti") # used to invoke correct multilib variant (no-rtti) during linking
|
|
endif()
|
|
|
|
if(CONFIG_COMPILER_SAVE_RESTORE_LIBCALLS)
|
|
list(APPEND compile_options "-msave-restore")
|
|
endif()
|
|
|
|
if(CMAKE_C_COMPILER_ID MATCHES "GNU")
|
|
list(APPEND c_compile_options "-Wno-old-style-declaration")
|
|
endif()
|
|
|
|
# Clang finds some warnings in IDF code which GCC doesn't.
|
|
# All these warnings should be fixed before Clang is presented
|
|
# as a toolchain choice for users.
|
|
if(CMAKE_C_COMPILER_ID MATCHES "Clang")
|
|
# Clang checks Doxygen comments for being in sync with function prototype.
|
|
# There are some inconsistencies, especially in ROM headers.
|
|
list(APPEND compile_options "-Wno-documentation")
|
|
# GCC allows repeated typedefs when the source and target types are the same.
|
|
# Clang doesn't allow this. This occurs in many components due to forward
|
|
# declarations.
|
|
list(APPEND compile_options "-Wno-typedef-redefinition")
|
|
# This issue is seemingly related to newlib's char type functions.
|
|
# Fix is not clear yet.
|
|
list(APPEND compile_options "-Wno-char-subscripts")
|
|
# Clang seems to notice format string issues which GCC doesn't.
|
|
list(APPEND compile_options "-Wno-format-security")
|
|
# Some pointer checks in mDNS component check addresses which can't be NULL
|
|
list(APPEND compile_options "-Wno-tautological-pointer-compare")
|
|
# Similar to the above, in tcp_transport
|
|
list(APPEND compile_options "-Wno-pointer-bool-conversion")
|
|
# mbedTLS md5.c triggers this warning in md5_test_buf (false positive)
|
|
list(APPEND compile_options "-Wno-string-concatenation")
|
|
# multiple cases of implicit conversions between unrelated enum types
|
|
list(APPEND compile_options "-Wno-enum-conversion")
|
|
# When IRAM_ATTR is specified both in function declaration and definition,
|
|
# it produces different section names, since section names include __COUNTER__.
|
|
# Occurs in multiple places.
|
|
list(APPEND compile_options "-Wno-section")
|
|
# Multiple cases of attributes unknown to clang, for example
|
|
# __attribute__((optimize("-O3")))
|
|
list(APPEND compile_options "-Wno-unknown-attributes")
|
|
# Disable Clang warnings for atomic operations with access size
|
|
# more then 4 bytes
|
|
list(APPEND compile_options "-Wno-atomic-alignment")
|
|
# several warnings in wpa_supplicant component
|
|
list(APPEND compile_options "-Wno-unused-but-set-variable")
|
|
# Clang also produces many -Wunused-function warnings which GCC doesn't.
|
|
list(APPEND compile_options "-Wno-unused-function")
|
|
# many warnings in bluedroid code
|
|
# warning: field 'hdr' with variable sized type 'BT_HDR' not at the end of a struct or class is a GNU extension
|
|
list(APPEND compile_options "-Wno-gnu-variable-sized-type-not-at-end")
|
|
# several warnings in bluedroid code
|
|
list(APPEND compile_options "-Wno-constant-logical-operand")
|
|
# warning: '_Static_assert' with no message is a C2x extension
|
|
list(APPEND compile_options "-Wno-c2x-extensions")
|
|
# warning on xMPU_SETTINGS for esp32s2 has size 0 for C and 1 for C++
|
|
list(APPEND compile_options "-Wno-extern-c-compat")
|
|
if(NOT (CONFIG_IDF_TARGET_LINUX AND CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin"))
|
|
# warning: implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1
|
|
list(APPEND compile_options "-Wno-single-bit-bitfield-constant-conversion")
|
|
endif()
|
|
endif()
|
|
# More warnings may exist in unit tests and example projects.
|
|
|
|
if(CONFIG_COMPILER_WARN_WRITE_STRINGS)
|
|
list(APPEND compile_options "-Wwrite-strings")
|
|
endif()
|
|
|
|
if(CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE)
|
|
list(APPEND compile_definitions "-DNDEBUG")
|
|
endif()
|
|
|
|
if(CONFIG_COMPILER_NO_MERGE_CONSTANTS)
|
|
list(APPEND compile_options "-fno-merge-constants")
|
|
endif()
|
|
|
|
if(CONFIG_COMPILER_STACK_CHECK_MODE_NORM)
|
|
list(APPEND compile_options "-fstack-protector")
|
|
elseif(CONFIG_COMPILER_STACK_CHECK_MODE_STRONG)
|
|
list(APPEND compile_options "-fstack-protector-strong")
|
|
elseif(CONFIG_COMPILER_STACK_CHECK_MODE_ALL)
|
|
list(APPEND compile_options "-fstack-protector-all")
|
|
endif()
|
|
|
|
if(CONFIG_COMPILER_DUMP_RTL_FILES)
|
|
list(APPEND compile_options "-fdump-rtl-expand")
|
|
endif()
|
|
|
|
if(CMAKE_C_COMPILER_ID MATCHES "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER 15.0)
|
|
list(APPEND c_compile_options "-fzero-init-padding-bits=all" "-fno-malloc-dce")
|
|
endif()
|
|
|
|
if(CONFIG_COMPILER_DISABLE_GCC12_WARNINGS)
|
|
list(APPEND compile_options "-Wno-address"
|
|
"-Wno-use-after-free")
|
|
endif()
|
|
|
|
if(CONFIG_COMPILER_DISABLE_GCC13_WARNINGS)
|
|
list(APPEND compile_options "-Wno-xor-used-as-pow")
|
|
list(APPEND c_compile_options "-Wno-enum-int-mismatch")
|
|
list(APPEND cxx_compile_options "-Wno-self-move"
|
|
"-Wno-dangling-reference")
|
|
endif()
|
|
|
|
if(CONFIG_COMPILER_DISABLE_GCC14_WARNINGS)
|
|
list(APPEND compile_options "-Wno-calloc-transposed-args")
|
|
endif()
|
|
|
|
if(CONFIG_COMPILER_DISABLE_GCC15_WARNINGS)
|
|
list(APPEND c_compile_options "-Wno-unterminated-string-initialization")
|
|
list(APPEND c_compile_options "-Wno-header-guard")
|
|
list(APPEND cxx_compile_options "-Wno-self-move")
|
|
list(APPEND cxx_compile_options "-Wno-template-body")
|
|
list(APPEND cxx_compile_options "-Wno-dangling-reference")
|
|
list(APPEND cxx_compile_options "-Wno-defaulted-function-deleted")
|
|
endif()
|
|
|
|
# GCC-specific options
|
|
if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
|
|
list(APPEND compile_options "-fstrict-volatile-bitfields")
|
|
if(CONFIG_COMPILER_STATIC_ANALYZER)
|
|
list(APPEND compile_options "-fanalyzer")
|
|
endif()
|
|
endif()
|
|
|
|
if(CONFIG_ESP_SYSTEM_USE_EH_FRAME)
|
|
list(APPEND compile_options "-fasynchronous-unwind-tables")
|
|
list(APPEND link_options "-Wl,--eh-frame-hdr")
|
|
endif()
|
|
|
|
if(CONFIG_ESP_SYSTEM_USE_FRAME_POINTER)
|
|
list(APPEND compile_options "-fno-omit-frame-pointer")
|
|
if(CMAKE_C_COMPILER_ID MATCHES "GNU")
|
|
list(APPEND compile_options "-mno-omit-leaf-frame-pointer")
|
|
endif()
|
|
endif()
|
|
|
|
list(APPEND link_options "-fno-lto")
|
|
|
|
if(CONFIG_IDF_TARGET_LINUX AND CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin")
|
|
# Not all versions of the MacOS linker support the -warn_commons flag.
|
|
# ld version 1053.12 (and above) have been tested to support it.
|
|
# Hence, we extract the version string from the linker output
|
|
# before including the flag.
|
|
|
|
# Get the ld version, capturing both stdout and stderr
|
|
execute_process(
|
|
COMMAND ${CMAKE_LINKER} -v
|
|
OUTPUT_VARIABLE LD_VERSION_OUTPUT
|
|
ERROR_VARIABLE LD_VERSION_ERROR
|
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
ERROR_STRIP_TRAILING_WHITESPACE
|
|
)
|
|
|
|
# Combine stdout and stderr
|
|
set(LD_VERSION_OUTPUT "${LD_VERSION_OUTPUT}\n${LD_VERSION_ERROR}")
|
|
|
|
# Extract the version string
|
|
string(REGEX MATCH "PROJECT:(ld|dyld)-([0-9]+)\\.([0-9]+)" LD_VERSION_MATCH "${LD_VERSION_OUTPUT}")
|
|
set(LD_VERSION_MAJOR_MINOR "${CMAKE_MATCH_2}.${CMAKE_MATCH_3}")
|
|
|
|
idf_msg("Linker Version: ${LD_VERSION_MAJOR_MINOR}")
|
|
|
|
# Compare the version with 1053.12
|
|
if(LD_VERSION_MAJOR_MINOR VERSION_GREATER_EQUAL "1053.12")
|
|
list(APPEND link_options "-Wl,-warn_commons")
|
|
endif()
|
|
|
|
list(APPEND link_options "-Wl,-dead_strip")
|
|
else()
|
|
list(APPEND link_options "-Wl,--gc-sections")
|
|
list(APPEND link_options "-Wl,--warn-common")
|
|
endif()
|
|
|
|
# SMP FreeRTOS user provided minimal idle hook. This allows the user to provide
|
|
# their own copy of vApplicationPassiveIdleHook()
|
|
if(CONFIG_FREERTOS_USE_PASSIVE_IDLE_HOOK)
|
|
list(APPEND link_options "-Wl,--wrap=vApplicationPassiveIdleHook")
|
|
endif()
|
|
|
|
# Placing jump tables in flash would cause issues with code that required
|
|
# to be placed in IRAM
|
|
list(APPEND compile_options "-fno-jump-tables")
|
|
if(CMAKE_C_COMPILER_ID MATCHES "GNU")
|
|
# This flag is GCC-specific.
|
|
# Not clear yet if some other flag should be used for Clang.
|
|
list(APPEND compile_options "-fno-tree-switch-conversion")
|
|
endif()
|
|
|
|
if(CMAKE_C_COMPILER_ID MATCHES "Clang")
|
|
list(APPEND compile_options "-fno-use-cxa-atexit") # TODO IDF-10934
|
|
else()
|
|
list(APPEND cxx_compile_options "-fuse-cxa-atexit")
|
|
endif()
|
|
|
|
if(COMPILER_RT_LIB_NAME)
|
|
list(APPEND link_options "-rtlib=${CONFIG_COMPILER_RT_LIB_NAME}")
|
|
endif()
|
|
|
|
if("${linker_type}" STREQUAL "GNU")
|
|
set(target_upper "${idf_target}")
|
|
string(TOUPPER ${target_upper} target_upper)
|
|
# Add this symbol as a hint for esp_idf_size to guess the target name
|
|
list(APPEND link_options "-Wl,--defsym=IDF_TARGET_${target_upper}=0")
|
|
# Check if linker supports --no-warn-rwx-segments
|
|
execute_process(COMMAND ${CMAKE_LINKER} "--no-warn-rwx-segments" "--version"
|
|
RESULT_VARIABLE result
|
|
OUTPUT_QUIET
|
|
ERROR_QUIET)
|
|
if(${result} EQUAL 0)
|
|
# Do not print RWX segment warnings
|
|
list(APPEND link_options "-Wl,--no-warn-rwx-segments")
|
|
endif()
|
|
if(CONFIG_COMPILER_ORPHAN_SECTIONS_WARNING)
|
|
# Print warnings if orphan sections are found
|
|
list(APPEND link_options "-Wl,--orphan-handling=warn")
|
|
endif()
|
|
endif()
|
|
|
|
# Prepares the list of compiler flags for remapping various paths to fixed
|
|
# names. This is used when reproducible builds are required. This function
|
|
# also creates a gdbinit file for the debugger to remap the substituted
|
|
# paths back to the real paths in the filesystem.
|
|
set(gdbinit_dir ${build_dir}/gdbinit)
|
|
set(gdbinit_path "${gdbinit_dir}/prefix_map")
|
|
|
|
if(CONFIG_COMPILER_HIDE_PATHS_MACROS)
|
|
list(APPEND compile_options "-fmacro-prefix-map=${CMAKE_SOURCE_DIR}=.")
|
|
list(APPEND compile_options "-fmacro-prefix-map=${idf_path}=/IDF")
|
|
endif()
|
|
|
|
if(CONFIG_APP_REPRODUCIBLE_BUILD)
|
|
list(APPEND compile_options "-fdebug-prefix-map=${idf_path}=/IDF")
|
|
list(APPEND compile_options "-fdebug-prefix-map=${project_dir}=/IDF_PROJECT")
|
|
list(APPEND compile_options "-fdebug-prefix-map=${build_dir}=/IDF_BUILD")
|
|
|
|
# Generate mapping for component paths
|
|
set(gdbinit_file_lines)
|
|
foreach(component_interface ${component_interfaces})
|
|
__idf_component_get_property_unchecked(component_name ${component_interface} COMPONENT_NAME)
|
|
__idf_component_get_property_unchecked(component_dir ${component_interface} COMPONENT_DIR)
|
|
|
|
string(TOUPPER ${component_name} component_name_uppercase)
|
|
set(substituted_path "/COMPONENT_${component_name_uppercase}_DIR")
|
|
list(APPEND compile_options "-fdebug-prefix-map=${component_dir}=${substituted_path}")
|
|
string(APPEND gdbinit_file_lines "set substitute-path ${substituted_path} ${component_dir}\n")
|
|
endforeach()
|
|
|
|
# Mapping for toolchain path
|
|
execute_process(
|
|
COMMAND ${CMAKE_C_COMPILER} -print-sysroot
|
|
OUTPUT_VARIABLE compiler_sysroot
|
|
)
|
|
if(compiler_sysroot STREQUAL "")
|
|
idf_die("Failed to determine toolchain sysroot")
|
|
endif()
|
|
string(STRIP "${compiler_sysroot}" compiler_sysroot)
|
|
get_filename_component(compiler_sysroot "${compiler_sysroot}/.." REALPATH)
|
|
list(APPEND compile_options "-fdebug-prefix-map=${compiler_sysroot}=/TOOLCHAIN")
|
|
string(APPEND gdbinit_file_lines "set substitute-path /TOOLCHAIN ${compiler_sysroot}\n")
|
|
else()
|
|
set(gdbinit_file_lines "# There is no prefix map defined for the project.\n")
|
|
endif()
|
|
# Write the prefix_map file even if it is empty.
|
|
file(MAKE_DIRECTORY ${gdbinit_dir})
|
|
file(WRITE "${gdbinit_path}" "${gdbinit_file_lines}")
|
|
|
|
idf_build_set_property(GDBINIT_FILES_PREFIX_MAP "${gdbinit_path}")
|
|
idf_build_set_property(COMPILE_OPTIONS "${compile_options}" APPEND)
|
|
idf_build_set_property(C_COMPILE_OPTIONS "${c_compile_options}" APPEND)
|
|
idf_build_set_property(CXX_COMPILE_OPTIONS "${cxx_compile_options}" APPEND)
|
|
idf_build_set_property(ASM_COMPILE_OPTIONS "${asm_compile_options}" APPEND)
|
|
idf_build_set_property(COMPILE_DEFINITIONS "${compile_definitions}" APPEND)
|
|
idf_build_set_property(LINK_OPTIONS "${link_options}" APPEND)
|
|
endfunction()
|
|
|
|
#[[
|
|
__create_project_flash_targets()
|
|
|
|
Add placeholder flash targets to the build. This is used by components to
|
|
declare dependencies on the flash target.
|
|
#]]
|
|
function(__create_project_flash_targets)
|
|
if(NOT TARGET flash)
|
|
add_custom_target(flash)
|
|
endif()
|
|
|
|
# When flash encryption is enabled, a corresponding 'encrypted-flash' target will be created.
|
|
idf_build_get_property(sdkconfig SDKCONFIG)
|
|
__get_sdkconfig_option(OPTION CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
|
|
SDKCONFIG "${sdkconfig}"
|
|
OUTPUT sdkconfig_target)
|
|
if(encrypted_flash_enabled AND NOT TARGET encrypted-flash)
|
|
add_custom_target(encrypted-flash)
|
|
endif()
|
|
endfunction()
|
|
|
|
#[[
|
|
__init_project_flash_targets()
|
|
|
|
If binary generation is enabled, initialize the esptool component and
|
|
enable the generation of esptool flash argument files for the flash and
|
|
encrypted-flash targets. Note that this is done after including the
|
|
project_include.cmake files, as we need the functions defined in the
|
|
esptool_py component.
|
|
#]]
|
|
function(__init_project_flash_targets)
|
|
if(CONFIG_APP_BUILD_GENERATE_BINARIES)
|
|
idf_component_get_property(main_args esptool_py FLASH_ARGS)
|
|
idf_component_get_property(sub_args esptool_py FLASH_SUB_ARGS)
|
|
esptool_py_flash_target(flash "${main_args}" "${sub_args}")
|
|
endif()
|
|
endfunction()
|
|
|
|
#[[
|
|
.. cmakev2:macro:: idf_project_init
|
|
|
|
.. code-block:: cmake
|
|
|
|
idf_project_init()
|
|
|
|
Initialize settings that need to be configured after the ``project()``
|
|
function is called. This must occur after the ``project()`` function and
|
|
before any other build system functions. It initializes the
|
|
``PROJECT_NAME`` and ``PROJECT_VER`` build properties, as well as all
|
|
default C, CXX, and ASM compile options, link options, and compile
|
|
definitions.
|
|
|
|
This macro also includes ``project_include.cmake`` files for the discovered
|
|
components, as these files define project-wide functionality that needs to
|
|
be available before any component's ``CMakeLists.txt`` is evaluated. The
|
|
``project_include.cmake`` files should be evaluated in the global scope.
|
|
Therefore, this is defined as a macro and should be called only from the
|
|
global scope or from within another macro.
|
|
#]]
|
|
macro(idf_project_init)
|
|
idf_build_get_property(project_initialized __PROJECT_INITIALIZED)
|
|
if(NOT project_initialized)
|
|
# Ensure this function is executed only once throughout the entire
|
|
# project.
|
|
|
|
# The IDF_TOOLCHAIN variable is established as a CMake cache variable
|
|
# during the toolchain initialization process in
|
|
# ``tools/cmake/toolchain.cmake``.
|
|
idf_build_set_property(IDF_TOOLCHAIN "${IDF_TOOLCHAIN}")
|
|
|
|
# Warn about the use of deprecated variables.
|
|
deprecate_variable(COMPONENTS)
|
|
deprecate_variable(EXCLUDE_COMPONENTS)
|
|
|
|
# Set PROJECT_NAME build property
|
|
__init_project_name()
|
|
|
|
# Set PROJECT_VER build property
|
|
__init_project_version()
|
|
|
|
# Create global flash targets.
|
|
__create_project_flash_targets()
|
|
|
|
# Discover and initialize components
|
|
__init_components()
|
|
|
|
# Save original sdkconfig before kconfgen may drop unknown options.
|
|
# Only creates a backup when the component manager is enabled.
|
|
__create_sdkconfig_orig_copy()
|
|
|
|
# Generate initial sdkconfig with discovered components
|
|
__generate_sdkconfig()
|
|
|
|
# Fetch managed components from registry if the component manager is enabled
|
|
idf_build_get_property(idf_component_manager IDF_COMPONENT_MANAGER)
|
|
if(idf_component_manager EQUAL 1)
|
|
__fetch_components_from_registry()
|
|
else()
|
|
__component_manager_warn_if_disabled_and_manifests_exist()
|
|
endif()
|
|
|
|
# Include sdkconfig.cmake
|
|
idf_build_get_property(sdkconfig_cmake __SDKCONFIG_CMAKE)
|
|
if(NOT EXISTS "${sdkconfig_cmake}")
|
|
idf_die("sdkconfig.cmake file not found.")
|
|
endif()
|
|
include("${sdkconfig_cmake}")
|
|
unset(sdkconfig_cmake)
|
|
|
|
# Initialize all compilation options and defines.
|
|
# This must be done after including sdkconfig.cmake
|
|
__init_project_configuration()
|
|
|
|
# Initialize the target architecture based on the configuration
|
|
# Ensure this is done after including the sdkconfig.
|
|
__init_idf_target_arch()
|
|
|
|
# Make build properties available as CMake variables for backward
|
|
# compatibility with project_include.cmake files (e.g. ULP component
|
|
# references ${SDKCONFIG_HEADER} and ${SDKCONFIG_CMAKE} directly).
|
|
idf_build_get_property(build_properties BUILD_PROPERTIES)
|
|
foreach(build_property IN LISTS build_properties)
|
|
idf_build_get_property(val ${build_property})
|
|
set(${build_property} "${val}")
|
|
endforeach()
|
|
|
|
# Include all project_include.cmake files for the components that have
|
|
# been discovered.
|
|
idf_build_get_property(component_interfaces COMPONENT_INTERFACES)
|
|
foreach(component_interface IN LISTS component_interfaces)
|
|
__idf_component_get_property_unchecked(project_include ${component_interface} __PROJECT_INCLUDE)
|
|
__idf_component_get_property_unchecked(component_dir ${component_interface} COMPONENT_DIR)
|
|
__idf_component_get_property_unchecked(component_name ${component_interface} COMPONENT_NAME)
|
|
if(project_include)
|
|
set(COMPONENT_NAME ${component_name})
|
|
set(COMPONENT_DIR ${component_dir})
|
|
# The use of COMPONENT_PATH is deprecated in cmakev1. Users
|
|
# are encouraged to use COMPONENT_DIR instead.
|
|
set(COMPONENT_PATH ${component_dir})
|
|
idf_dbg("Including ${project_include}")
|
|
include("${project_include}")
|
|
unset(COMPONENT_NAME)
|
|
unset(COMPONENT_DIR)
|
|
unset(COMPONENT_PATH)
|
|
endif()
|
|
endforeach()
|
|
|
|
# Initialize global flash targets.
|
|
__init_project_flash_targets()
|
|
|
|
# If explicitly requested, include all components by calling
|
|
# `add_subdirectory` for every discovered component. The default
|
|
# behavior is to include only the components based on the requirements.
|
|
__get_default_value(VARIABLE IDF_INCLUDE_ALL_COMPONENTS
|
|
DEFAULT NO
|
|
OUTPUT include_all_components)
|
|
if(include_all_components)
|
|
idf_msg("Including all discovered components")
|
|
foreach(component_name IN LISTS component_names)
|
|
idf_component_include("${component_name}")
|
|
endforeach()
|
|
endif()
|
|
unset(include_all_components)
|
|
|
|
idf_build_set_property(__PROJECT_INITIALIZED YES)
|
|
endif()
|
|
unset(project_initialized)
|
|
endmacro()
|
|
|
|
#[[
|
|
.. cmakev2:function:: idf_build_generate_flasher_args
|
|
|
|
.. code-block:: cmake
|
|
|
|
idf_build_generate_flasher_args()
|
|
|
|
Generate the flasher_args.json file for the global flash target for tools
|
|
that require it.
|
|
#]]
|
|
function(idf_build_generate_flasher_args)
|
|
# The variables listed below are used to configure the template
|
|
# flasher_args.json.in. Some of these variables, such as flash mode, size,
|
|
# and frequency, are set as properties of the esptool_py component.
|
|
|
|
idf_build_get_property(target IDF_TARGET)
|
|
set(ESPTOOLPY_CHIP "${target}")
|
|
set(ESPTOOLPY_BEFORE "${CONFIG_ESPTOOLPY_BEFORE}")
|
|
set(ESPTOOLPY_AFTER "${CONFIG_ESPTOOLPY_AFTER}")
|
|
if(CONFIG_ESPTOOLPY_NO_STUB)
|
|
set(ESPTOOLPY_WITH_STUB false)
|
|
else()
|
|
set(ESPTOOLPY_WITH_STUB true)
|
|
endif()
|
|
|
|
if(CONFIG_SECURE_BOOT OR CONFIG_SECURE_FLASH_ENC_ENABLED)
|
|
# If security enabled then override post flash option
|
|
set(ESPTOOLPY_AFTER "no-reset")
|
|
endif()
|
|
|
|
idf_component_get_property(ESPFLASHMODE esptool_py ESPFLASHMODE)
|
|
idf_component_get_property(ESPFLASHFREQ esptool_py ESPFLASHFREQ)
|
|
idf_component_get_property(ESPFLASHSIZE esptool_py ESPFLASHSIZE)
|
|
idf_component_get_property(esptool_py_dir esptool_py COMPONENT_DIR)
|
|
|
|
# Generate flasher args files
|
|
idf_build_get_property(build_dir BUILD_DIR)
|
|
file(READ "${esptool_py_dir}/flasher_args.json.in" flasher_args_content)
|
|
string(CONFIGURE "${flasher_args_content}" flasher_args_content)
|
|
|
|
# We need to create a flasher_args.json.in to create the final flasher_args.json
|
|
# because CMake only resolves generator expressions in the file_generate command
|
|
# with the INPUT keyword during the generation phase.
|
|
file_generate("${build_dir}/flasher_args.json.in"
|
|
CONTENT "${flasher_args_content}")
|
|
file_generate("${build_dir}/flasher_args.json"
|
|
INPUT "${build_dir}/flasher_args.json.in")
|
|
endfunction()
|
|
|
|
#[[
|
|
.. cmakev2:macro:: __project_default
|
|
|
|
.. code-block:: cmake
|
|
|
|
__project_default()
|
|
|
|
Helper function implementing the main idf_project_default macro
|
|
functionality, preventing global variable scope pollution.
|
|
#]]
|
|
function(__project_default)
|
|
idf_build_get_property(build_dir BUILD_DIR)
|
|
idf_build_get_property(executable PROJECT_NAME)
|
|
idf_build_executable("${executable}"
|
|
COMPONENTS main
|
|
MAPFILE_TARGET "${executable}_mapfile")
|
|
|
|
if(CONFIG_APP_BUILD_GENERATE_BINARIES AND TARGET idf::esptool_py)
|
|
# Is it possible to have a configuration where
|
|
# CONFIG_APP_BUILD_GENERATE_BINARIES is not set?
|
|
|
|
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
|
|
idf_build_binary("${executable}"
|
|
OUTPUT_FILE "${build_dir}/${executable}-unsigned.bin"
|
|
TARGET "${executable}_binary_unsigned")
|
|
idf_sign_binary("${executable}_binary_unsigned"
|
|
OUTPUT_FILE "${build_dir}/${executable}.bin"
|
|
TARGET "${executable}_binary_signed")
|
|
idf_check_binary_size("${executable}_binary_signed")
|
|
|
|
add_custom_target(app ALL DEPENDS "${executable}_binary_signed")
|
|
|
|
idf_flash_binary("${executable}_binary_signed"
|
|
TARGET app-flash
|
|
NAME "app"
|
|
FLASH)
|
|
idf_build_generate_metadata(BINARY "${executable}_binary_signed"
|
|
HINTS_OUTPUT_FILE "${BUILD_DIR}/hints.yml")
|
|
else()
|
|
idf_build_binary("${executable}"
|
|
OUTPUT_FILE "${build_dir}/${executable}.bin"
|
|
TARGET "${executable}_binary")
|
|
idf_check_binary_size("${executable}_binary")
|
|
idf_check_binary_signed("${executable}_binary")
|
|
|
|
add_custom_target(app ALL DEPENDS "${executable}_binary")
|
|
|
|
idf_flash_binary("${executable}_binary"
|
|
TARGET app-flash
|
|
NAME "app"
|
|
FLASH)
|
|
|
|
idf_create_dfu("${executable}_binary"
|
|
TARGET dfu)
|
|
idf_build_generate_metadata(BINARY "${executable}_binary"
|
|
HINTS_OUTPUT_FILE "${BUILD_DIR}/hints.yml")
|
|
endif()
|
|
|
|
idf_build_generate_flasher_args()
|
|
else()
|
|
idf_build_generate_metadata(EXECUTABLE "${executable}"
|
|
HINTS_OUTPUT_FILE "${BUILD_DIR}/hints.yml")
|
|
endif()
|
|
|
|
idf_create_menuconfig("${executable}"
|
|
TARGET menuconfig)
|
|
|
|
idf_create_confserver("${executable}"
|
|
TARGET confserver)
|
|
|
|
idf_create_save_defconfig()
|
|
|
|
idf_create_config_report("${executable}"
|
|
TARGET config-report)
|
|
|
|
idf_create_uf2("${executable}"
|
|
TARGET uf2)
|
|
idf_create_uf2("${executable}"
|
|
TARGET uf2-app
|
|
APP_ONLY)
|
|
|
|
if(TARGET "${executable}_mapfile")
|
|
idf_create_size_report("${executable}_mapfile"
|
|
TARGET size)
|
|
endif()
|
|
|
|
idf_build_generate_depgraph("${executable}")
|
|
endfunction()
|
|
|
|
#[[api
|
|
.. cmakev2:macro:: idf_project_default
|
|
|
|
.. code-block:: cmake
|
|
|
|
idf_project_default()
|
|
|
|
Create a default project executable based on the main component and its
|
|
transitive dependencies. The executable name is derived from the
|
|
``PROJECT_NAME`` variable, which by default uses the ``CMAKE_PROJECT_NAME``
|
|
value specified in the CMake's ``project()`` call.
|
|
|
|
Generate the binary image for the executable, signed or unsigned based on
|
|
the configuration, and add flash targets for it.
|
|
#]]
|
|
macro(idf_project_default)
|
|
idf_project_init()
|
|
|
|
# Use DEFERRED optional-requires resolution only when this will be the sole
|
|
# library being built.
|
|
idf_build_set_property(IDF_COMPONENT_OPTIONAL_REQUIRES_MODE DEFERRED)
|
|
|
|
# Only the idf_project_init macro needs be called within the global scope,
|
|
# as it includes the project_include.cmake files and the cmake version of
|
|
# the configuration. The remaining functionality of the idf_project_default
|
|
# macro is implemented in a __project_default helper function to avoid
|
|
# polluting the global variable space.
|
|
__project_default()
|
|
endmacro()
|