diff --git a/components/bootloader/subproject/CMakeLists_v2.txt b/components/bootloader/subproject/CMakeLists_v2.txt
index 231f315579b..50bda3faa2c 100644
--- a/components/bootloader/subproject/CMakeLists_v2.txt
+++ b/components/bootloader/subproject/CMakeLists_v2.txt
@@ -40,6 +40,9 @@ include("${IDF_PATH}/tools/cmakev2/idf.cmake")
project(bootloader C CXX ASM)
+# Suppress warning: "Manually-specified variables were not used by the project: SECURE_BOOT_SIGNING_KEY"
+set(_ignore_signing_key "${SECURE_BOOT_SIGNING_KEY}")
+
# ---------------------------------------------------------------------------
# Bootloader-specific build properties set before project initialization
# ---------------------------------------------------------------------------
diff --git a/components/bootloader_support/test_apps/rtc_custom_section/main/CMakeLists.txt b/components/bootloader_support/test_apps/rtc_custom_section/main/CMakeLists.txt
index 1df31fac804..b8928fdeb7b 100644
--- a/components/bootloader_support/test_apps/rtc_custom_section/main/CMakeLists.txt
+++ b/components/bootloader_support/test_apps/rtc_custom_section/main/CMakeLists.txt
@@ -1,2 +1,3 @@
idf_component_register(SRCS "test_main.c"
- INCLUDE_DIRS ".")
+ INCLUDE_DIRS "."
+ PRIV_REQUIRES bootloader_support)
diff --git a/tools/cmake/project.cmake b/tools/cmake/project.cmake
index aecb4dc6384..3be09b24d6e 100644
--- a/tools/cmake/project.cmake
+++ b/tools/cmake/project.cmake
@@ -1,6 +1,101 @@
# Designed to be included from an IDF app's CMakeLists.txt file
cmake_minimum_required(VERSION 3.22)
+# When the IDF_BUILD_V2 environment variable is set, transparently delegate
+# to Build system v2 (cmakev2). This allows existing Build system v1 projects
+# to be built with Build system v2 without modifying their CMakeLists.txt.
+# The project() macro is wrapped to automatically call idf_project_default()
+# after the real CMake project() call, bridging the API difference between
+# Build system v1 and Build system v2.
+#
+# Build system v1 pattern (no changes needed):
+# include($ENV{IDF_PATH}/tools/cmake/project.cmake)
+# idf_build_set_property(...) # optional, works with Build system v2 infra
+# project(my_app)
+#
+# With IDF_BUILD_V2=y set in the environment, this becomes equivalent to:
+# include($ENV{IDF_PATH}/tools/cmakev2/idf.cmake)
+# idf_build_set_property(...)
+# project(my_app C CXX ASM)
+# idf_project_default()
+if($ENV{IDF_BUILD_V2})
+ message(STATUS "IDF Build System V2 (cmakev2) activated via IDF_BUILD_V2 shim")
+
+ # Include the Build system v2 (cmakev2) entry point. This sets up all
+ # Build system v2 infrastructure (build properties, target, toolchain,
+ # kconfig, etc.). idf.cmake's file-level __init_idf_path() call publishes
+ # ${idf_path} to this scope, so no further set() is needed here.
+ include(${CMAKE_CURRENT_LIST_DIR}/../cmakev2/idf.cmake)
+
+ # Mark that we are running through the Build system v1 compatibility shim
+ # so that Build system v2 internals can enable backward-compatible build
+ # properties.
+ idf_build_set_property(__V1_COMPAT_SHIM 1)
+
+ # Use the standard CMake trick to save the real project() command.
+ # After these two overrides, __project() calls the original CMake
+ # project(). See https://cmake.org/pipermail/cmake/2015-October/061751.html
+ function(project)
+ endfunction()
+
+ function(_project)
+ endfunction()
+
+ macro(project project_name)
+ # Call the real CMake project() with the languages required by cmakev2.
+ __project(${project_name} C CXX ASM)
+
+ # Restore project() for sub-projects and third-party libraries that
+ # may call project() themselves (e.g. components/mbedtls calls
+ # add_subdirectory(mbedtls) which runs `project("Mbed TLS")`).
+ #
+ # The override is a function() (own variable scope), so PROJECT_*
+ # variables set by __project() must be explicitly propagated to
+ # PARENT_SCOPE — otherwise the caller (and any subsequent
+ # add_subdirectory() within that caller) sees the IDF top-level
+ # project's source/binary dirs instead of the third-party project's.
+ # See tools/cmake/project.cmake's mature override at the Build
+ # system v1 path for the full set of mirrored variables.
+ function(project)
+ set(project_ARGV ARGV)
+ __project(${${project_ARGV}})
+
+ set(PROJECT_NAME "${PROJECT_NAME}" PARENT_SCOPE)
+ set(PROJECT_BINARY_DIR "${PROJECT_BINARY_DIR}" PARENT_SCOPE)
+ set(PROJECT_SOURCE_DIR "${PROJECT_SOURCE_DIR}" PARENT_SCOPE)
+ set(PROJECT_VERSION "${PROJECT_VERSION}" PARENT_SCOPE)
+ set(PROJECT_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}" PARENT_SCOPE)
+ set(PROJECT_VERSION_MINOR "${PROJECT_VERSION_MINOR}" PARENT_SCOPE)
+ set(PROJECT_VERSION_PATCH "${PROJECT_VERSION_PATCH}" PARENT_SCOPE)
+ set(PROJECT_VERSION_TWEAK "${PROJECT_VERSION_TWEAK}" PARENT_SCOPE)
+ set(PROJECT_DESCRIPTION "${PROJECT_DESCRIPTION}" PARENT_SCOPE)
+ set(PROJECT_HOMEPAGE_URL "${PROJECT_HOMEPAGE_URL}" PARENT_SCOPE)
+
+ set(${PROJECT_NAME}_BINARY_DIR "${${PROJECT_NAME}_BINARY_DIR}" PARENT_SCOPE)
+ set(${PROJECT_NAME}_SOURCE_DIR "${${PROJECT_NAME}_SOURCE_DIR}" PARENT_SCOPE)
+ set(${PROJECT_NAME}_VERSION "${${PROJECT_NAME}_VERSION}" PARENT_SCOPE)
+ set(${PROJECT_NAME}_VERSION_MAJOR "${${PROJECT_NAME}_VERSION_MAJOR}" PARENT_SCOPE)
+ set(${PROJECT_NAME}_VERSION_MINOR "${${PROJECT_NAME}_VERSION_MINOR}" PARENT_SCOPE)
+ set(${PROJECT_NAME}_VERSION_PATCH "${${PROJECT_NAME}_VERSION_PATCH}" PARENT_SCOPE)
+ set(${PROJECT_NAME}_VERSION_TWEAK "${${PROJECT_NAME}_VERSION_TWEAK}" PARENT_SCOPE)
+ set(${PROJECT_NAME}_DESCRIPTION "${${PROJECT_NAME}_DESCRIPTION}" PARENT_SCOPE)
+ set(${PROJECT_NAME}_HOMEPAGE_URL "${${PROJECT_NAME}_HOMEPAGE_URL}" PARENT_SCOPE)
+ endfunction()
+
+ # If the app set COMPONENTS before project(), forward it to Build
+ # system v2 via a build property so __project_default() can use the
+ # correct component list instead of the hardcoded "main".
+ if(DEFINED COMPONENTS)
+ idf_build_set_property(__SHIM_COMPONENTS "${COMPONENTS}")
+ endif()
+
+ # Initialize and build the project using Build system v2.
+ idf_project_default()
+ endmacro()
+
+ return()
+endif()
+
# Get the currently selected sdkconfig file early, so this doesn't
# have to be done multiple times on different places.
if(SDKCONFIG)
diff --git a/tools/cmakev2/build.cmake b/tools/cmakev2/build.cmake
index ab6d71ed0de..15ed609b487 100644
--- a/tools/cmakev2/build.cmake
+++ b/tools/cmakev2/build.cmake
@@ -83,7 +83,12 @@ function(idf_build_get_property variable property)
cmake_parse_arguments(ARG "${options}" "${one_value}" "${multi_value}" ${ARGN})
if("${property}" STREQUAL BUILD_COMPONENTS)
- idf_die("Build property 'BUILD_COMPONENTS' is not supported")
+ # BUILD_COMPONENTS is populated by the Build system v1 compatibility
+ # shim; reject only when running as a native Build system v2 project.
+ idf_build_get_property(_v1_compat __V1_COMPAT_SHIM)
+ if(NOT _v1_compat)
+ idf_die("Build property 'BUILD_COMPONENTS' is not supported")
+ endif()
endif()
set(genexpr)
@@ -356,11 +361,25 @@ function(idf_build_library library)
# Include the requested components and link their interface targets to the
# library.
+ #
+ # On the GNU linker, bracket the component interface list with
+ # --start-group/--end-group so the linker re-scans archives until all
+ # symbols resolve. Required when the archive defining a __wrap_*
+ # implementation is encountered after the archive consuming the wrapped
+ # symbol on the link line; without group iteration the wrap symbol is
+ # unresolved.
+ idf_build_get_property(linker_type LINKER_TYPE)
+ if("${linker_type}" STREQUAL "GNU")
+ target_link_libraries("${library}" INTERFACE "-Wl,--start-group")
+ endif()
foreach(component_name IN LISTS ARG_COMPONENTS)
idf_component_include("${component_name}")
idf_component_get_property(component_interface "${component_name}" COMPONENT_INTERFACE)
target_link_libraries("${library}" INTERFACE "${component_interface}")
endforeach()
+ if("${linker_type}" STREQUAL "GNU")
+ target_link_libraries("${library}" INTERFACE "-Wl,--end-group")
+ endif()
# Process optional requirements in DEFERRED mode only (no-op in IMMEDIATE or when unset).
idf_build_get_property(opt_req_mode IDF_COMPONENT_OPTIONAL_REQUIRES_MODE)
diff --git a/tools/cmakev2/compat.cmake b/tools/cmakev2/compat.cmake
index 9a25c0f6547..c6100ab9dfb 100644
--- a/tools/cmakev2/compat.cmake
+++ b/tools/cmakev2/compat.cmake
@@ -425,6 +425,14 @@ function(__init_common_components)
# component.
if(explicit_requires_common)
set(requires_common "${explicit_requires_common}")
+ # Auto-append the target's arch component when the app overrides
+ # common-requires without it. Lets G0-style apps (which set the property
+ # before project() to a restricted list) avoid hand-rolling a
+ # target -> arch map pre-project, since IDF_TARGET_ARCH isn't known
+ # until after sdkconfig is included. Empty on linux -> no append.
+ if(idf_target_arch AND NOT idf_target_arch IN_LIST requires_common)
+ list(APPEND requires_common "${idf_target_arch}")
+ endif()
elseif("${idf_target}" STREQUAL "linux")
set(requires_common freertos esp_hw_support heap log soc hal esp_rom esp_common esp_system linux
@@ -452,6 +460,89 @@ function(__init_common_components)
idf_build_set_property(__COMMON_COMPONENTS_INITIALIZED YES)
endfunction()
+#[[api
+.. cmakev2:function:: idf_component_mock
+
+ .. code-block:: cmake
+
+ idf_component_mock([INCLUDE_DIRS
...]
+ [MOCK_HEADER_FILES ...]
+ [REQUIRES ...]
+ [MOCK_SUBDIR ])
+
+ *INCLUDE_DIRS[in,opt]*
+
+ Include directories for the header files provided in MOCK_HEADER_FILES.
+
+ *MOCK_HEADER_FILES[in,opt]*
+
+ Header files from which CMock generates mock implementations.
+
+ *REQUIRES[in,opt]*
+
+ Additional components required by the mock component.
+
+ *MOCK_SUBDIR[in,opt]*
+
+ Subdirectory under the mocks output where generated files are placed.
+
+ Create a mock component using CMock and register it with the build system.
+ This is a compatibility shim matching the v1 ``idf_component_mock``
+ function in ``tools/cmake/component.cmake``. It generates Mock*.c and
+ Mock*.h files from the given headers using Ruby + CMock, then delegates to
+ ``idf_component_register`` so the mock participates in normal dependency
+ resolution.
+#]]
+function(idf_component_mock)
+ set(options)
+ set(single_value MOCK_SUBDIR)
+ set(multi_value MOCK_HEADER_FILES INCLUDE_DIRS REQUIRES)
+ cmake_parse_arguments(_ "${options}" "${single_value}" "${multi_value}" ${ARGN})
+
+ list(APPEND __REQUIRES "cmock")
+
+ set(MOCK_GENERATED_HEADERS "")
+ set(MOCK_GENERATED_SRCS "")
+ set(IDF_PATH $ENV{IDF_PATH})
+ set(CMOCK_DIR "${IDF_PATH}/components/cmock/CMock")
+ set(MOCK_GEN_DIR "${CMAKE_CURRENT_BINARY_DIR}")
+ list(APPEND __INCLUDE_DIRS "${MOCK_GEN_DIR}/mocks")
+
+ foreach(header_file ${__MOCK_HEADER_FILES})
+ get_filename_component(file_without_dir ${header_file} NAME_WE)
+ if("${__MOCK_SUBDIR}" STREQUAL "")
+ list(APPEND MOCK_GENERATED_HEADERS "${MOCK_GEN_DIR}/mocks/Mock${file_without_dir}.h")
+ list(APPEND MOCK_GENERATED_SRCS "${MOCK_GEN_DIR}/mocks/Mock${file_without_dir}.c")
+ else()
+ list(APPEND MOCK_GENERATED_HEADERS "${MOCK_GEN_DIR}/mocks/${__MOCK_SUBDIR}/Mock${file_without_dir}.h")
+ list(APPEND MOCK_GENERATED_SRCS "${MOCK_GEN_DIR}/mocks/${__MOCK_SUBDIR}/Mock${file_without_dir}.c")
+ endif()
+ endforeach()
+
+ file(MAKE_DIRECTORY "${MOCK_GEN_DIR}/mocks")
+
+ idf_component_register(SRCS "${MOCK_GENERATED_SRCS}"
+ INCLUDE_DIRS ${__INCLUDE_DIRS}
+ REQUIRES ${__REQUIRES})
+
+ set(COMPONENT_LIB ${COMPONENT_LIB} PARENT_SCOPE)
+ add_custom_command(
+ OUTPUT ruby_found SYMBOLIC
+ COMMAND "ruby" "-v"
+ COMMENT "Try to find ruby. If this fails, you need to install ruby"
+ )
+
+ add_custom_command(
+ OUTPUT ${MOCK_GENERATED_SRCS} ${MOCK_GENERATED_HEADERS}
+ DEPENDS ruby_found
+ COMMAND ${CMAKE_COMMAND} -E env "UNITY_DIR=${IDF_PATH}/components/unity/unity"
+ ruby
+ ${CMOCK_DIR}/lib/cmock.rb
+ -o${CMAKE_CURRENT_SOURCE_DIR}/mock/mock_config.yaml
+ ${__MOCK_HEADER_FILES}
+ )
+endfunction()
+
#[[api
.. cmakev2:function:: idf_component_register
@@ -642,6 +733,47 @@ function(idf_component_register)
target_link_libraries("${COMPONENT_TARGET}" PRIVATE "${req_interface}")
endforeach()
+ # Special treatment for 'main' component is only applied when the project
+ # was entered through the Build system v1 compatibility shim. Native
+ # Build system v2 projects with no REQUIRES on main should remain the
+ # author-declared dependency set rooted at main; forcing every discovered
+ # component into main's link graph in that case contradicts the Build
+ # system v2 contract that the dependency graph is what the author writes.
+ idf_build_get_property(v1_compat_shim __V1_COMPAT_SHIM)
+ if(v1_compat_shim AND COMPONENT_NAME STREQUAL "main"
+ AND NOT ARG_REQUIRES AND NOT ARG_PRIV_REQUIRES)
+ idf_component_get_property(component_source "${COMPONENT_NAME}" COMPONENT_SOURCE)
+ if(component_source STREQUAL "project_components")
+ idf_build_get_property(shim_components __SHIM_COMPONENTS)
+ if(shim_components)
+ # The project explicitly restricted COMPONENTS=. Honor
+ # the restriction literally — do not pull every discovered
+ # component into main's link graph, even when the user's list
+ # collapses to just "main". Apps that need additional
+ # components must enumerate them in COMPONENTS or main's
+ # REQUIRES.
+ set(all_components ${shim_components})
+ else()
+ idf_build_get_property(all_components COMPONENTS_DISCOVERED)
+ endif()
+ list(REMOVE_ITEM all_components "main")
+ # Common components are already linked via link_libraries()
+ idf_build_get_property(common_components __COMPONENT_REQUIRES_COMMON)
+ if(common_components)
+ list(REMOVE_ITEM all_components ${common_components})
+ endif()
+ foreach(req IN LISTS all_components)
+ idf_component_include("${req}")
+ idf_component_get_property(req_interface "${req}" COMPONENT_INTERFACE)
+ if(${component_type} STREQUAL LIBRARY)
+ target_link_libraries("${COMPONENT_TARGET}" PUBLIC "${req_interface}")
+ else()
+ target_link_libraries("${COMPONENT_TARGET}" INTERFACE "${req_interface}")
+ endif()
+ endforeach()
+ endif()
+ endif()
+
# Signal to idf_component_include that this component was included via the
# backward compatible idf_component_register function.
idf_component_set_property("${COMPONENT_NAME}" COMPONENT_FORMAT CMAKEV1)
@@ -661,8 +793,30 @@ function(idf_component_register)
# Embedded files are managed in the idf_component_include function.
idf_component_set_property("${COMPONENT_NAME}" EMBED_FILES "${ARG_EMBED_FILES}")
idf_component_set_property("${COMPONENT_NAME}" EMBED_TXTFILES "${ARG_EMBED_TXTFILES}")
- idf_component_set_property("${COMPONENT_NAME}" REQUIRES "${ARG_REQUIRES}")
- idf_component_set_property("${COMPONENT_NAME}" PRIV_REQUIRES "${ARG_PRIV_REQUIRES}")
+ # The component manager's dependency injection runs before this component's
+ # CMakeLists.txt is evaluated (see idf_component_include() in
+ # component.cmake), and writes the manifest-derived names into both the
+ # MANAGED_* properties and the regular REQUIRES / PRIV_REQUIRES properties.
+ # The latter must not be overwritten by the component's own register call,
+ # else the manifest-derived transitive deps disappear from the build. Union
+ # the two so the persisted property is what the component author wrote
+ # PLUS what the manifest contributed.
+ idf_component_get_property(__existing_requires "${COMPONENT_NAME}" REQUIRES)
+ idf_component_get_property(__existing_priv_requires "${COMPONENT_NAME}" PRIV_REQUIRES)
+ set(__merged_requires "${ARG_REQUIRES}")
+ set(__merged_priv_requires "${ARG_PRIV_REQUIRES}")
+ foreach(__r IN LISTS __existing_requires)
+ if(__r AND NOT __r IN_LIST __merged_requires)
+ list(APPEND __merged_requires "${__r}")
+ endif()
+ endforeach()
+ foreach(__r IN LISTS __existing_priv_requires)
+ if(__r AND NOT __r IN_LIST __merged_priv_requires)
+ list(APPEND __merged_priv_requires "${__r}")
+ endif()
+ endforeach()
+ idf_component_set_property("${COMPONENT_NAME}" REQUIRES "${__merged_requires}")
+ idf_component_set_property("${COMPONENT_NAME}" PRIV_REQUIRES "${__merged_priv_requires}")
idf_component_set_property("${COMPONENT_NAME}" REQUIRED_IDF_TARGETS "${ARG_REQUIRED_IDF_TARGETS}")
idf_component_set_property("${COMPONENT_NAME}" COMPONENT_TYPE "${component_type}")
endfunction()
@@ -776,3 +930,27 @@ function(idf_build_component component_dir)
PREFIX "${component_prefix}"
SOURCE "${component_source}")
endfunction()
+
+#[[
+ __import_sdkconfig_as_build_properties()
+
+ Mirror every CONFIG_* symbol from the generated sdkconfig.cmake onto the
+ build-properties target so that the
+ `idf_build_get_property(var CONFIG_FOO)` idiom keeps working under the
+ compatibility shim. Called from kconfig.cmake::__generate_sdkconfig after
+ each kconfgen run.
+#]]
+function(__import_sdkconfig_as_build_properties)
+ idf_build_get_property(sdkconfig_cmake __SDKCONFIG_CMAKE)
+ if(NOT sdkconfig_cmake OR NOT EXISTS "${sdkconfig_cmake}")
+ return()
+ endif()
+ include("${sdkconfig_cmake}")
+ if(NOT DEFINED CONFIGS_LIST)
+ return()
+ endif()
+ idf_build_set_property(__CONFIG_VARIABLES "${CONFIGS_LIST}")
+ foreach(config IN LISTS CONFIGS_LIST)
+ idf_build_set_property("${config}" "${${config}}")
+ endforeach()
+endfunction()
diff --git a/tools/cmakev2/component.cmake b/tools/cmakev2/component.cmake
index 8a07d0a91d6..da557c55123 100644
--- a/tools/cmakev2/component.cmake
+++ b/tools/cmakev2/component.cmake
@@ -891,6 +891,29 @@ function(idf_component_include name)
endif()
list(APPEND __DEPENDENCY_CHAIN "${component_interface}")
+
+ # Inject managed dependencies BEFORE add_subdirectory() evaluates the
+ # component's CMakeLists.txt — otherwise any component that queries a
+ # managed dependency at register time via
+ # idf_component_get_property(... COMPONENT_LIB) finds nothing because the
+ # target hasn't been created yet.
+ idf_build_get_property(idf_component_manager IDF_COMPONENT_MANAGER)
+ if(idf_component_manager EQUAL 1)
+ idf_component_get_property(_comp_dir "${component_name}" COMPONENT_DIR)
+ if(EXISTS "${_comp_dir}/idf_component.yml")
+ __inject_requirements_for_component_from_manager("${component_name}")
+
+ idf_component_get_property(_managed_req "${component_name}" MANAGED_REQUIRES)
+ idf_component_get_property(_managed_priv_req "${component_name}" MANAGED_PRIV_REQUIRES)
+
+ foreach(_dep IN LISTS _managed_req _managed_priv_req)
+ if(_dep)
+ idf_component_include("${_dep}")
+ endif()
+ endforeach()
+ endif()
+ endif()
+
# Evaluate the CMakeLists.txt file of the component.
idf_component_get_property(component_build_dir "${component_name}" COMPONENT_BUILD_DIR)
add_subdirectory("${component_directory}" "${component_build_dir}")
@@ -977,25 +1000,16 @@ function(idf_component_include name)
target_add_binary_data(${COMPONENT_TARGET} "${file}" "TEXT")
endforeach()
- # Inject managed dependencies if component manager is enabled
+ # Link managed dependencies for cmakev1 components (backward compat).
+ # The injection and inclusion already happened before add_subdirectory().
idf_build_get_property(idf_component_manager IDF_COMPONENT_MANAGER)
idf_component_get_property(component_format "${component_name}" COMPONENT_FORMAT)
if(idf_component_manager EQUAL 1)
idf_component_get_property(component_dir "${component_name}" COMPONENT_DIR)
- # Check if component has manifest for managed dependency injection
if(EXISTS "${component_dir}/idf_component.yml")
- __inject_requirements_for_component_from_manager("${component_name}")
-
- # Include any managed dependencies
idf_component_get_property(managed_requires "${component_name}" MANAGED_REQUIRES)
idf_component_get_property(managed_priv_requires "${component_name}" MANAGED_PRIV_REQUIRES)
- foreach(dep IN LISTS managed_requires managed_priv_requires)
- if(dep)
- idf_component_include("${dep}")
- endif()
- endforeach()
-
# For cmakev1 components, automatically link managed dependencies to maintain
# backward compatibility.
if("${component_format}" STREQUAL "CMAKEV1")
diff --git a/tools/cmakev2/kconfig.cmake b/tools/cmakev2/kconfig.cmake
index 977e0b38558..58fa411d1f9 100644
--- a/tools/cmakev2/kconfig.cmake
+++ b/tools/cmakev2/kconfig.cmake
@@ -208,6 +208,10 @@ function(__generate_sdkconfig)
# Generate Kconfig outputs
__generate_kconfig_outputs()
+ # Mirror CONFIG_* values onto build properties so
+ # `idf_build_get_property(var CONFIG_FOO)` keeps working.
+ __import_sdkconfig_as_build_properties()
+
idf_msg("Generated sdkconfig configuration")
endfunction()
diff --git a/tools/cmakev2/project.cmake b/tools/cmakev2/project.cmake
index 22189e962aa..03e3fbcb351 100644
--- a/tools/cmakev2/project.cmake
+++ b/tools/cmakev2/project.cmake
@@ -190,7 +190,7 @@ function(__init_project_configuration)
# 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)
+ if(NOT DEFINED set_compiler_optimization OR set_compiler_optimization STREQUAL "")
set(set_compiler_optimization YES)
endif()
if(set_compiler_optimization)
@@ -533,7 +533,9 @@ endfunction()
esptool_py component.
#]]
function(__init_project_flash_targets)
- if(CONFIG_APP_BUILD_GENERATE_BINARIES)
+ # Skip if esptool_py is not in the build set; the flash-target function
+ # would otherwise be undefined.
+ if(CONFIG_APP_BUILD_GENERATE_BINARIES AND COMMAND esptool_py_flash_target)
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}")
@@ -741,10 +743,54 @@ endfunction()
function(__project_default)
idf_build_get_property(build_dir BUILD_DIR)
idf_build_get_property(executable PROJECT_NAME)
+
+ # When the Build system v1 compatibility shim forwarded a COMPONENTS
+ # list, use it instead of default main.
+ idf_build_get_property(shim_components __SHIM_COMPONENTS)
+ if(shim_components)
+ set(root_components ${shim_components})
+ else()
+ set(root_components main)
+ endif()
+
idf_build_executable("${executable}"
- COMPONENTS main
+ COMPONENTS ${root_components}
MAPFILE_TARGET "${executable}_mapfile")
+ # In Build system v1, the ``project_elf`` variable (set to
+ # "${project_name}.elf") is used by several app CMakeLists.txt files to add
+ # linker flags after project(). In Build system v2 the executable target
+ # is just "${executable}" (the .elf suffix is an output property, not part
+ # of the target name). Propagate it to the caller's scope so existing
+ # code keeps working.
+ set(project_elf "${executable}" PARENT_SCOPE)
+
+ # Provide Build system v1-compatible build properties so that existing
+ # test apps and project CMakeLists.txt files that query EXECUTABLE or
+ # BUILD_COMPONENTS continue to work when built through the shim.
+ idf_build_get_property(v1_compat __V1_COMPAT_SHIM)
+ if(v1_compat)
+ idf_build_set_property(EXECUTABLE "${executable}")
+ idf_build_set_property(EXECUTABLE_NAME "${executable}")
+
+ # BUILD_COMPONENTS: in Build system v1 this is the set of components
+ # actually processed during the build (COMPONENTS + their transitive
+ # REQUIRES within the restricted scope). Use LIBRARY_COMPONENTS_LINKED
+ # from the Build system v2 library target which reflects the actual
+ # list of components linked, plus the architecture component which
+ # Build system v1 always includes but Build system v2 does not track
+ # as a linked library.
+ get_target_property(library ${executable} LIBRARY_INTERFACE)
+ if(library)
+ idf_library_get_property(linked_components "${library}" LIBRARY_COMPONENTS_LINKED)
+ idf_build_get_property(target_arch IDF_TARGET_ARCH)
+ if(target_arch AND NOT target_arch IN_LIST linked_components)
+ list(APPEND linked_components ${target_arch})
+ endif()
+ idf_build_set_property(BUILD_COMPONENTS "${linked_components}")
+ endif()
+ endif()
+
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?