mirror of
				https://github.com/espressif/esp-idf.git
				synced 2025-11-04 09:01:40 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			577 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			CMake
		
	
	
	
	
	
			
		
		
	
	
			577 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			CMake
		
	
	
	
	
	
# Designed to be included from an IDF app's CMakeLists.txt file
 | 
						|
cmake_minimum_required(VERSION 3.16)
 | 
						|
 | 
						|
include(${CMAKE_CURRENT_LIST_DIR}/targets.cmake)
 | 
						|
# Initialize build target for this build using the environment variable or
 | 
						|
# value passed externally.
 | 
						|
__target_init()
 | 
						|
 | 
						|
# The mere inclusion of this CMake file sets up some interal build properties.
 | 
						|
# These properties can be modified in between this inclusion the the idf_build_process
 | 
						|
# call.
 | 
						|
include(${CMAKE_CURRENT_LIST_DIR}/idf.cmake)
 | 
						|
 | 
						|
# setting PYTHON variable here for compatibility only, new code should use
 | 
						|
# idf_build_get_property(variable PYTHON)
 | 
						|
idf_build_get_property(PYTHON PYTHON)
 | 
						|
if(NOT PYTHON)
 | 
						|
    message(FATAL_ERROR "Internal error, PYTHON build property not set correctly.")
 | 
						|
endif()
 | 
						|
 | 
						|
# legacy variable for compatibility
 | 
						|
set(IDFTOOL ${PYTHON} "${IDF_PATH}/tools/idf.py")
 | 
						|
 | 
						|
# On processing, checking Python required modules can be turned off if it was
 | 
						|
# already checked externally.
 | 
						|
if(PYTHON_DEPS_CHECKED)
 | 
						|
    idf_build_set_property(__CHECK_PYTHON 0)
 | 
						|
endif()
 | 
						|
 | 
						|
# Store CMake arguments that need to be passed into all CMake sub-projects as well
 | 
						|
# (bootloader, ULP, etc)
 | 
						|
#
 | 
						|
# It's not possible to tell if CMake was called with --warn-uninitialized, so to also
 | 
						|
# have these warnings in sub-projects we set a cache variable as well and then check that.
 | 
						|
if(WARN_UNINITIALIZED)
 | 
						|
    idf_build_set_property(EXTRA_CMAKE_ARGS --warn-uninitialized)
 | 
						|
else()
 | 
						|
    idf_build_set_property(EXTRA_CMAKE_ARGS "")
 | 
						|
endif()
 | 
						|
 | 
						|
 | 
						|
# Enable the component manager for regular projects if not explicitly disabled.
 | 
						|
if(NOT "$ENV{IDF_COMPONENT_MANAGER}" EQUAL "0")
 | 
						|
    idf_build_set_property(IDF_COMPONENT_MANAGER 1)
 | 
						|
endif()
 | 
						|
# Set component manager interface version
 | 
						|
idf_build_set_property(__COMPONENT_MANAGER_INTERFACE_VERSION 1)
 | 
						|
 | 
						|
#
 | 
						|
# Get the project version from either a version file or the Git revision. This is passed
 | 
						|
# to the idf_build_process call. Dependencies are also set here for when the version file
 | 
						|
# changes (if it is used).
 | 
						|
#
 | 
						|
function(__project_get_revision var)
 | 
						|
    set(_project_path "${CMAKE_CURRENT_LIST_DIR}")
 | 
						|
    if(NOT DEFINED PROJECT_VER)
 | 
						|
        if(EXISTS "${_project_path}/version.txt")
 | 
						|
            file(STRINGS "${_project_path}/version.txt" PROJECT_VER)
 | 
						|
            set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${_project_path}/version.txt")
 | 
						|
        else()
 | 
						|
            git_describe(PROJECT_VER_GIT "${_project_path}")
 | 
						|
            if(PROJECT_VER_GIT)
 | 
						|
                set(PROJECT_VER ${PROJECT_VER_GIT})
 | 
						|
            else()
 | 
						|
                message(STATUS "Project is not inside a git repository, or git repository has no commits;"
 | 
						|
                        " will not use 'git describe' to determine PROJECT_VER.")
 | 
						|
                set(PROJECT_VER 1)
 | 
						|
            endif()
 | 
						|
        endif()
 | 
						|
    endif()
 | 
						|
    set(${var} "${PROJECT_VER}" PARENT_SCOPE)
 | 
						|
