mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'bugfix/non_default_sdkconfig' into 'master'
tools: fix usage of sdkconfig with custom path or name Closes IDF-1369 See merge request espressif/esp-idf!22520
This commit is contained in:
commit
4bf12081e2
@ -383,9 +383,6 @@ macro(__build_process_project_includes)
|
||||
set(${build_property} "${val}")
|
||||
endforeach()
|
||||
|
||||
# Check that the CMake target value matches the Kconfig target value.
|
||||
__target_check()
|
||||
|
||||
idf_build_get_property(build_component_targets __BUILD_COMPONENT_TARGETS)
|
||||
|
||||
# Include each component's project_include.cmake
|
||||
|
@ -1,12 +1,29 @@
|
||||
# Designed to be included from an IDF app's CMakeLists.txt file
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
# Get the currently selected sdkconfig file early, so this doesn't
|
||||
# have to be done multiple times on different places.
|
||||
if(SDKCONFIG)
|
||||
get_filename_component(sdkconfig "${SDKCONFIG}" ABSOLUTE)
|
||||
else()
|
||||
set(sdkconfig "${CMAKE_SOURCE_DIR}/sdkconfig")
|
||||
endif()
|
||||
|
||||
# Check if the cmake was started as part of the set-target action.
|
||||
# If so, check for existing sdkconfig file and rename it.
|
||||
# This is done before __target_init, so the existing IDF_TARGET from sdkconfig
|
||||
# is not considered for consistence checking.
|
||||
if("$ENV{_IDF_PY_SET_TARGET_ACTION}" EQUAL "1" AND EXISTS "${sdkconfig}")
|
||||
file(RENAME "${sdkconfig}" "${sdkconfig}.old")
|
||||
message(STATUS "Existing sdkconfig '${sdkconfig}' renamed to '${sdkconfig}.old'.")
|
||||
endif()
|
||||
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/targets.cmake)
|
||||
# Initialize build target for this build using the environment variable or
|
||||
# value passed externally.
|
||||
__target_init()
|
||||
__target_init("${sdkconfig}")
|
||||
|
||||
# The mere inclusion of this CMake file sets up some interal build properties.
|
||||
# The mere inclusion of this CMake file sets up some internal build properties.
|
||||
# These properties can be modified in between this inclusion the the idf_build_process
|
||||
# call.
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/idf.cmake)
|
||||
@ -316,7 +333,7 @@ function(__project_init components_var test_components_var)
|
||||
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
|
||||
# Trick to temporarily redefine project(). When functions are overridden 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)
|
||||
@ -431,12 +448,6 @@ macro(project project_name)
|
||||
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}")
|
||||
|
@ -1,7 +1,76 @@
|
||||
#
|
||||
# Get target from single sdkconfig file
|
||||
#
|
||||
function(__target_from_config config target_out file_out)
|
||||
set(${target_out} NOTFOUND PARENT_SCOPE)
|
||||
set(${file_out} NOTFOUND PARENT_SCOPE)
|
||||
|
||||
if(NOT EXISTS "${config}")
|
||||
return()
|
||||
endif()
|
||||
|
||||
file(STRINGS "${config}" lines)
|
||||
foreach(line ${lines})
|
||||
if(NOT "${line}" MATCHES "^CONFIG_IDF_TARGET=\"[^\"]+\"$")
|
||||
continue()
|
||||
endif()
|
||||
|
||||
string(REGEX REPLACE "CONFIG_IDF_TARGET=\"([^\"]+)\"" "\\1" target "${line}")
|
||||
set(${target_out} ${target} PARENT_SCOPE)
|
||||
set(${file_out} ${config} PARENT_SCOPE)
|
||||
return()
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
#
|
||||
# Get target from list of sdkconfig files
|
||||
#
|
||||
function(__target_from_configs configs target_out file_out)
|
||||
set(target NOTFOUND)
|
||||
set(file NOTFOUND)
|
||||
|
||||
foreach(config ${configs})
|
||||
message(DEBUG "Searching for target in '${config}'")
|
||||
get_filename_component(config "${config}" ABSOLUTE)
|
||||
__target_from_config("${config}" target file)
|
||||
if(target)
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
set(${target_out} ${target} PARENT_SCOPE)
|
||||
set(${file_out} ${file} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
#
|
||||
# Search for target in config files in the following order.
|
||||
# SDKCONFIG cmake var, default sdkconfig, SDKCONFIG_DEFAULTS cmake var
|
||||
# if non-empty or SDKCONFIG_DEFAULTS env var if non-empty or
|
||||
# sdkconfig.defaults.
|
||||
#
|
||||
function(__target_guess target_out file_out)
|
||||
# Select sdkconfig_defaults to look for target
|
||||
if(SDKCONFIG_DEFAULTS)
|
||||
set(defaults "${SDKCONFIG_DEFAULTS}")
|
||||
elseif(DEFINED ENV{SDKCONFIG_DEFAULTS})
|
||||
set(defaults "$ENV{SDKCONFIG_DEFAULTS}")
|
||||
endif()
|
||||
|
||||
if(NOT defaults)
|
||||
set(defaults "${CMAKE_SOURCE_DIR}/sdkconfig.defaults")
|
||||
endif()
|
||||
|
||||
set(configs "${SDKCONFIG}" "${CMAKE_SOURCE_DIR}/sdkconfig" "${defaults}")
|
||||
message(DEBUG "Searching for target in '${configs}'")
|
||||
__target_from_configs("${configs}" target file)
|
||||
set(${target_out} ${target} PARENT_SCOPE)
|
||||
set(${file_out} ${file} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
#
|
||||
# Set the target used for the standard project build.
|
||||
#
|
||||
macro(__target_init)
|
||||
macro(__target_init config_file)
|
||||
# Input is IDF_TARGET environement variable
|
||||
set(env_idf_target $ENV{IDF_TARGET})
|
||||
|
||||
@ -9,39 +78,47 @@ macro(__target_init)
|
||||
# IDF_TARGET not set in environment, see if it is set in cache
|
||||
if(IDF_TARGET)
|
||||
set(env_idf_target ${IDF_TARGET})
|
||||
else()
|
||||
# Try to guess IDF_TARGET from sdkconfig files while honoring
|
||||
# SDKCONFIG and SDKCONFIG_DEFAULTS values
|
||||
__target_guess(env_idf_target where)
|
||||
if(env_idf_target)
|
||||
message(STATUS "IDF_TARGET is not set, guessed '${env_idf_target}' from sdkconfig '${where}'")
|
||||
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
|
||||
# Check if selected target is consistent with CMake cache
|
||||
if(DEFINED CACHE{IDF_TARGET})
|
||||
if(NOT $CACHE{IDF_TARGET} STREQUAL ${env_idf_target})
|
||||
message(FATAL_ERROR " IDF_TARGET '$CACHE{IDF_TARGET}' in CMake"
|
||||
" cache does not match currently selected IDF_TARGET '${env_idf_target}'."
|
||||
" To change the target, clear the build directory and sdkconfig file,"
|
||||
" and build the project again.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Check if selected target is consistent with sdkconfig
|
||||
__target_from_config("${config_file}" sdkconfig_target where)
|
||||
if(sdkconfig_target)
|
||||
if(NOT ${sdkconfig_target} STREQUAL ${env_idf_target})
|
||||
message(FATAL_ERROR " Target '${sdkconfig_target}' in sdkconfig '${where}'"
|
||||
" 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()
|
||||
|
||||
# IDF_TARGET will be used by component manager, 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")
|
||||
endmacro()
|
||||
|
||||
#
|
||||
# Check that the set build target and the config target matches.
|
||||
#
|
||||
function(__target_check)
|
||||
# Should be called after sdkconfig CMake file has been included.
|
||||
idf_build_get_property(idf_target IDF_TARGET)
|
||||
if(NOT ${idf_target} STREQUAL ${CONFIG_IDF_TARGET})
|
||||
message(FATAL_ERROR "CONFIG_IDF_TARGET in sdkconfig does not match "
|
||||
"IDF_TARGET environment variable. To change the target, delete "
|
||||
"sdkconfig file and build the project again.")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
#
|
||||
# Used by the project CMake file to set the toolchain before project() call.
|
||||
#
|
||||
@ -57,12 +134,12 @@ macro(__target_set_toolchain)
|
||||
else()
|
||||
set(env_idf_toolchain gcc)
|
||||
endif()
|
||||
else()
|
||||
elseif(DEFINED CACHE{IDF_TOOLCHAIN})
|
||||
# IDF_TOOLCHAIN set both in environment and in cache, must be the same
|
||||
if(NOT ${IDF_TOOLCHAIN} STREQUAL ${env_idf_toolchain})
|
||||
message(FATAL_ERROR "IDF_TOOLCHAIN in CMake cache does not match "
|
||||
"IDF_TOOLCHAIN environment variable. To change the toolchain, clear "
|
||||
"the build directory and sdkconfig file, and build the project again")
|
||||
if(NOT $CACHE{IDF_TOOLCHAIN} STREQUAL ${env_idf_toolchain})
|
||||
message(FATAL_ERROR " IDF_TOOLCHAIN '$CACHE{IDF_TOOLCHAIN}' in CMake cache does not match"
|
||||
" currently selected IDF_TOOLCHAIN '${env_idf_toolchain}'. To change the toolchain, clear"
|
||||
" the build directory and sdkconfig file, and build the project again.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@ -73,6 +150,18 @@ macro(__target_set_toolchain)
|
||||
set(toolchain_type "clang-")
|
||||
endif()
|
||||
|
||||
# Check if selected target is consistent with toolchain file in CMake cache
|
||||
if(DEFINED CMAKE_TOOLCHAIN_FILE)
|
||||
string(FIND "${CMAKE_TOOLCHAIN_FILE}" "-${toolchain_type}${IDF_TARGET}.cmake" found)
|
||||
if(${found} EQUAL -1)
|
||||
get_filename_component(toolchain "${CMAKE_TOOLCHAIN_FILE}" NAME_WE)
|
||||
message(FATAL_ERROR " CMAKE_TOOLCHAIN_FILE '${toolchain}'"
|
||||
" 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()
|
||||
|
||||
# First try to load the toolchain file from the tools/cmake/directory of IDF
|
||||
set(toolchain_file_global ${idf_path}/tools/cmake/toolchain-${toolchain_type}${IDF_TARGET}.cmake)
|
||||
if(EXISTS ${toolchain_file_global})
|
||||
|
@ -155,14 +155,9 @@ def action_extensions(base_actions: Dict, project_path: str) -> Any:
|
||||
"%s is still in preview. You have to append '--preview' option after idf.py to use any preview feature."
|
||||
% idf_target)
|
||||
args.define_cache_entry.append('IDF_TARGET=' + idf_target)
|
||||
sdkconfig_path = os.path.join(args.project_dir, 'sdkconfig')
|
||||
sdkconfig_old = sdkconfig_path + '.old'
|
||||
if os.path.exists(sdkconfig_old):
|
||||
os.remove(sdkconfig_old)
|
||||
if os.path.exists(sdkconfig_path):
|
||||
os.rename(sdkconfig_path, sdkconfig_old)
|
||||
print('Set Target to: %s, new sdkconfig created. Existing sdkconfig renamed to sdkconfig.old.' % idf_target)
|
||||
ensure_build_directory(args, ctx.info_name, True)
|
||||
print(f'Set Target to: {idf_target}, new sdkconfig will be created.')
|
||||
env = {'_IDF_PY_SET_TARGET_ACTION': '1'}
|
||||
ensure_build_directory(args, ctx.info_name, True, env)
|
||||
|
||||
def reconfigure(action: str, ctx: Context, args: PropertyDict) -> None:
|
||||
ensure_build_directory(args, ctx.info_name, True)
|
||||
|
@ -1,6 +1,7 @@
|
||||
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
import asyncio
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
@ -384,19 +385,27 @@ def _parse_cmakecache(path: str) -> Dict:
|
||||
return result
|
||||
|
||||
|
||||
def _new_cmakecache_entries(cache_path: str, new_cache_entries: List) -> bool:
|
||||
if not os.path.exists(cache_path):
|
||||
return True
|
||||
def _parse_cmdl_cmakecache(entries: List) -> Dict[str, str]:
|
||||
"""
|
||||
Parse list of CMake cache entries passed in via the -D option.
|
||||
|
||||
if new_cache_entries:
|
||||
current_cache = _parse_cmakecache(cache_path)
|
||||
|
||||
for entry in new_cache_entries:
|
||||
Returns a dict of name:value.
|
||||
"""
|
||||
result: Dict = {}
|
||||
for entry in entries:
|
||||
key, value = entry.split('=', 1)
|
||||
current_value = current_cache.get(key, None)
|
||||
if current_value is None or _strip_quotes(value) != current_value:
|
||||
return True
|
||||
value = _strip_quotes(value)
|
||||
result[key] = value
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def _new_cmakecache_entries(cache: Dict, cache_cmdl: Dict) -> bool:
|
||||
for entry in cache_cmdl:
|
||||
if entry not in cache:
|
||||
return True
|
||||
if cache_cmdl[entry] != cache[entry]:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
@ -410,7 +419,8 @@ def _detect_cmake_generator(prog_name: str) -> Any:
|
||||
raise FatalError("To use %s, either the 'ninja' or 'GNU make' build tool must be available in the PATH" % prog_name)
|
||||
|
||||
|
||||
def ensure_build_directory(args: 'PropertyDict', prog_name: str, always_run_cmake: bool=False) -> None:
|
||||
def ensure_build_directory(args: 'PropertyDict', prog_name: str, always_run_cmake: bool=False,
|
||||
env: Dict=None) -> None:
|
||||
"""Check the build directory exists and that cmake has been run there.
|
||||
|
||||
If this isn't the case, create the build directory (if necessary) and
|
||||
@ -444,12 +454,14 @@ def ensure_build_directory(args: 'PropertyDict', prog_name: str, always_run_cmak
|
||||
cache_path = os.path.join(build_dir, 'CMakeCache.txt')
|
||||
cache = _parse_cmakecache(cache_path) if os.path.exists(cache_path) else {}
|
||||
|
||||
# Validate or set IDF_TARGET
|
||||
_guess_or_check_idf_target(args, prog_name, cache)
|
||||
|
||||
args.define_cache_entry.append('CCACHE_ENABLE=%d' % args.ccache)
|
||||
|
||||
if always_run_cmake or _new_cmakecache_entries(cache_path, args.define_cache_entry):
|
||||
cache_cmdl = _parse_cmdl_cmakecache(args.define_cache_entry)
|
||||
|
||||
# Validate IDF_TARGET
|
||||
_check_idf_target(args, prog_name, cache, cache_cmdl)
|
||||
|
||||
if always_run_cmake or _new_cmakecache_entries(cache, cache_cmdl):
|
||||
if args.generator is None:
|
||||
args.generator = _detect_cmake_generator(prog_name)
|
||||
try:
|
||||
@ -469,7 +481,7 @@ def ensure_build_directory(args: 'PropertyDict', prog_name: str, always_run_cmak
|
||||
cmake_args += [project_dir]
|
||||
|
||||
hints = not args.no_hints
|
||||
RunTool('cmake', cmake_args, cwd=args.build_dir, hints=hints)()
|
||||
RunTool('cmake', cmake_args, cwd=args.build_dir, env=env, hints=hints)()
|
||||
except Exception:
|
||||
# don't allow partially valid CMakeCache.txt files,
|
||||
# to keep the "should I run cmake?" logic simple
|
||||
@ -522,6 +534,27 @@ def merge_action_lists(*action_lists: Dict) -> Dict:
|
||||
return merged_actions
|
||||
|
||||
|
||||
def get_sdkconfig_filename(args: 'PropertyDict', cache_cmdl: Dict=None) -> str:
|
||||
"""
|
||||
Get project's sdkconfig file name.
|
||||
"""
|
||||
if not cache_cmdl:
|
||||
cache_cmdl = _parse_cmdl_cmakecache(args.define_cache_entry)
|
||||
config = cache_cmdl.get('SDKCONFIG')
|
||||
if config:
|
||||
return os.path.abspath(config)
|
||||
|
||||
proj_desc_path = os.path.join(args.build_dir, 'project_description.json')
|
||||
try:
|
||||
with open(proj_desc_path, 'r') as f:
|
||||
proj_desc = json.load(f)
|
||||
return str(proj_desc['config_file'])
|
||||
except (OSError, KeyError):
|
||||
pass
|
||||
|
||||
return os.path.join(args.project_dir, 'sdkconfig')
|
||||
|
||||
|
||||
def get_sdkconfig_value(sdkconfig_file: str, key: str) -> Optional[str]:
|
||||
"""
|
||||
Return the value of given key from sdkconfig_file.
|
||||
@ -549,48 +582,48 @@ def is_target_supported(project_path: str, supported_targets: List) -> bool:
|
||||
return get_target(project_path) in supported_targets
|
||||
|
||||
|
||||
def _guess_or_check_idf_target(args: 'PropertyDict', prog_name: str, cache: Dict) -> None:
|
||||
def _check_idf_target(args: 'PropertyDict', prog_name: str, cache: Dict, cache_cmdl: Dict) -> None:
|
||||
"""
|
||||
If CMakeCache.txt doesn't exist, and IDF_TARGET is not set in the environment, guess the value from
|
||||
sdkconfig or sdkconfig.defaults, and pass it to CMake in IDF_TARGET variable.
|
||||
|
||||
Otherwise, cross-check the three settings (sdkconfig, CMakeCache, environment) and if there is
|
||||
Cross-check the three settings (sdkconfig, CMakeCache, environment) and if there is
|
||||
mismatch, fail with instructions on how to fix this.
|
||||
"""
|
||||
# Default locations of sdkconfig files.
|
||||
# FIXME: they may be overridden in the project or by a CMake variable (IDF-1369).
|
||||
# These are used to guess the target from sdkconfig, or set the default target by sdkconfig.defaults.
|
||||
idf_target_from_sdkconfig = get_target(args.project_dir)
|
||||
idf_target_from_sdkconfig_defaults = get_target(args.project_dir, 'sdkconfig.defaults')
|
||||
sdkconfig = get_sdkconfig_filename(args, cache_cmdl)
|
||||
idf_target_from_sdkconfig = get_sdkconfig_value(sdkconfig, 'CONFIG_IDF_TARGET')
|
||||
idf_target_from_env = os.environ.get('IDF_TARGET')
|
||||
idf_target_from_cache = cache.get('IDF_TARGET')
|
||||
idf_target_from_cache_cmdl = cache_cmdl.get('IDF_TARGET')
|
||||
|
||||
if not cache and not idf_target_from_env:
|
||||
# CMakeCache.txt does not exist yet, and IDF_TARGET is not set in the environment.
|
||||
guessed_target = idf_target_from_sdkconfig or idf_target_from_sdkconfig_defaults
|
||||
if guessed_target:
|
||||
if args.verbose:
|
||||
print("IDF_TARGET is not set, guessed '%s' from sdkconfig" % (guessed_target))
|
||||
args.define_cache_entry.append('IDF_TARGET=' + guessed_target)
|
||||
|
||||
elif idf_target_from_env:
|
||||
if idf_target_from_env:
|
||||
# Let's check that IDF_TARGET values are consistent
|
||||
if idf_target_from_sdkconfig and idf_target_from_sdkconfig != idf_target_from_env:
|
||||
raise FatalError("Project sdkconfig was generated for target '{t_conf}', but environment variable IDF_TARGET "
|
||||
raise FatalError("Project sdkconfig '{cfg}' was generated for target '{t_conf}', but environment variable IDF_TARGET "
|
||||
"is set to '{t_env}'. Run '{prog} set-target {t_env}' to generate new sdkconfig file for target {t_env}."
|
||||
.format(t_conf=idf_target_from_sdkconfig, t_env=idf_target_from_env, prog=prog_name))
|
||||
.format(cfg=sdkconfig, t_conf=idf_target_from_sdkconfig, t_env=idf_target_from_env, prog=prog_name))
|
||||
|
||||
if idf_target_from_cache and idf_target_from_cache != idf_target_from_env:
|
||||
raise FatalError("Target settings are not consistent: '{t_env}' in the environment, '{t_cache}' in CMakeCache.txt. "
|
||||
"Run '{prog} fullclean' to start again."
|
||||
.format(t_env=idf_target_from_env, t_cache=idf_target_from_cache, prog=prog_name))
|
||||
|
||||
elif idf_target_from_cache and idf_target_from_sdkconfig and idf_target_from_cache != idf_target_from_sdkconfig:
|
||||
if idf_target_from_cache_cmdl and idf_target_from_cache_cmdl != idf_target_from_env:
|
||||
raise FatalError("Target '{t_cmdl}' specified on command line is not consistent with "
|
||||
"target '{t_env}' in the environment."
|
||||
.format(t_cmdl=idf_target_from_cache_cmdl, t_env=idf_target_from_env))
|
||||
elif idf_target_from_cache_cmdl:
|
||||
# Check if -DIDF_TARGET is consistent with target in CMakeCache.txt
|
||||
if idf_target_from_cache and idf_target_from_cache != idf_target_from_cache_cmdl:
|
||||
raise FatalError("Target '{t_cmdl}' specified on command line is not consistent with "
|
||||
"target '{t_cache}' in CMakeCache.txt. Run '{prog} set-target {t_cmdl}' to re-generate "
|
||||
'CMakeCache.txt.'
|
||||
.format(t_cache=idf_target_from_cache, t_cmdl=idf_target_from_cache_cmdl, prog=prog_name))
|
||||
|
||||
elif idf_target_from_cache:
|
||||
# This shouldn't happen, unless the user manually edits CMakeCache.txt or sdkconfig, but let's check anyway.
|
||||
raise FatalError("Project sdkconfig was generated for target '{t_conf}', but CMakeCache.txt contains '{t_cache}'. "
|
||||
if idf_target_from_sdkconfig and idf_target_from_cache != idf_target_from_sdkconfig:
|
||||
raise FatalError("Project sdkconfig '{cfg}' was generated for target '{t_conf}', but CMakeCache.txt contains '{t_cache}'. "
|
||||
"To keep the setting in sdkconfig ({t_conf}) and re-generate CMakeCache.txt, run '{prog} fullclean'. "
|
||||
"To re-generate sdkconfig for '{t_cache}' target, run '{prog} set-target {t_cache}'."
|
||||
.format(t_conf=idf_target_from_sdkconfig, t_cache=idf_target_from_cache, prog=prog_name))
|
||||
.format(cfg=sdkconfig, t_conf=idf_target_from_sdkconfig, t_cache=idf_target_from_cache, prog=prog_name))
|
||||
|
||||
|
||||
class TargetChoice(click.Choice):
|
||||
|
@ -94,7 +94,8 @@ def run_idf_py(*args: str,
|
||||
text=True, encoding='utf-8', errors='backslashreplace')
|
||||
|
||||
|
||||
def run_cmake(*cmake_args: str, env: typing.Optional[EnvDict] = None) -> None:
|
||||
def run_cmake(*cmake_args: str, env: typing.Optional[EnvDict] = None,
|
||||
check: bool = True) -> subprocess.CompletedProcess:
|
||||
"""
|
||||
Run cmake command with given arguments, raise an exception on failure
|
||||
:param cmake_args: arguments to pass cmake
|
||||
@ -108,9 +109,10 @@ def run_cmake(*cmake_args: str, env: typing.Optional[EnvDict] = None) -> None:
|
||||
cmd = ['cmake'] + list(cmake_args)
|
||||
|
||||
logging.debug('running {} in {}'.format(' '.join(cmd), workdir))
|
||||
subprocess.check_call(
|
||||
return subprocess.run(
|
||||
cmd, env=env, cwd=workdir,
|
||||
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
check=check, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
|
||||
text=True, encoding='utf-8', errors='backslashreplace')
|
||||
|
||||
|
||||
def check_file_contains(filename: Union[str, Path], what: Union[str, Pattern]) -> None:
|
||||
|
@ -4,10 +4,14 @@
|
||||
import logging
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
from typing import List, Optional
|
||||
|
||||
import pytest
|
||||
from test_build_system_helpers import EnvDict, IdfPyFunc, check_file_contains, run_cmake
|
||||
|
||||
ESP32C3_TARGET = 'esp32c3'
|
||||
ESP32C2_TARGET = 'esp32c2'
|
||||
ESP32S3_TARGET = 'esp32s3'
|
||||
ESP32S2_TARGET = 'esp32s2'
|
||||
ESP32_TARGET = 'esp32'
|
||||
|
||||
@ -28,17 +32,21 @@ def test_target_from_environment_cmake(default_idf_env: EnvDict) -> None:
|
||||
|
||||
|
||||
def test_target_from_environment_idf_py(idf_py: IdfPyFunc, default_idf_env: EnvDict, test_app_copy: Path) -> None:
|
||||
def reconfigure_and_check_return_values(errmsg: str) -> None:
|
||||
ret = idf_py('reconfigure', check=False)
|
||||
def reconfigure_and_check_return_values(errmsg: str, opts: Optional[List[str]] = None) -> None:
|
||||
opts = opts or []
|
||||
ret = idf_py(*opts, 'reconfigure', check=False)
|
||||
assert ret.returncode == 2
|
||||
assert errmsg in ret.stderr
|
||||
|
||||
idf_py('set-target', ESP32S2_TARGET)
|
||||
default_idf_env.update({'IDF_TARGET': ESP32_TARGET})
|
||||
|
||||
cfg_path = (test_app_copy / 'sdkconfig')
|
||||
|
||||
logging.info("idf.py fails if IDF_TARGET settings don't match the environment")
|
||||
reconfigure_and_check_return_values("Project sdkconfig was generated for target '{}', but environment "
|
||||
"variable IDF_TARGET is set to '{}'.".format(ESP32S2_TARGET, ESP32_TARGET))
|
||||
reconfigure_and_check_return_values("Project sdkconfig '{}' was generated for target '{}', but environment "
|
||||
"variable IDF_TARGET is set to '{}'.".format(cfg_path, ESP32S2_TARGET,
|
||||
ESP32_TARGET))
|
||||
|
||||
logging.info("idf.py fails if IDF_TARGET settings in CMakeCache.txt don't match the environment")
|
||||
(test_app_copy / 'sdkconfig').write_text('CONFIG_IDF_TARGET="{}"'.format(ESP32_TARGET))
|
||||
@ -47,8 +55,57 @@ def test_target_from_environment_idf_py(idf_py: IdfPyFunc, default_idf_env: EnvD
|
||||
|
||||
logging.info("idf.py fails if IDF_TARGET settings in CMakeCache.txt don't match the sdkconfig")
|
||||
default_idf_env.pop('IDF_TARGET')
|
||||
reconfigure_and_check_return_values("Project sdkconfig was generated for target '{}', but CMakeCache.txt "
|
||||
"contains '{}'.".format(ESP32_TARGET, ESP32S2_TARGET))
|
||||
reconfigure_and_check_return_values("Project sdkconfig '{}' was generated for target '{}', but CMakeCache.txt "
|
||||
"contains '{}'.".format(cfg_path, ESP32_TARGET, ESP32S2_TARGET))
|
||||
|
||||
logging.info('idf.py fails if IDF_TARGET is set differently in environment and with -D option')
|
||||
(test_app_copy / 'sdkconfig').write_text('CONFIG_IDF_TARGET="{}"'.format(ESP32S2_TARGET))
|
||||
default_idf_env.update({'IDF_TARGET': ESP32S2_TARGET})
|
||||
reconfigure_and_check_return_values("Target '{}' specified on command line is not consistent with target '{}' "
|
||||
'in the environment.'.format(ESP32_TARGET, ESP32S2_TARGET),
|
||||
['-D', 'IDF_TARGET={}'.format(ESP32_TARGET)])
|
||||
|
||||
logging.info('idf.py fails if IDF_TARGET is set differently in CMakeCache.txt and with -D option')
|
||||
default_idf_env.pop('IDF_TARGET')
|
||||
reconfigure_and_check_return_values("Target '{}' specified on command line is not consistent with "
|
||||
"target '{}' in CMakeCache.txt.".format(ESP32_TARGET, ESP32S2_TARGET),
|
||||
['-D', 'IDF_TARGET={}'.format(ESP32_TARGET)])
|
||||
|
||||
|
||||
def test_target_consistency_cmake(default_idf_env: EnvDict, test_app_copy: Path) -> None:
|
||||
def reconfigure_and_check_return_values(errmsg: str, opts: Optional[List[str]] = None) -> None:
|
||||
opts = opts or []
|
||||
ret = run_cmake(*opts, '-G', 'Ninja', '..', env=default_idf_env, check=False)
|
||||
assert ret.returncode == 1
|
||||
assert errmsg in ret.stderr
|
||||
|
||||
run_cmake('-G', 'Ninja', '..')
|
||||
|
||||
cfg_path = (test_app_copy / 'sdkconfig')
|
||||
|
||||
logging.info("cmake fails if IDF_TARGET settings don't match the environment")
|
||||
default_idf_env.update({'IDF_TARGET': ESP32S2_TARGET})
|
||||
reconfigure_and_check_return_values(f"IDF_TARGET '{ESP32_TARGET}' in CMake cache does not "
|
||||
f"match currently selected IDF_TARGET '{ESP32S2_TARGET}'")
|
||||
|
||||
logging.info("cmake fails if IDF_TARGET settings don't match the sdkconfig")
|
||||
default_idf_env.pop('IDF_TARGET')
|
||||
(test_app_copy / 'sdkconfig').write_text(f'CONFIG_IDF_TARGET="{ESP32S2_TARGET}"')
|
||||
reconfigure_and_check_return_values(f"Target '{ESP32S2_TARGET}' in sdkconfig '{cfg_path}' does not "
|
||||
f"match currently selected IDF_TARGET '{ESP32_TARGET}'.")
|
||||
|
||||
logging.info("cmake fails if IDF_TOOLCHAIN settings don't match the environment")
|
||||
(test_app_copy / 'sdkconfig').write_text(f'CONFIG_IDF_TARGET="{ESP32_TARGET}"')
|
||||
default_idf_env.update({'IDF_TOOLCHAIN': 'clang'})
|
||||
reconfigure_and_check_return_values("IDF_TOOLCHAIN 'gcc' in CMake cache does not match "
|
||||
"currently selected IDF_TOOLCHAIN 'clang'")
|
||||
|
||||
logging.info("cmake fails if IDF_TARGET settings don't match CMAKE_TOOLCHAIN_FILE")
|
||||
default_idf_env.pop('IDF_TOOLCHAIN')
|
||||
reconfigure_and_check_return_values("CMAKE_TOOLCHAIN_FILE 'toolchain-esp32' does not "
|
||||
f"match currently selected IDF_TARGET '{ESP32S2_TARGET}'",
|
||||
['-D', f'IDF_TARGET={ESP32S2_TARGET}',
|
||||
'-D', 'SDKCONFIG=custom_sdkconfig'])
|
||||
|
||||
|
||||
def test_target_precedence(idf_py: IdfPyFunc, default_idf_env: EnvDict, test_app_copy: Path) -> None:
|
||||
@ -102,3 +159,41 @@ def test_target_using_sdkconfig(idf_py: IdfPyFunc, test_app_copy: Path) -> None:
|
||||
idf_py('reconfigure')
|
||||
check_file_contains('sdkconfig', 'CONFIG_IDF_TARGET="{}"'.format(ESP32S2_TARGET))
|
||||
check_file_contains('sdkconfig', 'CONFIG_IDF_TARGET_{}=y'.format(ESP32S2_TARGET.upper()))
|
||||
|
||||
|
||||
def test_target_guessing(idf_py: IdfPyFunc, test_app_copy: Path, default_idf_env: EnvDict) -> None:
|
||||
"""
|
||||
Tests are performed from the lowest to the highest priority, while
|
||||
configs, except from the sdkconfig, and parameters of previous tests are
|
||||
preserved.
|
||||
"""
|
||||
|
||||
logging.info('Can guess target from sdkconfig.defaults')
|
||||
(test_app_copy / 'sdkconfig.defaults').write_text('CONFIG_IDF_TARGET="{}"'.format(ESP32_TARGET))
|
||||
idf_py('reconfigure')
|
||||
check_file_contains('sdkconfig', 'CONFIG_IDF_TARGET="{}"'.format(ESP32_TARGET))
|
||||
check_file_contains('build/CMakeCache.txt', 'IDF_TARGET:STRING={}'.format(ESP32_TARGET))
|
||||
|
||||
logging.info('Can guess target from SDKCONFIG_DEFAULTS environment variable')
|
||||
(test_app_copy / 'sdkconfig1').write_text('NOTHING HERE')
|
||||
(test_app_copy / 'sdkconfig2').write_text('CONFIG_IDF_TARGET="{}"'.format(ESP32S2_TARGET))
|
||||
clean_app(test_app_copy)
|
||||
default_idf_env.update({'SDKCONFIG_DEFAULTS': 'sdkconfig1;sdkconfig2'})
|
||||
idf_py('reconfigure')
|
||||
check_file_contains('sdkconfig', 'CONFIG_IDF_TARGET="{}"'.format(ESP32S2_TARGET))
|
||||
check_file_contains('build/CMakeCache.txt', 'IDF_TARGET:STRING={}'.format(ESP32S2_TARGET))
|
||||
|
||||
logging.info('Can guess target from SDKCONFIG_DEFAULTS using -D')
|
||||
(test_app_copy / 'sdkconfig3').write_text('CONFIG_IDF_TARGET="{}"'.format(ESP32S2_TARGET))
|
||||
(test_app_copy / 'sdkconfig4').write_text('CONFIG_IDF_TARGET="{}"'.format(ESP32S3_TARGET))
|
||||
clean_app(test_app_copy)
|
||||
idf_py('-D', 'SDKCONFIG_DEFAULTS=sdkconfig4;sdkconfig3', 'reconfigure')
|
||||
check_file_contains('sdkconfig', 'CONFIG_IDF_TARGET="{}"'.format(ESP32S3_TARGET))
|
||||
check_file_contains('build/CMakeCache.txt', 'IDF_TARGET:STRING={}'.format(ESP32S3_TARGET))
|
||||
|
||||
logging.info('Can guess target from custom sdkconfig')
|
||||
(test_app_copy / 'sdkconfig5').write_text('CONFIG_IDF_TARGET="{}"'.format(ESP32C3_TARGET))
|
||||
clean_app(test_app_copy)
|
||||
idf_py('-D', 'SDKCONFIG=sdkconfig5', '-D', 'SDKCONFIG_DEFAULTS=sdkconfig4;sdkconfig3', 'reconfigure')
|
||||
check_file_contains('sdkconfig5', 'CONFIG_IDF_TARGET="{}"'.format(ESP32C3_TARGET))
|
||||
check_file_contains('build/CMakeCache.txt', 'IDF_TARGET:STRING={}'.format(ESP32C3_TARGET))
|
||||
|
Loading…
Reference in New Issue
Block a user