build system: support for multiple targets

This commit is contained in:
Ivan Grokhotkov 2018-10-19 11:51:51 +08:00
parent e2ca285fae
commit ccfa134533
18 changed files with 281 additions and 97 deletions

16
Kconfig
View File

@ -8,6 +8,22 @@ config IDF_CMAKE
bool
option env="IDF_CMAKE"
# A proxy to get environment variable $IDF_TARGET
config IDF_TARGET_ENV
string
option env="IDF_TARGET"
# This option records the IDF target when sdkconfig is generated the first time.
# It is not updated if environment variable $IDF_TARGET changes later, and
# the build system is responsible for detecting the mismatch between
# CONFIG_IDF_TARGET and $IDF_TARGET.
config IDF_TARGET
string
default "IDF_TARGET_NOT_SET" if IDF_TARGET_ENV=""
default IDF_TARGET_ENV
menu "SDK tool configuration"
config TOOLPREFIX
string "Compiler toolchain path/prefix"

View File

@ -1,3 +1,5 @@
require_idf_targets(esp32)
if(BOOTLOADER_BUILD)
# For bootloader, all we need from esp32 is headers
set(COMPONENT_ADD_INCLUDEDIRS include)

View File

@ -1,5 +1,11 @@
menu "ESP32-specific"
# Hidden option to support checking for this specific target in C code and Kconfig files
config IDF_TARGET_ESP32
bool
default "y" if IDF_TARGET="esp32"
default "n"
choice ESP32_DEFAULT_CPU_FREQ_MHZ
prompt "CPU frequency"
default ESP32_DEFAULT_CPU_FREQ_160

View File

@ -1,12 +1,15 @@
set(SOC_NAME esp32)
set(SOC_NAME ${IDF_TARGET})
include(${IDF_PATH}/components/soc/${SOC_NAME}/sources.cmake)
if(EXISTS "${COMPONENT_PATH}/${SOC_NAME}")
include(${COMPONENT_PATH}/${SOC_NAME}/sources.cmake)
spaces2list(SOC_SRCS)
add_prefix(COMPONENT_SRCS "${SOC_NAME}/" ${SOC_SRCS})
list(APPEND COMPONENT_SRCS "src/memory_layout_utils.c")
set(COMPONENT_ADD_INCLUDEDIRS ${SOC_NAME}/include)
endif()
set(COMPONENT_ADD_INCLUDEDIRS ${SOC_NAME}/include include)
list(APPEND COMPONENT_ADD_INCLUDEDIRS include)
list(APPEND COMPONENT_SRCS "src/memory_layout_utils.c")
set(COMPONENT_REQUIRES)
register_component()

View File

@ -1,5 +1,4 @@
# currently the only SoC supported; to be moved into Kconfig
SOC_NAME := esp32
SOC_NAME := $(IDF_TARGET)
COMPONENT_SRCDIRS := $(SOC_NAME) src/

View File

@ -1,7 +1,9 @@
set(SOC_NAME esp32)
set(SOC_NAME ${IDF_TARGET})
if(EXISTS "../${SOC_NAME}/test")
set(COMPONENT_SRCDIRS "../${SOC_NAME}/test")
set(COMPONENT_ADD_INCLUDEDIRS "../${SOC_NAME}/test")
set(COMPONENT_REQUIRES unity)
register_component()
endif()

View File

@ -1,5 +1,4 @@
# currently the only SoC supported; to be moved into Kconfig
SOC_NAME := esp32
SOC_NAME := $(IDF_TARGET)
COMPONENT_SRCDIRS := ../$(SOC_NAME)/test

View File