endfunction()
 | 
						|
 | 
						|
 | 
						|
# paths_with_spaces_to_list
 | 
						|
#
 | 
						|
# Replacement for spaces2list in cases where it was previously used on
 | 
						|
# directory lists.
 | 
						|
#
 | 
						|
# If the variable doesn't contain spaces, (e.g. is already a CMake list)
 | 
						|
# then the variable is unchanged. Otherwise an external Python script is called
 | 
						|
# to try to split the paths, and the variable is updated with the result.
 | 
						|
#
 | 
						|
# This feature is added only for compatibility. Please do not introduce new
 | 
						|
# space separated path lists.
 | 
						|
#
 | 
						|
function(paths_with_spaces_to_list variable_name)
 | 
						|
    if("${${variable_name}}" MATCHES "[ \t]")
 | 
						|
        idf_build_get_property(python PYTHON)
 | 
						|
        idf_build_get_property(idf_path IDF_PATH)
 | 
						|
        execute_process(
 | 
						|
            COMMAND ${python}
 | 
						|
                "${idf_path}/tools/split_paths_by_spaces.py"
 | 
						|
                "--var-name=${variable_name}"
 | 
						|
                "${${variable_name}}"
 | 
						|
            WORKING_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}"
 | 
						|
            OUTPUT_VARIABLE result
 | 
						|
            RESULT_VARIABLE ret)
 | 
						|
        if(NOT ret EQUAL 0)
 | 
						|
            message(FATAL_ERROR "Failed to parse ${variable_name}, see diagnostics above")
 | 
						|
        endif()
 | 
						|
        set("${variable_name}" "${result}" PARENT_SCOPE)
 | 
						|
    endif()
 | 
						|
endfunction()
 | 
						|
 | 
						|
#
 | 
						|
# Output the built components to the user. Generates files for invoking idf_monitor.py
 | 
						|
# that doubles as an overview of some of the more important build properties.
 | 
						|
#
 | 
						|
