757 lines
26 KiB
CMake
757 lines
26 KiB
CMake
# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
include_guard(GLOBAL)
|
|
|
|
cmake_minimum_required(VERSION 3.22)
|
|
|
|
# Update the CMAKE_MODULE_PATH to ensure that additional cmakev2 build system
|
|
# modules can be included. The third_party directory from cmakev1 is also
|
|
# included for third-party modules shared with cmakev1.
|
|
set(CMAKE_MODULE_PATH
|
|
"${CMAKE_CURRENT_LIST_DIR}"
|
|
"${CMAKE_CURRENT_LIST_DIR}/../cmake/third_party"
|
|
${CMAKE_MODULE_PATH})
|
|
|
|
# The version.cmake file contains the IDF_VERSION variables, which are the same
|
|
# for both cmakev1 and cmakev2.
|
|
include(${CMAKE_CURRENT_LIST_DIR}/../cmake/version.cmake)
|
|
|
|
# Suppress CMake warning: "Manually-specified variables were not used by the project: CONFIGDEP_ENABLE"
|
|
# (CONFIGDEP_ENABLE is passed by idf.py but only used in the cmake v1 project() flow in project.cmake)
|
|
# FIXME: When cmakev2 will start supporting configdep, this can be removed.
|
|
set(_idf_ignore_configdep_enable "${CONFIGDEP_ENABLE}")
|
|
|
|
# The gdbinit.cmake file from cmakev1 contains a single function,
|
|
# __generate_gdbinit, which is used in the generation of
|
|
# project_description.json.
|
|
include(${CMAKE_CURRENT_LIST_DIR}/../cmake/gdbinit.cmake)
|
|
|
|
# The openocd.cmake file from cmakev1 contains a single function,
|
|
# __get_openocd_options, which is used in the generation of
|
|
# project_description.json.
|
|
include(${CMAKE_CURRENT_LIST_DIR}/../cmake/openocd.cmake)
|
|
|
|
# The depgraph.cmake file from cmakev1 contains helper functions for generating
|
|
# a component dependency graph. Let's reuse these functions in the
|
|
# idf_build_generate_depgraph function.
|
|
include(${CMAKE_CURRENT_LIST_DIR}/../cmake/depgraph.cmake)
|
|
|
|
# The err_codes.cmake file from cmakev1 provides idf_define_esp_err_codes(),
|
|
# which generates per-component error code tables placed in a link-time array.
|
|
include(${CMAKE_CURRENT_LIST_DIR}/../cmake/err_codes.cmake)
|
|
|
|
include(component)
|
|
include(build)
|
|
include(kconfig)
|
|
include(project)
|
|
include(manager)
|
|
include(compat)
|
|
include(ldgen)
|
|
include(dfu)
|
|
include(uf2)
|
|
include(size)
|
|
|
|
include(GetGitRevisionDescription)
|
|
# For backward compatibility, since externalproject_add is used by
|
|
# project_include.cmake in the bootloader component. The ExternalProject
|
|
# should probably be included there instead.
|
|
include(ExternalProject)
|
|
|
|
#[[api
|
|
.. cmakev2:variable:: IDF_BUILD_V2
|
|
|
|
Set to ``y`` when the project is built with the CMake-based build system
|
|
v2. Use it to write component code that works with both v1 and v2, for
|
|
example ``if(IDF_BUILD_V2)``. It is also exported as an environment variable
|
|
and stored as a build property.
|
|
|
|
.. cmakev2:variable:: IDF_BUILD_VER
|
|
|
|
The major version number of the build system, ``2`` for v2.
|
|
|
|
.. cmakev2:variable:: IDF_BUILD_VER_TAG
|
|
|
|
The build system version tag, ``v2`` for v2.
|
|
#]]
|
|
|
|
#[[
|
|
__init_build_version()
|
|
|
|
Set the global variables IDF_BUILD_V2, IDF_BUILD_VER and IDF_BUILD_VER_TAG,
|
|
as well as the build properties and environmental variables.
|
|
#]]
|
|
function(__init_build_version)
|
|
set(IDF_BUILD_V2 y PARENT_SCOPE)
|
|
set(IDF_BUILD_VER 2 PARENT_SCOPE)
|
|
set(IDF_BUILD_VER_TAG "v2" PARENT_SCOPE)
|
|
idf_build_set_property(IDF_BUILD_V2 y)
|
|
idf_build_set_property(IDF_BUILD_VER 2)
|
|
idf_build_set_property(IDF_BUILD_VER_TAG "v2")
|
|
set(ENV{IDF_BUILD_V2} y)
|
|
set(ENV{IDF_BUILD_VER} 2)
|
|
set(ENV{IDF_BUILD_VER_TAG} "v2")
|
|
endfunction()
|
|
|
|
#[[
|
|
__init_idf_path()
|
|
|
|
Determine the IDF_PATH value, either from the IDF_PATH environmental
|
|
variable or based on the location of this file. Also check there is no
|
|
inconsistency between the two.
|
|
|
|
Set the IDF_PATH global variable, environment variable and build property.
|
|
#]]
|
|
function(__init_idf_path)
|
|
get_filename_component(idf_path_infer "${CMAKE_CURRENT_LIST_DIR}/../.." REALPATH)
|
|
|
|
if(NOT DEFINED ENV{IDF_PATH})
|
|
idf_warn("IDF_PATH environment variable not found. "
|
|
"Setting IDF_PATH to '${idf_path_infer}'.")
|
|
set(idf_path "${idf_path_infer}")
|
|
else()
|
|
get_filename_component(idf_path_env "$ENV{IDF_PATH}" REALPATH)
|
|
if(NOT "${idf_path_env}" STREQUAL "${idf_path_infer}")
|
|
idf_warn("IDF_PATH environment variable is different from inferred IDF_PATH. "
|
|
"Check if your project's top-level CMakeLists.txt includes the right "
|
|
"CMake files. Environment IDF_PATH will be used for the build: "
|
|
"'${idf_path_env}'")
|
|
endif()
|
|
set(idf_path "${idf_path_env}")
|
|
endif()
|
|
|
|
idf_build_set_property(IDF_PATH "${idf_path}")
|
|
# Components reference either ${IDF_PATH} or ${idf_path}; publish both.
|
|
set(IDF_PATH ${idf_path} PARENT_SCOPE)
|
|
set(idf_path ${idf_path} PARENT_SCOPE)
|
|
set(ENV{IDF_PATH} ${idf_path})
|
|
endfunction()
|
|
|
|
#[[
|
|
__init_git()
|
|
|
|
Determine the executable.
|
|
|
|
Set the GIT build property.
|
|
#]]
|
|
function(__init_git)
|
|
find_package(Git)
|
|
if(NOT GIT_FOUND)
|
|
idf_build_set_property(GIT NOTFOUND)
|
|
idf_warn("Git executable not found.")
|
|
return()
|
|
endif()
|
|
|
|
idf_build_set_property(GIT "${GIT_EXECUTABLE}")
|
|
endfunction()
|
|
|
|
#[[
|
|
__init_idf_version()
|
|
|
|
Determine the IDF version from the version.txt file. If it is not present,
|
|
use git-describe. If both previous attempts fail, use the IDF_VERSION from
|
|
the environment variables as a fallback.
|
|
|
|
Set IDF_VER build property.
|
|
#]]
|
|
function(__init_idf_version)
|
|
idf_build_get_property(idf_path IDF_PATH)
|
|
idf_build_get_property(git GIT)
|
|
if(EXISTS "${idf_path}/version.txt")
|
|
file(STRINGS "${idf_path}/version.txt" idf_ver)
|
|
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${idf_path}/version.txt")
|
|
else()
|
|
# Try to get the version using git-describe.
|
|
git_describe(idf_ver "${idf_path}" "--match=v*.*")
|
|
if(NOT idf_ver)
|
|
# The Git describe command failed unexpectedly, so the version is
|
|
# set to IDF_VERSION as specified in version.cmake.
|
|
set(idf_ver "$ENV{IDF_VERSION}")
|
|
endif()
|
|
endif()
|
|
# Trim IDF_VER to the necessary 32 characters.
|
|
string(SUBSTRING "${idf_ver}" 0 31 idf_ver)
|
|
idf_build_set_property(IDF_VER ${idf_ver})
|
|
endfunction()
|
|
|
|
#[[
|
|
__init_python()
|
|
|
|
Determine Python interpreter, either from the PYTHON CMake cache variable
|
|
or environmental variable or default it to "python".
|
|
|
|
If the PYTHON_DEPS_CHECKED CMake cache variable is not set, check if all
|
|
Python packages dependencies are satisfied. For instance, if a tool calling
|
|
CMake has already performed this check, it doesn't need to be repeated.
|
|
|
|
Set the global PYTHON variable, environment variable and build property.
|
|
#]]
|
|
function(__init_python)
|
|
__get_default_value(VARIABLE PYTHON
|
|
DEFAULT "python"
|
|
OUTPUT python)
|
|
file(TO_CMAKE_PATH ${python} python)
|
|
|
|
idf_build_set_property(PYTHON "${python}")
|
|
set(PYTHON "${python}" PARENT_SCOPE)
|
|
|
|
if(PYTHON_DEPS_CHECKED)
|
|
idf_dbg("Python dependencies have already been verified.")
|
|
return()
|
|
endif()
|
|
|
|
idf_build_get_property(idf_path IDF_PATH)
|
|
|
|
idf_msg("Checking Python dependencies...")
|
|
execute_process(
|
|
COMMAND "${python}" "${idf_path}/tools/idf_tools.py" "check-python-dependencies"
|
|
RESULT_VARIABLE result
|
|
)
|
|
if(result EQUAL 1)
|
|
# The function check_python_dependencies returns an error code of 1 if
|
|
# it fails.
|
|
idf_die("Some Python dependencies must be installed. Check above message for details.")
|
|
elseif(NOT result EQUAL 0)
|
|
# This means that check_python_dependencies.py failed to run entirely,
|
|
# and the result should be an error message.
|
|
idf_die("Failed to run Python dependency check. Python: ${python}, Error: ${result}")
|
|
endif()
|
|
endfunction()
|
|
|
|
#[[
|
|
__init_idf_target()
|
|
|
|
Determine the IDF_TARGET value from the IDF_TARGET environment variable,
|
|
the CMake cache variable, or the sdkconfig files. If none of these are set,
|
|
use the default esp32 target. Ensure there are no inconsistencies in the
|
|
IDF_TARGET values set in different locations.
|
|
|
|
Set the IDF_TARGET as a global variable, in the CMake cache, as an
|
|
environment variable, and as a build property.
|
|
#]]
|
|
function(__init_idf_target)
|
|
set(sdkconfig_target "")
|
|
set(target "")
|
|
set(sdkconfig_file "")
|
|
|
|
idf_build_get_property(sdkconfig SDKCONFIG)
|
|
idf_build_get_property(sdkconfig_defaults SDKCONFIG_DEFAULTS)
|
|
|
|
foreach(config ${sdkconfig} ${sdkconfig_defaults})
|
|
idf_dbg("Searching for target in '${config}'")
|
|
__get_sdkconfig_option(OPTION CONFIG_IDF_TARGET
|
|
SDKCONFIG "${config}"
|
|
OUTPUT sdkconfig_target)
|
|
if(sdkconfig_target)
|
|
set(sdkconfig_file "${config}")
|
|
break()
|
|
endif()
|
|
endforeach()
|
|
|
|
__get_default_value(VARIABLE IDF_TARGET
|
|
DEFAULT NOTFOUND
|
|
OUTPUT target)
|
|
|
|
if(NOT target)
|
|
if(sdkconfig_target)
|
|
idf_msg("IDF_TARGET is not set, guessed '${sdkconfig_target}' "
|
|
"from sdkconfig '${sdkconfig_file}'")
|
|
set(target "${sdkconfig_target}")
|
|
else()
|
|
idf_msg("IDF_TARGET not set, using default target: esp32")
|
|
set(target "esp32")
|
|
endif()
|
|
endif()
|
|
|
|
# Verify that the chosen target aligns with the CMake cache.
|
|
set(cache_target $CACHE{IDF_TARGET})
|
|
if(cache_target)
|
|
if(NOT "${cache_target}" STREQUAL "${target}")
|
|
idf_die("IDF_TARGET '${cache_target}' in CMake cache does not match "
|
|
"currently selected IDF_TARGET '${target}'. "
|
|
"To change the target, clear the build directory and sdkconfig file, "
|
|
"and build the project again.")
|
|
endif()
|
|
endif()
|
|
|
|
# Verify that the chosen target aligns with the sdkconfig.
|
|
if(sdkconfig_target AND "${sdkconfig_file}" STREQUAL "${sdkconfig}")
|
|
if("$ENV{_IDF_PY_SET_TARGET_ACTION}" STREQUAL "1")
|
|
idf_dbg("The target consistency check for the target specified in ${sdkconfig} "
|
|
"was skipped because the set-target action is being executed.")
|
|
elseif(NOT "${sdkconfig_target}" STREQUAL "${target}")
|
|
idf_die("Target '${sdkconfig_target}' in sdkconfig '${sdkconfig}' "
|
|
"does not match currently selected IDF_TARGET '${target}'. "
|
|
"To change the target, clear the build directory and sdkconfig file, "
|
|
"and build the project again.")
|
|
endif()
|
|
endif()
|
|
|
|
idf_build_set_property(IDF_TARGET "${target}")
|
|
set(ENV{IDF_TARGET} ${target})
|
|
set(IDF_TARGET ${target} CACHE STRING "IDF Build Target")
|
|
endfunction()
|
|
|
|
#[[
|
|
__init_toolchain()
|
|
|
|
Determine the toolchain file, set IDF_TOOLCHAIN_FILE build property and
|
|
global CMAKE_TOOLCHAIN_FILE CMake variable. Also ensure that the
|
|
CMAKE_TOOLCHAIN_FILE is set to the correct file according to the current
|
|
IDF_TARGET.
|
|
|
|
Note: The IDF_TOOLCHAIN build property is set after the toolchain
|
|
configuration in ``idf_project_init``. The ``tools/cmake/toolchain.cmake``
|
|
is included in the toolchain file and it sets the IDF_TOOLCHAIN variable in
|
|
CMake's cache.
|
|
#]]
|
|
function(__init_toolchain)
|
|
set(cache_toolchain $CACHE{IDF_TOOLCHAIN})
|
|
set(cache_toolchain_file $CACHE{CMAKE_TOOLCHAIN_FILE})
|
|
|
|
idf_build_get_property(idf_path IDF_PATH)
|
|
idf_build_get_property(idf_target IDF_TARGET)
|
|
|
|
__get_default_value(VARIABLE IDF_TOOLCHAIN
|
|
DEFAULT gcc
|
|
OUTPUT toolchain)
|
|
if(cache_toolchain)
|
|
if(NOT "${cache_toolchain}" STREQUAL "${toolchain}")
|
|
idf_die("IDF_TOOLCHAIN '${cache_toolchain}' in CMake cache does not match "
|
|
"currently selected IDF_TOOLCHAIN '${toolchain}'. To change "
|
|
"the toolchain, clear the build directory and sdkconfig file, "
|
|
"and build the project again.")
|
|
endif()
|
|
endif()
|
|
|
|
if("${toolchain}" STREQUAL "clang")
|
|
set(toolchain_type "clang-")
|
|
endif()
|
|
|
|
# Check that the selected target is consistent with the toolchain file in
|
|
# the CMake cache.
|
|
if(cache_toolchain_file)
|
|
string(FIND "${cache_toolchain_file}" "-${toolchain_type}${idf_target}.cmake" found)
|
|
if(${found} EQUAL -1)
|
|
get_filename_component(cache_toolchain_file_stem "${cache_toolchain_file}" NAME_WE)
|
|
idf_die("CMAKE_TOOLCHAIN_FILE '${cache_toolchain_file_stem}' "
|
|
"does not match currently selected IDF_TARGET '${idf_target}'. "
|
|
"To change the target, clear the build directory and sdkconfig file, "
|
|
"and build the project again.")
|
|
endif()
|
|
endif()
|
|
|
|
set(toolchain_file "${idf_path}/tools/cmake/toolchain-${toolchain_type}${idf_target}.cmake")
|
|
if(NOT EXISTS ${toolchain_file})
|
|
idf_die("Toolchain file ${toolchain_file} not found")
|
|
endif()
|
|
|
|
# IDF_TOOLCHAIN applies to Espressif targets only; on linux (host build)
|
|
# it must stay empty so Kconfig leaves both CONFIG_IDF_TOOLCHAIN_GCC and
|
|
# CONFIG_IDF_TOOLCHAIN_CLANG unset.
|
|
if(NOT "${idf_target}" STREQUAL "linux")
|
|
set(IDF_TOOLCHAIN "${toolchain}" CACHE STRING "IDF Build Toolchain Type" FORCE)
|
|
endif()
|
|
|
|
set(CMAKE_TOOLCHAIN_FILE "${toolchain_file}" PARENT_SCOPE)
|
|
idf_build_set_property(IDF_TOOLCHAIN_FILE "${toolchain_file}")
|
|
endfunction()
|
|
|
|
#[[
|
|
__init_ccache()
|
|
|
|
Enable ccache if requested through CCACHE_ENABLE.
|
|
#]]
|
|
function(__init_ccache)
|
|
if(NOT CCACHE_ENABLE)
|
|
return()
|
|
endif()
|
|
|
|
find_program(CCACHE_FOUND ccache)
|
|
if(CCACHE_FOUND)
|
|
idf_msg("ccache will be used for faster recompilation")
|
|
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
|
|
else()
|
|
idf_warn("enabled ccache in build but ccache program not found")
|
|
endif()
|
|
endfunction()
|
|
|
|
#[[
|
|
__init_components()
|
|
|
|
Search for possible component directories categorized by their source,
|
|
which could be ``idf_components``, ``project_extra_components``, or
|
|
``project_components``. Components added by the component manager are
|
|
initialized later as ``project_managed_components`` after the component
|
|
manager is called.
|
|
|
|
The search respects the variables set by the user e.g. in the project's
|
|
CMakeLists.txt file. These are maintained for backward compatibility.
|
|
|
|
COMPONENT_DIRS
|
|
If set, component directories are searched exclusively in the paths
|
|
provided in ``COMPONENT_DIRS``.
|
|
|
|
EXTRA_COMPONENT_DIRS
|
|
Includes extra paths to search if ``COMPONENT_DIRS`` is not specified.
|
|
|
|
EXTRA_COMPONENT_EXCLUDE_DIRS
|
|
List of paths to exclude from searching the component directories.
|
|
|
|
The ``PROJECT_COMPONENTS_SOURCE`` build property controls how the
|
|
project's own components are categorised -- i.e. those discovered
|
|
under ``CMAKE_CURRENT_SOURCE_DIR/main``,
|
|
``CMAKE_CURRENT_SOURCE_DIR/components``, or the paths listed in
|
|
``COMPONENT_DIRS``. It defaults to ``project_components``
|
|
(priority 3 -- highest). Setting it to ``idf_components``
|
|
(priority 0) makes them overridable by components supplied through
|
|
``EXTRA_COMPONENT_DIRS`` (priority 2). This is useful for
|
|
sub-projects whose built-in components are provided by ESP-IDF and
|
|
should be overridable by user-supplied components.
|
|
|
|
Each component is initialized for every component directory found.
|
|
#]]
|
|
function(__init_components)
|
|
idf_build_get_property(idf_path IDF_PATH)
|
|
idf_build_get_property(prefix PREFIX)
|
|
|
|
idf_build_get_property(project_components_source PROJECT_COMPONENTS_SOURCE)
|
|
if(NOT project_components_source)
|
|
set(project_components_source "project_components")
|
|
endif()
|
|
|
|
set(valid_sources "project_components" "idf_components")
|
|
if(NOT project_components_source IN_LIST valid_sources)
|
|
idf_die("Invalid PROJECT_COMPONENTS_SOURCE '${project_components_source}'."
|
|
" Must be one of: ${valid_sources}")
|
|
endif()
|
|
|
|
__get_component_paths(PATHS "${idf_path}/components"
|
|
OUTPUT idf_components)
|
|
if(COMPONENT_DIRS)
|
|
# The user explicitly stated the locations to search for components.
|
|
# For backward compatibility, check that the paths in
|
|
# COMPONENT_DIRS exist.
|
|
__get_component_paths(PATHS ${COMPONENT_DIRS}
|
|
EXCLUDE_PATHS ${EXTRA_COMPONENT_EXCLUDE_DIRS}
|
|
SOURCE "COMPONENT_DIRS"
|
|
CHECK
|
|
OUTPUT project_components)
|
|
else()
|
|
__get_component_paths(PATHS "${CMAKE_CURRENT_SOURCE_DIR}/main"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/components"
|
|
EXCLUDE_PATHS ${EXTRA_COMPONENT_EXCLUDE_DIRS}
|
|
OUTPUT project_components)
|
|
if(EXTRA_COMPONENT_DIRS)
|
|
# For backward compatibility, check that the paths in
|
|
# EXTRA_COMPONENT_DIRS exist.
|
|
__get_component_paths(PATHS ${EXTRA_COMPONENT_DIRS}
|
|
EXCLUDE_PATHS ${EXTRA_COMPONENT_EXCLUDE_DIRS}
|
|
SOURCE "EXTRA_COMPONENT_DIRS"
|
|
CHECK
|
|
OUTPUT project_extra_components)
|
|
endif()
|
|
endif()
|
|
|
|
foreach(path IN LISTS idf_components)
|
|
__init_component(DIRECTORY "${path}"
|
|
PREFIX "${prefix}"
|
|
SOURCE "idf_components")
|
|
endforeach()
|
|
|
|
foreach(path IN LISTS project_components)
|
|
__init_component(DIRECTORY "${path}"
|
|
PREFIX "${prefix}"
|
|
SOURCE "${project_components_source}")
|
|
endforeach()
|
|
|
|
foreach(path IN LISTS project_extra_components)
|
|
__init_component(DIRECTORY "${path}"
|
|
PREFIX "${prefix}"
|
|
SOURCE "project_extra_components")
|
|
endforeach()
|
|
endfunction()
|
|
|
|
#[[
|
|
__init_submodules()
|
|
|
|
Initialize submodules that are not yet initialized, and issue a warning for
|
|
submodules that do not match the recorded hash in the git tree.
|
|
#]]
|
|
function(__init_submodules)
|
|
idf_build_get_property(idf_path IDF_PATH)
|
|
idf_build_get_property(git GIT)
|
|
|
|
# For internal use: Skip the submodule check if running on GitLab CI
|
|
# and the job is configured to not clone submodules.
|
|
if("$ENV{IDF_SKIP_CHECK_SUBMODULES}" STREQUAL "1")
|
|
idf_msg("skip submodule check on internal CI")
|
|
return()
|
|
endif()
|
|
|
|
if(NOT git)
|
|
idf_warn("Git executable was not found. Git submodule checks will not be executed. "
|
|
"If you have any build issues at all, start by adding git executable to "
|
|
"the PATH and rerun cmake to not see this warning again.")
|
|
return()
|
|
endif()
|
|
|
|
execute_process(
|
|
COMMAND ${git} submodule status
|
|
WORKING_DIRECTORY ${idf_path}
|
|
OUTPUT_VARIABLE status
|
|
ERROR_VARIABLE stderr
|
|
RESULT_VARIABLE rv
|
|
)
|
|
|
|
if(rv)
|
|
idf_warn("Git submodule status command failed(${rv}): ${stderr}"
|
|
"Git submodule checks will not be performed. ")
|
|
return()
|
|
endif()
|
|
|
|
__split(STRING "${status}"
|
|
OUTPUT lines
|
|
REMOVE_EMPTY)
|
|
|
|
# The output of the git submodule status command is not guaranteed to be
|
|
# stable. It may be necessary to check the GIT_VERSION_STRING and make
|
|
# adjustments in the future.
|
|
foreach(line IN LISTS lines)
|
|
string(REGEX MATCH "(.)[0-9a-f]+ ([^\( ]+) ?" _ignored "${line}")
|
|
set(status "${CMAKE_MATCH_1}")
|
|
set(submodule_path "${CMAKE_MATCH_2}")
|
|
|
|
if("${status}" STREQUAL "-") # missing submodule
|
|
idf_msg("Initialising new submodule ${submodule_path}...")
|
|
execute_process(
|
|
COMMAND ${git} submodule update --init --recursive ${submodule_path}
|
|
WORKING_DIRECTORY ${idf_path}
|
|
ERROR_VARIABLE stderr
|
|
RESULT_VARIABLE rv
|
|
)
|
|
if(rv)
|
|
idf_die("Git submodule '${submodule_path}' init failed(${rv}): ${stderr}")
|
|
endif()
|
|
|
|
elseif(NOT "${status}" STREQUAL " ")
|
|
idf_warn("Git submodule ${submodule_path} is out of date. "
|
|
"Run the following command to fix: "
|
|
"git submodule update --init --recursive")
|
|
endif()
|
|
|
|
# Ensure CMake is rerun if the submodule's .git file is modified or
|
|
# altered, such as in the case of an accidental deinitialization.
|
|
get_filename_component(submodule_abs_path ${submodule_path} ABSOLUTE BASE_DIR ${idf_path})
|
|
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${submodule_abs_path}/.git)
|
|
# If the HEAD file in the submodule's directory changes (i.e., if there
|
|
# are commit changes), it will at least display the 'out of date'
|
|
# warning.
|
|
set(submodule_head "${idf_path}/.git/modules/${submodule_path}/HEAD")
|
|
if(EXISTS "${submodule_head}")
|
|
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${submodule_head})
|
|
endif()
|
|
|
|
endforeach()
|
|
endfunction()
|
|
|
|
#[[
|
|
__init_idf_target_arch()
|
|
|
|
Set the IDF_TARGET_ARCH value based on the sdkconfig. This means it must be
|
|
initialized after the sdkconfig is generated and its CMake version is
|
|
included.
|
|
#]]
|
|
function(__init_idf_target_arch)
|
|
if(CONFIG_IDF_TARGET_ARCH_XTENSA)
|
|
idf_build_set_property(IDF_TARGET_ARCH "xtensa")
|
|
elseif(CONFIG_IDF_TARGET_ARCH_RISCV)
|
|
idf_build_set_property(IDF_TARGET_ARCH "riscv")
|
|
else()
|
|
# Currently, no architecture is specified for Linux host builds.
|
|
idf_build_set_property(IDF_TARGET_ARCH "")
|
|
endif()
|
|
endfunction()
|
|
|
|
# The idf_build_properties interface target stores all global build
|
|
# properties. It is created very early so that the initialization functions
|
|
# can use it. Build properties are read and written with the
|
|
# idf_build_get_property and idf_build_set_property functions.
|
|
|
|
#[[api
|
|
.. cmakev2:build_property:: IDF_PATH
|
|
|
|
Absolute path to the ESP-IDF directory.
|
|
|
|
.. cmakev2:build_property:: IDF_TARGET
|
|
|
|
The target chip the project is built for, for example ``esp32``.
|
|
|
|
.. cmakev2:build_property:: IDF_TARGET_ARCH
|
|
|
|
The architecture of the target, ``xtensa`` or ``riscv`` (empty for the Linux host build).
|
|
|
|
.. cmakev2:build_property:: IDF_VER
|
|
|
|
The ESP-IDF version string.
|
|
|
|
.. cmakev2:build_property:: IDF_TOOLCHAIN
|
|
|
|
The selected toolchain, ``gcc`` or ``clang``.
|
|
|
|
.. cmakev2:build_property:: PROJECT_NAME
|
|
|
|
The project name. Defaults to the name passed to CMake's ``project()`` command.
|
|
|
|
.. cmakev2:build_property:: PROJECT_VER
|
|
|
|
The project version.
|
|
|
|
.. cmakev2:build_property:: PROJECT_DIR
|
|
|
|
Absolute path to the project directory.
|
|
|
|
.. cmakev2:build_property:: BUILD_DIR
|
|
|
|
Absolute path to the build directory.
|
|
|
|
.. cmakev2:build_property:: PYTHON
|
|
|
|
Path to the Python interpreter used by the build.
|
|
|
|
.. cmakev2:build_property:: COMPONENTS_DISCOVERED
|
|
|
|
List of the names of all discovered components.
|
|
|
|
.. cmakev2:build_property:: COMPONENT_INTERFACES
|
|
|
|
List of the interface targets of all discovered components.
|
|
|
|
.. cmakev2:build_property:: COMPONENTS_INCLUDED
|
|
|
|
List of the components that have been included (evaluated) in the build.
|
|
|
|
.. cmakev2:build_property:: SDKCONFIG
|
|
|
|
Path to the project ``sdkconfig`` file.
|
|
|
|
.. cmakev2:build_property:: SDKCONFIG_DEFAULTS
|
|
|
|
List of ``sdkconfig.defaults`` files applied to the configuration.
|
|
|
|
.. cmakev2:build_property:: SDKCONFIG_HEADER
|
|
|
|
Path to the generated ``sdkconfig.h`` with C and C++ preprocessor defines.
|
|
|
|
.. cmakev2:build_property:: SDKCONFIG_CMAKE
|
|
|
|
Path to the generated ``sdkconfig.cmake`` with the ``CONFIG_*`` CMake variables.
|
|
|
|
.. cmakev2:build_property:: SDKCONFIG_JSON
|
|
|
|
Path to the generated ``sdkconfig.json``.
|
|
|
|
.. cmakev2:build_property:: COMPILE_OPTIONS
|
|
|
|
Compile options applied to all components, for all languages.
|
|
|
|
.. cmakev2:build_property:: C_COMPILE_OPTIONS
|
|
|
|
Compile options applied to all components, for C only.
|
|
|
|
.. cmakev2:build_property:: CXX_COMPILE_OPTIONS
|
|
|
|
Compile options applied to all components, for C++ only.
|
|
|
|
.. cmakev2:build_property:: ASM_COMPILE_OPTIONS
|
|
|
|
Compile options applied to all components, for assembly only.
|
|
|
|
.. cmakev2:build_property:: COMPILE_DEFINITIONS
|
|
|
|
Preprocessor definitions applied to all components.
|
|
|
|
.. cmakev2:build_property:: LINK_OPTIONS
|
|
|
|
Link options applied when linking the application.
|
|
|
|
.. cmakev2:build_property:: INCLUDE_DIRECTORIES
|
|
|
|
Include directories applied to all components.
|
|
|
|
.. cmakev2:build_property:: LINKER_TYPE
|
|
|
|
The linker family, ``GNU`` or ``Darwin``.
|
|
|
|
.. cmakev2:build_property:: IDF_COMPONENT_MANAGER
|
|
|
|
Whether the component manager is enabled (``1``) or disabled (``0``).
|
|
|
|
.. cmakev2:build_property:: IDF_COMPONENT_OPTIONAL_REQUIRES_MODE
|
|
|
|
How :cmakev2:ref:`idf_component_optional_requires` is resolved, ``IMMEDIATE`` or ``DEFERRED``.
|
|
#]]
|
|
|
|
add_library(idf_build_properties INTERFACE)
|
|
|
|
# The __idf_component_interface_cache target is used to maintain internal
|
|
# mappings between component identifiers, such as component name or alias, and
|
|
# the component interface target, which is the primary target for the
|
|
# component.
|
|
add_library(__idf_component_interface_cache INTERFACE)
|
|
|
|
# Set build system prefix for component targets.
|
|
idf_build_set_property(PREFIX "idf")
|
|
|
|
# Set project directory property.
|
|
idf_build_set_property(PROJECT_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
|
|
|
# Set build directory property.
|
|
idf_build_set_property(BUILD_DIR "${CMAKE_BINARY_DIR}")
|
|
|
|
# Enable the generation of compile_commands.json.
|
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
|
|
|
# Initialize build system version.
|
|
__init_build_version()
|
|
|
|
# Initialize IDF_PATH and set it as a global and environmental variable, as
|
|
# well as a build property.
|
|
__init_idf_path()
|
|
|
|
# Determine git executable and set GIT build property.
|
|
__init_git()
|
|
|
|
# Initialize git submodules.
|
|
__init_submodules()
|
|
|
|
# Initialize the IDF_VER build property.
|
|
__init_idf_version()
|
|
|
|
# Determine the Python interpreter and check package dependencies if necessary.
|
|
__init_python()
|
|
|
|
# Initialize Kconfig system infrastructure.
|
|
__init_kconfig()
|
|
|
|
# Initialize component manager build properties (IDF_COMPONENT_MANAGER, etc.).
|
|
__init_component_manager()
|
|
|
|
# Set IDF_TARGET.
|
|
__init_idf_target()
|
|
|
|
# Set IDF_TOOLCHAIN, IDF_TOOLCHAIN_FILE and CMAKE_TOOLCHAIN_FILE.
|
|
__init_toolchain()
|
|
|
|
# Enable ccache if requested.
|
|
__init_ccache()
|
|
|
|
#[[
|
|
|
|
At this point, the build system infrastructure is ready.
|
|
Project-specific operations (component discovery, Kconfig generation,
|
|
component manager, etc.) are handled in idf_project_init() after the
|
|
project() call.
|
|
|
|
#]]
|