@ -43,6 +43,8 @@ Concepts
- "components" are modular pieces of standalone code which are compiled into static libraries (.a files) and linked into an app. Some are provided by ESP-IDF itself, others may be sourced from other places.
- "Target" is the hardware for which an application is built. At the moment, ESP-IDF supports only one target, ``esp32``.
Some things are not part of the project:
- "ESP-IDF" is not part of the project. Instead it is standalone, and linked to the project via the ``IDF_PATH`` environment variable which holds the path of the ``esp-idf`` directory. This allows the IDF framework to be decoupled from your project.
@ -79,7 +81,6 @@ Type ``idf.py --help`` for a full list of commands. Here are a summary of the mo
Building is incremental so if no source files or configuration has changed since the last build, nothing will be done.
- ``idf.py clean`` will "clean" the project by deleting build output files from the build directory, forcing a "full rebuild" the next time the project is built. Cleaning doesn't delete CMake configuration output and some other files.
- ``idf.py fullclean`` will delete the entire "build" directory contents. This includes all CMake configuration output. The next time the project is built, CMake will configure it from scratch. Note that this option recursively deletes *all* files in the build directory, so use with care. Project configuration is not deleted.
- ``idf.py reconfigure`` re-runs CMake_ even if it doesn't seem to need re-running. This isn't necessary during normal usage, but can be useful after adding/removing files from the source tree.
- ``idf.py flash`` will automatically build the project if necessary, and then flash it to an ESP32. The ``-p`` and ``-b`` options can be used to set serial port name and flasher baud rate, respectively.
- ``idf.py monitor`` will display serial output from the ESP32. The ``-p`` option can be used to set the serial port name. Type ``Ctrl-]`` to exit the monitor. See :doc:`/get-started/idf-monitor` for more details about using the monitor.
@ -94,6 +95,7 @@ Advanced Commands
- There are matching commands ``idf.py app-flash``, etc. to flash only that single part of the project to the ESP32.
- ``idf.py -p PORT erase_flash`` will use esptool.py to erase the ESP32's entire flash chip.
- ``idf.py size`` prints some size information about the app. ``size-components`` and ``size-files`` are similar commands which print more detailed per-component or per-source-file information, respectively.
- ``idf.py reconfigure`` re-runs CMake_ even if it doesn't seem to need re-running. This isn't necessary during normal usage, but can be useful after adding/removing files from the source tree, or when modifying CMake cache variables. For example, ``idf.py -DNAME='VALUE' reconfigure`` can be used to set variable ``NAME`` in CMake cache to value ``VALUE``.
The order of multiple ``idf.py`` commands on the same invocation is not important, they will automatically be executed in the correct order for everything to take effect (ie building before flashing, erasing before flashing, etc.).
@ -319,6 +321,7 @@ The following variables are set at the project level, but available for use in c
- ``COMPONENTS``: Names of all components that are included in this build, formatted as a semicolon-delimited CMake list.
- ``CONFIG_*``: Each value in the project configuration has a corresponding variable available in make. All names begin with ``CONFIG_``. :doc:`More information here </api-reference/kconfig>`.
- ``IDF_VER``: Git version of ESP-IDF (produced by ``git describe``)
- ``IDF_TARGET``: Name of the target for which the project is being built.
If you modify any of these variables inside ``CMakeLists.txt`` then this will not prevent other components from building but it may make your component hard to build and/or debug.
@ -417,6 +420,8 @@ When writing a component
- The values of ``COMPONENT_REQUIRES`` and ``COMPONENT_PRIV_REQUIRES`` should not depend on any configuration choices (``CONFIG_xxx`` macros). This is because requirements are expanded before configuration is loaded. Other component variables (like include paths or source files) can depend on configuration choices.
- Not setting either or both ``REQUIRES`` variables is fine. If the component has no requirements except for the "common" components needed for RTOS, libc, etc (``COMPONENT_REQUIRES_COMMON``) then both variables can be empty or unset.
Components which support only some targets (values of ``IDF_TARGET``) may call ``require_idf_targets(NAMES...)`` CMake function to express these requirements. In this case the build system will generate an error if the component is included into the build, but does not support selected target.
When creating a project
-----------------------
@ -465,16 +470,17 @@ project function
The custom ``project()`` function performs the following steps:
- Determines the target (set by ``IDF_TARGET`` environment variable) and saves the target in CMake cache. If the target set in the environment does not match the one in cache, exits with an error.
- Evaluates component dependencies and builds the ``BUILD_COMPONENTS`` list of components to include in the build (see :ref:`above<component-requirements-implementation>`).
- Finds all components in the project (searching ``COMPONENT_DIRS`` and filtering by ``COMPONENTS`` if this is set).
- Loads the project configuration from the ``sdkconfig`` file and generates a ``sdkconfig.cmake`` file and a ``sdkconfig.h`` header. These define configuration values in CMake and C/C++, respectively. If the project configuration changes, cmake will automatically be re-run to re-generate these files and re-configure the project.
- Sets the `CMAKE_TOOLCHAIN_FILE`_ variable to the ESP-IDF toolchain file with the Xtensa ESP32 toolchain.
- Declare the actual cmake-level project by calling the `CMake project function <cmake project_>`_.
- Load the git version. This includes some magic which will automatically re-run CMake if a new revision is checked out in git. See `File Globbing & Incremental Builds`_.
- Include :ref:`project_include.cmake` files from any components which have them.
- Add each component to the build. Each component CMakeLists file calls ``register_component``, calls the CMake `add_library <cmake add_library_>`_ function to add a library and then adds source files, compile options, etc.
- Add the final app executable to the build.
- Go back and add inter-component dependencies between components (ie adding the public header directories of each component to each other component).
- Sets the `CMAKE_TOOLCHAIN_FILE`_ variable to the correct toolchain file, depending on the target.
- Declares the actual cmake-level project by calling the `CMake project function <cmake project_>`_.
- Loads the git version. This includes some magic which will automatically re-run CMake if a new revision is checked out in git. See `File Globbing & Incremental Builds`_.
- Includes :ref:`project_include.cmake` files from any components which have them.
- Adds each component to the build. Each component CMakeLists file calls ``register_component``, calls the CMake `add_library <cmake add_library_>`_ function to add a library and then adds source files, compile options, etc.
- Adds the final app executable to the build.
- Goes back and adds inter-component dependencies between components (ie adding the public header directories of each component to each other component).
Browse the :idf_file:`/tools/cmake/project.cmake` file and supporting functions in :idf_file:`/tools/cmake/idf_functions.cmake` for more details.
@ -604,6 +610,16 @@ This can also be used to select or stub out an implementation, as such:
endif()
Conditions which depend on the target
-------------------------------------
The current target is available to CMake files via ``IDF_TARGET`` variable.
In addition to that, if target ``xyz`` is used (``IDF_TARGET=xyz``), then Kconfig variable ``CONFIG_IDF_TARGET_XYZ`` will be set.
Note that component dependencies may depend on ``IDF_TARGET`` variable, but not on Kconfig variables. Also one can not use Kconfig variables in ``include`` statements in CMake files, but ``IDF_TARGET`` can be used in such context.
Source Code Generation
----------------------
@ -745,6 +761,13 @@ For example projects or other projects where you don't want to specify a full sd
To override the name of this file, set the ``SDKCONFIG_DEFAULTS`` environment variable.
Target-dependent sdkconfig defaults
-----------------------------------
In addition to ``sdkconfig.defaults`` file, build system will also load defaults from ``sdkconfig.defaults.TARGET_NAME`` file, where ``TARGET_NAME`` is the value of ``IDF_TARGET``. For example, for ``esp32`` target, default settings will be taken from ``sdkconfig.defaults`` first, and then from ``sdkconfig.defaults.esp32``.
If ``SDKCONFIG_DEFAULTS`` is used to override the name of defaults file, the name of target-specific defaults file will be derived from ``SDKCONFIG_DEFAULTS`` value.
Flash arguments
===============
@ -776,6 +799,15 @@ The bootloader is a special "subproject" inside :idf:`/components/bootloader/sub
The subproject is inserted as an external project from the top-level project, by the file :idf_file:`/components/bootloader/project_include.cmake`. The main build process runs CMake for the subproject, which includes discovering components (a subset of the main components) and generating a bootloader-specific config (derived from the main ``sdkconfig``).
Selecting the Target
====================
Currently ESP-IDF supports one target, ``esp32``. It is used by default by the build system. Developers working on adding multiple target support can change the target as follows::
rm sdkconfig
idf.py -DIDF_TARGET=new_target reconfigure
Writing Pure CMake Components
=============================

View File

@ -91,6 +91,15 @@ ifndef IDF_PATH
$(error IDF_PATH variable is not set to a valid directory.)
endif
ifdef IDF_TARGET
ifneq ($(IDF_TARGET),esp32)
$(error GNU Make based build system only supports esp32 target, but IDF_TARGET is set to $(IDF_TARGET))
endif
else
export IDF_TARGET := esp32
endif
ifneq ("$(IDF_PATH)","$(SANITISED_IDF_PATH)")
# implies IDF_PATH was overriden on make command line.
# Due to the way make manages variables, this is hard to account for

View File

@ -212,6 +212,41 @@ function run_tests()
mv CMakeLists.bak CMakeLists.txt
assert_built ${APP_BINS} ${BOOTLOADER_BINS} ${PARTITION_BIN}
# Next two tests will use this fake 'esp31b' target
export fake_target=esp31b
mkdir -p components/$fake_target
touch components/$fake_target/CMakeLists.txt
cp ${IDF_PATH}/tools/cmake/toolchain-esp32.cmake components/$fake_target/toolchain-$fake_target.cmake
sed -i.old '/cmake_minimum_required/ a\
set(COMPONENTS esptool_py)' CMakeLists.txt
print_status "Can override IDF_TARGET from environment"
clean_build_dir
rm sdkconfig
export IDF_TARGET=$fake_target
(cd build && cmake -G Ninja .. ) || failure "Failed to configure with IDF_TARGET set in environment"
grep "CONFIG_IDF_TARGET=\"${fake_target}\"" sdkconfig || failure "Project not configured for IDF_TARGET correctly"
grep "IDF_TARGET:STRING=${fake_target}" build/CMakeCache.txt || failure "IDF_TARGET not set in CMakeCache.txt"
unset IDF_TARGET
print_status "Can set target using idf.py -D"
clean_build_dir
rm sdkconfig
idf.py -DIDF_TARGET=$fake_target reconfigure || failure "Failed to set target via idf.py"
grep "CONFIG_IDF_TARGET=\"${fake_target}\"" sdkconfig || failure "Project not configured correctly using idf.py -D"
grep "IDF_TARGET:STRING=${fake_target}" build/CMakeCache.txt || failure "IDF_TARGET not set in CMakeCache.txt using idf.py -D"
# Clean up modifications for the fake target
mv CMakeLists.txt.old CMakeLists.txt
rm -rf components
print_status "Can find toolchain file in component directory"
clean_build_dir
mv ${IDF_PATH}/tools/cmake/toolchain-esp32.cmake ${IDF_PATH}/components/esp32/
idf.py build || failure "Failed to build with toolchain file in component directory"
mv ${IDF_PATH}/components/esp32/toolchain-esp32.cmake ${IDF_PATH}/tools/cmake/
assert_built ${APP_BINS} ${BOOTLOADER_BINS} ${PARTITION_BIN}
print_status "All tests completed"
if [ -n "${FAILURES}" ]; then
echo "Some failures were detected:"

View File

@ -0,0 +1,70 @@
# Given a component name (find_name) and a list of component paths (component_paths),
# return the path to the component in 'variable'
#
# Fatal error is printed if the component is not found.
function(find_component_path find_name components component_paths variable)
list(FIND components ${find_name} idx)
if(NOT idx EQUAL -1)
list(GET component_paths ${idx} path)
set("${variable}" "${path}" PARENT_SCOPE)
return()
else()
endif()
# TODO: find a way to print the dependency chain that lead to this not-found component
message(WARNING "Required component ${find_name} is not found in any of the provided COMPONENT_DIRS")
endfunction()
# components_find_all: Search 'component_dirs' for components and return them
# as a list of names in 'component_names' and a list of full paths in
# 'component_paths'
#
# component_paths contains only unique component names. Directories
# earlier in the component_dirs list take precedence.
function(components_find_all component_dirs component_paths component_names test_component_names)
# component_dirs entries can be files or lists of files
set(paths "")
set(names "")
set(test_names "")
# start by expanding the component_dirs list with all subdirectories
foreach(dir ${component_dirs})
# Iterate any subdirectories for values
file(GLOB subdirs LIST_DIRECTORIES true "${dir}/*")
foreach(subdir ${subdirs})
set(component_dirs "${component_dirs};${subdir}")
endforeach()
endforeach()
# Look for a component in each component_dirs entry
foreach(dir ${component_dirs})
debug("Looking for CMakeLists.txt in ${dir}")
file(GLOB component "${dir}/CMakeLists.txt")
if(component)
debug("CMakeLists.txt file ${component}")
get_filename_component(component "${component}" DIRECTORY)
get_filename_component(name "${component}" NAME)
if(NOT name IN_LIST names)
list(APPEND names "${name}")
list(APPEND paths "${component}")
# Look for test component directory
file(GLOB test "${component}/test/CMakeLists.txt")
if(test)
list(APPEND test_names "${name}")
endif()
endif()
else() # no CMakeLists.txt file
# test for legacy component.mk and warn
file(GLOB legacy_component "${dir}/component.mk")
if(legacy_component)
get_filename_component(legacy_component "${legacy_component}" DIRECTORY)
message(WARNING "Component ${legacy_component} contains old-style component.mk but no CMakeLists.txt. "
"Component will be skipped.")
endif()
endif()
endforeach()
set(${component_paths} ${paths} PARENT_SCOPE)
set(${component_names} ${names} PARENT_SCOPE)
set(${test_component_names} ${test_names} PARENT_SCOPE)
endfunction()

View File

@ -133,6 +133,12 @@ function(add_component_dependencies target dep dep_type)
endif()
endfunction()
function(require_idf_targets)
if(NOT ${IDF_TARGET} IN_LIST ARGN)
message(FATAL_ERROR "Component ${COMPONENT_NAME} only supports targets: ${ARGN}")
endif()
endfunction()
function(components_finish_registration)
# have the executable target depend on all components in the build

View File

@ -15,7 +15,7 @@ macro(idf_set_global_variables)
# Commmon components, required by every component in the build
#
set_default(COMPONENT_REQUIRES_COMMON "cxx esp32 newlib freertos heap log soc")
set_default(COMPONENT_REQUIRES_COMMON "cxx ${IDF_TARGET} newlib freertos heap log soc")
# PROJECT_PATH has the path to the IDF project (top-level cmake directory)
#
@ -76,7 +76,7 @@ function(idf_set_global_compiler_options)
endif()
# Default compiler configuration
add_compile_options(-ffunction-sections -fdata-sections -fstrict-volatile-bitfields -mlongcalls -nostdlib)
add_compile_options(-ffunction-sections -fdata-sections -fstrict-volatile-bitfields -nostdlib)
# Default warnings configuration
add_compile_options(

View File

@ -99,6 +99,10 @@ function(kconfig_process_config)
set(defaults_arg --defaults "${SDKCONFIG_DEFAULTS}")
endif()
if(EXISTS "${SDKCONFIG_DEFAULTS}.${IDF_TARGET}")
list(APPEND defaults_arg --defaults "${SDKCONFIG_DEFAULTS}.${IDF_TARGET}")
endif()
# Set these in the parent scope, so that they can be written to project_description.json
set(kconfigs "${kconfigs}")
set(COMPONENT_KCONFIGS "${kconfigs}" PARENT_SCOPE)

View File

@ -23,6 +23,7 @@ set(CMAKE_MODULE_PATH
include(GetGitRevisionDescription)
include(utilities)
include(components)
include(targets)
include(kconfig)
include(git_submodules)
include(idf_functions)
@ -53,6 +54,9 @@ endif()
# top-level "project" call but customize it to do what we want in the IDF build.
#
macro(project name)
# Determine the build target
idf_set_target()
# Set global variables used by rest of the build
idf_set_global_variables()
@ -71,6 +75,7 @@ macro(project name)
-D "COMPONENT_DIRS=${COMPONENT_DIRS}"
-D "BOOTLOADER_BUILD=${BOOTLOADER_BUILD}"
-D "IDF_PATH=${IDF_PATH}"
-D "IDF_TARGET=${IDF_TARGET}"
-D "DEBUG=${DEBUG}"
-P "${IDF_PATH}/tools/cmake/scripts/expand_requirements.cmake"
WORKING_DIRECTORY "${PROJECT_PATH}")
@ -102,10 +107,11 @@ macro(project name)
# Include sdkconfig.cmake so rest of the build knows the configuration
include(${SDKCONFIG_CMAKE})
# Check that the targets set in cache, sdkconfig, and in environment all match
idf_check_config_target()
# Now the configuration is loaded, set the toolchain appropriately
#
# TODO: support more toolchains than just ESP32
set(CMAKE_TOOLCHAIN_FILE $ENV{IDF_PATH}/tools/cmake/toolchain-esp32.cmake)
idf_set_toolchain()
# Declare the actual cmake-level project
_project(${name} ASM C CXX)

View File

@ -31,6 +31,7 @@
# TODO: Error out if a component requirement is missing
cmake_minimum_required(VERSION 3.5)
include("${IDF_PATH}/tools/cmake/utilities.cmake")
include("${IDF_PATH}/tools/cmake/component_utils.cmake")
if(NOT DEPENDENCIES_FILE)
message(FATAL_ERROR "DEPENDENCIES_FILE must be set.")
@ -78,75 +79,10 @@ macro(register_config_only_component)
register_component()
endmacro()
# Given a component name (find_name) and a list of component paths (component_paths),
# return the path to the component in 'variable'
#
# Fatal error is printed if the component is not found.
function(find_component_path find_name components component_paths variable)
list(FIND components ${find_name} idx)
if(NOT idx EQUAL -1)
list(GET component_paths ${idx} path)
set("${variable}" "${path}" PARENT_SCOPE)
return()
else()
function(require_idf_targets)
if(NOT ${IDF_TARGET} IN_LIST ARGN)
message(FATAL_ERROR "Component ${COMPONENT_NAME} only supports targets: ${ARGN}")
endif()
# TODO: find a way to print the dependency chain that lead to this not-found component
message(WARNING "Required component ${find_name} is not found in any of the provided COMPONENT_DIRS")
endfunction()
# components_find_all: Search 'component_dirs' for components and return them
# as a list of names in 'component_names' and a list of full paths in
# 'component_paths'
#
# component_paths contains only unique component names. Directories
# earlier in the component_dirs list take precedence.
function(components_find_all component_dirs component_paths component_names test_component_names)
# component_dirs entries can be files or lists of files
set(paths "")
set(names "")
set(test_names "")
# start by expanding the component_dirs list with all subdirectories
foreach(dir ${component_dirs})
# Iterate any subdirectories for values
file(GLOB subdirs LIST_DIRECTORIES true "${dir}/*")
foreach(subdir ${subdirs})
set(component_dirs "${component_dirs};${subdir}")
endforeach()
endforeach()
# Look for a component in each component_dirs entry
foreach(dir ${component_dirs})
debug("Looking for CMakeLists.txt in ${dir}")
file(GLOB component "${dir}/CMakeLists.txt")
if(component)
debug("CMakeLists.txt file ${component}")
get_filename_component(component "${component}" DIRECTORY)
get_filename_component(name "${component}" NAME)
if(NOT name IN_LIST names)
list(APPEND names "${name}")
list(APPEND paths "${component}")
# Look for test component directory
file(GLOB test "${component}/test/CMakeLists.txt")
if(test)
list(APPEND test_names "${name}")
endif()
endif()
else() # no CMakeLists.txt file
# test for legacy component.mk and warn
file(GLOB legacy_component "${dir}/component.mk")
if(legacy_component)
get_filename_component(legacy_component "${legacy_component}" DIRECTORY)
message(WARNING "Component ${legacy_component} contains old-style component.mk but no CMakeLists.txt. "
"Component will be skipped.")
endif()
endif()
endforeach()
set(${component_paths} ${paths} PARENT_SCOPE)
set(${component_names} ${names} PARENT_SCOPE)
set(${test_component_names} ${test_names} PARENT_SCOPE)
endfunction()

57
tools/cmake/targets.cmake Normal file
View File

@ -0,0 +1,57 @@
include(component_utils)
macro(idf_set_target)
# Input is IDF_TARGET environement variable
set(env_idf_target $ENV{IDF_TARGET})
if(NOT env_idf_target)
# IDF_TARGET not set in environment, see if it is set in cache
if(IDF_TARGET)
set(env_idf_target ${IDF_TARGET})
else()
set(env_idf_target esp32)
message(STATUS "IDF_TARGET not set, using default target: ${env_idf_target}")
endif()
else()
# IDF_TARGET set both in environment and in cache, must be the same
if(NOT ${IDF_TARGET} STREQUAL ${env_idf_target})
message(FATAL_ERROR "IDF_TARGET in CMake cache does not match "
"IDF_TARGET environment variable. To change the target, clear "
"the build directory and sdkconfig file, and build the project again")
endif()
endif()
# IDF_TARGET will be used by Kconfig, make sure it is set
set(ENV{IDF_TARGET} ${env_idf_target})
# Finally, set IDF_TARGET in cache
set(IDF_TARGET ${env_idf_target} CACHE STRING "IDF Build Target")
message(STATUS "Building for target ${IDF_TARGET}")
endmacro()
macro(idf_check_config_target)
if(NOT ${IDF_TARGET} STREQUAL ${CONFIG_IDF_TARGET})
message(FATAL_ERROR "CONFIG_IDF_TARGET in sdkconfig does not match "
"IDF_TARGET environement variable. To change the target, delete "
"sdkconfig file and build the project again.")
endif()
endmacro()
macro(idf_set_toolchain)
# First try to load the toolchain file from the tools/cmake/ directory of IDF
set(toolchain_file_global $ENV{IDF_PATH}/tools/cmake/toolchain-${IDF_TARGET}.cmake)
if(EXISTS ${toolchain_file_global})
set(CMAKE_TOOLCHAIN_FILE ${toolchain_file_global})
else()
# Try to load the toolchain file from the directory of ${IDF_TARGET} component
find_component_path(${IDF_TARGET} "${BUILD_COMPONENTS}" "${BUILD_COMPONENT_PATHS}" target_component_path)
set(toolchain_file_component ${target_component_path}/toolchain-${IDF_TARGET}.cmake)
if(EXISTS ${toolchain_file_component})
set(CMAKE_TOOLCHAIN_FILE ${toolchain_file_component})
else()
message(FATAL_ERROR "Toolchain file toolchain-${IDF_TARGET}.cmake not found,"
"checked ${toolchain_file_global} and ${toolchain_file_component}")
endif()
endif()
endmacro()

View File

@ -5,3 +5,5 @@ set(CMAKE_CXX_COMPILER xtensa-esp32-elf-g++)
set(CMAKE_ASM_COMPILER xtensa-esp32-elf-gcc)
set(CMAKE_EXE_LINKER_FLAGS "-nostdlib" CACHE STRING "Linker Base Flags")
set(CMAKE_C_FLAGS "-mlongcalls" CACHE STRING "C Compiler Base Flags")
set(CMAKE_CXX_FLAGS "-mlongcalls" CACHE STRING "C++ Compiler Base Flags")