function(__project_info test_components)
 | 
						|
    idf_build_get_property(prefix __PREFIX)
 | 
						|
    idf_build_get_property(_build_components BUILD_COMPONENTS)
 | 
						|
    idf_build_get_property(build_dir BUILD_DIR)
 | 
						|
    idf_build_get_property(idf_path IDF_PATH)
 | 
						|
 | 
						|
    list(SORT _build_components)
 | 
						|
 | 
						|
    unset(build_components)
 | 
						|
    unset(build_component_paths)
 | 
						|
 | 
						|
    foreach(build_component ${_build_components})
 | 
						|
        __component_get_target(component_target "${build_component}")
 | 
						|
        __component_get_property(_name ${component_target} COMPONENT_NAME)
 | 
						|
        __component_get_property(_prefix ${component_target} __PREFIX)
 | 
						|
        __component_get_property(_alias ${component_target} COMPONENT_ALIAS)
 | 
						|
        __component_get_property(_dir ${component_target} COMPONENT_DIR)
 | 
						|
 | 
						|
        if(_alias IN_LIST test_components)
 | 
						|
            list(APPEND test_component_paths ${_dir})
 | 
						|
        else()
 | 
						|
            if(_prefix STREQUAL prefix)
 | 
						|
                set(component ${_name})
 | 
						|
            else()
 | 
						|
                set(component ${_alias})
 | 
						|
            endif()
 | 
						|
            list(APPEND build_components ${component})
 | 
						|
            list(APPEND build_component_paths ${_dir})
 | 
						|
        endif()
 | 
						|
    endforeach()
 | 
						|
 | 
						|
    set(PROJECT_NAME ${CMAKE_PROJECT_NAME})
 | 
						|
    idf_build_get_property(PROJECT_PATH PROJECT_DIR)
 | 
						|
    idf_build_get_property(BUILD_DIR BUILD_DIR)
 | 
						|
    idf_build_get_property(SDKCONFIG SDKCONFIG)
 | 
						|
    idf_build_get_property(SDKCONFIG_DEFAULTS SDKCONFIG_DEFAULTS)
 | 
						|
    idf_build_get_property(PROJECT_EXECUTABLE EXECUTABLE)
 | 
						|
    set(PROJECT_BIN ${CMAKE_PROJECT_NAME}.bin)
 | 
						|
    idf_build_get_property(IDF_VER IDF_VER)
 | 
						|
 | 
						|
    idf_build_get_property(sdkconfig_cmake SDKCONFIG_CMAKE)
 | 
						|
    include(${sdkconfig_cmake})
 | 
						|
    idf_build_get_property(COMPONENT_KCONFIGS KCONFIGS)
 | 
						|
    idf_build_get_property(COMPONENT_KCONFIGS_PROJBUILD KCONFIG_PROJBUILDS)
 | 
						|
    idf_build_get_property(debug_prefix_map_gdbinit DEBUG_PREFIX_MAP_GDBINIT)
 | 
						|
 | 
						|
    # Write project description JSON file
 | 
						|
    idf_build_get_property(build_dir BUILD_DIR)
 | 
						|
    make_json_list("${build_components};${test_components}" build_components_json)
 | 
						|
    make_json_list("${build_component_paths};${test_component_paths}" build_component_paths_json)
 | 
						|
    configure_file("${idf_path}/tools/cmake/project_description.json.in"
 | 
						|
        "${build_dir}/project_description.json")
 | 
						|
 | 
						|
    # Generate component dependency graph
 | 
						|
    depgraph_generate("${build_dir}/component_deps.dot")
 | 
						|
 | 
						|
    # We now have the following component-related variables:
 | 
						|
    #
 | 
						|
    # build_components is the list of components to include in the build.
 | 
						|
    # build_component_paths is the paths to all of these components, obtained from the component dependencies file.
 | 
						|
    #
 | 
						|
    # Print the list of found components and test components
 | 
						|
    string(REPLACE ";" " " build_components "${build_components}")
 | 
						|
    string(REPLACE ";" " " build_component_paths "${build_component_paths}")
 | 
						|
    message(STATUS "Components: ${build_components}")
 | 
						|
    message(STATUS "Component paths: ${build_component_paths}")
 | 
						|
 | 
						|
    if(test_components)
 | 
						|
        string(REPLACE ";" " " test_components "${test_components}")
 | 
						|
        string(REPLACE ";" " " test_component_paths "${test_component_paths}")
 | 
						|
        message(STATUS "Test components: ${test_components}")
 | 
						|
        message(STATUS "Test component paths: ${test_component_paths}")
 | 
						|
    endif()
 | 
						|
endfunction()
 | 
						|
 | 
						|
function(__project_init components_var test_components_var)
 | 
						|
    # Use EXTRA_CFLAGS, EXTRA_CXXFLAGS and EXTRA_CPPFLAGS to add more priority options to the compiler
 | 
						|
    # EXTRA_CPPFLAGS is used for both C and C++
 | 
						|
    # Unlike environments' CFLAGS/CXXFLAGS/CPPFLAGS which work for both host and target build,
 | 
						|
    # these works only for target build
 | 
						|
    set(extra_cflags "$ENV{EXTRA_CFLAGS}")
 | 
						|
    set(extra_cxxflags "$ENV{EXTRA_CXXFLAGS}")
 | 
						|
    set(extra_cppflags "$ENV{EXTRA_CPPFLAGS}")
 | 
						|
 | 
						|
    spaces2list(extra_cflags)
 | 
						|
    spaces2list(extra_cxxflags)
 | 
						|
    spaces2list(extra_cppflags)
 | 
						|
 | 
						|
    idf_build_set_property(C_COMPILE_OPTIONS "${extra_cflags}" APPEND)
 | 
						|
    idf_build_set_property(CXX_COMPILE_OPTIONS "${extra_cxxflags}" APPEND)
 | 
						|
    idf_build_set_property(COMPILE_OPTIONS "${extra_cppflags}" APPEND)
 | 
						|
 | 
						|
    function(__project_component_dir component_dir)
 | 
						|
        get_filename_component(component_dir "${component_dir}" ABSOLUTE)
 | 
						|
        # The directory itself is a valid idf component
 | 
						|
        if(EXISTS ${component_dir}/CMakeLists.txt)
 | 
						|
            idf_build_component(${component_dir})
 | 
						|
        else()
 | 
						|
            # otherwise, check whether the subfolders are potential idf components
 | 
						|
            file(GLOB component_dirs ${component_dir}/*)
 | 
						|
            foreach(component_dir ${component_dirs})
 | 
						|
                if(IS_DIRECTORY ${component_dir})
 | 
						|
                    __component_dir_quick_check(is_component ${component_dir})
 | 
						|
                    if(is_component)
 | 
						|
                        idf_build_component(${component_dir})
 | 
						|
                    endif()
 | 
						|
                endif()
 | 
						|
            endforeach()
 | 
						|
        endif()
 | 
						|
    endfunction()
 | 
						|
 | 
						|
    # Add component directories to the build, given the component filters, exclusions
 | 
						|
    # extra directories, etc. passed from the root CMakeLists.txt.
 | 
						|
    if(COMPONENT_DIRS)
 | 
						|
        # User wants to fully override where components are pulled from.
 | 
						|
        paths_with_spaces_to_list(COMPONENT_DIRS)
 | 
						|
        idf_build_set_property(__COMPONENT_TARGETS "")
 | 
						|
        foreach(component_dir ${COMPONENT_DIRS})
 | 
						|
            get_filename_component(component_abs_path ${component_dir} ABSOLUTE)
 | 
						|
            if(NOT EXISTS ${component_abs_path})
 | 
						|
                message(FATAL_ERROR "Directory specified in COMPONENT_DIRS doesn't exist: ${component_abs_path}")
 | 
						|
            endif()
 | 
						|
            __project_component_dir(${component_dir})
 | 
						|
        endforeach()
 | 
						|
    else()
 | 
						|
        if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/main")
 | 
						|
            __project_component_dir("${CMAKE_CURRENT_LIST_DIR}/main")
 | 
						|
        endif()
 | 
						|
 | 
						|
        paths_with_spaces_to_list(EXTRA_COMPONENT_DIRS)
 | 
						|
        foreach(component_dir ${EXTRA_COMPONENT_DIRS})
 | 
						|
            get_filename_component(component_abs_path ${component_dir} ABSOLUTE)
 | 
						|
            if(NOT EXISTS ${component_abs_path})
 | 
						|
                message(FATAL_ERROR "Directory specified in EXTRA_COMPONENT_DIRS doesn't exist: ${component_abs_path}")
 | 
						|
            endif()
 | 
						|
            __project_component_dir("${component_dir}")
 | 
						|
        endforeach()
 | 
						|
 | 
						|
        # Look for components in the usual places: CMAKE_CURRENT_LIST_DIR/main,
 | 
						|
        # extra component dirs, and CMAKE_CURRENT_LIST_DIR/components
 | 
						|
        __project_component_dir("${CMAKE_CURRENT_LIST_DIR}/components")
 | 
						|
    endif()
 | 
						|
 | 
						|
    # For bootloader components, we only need to set-up the Kconfig files.
 | 
						|
    # Indeed, bootloader is currently compiled as a subproject, thus,
 | 
						|
    # its components are not part of the main project.
 | 
						|
    # However, in order to be able to configure these bootloader components
 | 
						|
    # using menuconfig, we need to look for their Kconfig-related files now.
 | 
						|
    file(GLOB bootloader_component_dirs "${CMAKE_CURRENT_LIST_DIR}/bootloader_components/*")
 | 
						|
    list(SORT bootloader_component_dirs)
 | 
						|
    foreach(bootloader_component_dir ${bootloader_component_dirs})
 | 
						|
        if(IS_DIRECTORY ${bootloader_component_dir})
 | 
						|
            __component_dir_quick_check(is_component ${bootloader_component_dir})
 | 
						|
            if(is_component)
 | 
						|
                __kconfig_bootloader_component_add("${bootloader_component_dir}")
 | 
						|
            endif()
 | 
						|
        endif()
 | 
						|
    endforeach()
 | 
						|
 | 
						|
    spaces2list(COMPONENTS)
 | 
						|
    spaces2list(EXCLUDE_COMPONENTS)
 | 
						|
    idf_build_get_property(component_targets __COMPONENT_TARGETS)
 | 
						|
    foreach(component_target ${component_targets})
 | 
						|
        __component_get_property(component_name ${component_target} COMPONENT_NAME)
 | 
						|
        set(include 1)
 | 
						|
        if(COMPONENTS AND NOT component_name IN_LIST COMPONENTS)
 | 
						|
            set(include 0)
 | 
						|
        endif()
 | 
						|
        if(EXCLUDE_COMPONENTS AND component_name IN_LIST EXCLUDE_COMPONENTS)
 | 
						|
            set(include 0)
 | 
						|
        endif()
 | 
						|
        if(include)
 | 
						|
            list(APPEND components ${component_name})
 | 
						|
        endif()
 | 
						|
    endforeach()
 | 
						|
 | 
						|
    if(TESTS_ALL OR BUILD_TESTS OR TEST_COMPONENTS OR TEST_EXCLUDE_COMPONENTS)
 | 
						|
        spaces2list(TEST_COMPONENTS)
 | 
						|
        spaces2list(TEST_EXCLUDE_COMPONENTS)
 | 
						|
        idf_build_get_property(component_targets __COMPONENT_TARGETS)
 | 
						|
        foreach(component_target ${component_targets})
 | 
						|
            __component_get_property(component_dir ${component_target} COMPONENT_DIR)
 | 
						|
            __component_get_property(component_name ${component_target} COMPONENT_NAME)
 | 
						|
            if(component_name IN_LIST components)
 | 
						|
                set(include 1)
 | 
						|
                if(TEST_COMPONENTS AND NOT component_name IN_LIST TEST_COMPONENTS)
 | 
						|
                    set(include 0)
 | 
						|
                endif()
 | 
						|
                if(TEST_EXCLUDE_COMPONENTS AND component_name IN_LIST TEST_EXCLUDE_COMPONENTS)
 | 
						|
                    set(include 0)
 | 
						|
                endif()
 | 
						|
                if(include AND EXISTS ${component_dir}/test)
 | 
						|
                    __component_add(${component_dir}/test ${component_name})
 | 
						|
                    list(APPEND test_components ${component_name}::test)
 | 
						|
                endif()
 | 
						|
            endif()
 | 
						|
        endforeach()
 | 
						|
    endif()
 | 
						|
 | 
						|
    set(${components_var} "${components}" PARENT_SCOPE)
 | 
						|
    set(${test_components_var} "${test_components}" PARENT_SCOPE)
 | 
						|
endfunction()
 | 
						|
 | 
						|
# Trick to temporarily redefine project(). When functions are overriden in CMake, the originals can still be accessed
 | 
						|
# using an underscore prefixed function of the same name. The following lines make sure that __project  calls
 | 
						|
# the original project(). See https://cmake.org/pipermail/cmake/2015-October/061751.html.
 | 
						|
function(project)
 | 
						|
endfunction()
 | 
						|
 | 
						|
function(_project)
 | 
						|
endfunction()
 | 
						|
 | 
						|
macro(project project_name)
 | 
						|
    # Initialize project, preparing COMPONENTS argument for idf_build_process()
 | 
						|
    # call later using external COMPONENT_DIRS, COMPONENTS_DIRS, EXTRA_COMPONENTS_DIR,
 | 
						|
    # EXTRA_COMPONENTS_DIRS, COMPONENTS, EXLUDE_COMPONENTS, TEST_COMPONENTS,
 | 
						|
    # TEST_EXLUDE_COMPONENTS, TESTS_ALL, BUILD_TESTS
 | 
						|
    __project_init(components test_components)
 | 
						|
 | 
						|
    __target_set_toolchain()
 | 
						|
 | 
						|
    if(CCACHE_ENABLE)
 | 
						|
        find_program(CCACHE_FOUND ccache)
 | 
						|
        if(CCACHE_FOUND)
 | 
						|
            message(STATUS "ccache will be used for faster recompilation")
 | 
						|
            set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
 | 
						|
        else()
 | 
						|
            message(WARNING "enabled ccache in build but ccache program not found")
 | 
						|
        endif()
 | 
						|
    endif()
 | 
						|
 | 
						|
    # The actual call to project()
 | 
						|
    __project(${project_name} C CXX ASM)
 | 
						|
 | 
						|
    # Generate compile_commands.json (needs to come after project call).
 | 
						|
    set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
 | 
						|
 | 
						|
    # If CMAKE_COLOR_DIAGNOSTICS not set in project CMakeLists.txt or in the environment,
 | 
						|
    # enable it by default.
 | 
						|
    if(NOT DEFINED CMAKE_COLOR_DIAGNOSTICS AND NOT DEFINED ENV{CMAKE_COLOR_DIAGNOSTICS})
 | 
						|
        set(CMAKE_COLOR_DIAGNOSTICS ON)
 | 
						|
    endif()
 | 
						|
 | 
						|
    # Since components can import third-party libraries, the original definition of project() should be restored
 | 
						|
    # before the call to add components to the build.
 | 
						|
    function(project)
 | 
						|
        set(project_ARGV ARGV)
 | 
						|
        __project(${${project_ARGV}})
 | 
						|
 | 
						|
        # Set the variables that project() normally sets, documented in the
 | 
						|
        # command's docs.
 | 
						|
        #
 | 
						|
        # https://cmake.org/cmake/help/v3.16/command/project.html
 | 
						|
        #
 | 
						|
        # There is some nuance when it comes to setting version variables in terms of whether
 | 
						|
        # CMP0048 is set to OLD or NEW. However, the proper behavior should have bee already handled by the original
 | 
						|
        # project call, and we're just echoing the values those variables were set to.
 | 
						|
        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()
 | 
						|
 | 
						|
    # Prepare the following arguments for the idf_build_process() call using external
 | 
						|
    # user values:
 | 
						|
    #
 | 
						|
    # SDKCONFIG_DEFAULTS is from external SDKCONFIG_DEFAULTS
 | 
						|
    # SDKCONFIG is from external SDKCONFIG
 | 
						|
    # BUILD_DIR is set to project binary dir
 | 
						|
    #
 | 
						|
    # PROJECT_NAME is taken from the passed name from project() call
 | 
						|
    # PROJECT_DIR is set to the current directory
 | 
						|
    # PROJECT_VER is from the version text or git revision of the current repo
 | 
						|
 | 
						|
    # SDKCONFIG_DEFAULTS environment variable may specify a file name relative to the root of the project.
 | 
						|
    # When building the bootloader, ignore this variable, since:
 | 
						|
    # 1. The bootloader project uses an existing SDKCONFIG file from the top-level project
 | 
						|
    # 2. File specified by SDKCONFIG_DEFAULTS will not be found relative to the root of the bootloader project
 | 
						|
    if(NOT BOOTLOADER_BUILD)
 | 
						|
        set(_sdkconfig_defaults "$ENV{SDKCONFIG_DEFAULTS}")
 | 
						|
    endif()
 | 
						|
 | 
						|
    if(NOT _sdkconfig_defaults)
 | 
						|
        if(EXISTS "${CMAKE_SOURCE_DIR}/sdkconfig.defaults")
 | 
						|
            set(_sdkconfig_defaults "${CMAKE_SOURCE_DIR}/sdkconfig.defaults")
 | 
						|
        else()
 | 
						|
            set(_sdkconfig_defaults "")
 | 
						|
        endif()
 | 
						|
    endif()
 | 
						|
 | 
						|
    if(SDKCONFIG_DEFAULTS)
 | 
						|
        set(_sdkconfig_defaults "${SDKCONFIG_DEFAULTS}")
 | 
						|
    endif()
 | 
						|
 | 
						|
    foreach(sdkconfig_default ${_sdkconfig_defaults})
 | 
						|
        get_filename_component(sdkconfig_default "${sdkconfig_default}" ABSOLUTE)
 | 
						|
        if(NOT EXISTS "${sdkconfig_default}")
 | 
						|
            message(FATAL_ERROR "SDKCONFIG_DEFAULTS '${sdkconfig_default}' does not exist.")
 | 
						|
        endif()
 | 
						|
        list(APPEND sdkconfig_defaults ${sdkconfig_default})
 | 
						|
    endforeach()
 | 
						|
 | 
						|
    if(SDKCONFIG)
 | 
						|
        get_filename_component(sdkconfig "${SDKCONFIG}" ABSOLUTE)
 | 
						|
    else()
 | 
						|
        set(sdkconfig "${CMAKE_CURRENT_LIST_DIR}/sdkconfig")
 | 
						|
    endif()
 | 
						|
 | 
						|
    if(BUILD_DIR)
 | 
						|
        get_filename_component(build_dir "${BUILD_DIR}" ABSOLUTE)
 | 
						|
        if(NOT EXISTS "${build_dir}")
 | 
						|
            message(FATAL_ERROR "BUILD_DIR '${build_dir}' does not exist.")
 | 
						|
        endif()
 | 
						|
    else()
 | 
						|
        set(build_dir ${CMAKE_BINARY_DIR})
 | 
						|
    endif()
 | 
						|
 | 
						|
    __project_get_revision(project_ver)
 | 
						|
 | 
						|
    message(STATUS "Building ESP-IDF components for target ${IDF_TARGET}")
 | 
						|
 | 
						|
    idf_build_process(${IDF_TARGET}
 | 
						|
                    SDKCONFIG_DEFAULTS "${sdkconfig_defaults}"
 | 
						|
                    SDKCONFIG ${sdkconfig}
 | 
						|
                    BUILD_DIR ${build_dir}
 | 
						|
                    PROJECT_NAME ${CMAKE_PROJECT_NAME}
 | 
						|
                    PROJECT_DIR ${CMAKE_CURRENT_LIST_DIR}
 | 
						|
                    PROJECT_VER "${project_ver}"
 | 
						|
                    COMPONENTS "${components};${test_components}")
 | 
						|
 | 
						|
    # Special treatment for 'main' component for standard projects (not part of core build system).
 | 
						|
    # Have it depend on every other component in the build. This is
 | 
						|
    # a convenience behavior for the standard project; thus is done outside of the core build system
 | 
						|
    # so that it treats components equally.
 | 
						|
    #
 | 
						|
    # This behavior should only be when user did not set REQUIRES/PRIV_REQUIRES manually.
 | 
						|
    idf_build_get_property(build_components BUILD_COMPONENT_ALIASES)
 | 
						|
    if(idf::main IN_LIST build_components)
 | 
						|
        __component_get_target(main_target idf::main)
 | 
						|
        __component_get_property(reqs ${main_target} REQUIRES)
 | 
						|
        __component_get_property(priv_reqs ${main_target} PRIV_REQUIRES)
 | 
						|
        __component_get_property(managed_reqs ${main_target} MANAGED_REQUIRES)
 | 
						|
        __component_get_property(managed_priv_reqs ${main_target} MANAGED_PRIV_REQUIRES)
 | 
						|
        #if user has not set any requirements, except ones added with the component manager
 | 
						|
        if((NOT reqs OR reqs STREQUAL managed_reqs) AND (NOT priv_reqs OR priv_reqs STREQUAL managed_priv_reqs))
 | 
						|
            if(test_components)
 | 
						|
                list(REMOVE_ITEM build_components ${test_components})
 | 
						|
            endif()
 | 
						|
            list(REMOVE_ITEM build_components idf::main)
 | 
						|
            __component_get_property(lib ${main_target} COMPONENT_LIB)
 | 
						|
            set_property(TARGET ${lib} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "${build_components}")
 | 
						|
            get_property(type TARGET ${lib} PROPERTY TYPE)
 | 
						|
            if(type STREQUAL STATIC_LIBRARY)
 | 
						|
                set_property(TARGET ${lib} APPEND PROPERTY LINK_LIBRARIES "${build_components}")
 | 
						|
            endif()
 | 
						|
        endif()
 | 
						|
    endif()
 | 
						|
 | 
						|
    set(project_elf ${CMAKE_PROJECT_NAME}.elf)
 | 
						|
 | 
						|
    # Create a dummy file to work around CMake requirement of having a source file while adding an
 | 
						|
    # executable. This is also used by idf_size.py to detect the target
 | 
						|
    set(project_elf_src ${CMAKE_BINARY_DIR}/project_elf_src_${IDF_TARGET}.c)
 | 
						|
    add_custom_command(OUTPUT ${project_elf_src}
 | 
						|
        COMMAND ${CMAKE_COMMAND} -E touch ${project_elf_src}
 | 
						|
        VERBATIM)
 | 
						|
    add_custom_target(_project_elf_src DEPENDS "${project_elf_src}")
 | 
						|
    add_executable(${project_elf} "${project_elf_src}")
 | 
						|
    add_dependencies(${project_elf} _project_elf_src)
 | 
						|
 | 
						|
    if(__PROJECT_GROUP_LINK_COMPONENTS)
 | 
						|
        target_link_libraries(${project_elf} PRIVATE "-Wl,--start-group")
 | 
						|
    endif()
 | 
						|
 | 
						|
    if(test_components)
 | 
						|
        target_link_libraries(${project_elf} PRIVATE "-Wl,--whole-archive")
 | 
						|
        foreach(test_component ${test_components})
 | 
						|
            if(TARGET ${test_component})
 | 
						|
                target_link_libraries(${project_elf} PRIVATE ${test_component})
 | 
						|
            endif()
 | 
						|
        endforeach()
 | 
						|
        target_link_libraries(${project_elf} PRIVATE "-Wl,--no-whole-archive")
 | 
						|
    endif()
 | 
						|
 | 
						|
    idf_build_get_property(build_components BUILD_COMPONENT_ALIASES)
 | 
						|
    if(test_components)
 | 
						|
        list(REMOVE_ITEM build_components ${test_components})
 | 
						|
    endif()
 | 
						|
 | 
						|
    foreach(build_component ${build_components})
 | 
						|
        __component_get_target(build_component_target ${build_component})
 | 
						|
        __component_get_property(whole_archive ${build_component_target} WHOLE_ARCHIVE)
 | 
						|
        if(whole_archive)
 | 
						|
            message(STATUS "Component ${build_component} will be linked with -Wl,--whole-archive")
 | 
						|
            target_link_libraries(${project_elf} PRIVATE
 | 
						|
                                  "-Wl,--whole-archive"
 | 
						|
                                   ${build_component}
 | 
						|
                                   "-Wl,--no-whole-archive")
 | 
						|
        else()
 | 
						|
            target_link_libraries(${project_elf} PRIVATE ${build_component})
 | 
						|
        endif()
 | 
						|
    endforeach()
 | 
						|
 | 
						|
 | 
						|
    if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
 | 
						|
        set(mapfile "${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}.map")
 | 
						|
        set(idf_target "${IDF_TARGET}")
 | 
						|
        string(TOUPPER ${idf_target} idf_target)
 | 
						|
        target_link_libraries(${project_elf} PRIVATE "-Wl,--cref" "-Wl,--defsym=IDF_TARGET_${idf_target}=0"
 | 
						|
        "-Wl,--Map=\"${mapfile}\"")
 | 
						|
        unset(idf_target)
 | 
						|
    endif()
 | 
						|
 | 
						|
    set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" APPEND PROPERTY
 | 
						|
        ADDITIONAL_MAKE_CLEAN_FILES
 | 
						|
        "${mapfile}" "${project_elf_src}")
 | 
						|
 | 
						|
    idf_build_get_property(idf_path IDF_PATH)
 | 
						|
    idf_build_get_property(python PYTHON)
 | 
						|
 | 
						|
    set(idf_size ${python} ${idf_path}/tools/idf_size.py)
 | 
						|
    if(DEFINED OUTPUT_JSON AND OUTPUT_JSON)
 | 
						|
        list(APPEND idf_size "--json")
 | 
						|
    endif()
 | 
						|
 | 
						|
    # Add size targets, depend on map file, run idf_size.py
 | 
						|
    add_custom_target(size
 | 
						|
        DEPENDS ${mapfile}
 | 
						|
        COMMAND ${idf_size} ${mapfile}
 | 
						|
        )
 | 
						|
    add_custom_target(size-files
 | 
						|
        DEPENDS ${mapfile}
 | 
						|
        COMMAND ${idf_size} --files ${mapfile}
 | 
						|
        )
 | 
						|
    add_custom_target(size-components
 | 
						|
        DEPENDS ${mapfile}
 | 
						|
        COMMAND ${idf_size} --archives ${mapfile}
 | 
						|
        )
 | 
						|
 | 
						|
    unset(idf_size)
 | 
						|
 | 
						|
    # Add DFU build and flash targets
 | 
						|
    __add_dfu_targets()
 | 
						|
 | 
						|
    # Add UF2 build targets
 | 
						|
    __add_uf2_targets()
 | 
						|
 | 
						|
    idf_build_executable(${project_elf})
 | 
						|
 | 
						|
    __project_info("${test_components}")
 | 
						|
endmacro()
 |