Rename deprecated Kconfig options in a backward compatible way

This commit is contained in:
Roland Dobai 2019-03-14 09:54:04 +01:00
parent cf9f2aa466
commit 23ee93ea76
14 changed files with 314 additions and 48 deletions

View file

@ -25,14 +25,14 @@ mainmenu "Espressif IoT Development Framework Configuration"
menu "SDK tool configuration" menu "SDK tool configuration"
config TOOLPREFIX config SDK_TOOLPREFIX
string "Compiler toolchain path/prefix" string "Compiler toolchain path/prefix"
default "xtensa-esp32-elf-" default "xtensa-esp32-elf-"
help help
The prefix/path that is used to call the toolchain. The default setting assumes The prefix/path that is used to call the toolchain. The default setting assumes
a crosstool-ng gcc setup that is in your PATH. a crosstool-ng gcc setup that is in your PATH.
config PYTHON config SDK_PYTHON
string "Python 2 interpreter" string "Python 2 interpreter"
depends on !IDF_CMAKE depends on !IDF_CMAKE
default "python" default "python"
@ -43,7 +43,7 @@ mainmenu "Espressif IoT Development Framework Configuration"
(Note: This option is used with the GNU Make build system only, not idf.py (Note: This option is used with the GNU Make build system only, not idf.py
or CMake-based builds.) or CMake-based builds.)
config MAKE_WARN_UNDEFINED_VARIABLES config SDK_MAKE_WARN_UNDEFINED_VARIABLES
bool "'make' warns on undefined variables" bool "'make' warns on undefined variables"
default "y" default "y"
help help

View file

@ -8,7 +8,7 @@ ESPFLASHSIZE ?= $(CONFIG_ESPTOOLPY_FLASHSIZE)
CONFIG_ESPTOOLPY_COMPRESSED ?= CONFIG_ESPTOOLPY_COMPRESSED ?=
PYTHON ?= $(call dequote,$(CONFIG_PYTHON)) PYTHON ?= $(call dequote,$(CONFIG_SDK_PYTHON))
# two commands that can be used from other components # two commands that can be used from other components
# to invoke esptool.py (with or without serial port args) # to invoke esptool.py (with or without serial port args)
@ -99,7 +99,7 @@ simple_monitor: $(call prereq_if_explicit,%flash) | check_python_dependencies
PRINT_FILTER ?= PRINT_FILTER ?=
MONITOR_OPTS := --baud $(MONITORBAUD) --port $(ESPPORT) --toolchain-prefix $(CONFIG_TOOLPREFIX) --make "$(MAKE)" --print_filter "$(PRINT_FILTER)" MONITOR_OPTS := --baud $(MONITORBAUD) --port $(ESPPORT) --toolchain-prefix $(CONFIG_SDK_TOOLPREFIX) --make "$(MAKE)" --print_filter "$(PRINT_FILTER)"
monitor: $(call prereq_if_explicit,%flash) | check_python_dependencies monitor: $(call prereq_if_explicit,%flash) | check_python_dependencies
$(summary) MONITOR $(summary) MONITOR

View file

@ -7,7 +7,7 @@ PROJECT_NAME := gcov_example
include $(IDF_PATH)/make/project.mk include $(IDF_PATH)/make/project.mk
GCOV := $(call dequote,$(CONFIG_TOOLPREFIX))gcov GCOV := $(call dequote,$(CONFIG_SDK_TOOLPREFIX))gcov
REPORT_DIR := $(BUILD_DIR_BASE)/coverage_report REPORT_DIR := $(BUILD_DIR_BASE)/coverage_report
lcov-report: lcov-report:

View file

@ -109,7 +109,7 @@ There are several ways to process collected data. Two of the most common are:
Add the following lines to you project's `Makefile` after the line including `project.mk`: Add the following lines to you project's `Makefile` after the line including `project.mk`:
``` ```
GCOV := $(call dequote,$(CONFIG_TOOLPREFIX))gcov GCOV := $(call dequote,$(CONFIG_SDK_TOOLPREFIX))gcov
REPORT_DIR := $(BUILD_DIR_BASE)/coverage_report REPORT_DIR := $(BUILD_DIR_BASE)/coverage_report
lcov-report: lcov-report:
@ -160,4 +160,4 @@ Overall coverage rate:
``` ```
NOTE: Since `lcov` tool is not part of GCC bundle it can happen that format of GCOV binary data has been changed and your local version of `lcov` fails to understand it. NOTE: Since `lcov` tool is not part of GCC bundle it can happen that format of GCOV binary data has been changed and your local version of `lcov` fails to understand it.
So it always better to use the latest `lcov` version from [LCOV repo](https://github.com/linux-test-project/lcov). So it always better to use the latest `lcov` version from [LCOV repo](https://github.com/linux-test-project/lcov).

View file

@ -2,7 +2,7 @@
# and component makefiles (component_wrapper.mk) # and component makefiles (component_wrapper.mk)
# #
PYTHON=$(call dequote,$(CONFIG_PYTHON)) PYTHON=$(call dequote,$(CONFIG_SDK_PYTHON))
# Include project config makefile, if it exists. # Include project config makefile, if it exists.
# #
@ -34,7 +34,7 @@ details := @true
MAKEFLAGS += --silent MAKEFLAGS += --silent
endif # $(V)==1 endif # $(V)==1
ifdef CONFIG_MAKE_WARN_UNDEFINED_VARIABLES ifdef CONFIG_SDK_MAKE_WARN_UNDEFINED_VARIABLES
MAKEFLAGS += --warn-undefined-variables MAKEFLAGS += --warn-undefined-variables
endif endif

View file

@ -471,13 +471,13 @@ export CFLAGS CPPFLAGS CXXFLAGS ARFLAGS
# Set target compiler. Defaults to whatever the user has # Set target compiler. Defaults to whatever the user has
# configured as prefix + ye olde gcc commands # configured as prefix + ye olde gcc commands
CC := $(call dequote,$(CONFIG_TOOLPREFIX))gcc CC := $(call dequote,$(CONFIG_SDK_TOOLPREFIX))gcc
CXX := $(call dequote,$(CONFIG_TOOLPREFIX))c++ CXX := $(call dequote,$(CONFIG_SDK_TOOLPREFIX))c++
LD := $(call dequote,$(CONFIG_TOOLPREFIX))ld LD := $(call dequote,$(CONFIG_SDK_TOOLPREFIX))ld
AR := $(call dequote,$(CONFIG_TOOLPREFIX))ar AR := $(call dequote,$(CONFIG_SDK_TOOLPREFIX))ar
OBJCOPY := $(call dequote,$(CONFIG_TOOLPREFIX))objcopy OBJCOPY := $(call dequote,$(CONFIG_SDK_TOOLPREFIX))objcopy
OBJDUMP := $(call dequote,$(CONFIG_TOOLPREFIX))objdump OBJDUMP := $(call dequote,$(CONFIG_SDK_TOOLPREFIX))objdump
SIZE := $(call dequote,$(CONFIG_TOOLPREFIX))size SIZE := $(call dequote,$(CONFIG_SDK_TOOLPREFIX))size
export CC CXX LD AR OBJCOPY OBJDUMP SIZE export CC CXX LD AR OBJCOPY OBJDUMP SIZE
COMPILER_VERSION_STR := $(shell $(CC) -dumpversion) COMPILER_VERSION_STR := $(shell $(CC) -dumpversion)
@ -665,7 +665,7 @@ print_flash_cmd: partition_table_get_info blank_ota_data
# The output normally looks as follows # The output normally looks as follows
# xtensa-esp32-elf-gcc (crosstool-NG crosstool-ng-1.22.0-80-g6c4433a) 5.2.0 # xtensa-esp32-elf-gcc (crosstool-NG crosstool-ng-1.22.0-80-g6c4433a) 5.2.0
# The part in brackets is extracted into TOOLCHAIN_COMMIT_DESC variable # The part in brackets is extracted into TOOLCHAIN_COMMIT_DESC variable
ifdef CONFIG_TOOLPREFIX ifdef CONFIG_SDK_TOOLPREFIX
ifndef MAKE_RESTARTS ifndef MAKE_RESTARTS
TOOLCHAIN_HEADER := $(shell $(CC) --version | head -1) TOOLCHAIN_HEADER := $(shell $(CC) --version | head -1)
@ -704,7 +704,7 @@ $(info WARNING: Failed to find Xtensa toolchain, may need to alter PATH or set o
endif # TOOLCHAIN_COMMIT_DESC endif # TOOLCHAIN_COMMIT_DESC
endif #MAKE_RESTARTS endif #MAKE_RESTARTS
endif #CONFIG_TOOLPREFIX endif #CONFIG_SDK_TOOLPREFIX
##################################################################### #####################################################################
endif #CONFIG_IDF_TARGET endif #CONFIG_IDF_TARGET

View file

@ -42,8 +42,24 @@ $(SDKCONFIG): defconfig
endif endif
endif endif
# macro for running confgen.py
define RunConfGen
mkdir -p $(BUILD_DIR_BASE)/include/config
$(PYTHON) $(IDF_PATH)/tools/kconfig_new/confgen.py \
--kconfig $(IDF_PATH)/Kconfig \
--config $(SDKCONFIG) \
--env "COMPONENT_KCONFIGS=$(strip $(COMPONENT_KCONFIGS))" \
--env "COMPONENT_KCONFIGS_PROJBUILD=$(strip $(COMPONENT_KCONFIGS_PROJBUILD))" \
--env "IDF_CMAKE=n" \
--output config ${SDKCONFIG} \
--output makefile $(SDKCONFIG_MAKEFILE) \
--output header $(BUILD_DIR_BASE)/include/sdkconfig.h
endef
# macro for the commands to run kconfig tools conf-idf or mconf-idf. # macro for the commands to run kconfig tools conf-idf or mconf-idf.
# $1 is the name (& args) of the conf tool to run # $1 is the name (& args) of the conf tool to run
# Note: Currently only mconf-idf is used for compatibility with the CMake build system. The header file used is also
# the same.
define RunConf define RunConf
mkdir -p $(BUILD_DIR_BASE)/include/config mkdir -p $(BUILD_DIR_BASE)/include/config
cd $(BUILD_DIR_BASE); KCONFIG_AUTOHEADER=$(abspath $(BUILD_DIR_BASE)/include/sdkconfig.h) \ cd $(BUILD_DIR_BASE); KCONFIG_AUTOHEADER=$(abspath $(BUILD_DIR_BASE)/include/sdkconfig.h) \
@ -65,7 +81,7 @@ ifndef MAKE_RESTARTS
# depend on any prerequisite that may cause a make restart as part of # depend on any prerequisite that may cause a make restart as part of
# the prerequisite's own recipe. # the prerequisite's own recipe.
menuconfig: $(KCONFIG_TOOL_DIR)/mconf-idf menuconfig: $(KCONFIG_TOOL_DIR)/mconf-idf | check_python_dependencies
$(summary) MENUCONFIG $(summary) MENUCONFIG
ifdef BATCH_BUILD ifdef BATCH_BUILD
@echo "Can't run interactive configuration inside non-interactive build process." @echo "Can't run interactive configuration inside non-interactive build process."
@ -74,25 +90,26 @@ ifdef BATCH_BUILD
@echo "See esp-idf documentation for more details." @echo "See esp-idf documentation for more details."
@exit 1 @exit 1
else else
$(call RunConfGen)
# RunConfGen before mconf-idf ensures that deprecated options won't be ignored (they've got renamed)
$(call RunConf,mconf-idf) $(call RunConf,mconf-idf)
# RunConfGen after mconf-idf ensures that deprecated options are appended to $(SDKCONFIG) for backward compatibility
$(call RunConfGen)
endif endif
# defconfig creates a default config, based on SDKCONFIG_DEFAULTS if present # defconfig creates a default config, based on SDKCONFIG_DEFAULTS if present
defconfig: $(KCONFIG_TOOL_DIR)/conf-idf defconfig: | check_python_dependencies
$(summary) DEFCONFIG $(summary) DEFCONFIG
ifneq ("$(wildcard $(SDKCONFIG_DEFAULTS))","") ifneq ("$(wildcard $(SDKCONFIG_DEFAULTS))","")
cat $(SDKCONFIG_DEFAULTS) >> $(SDKCONFIG) # append defaults to sdkconfig, will override existing values cat $(SDKCONFIG_DEFAULTS) >> $(SDKCONFIG) # append defaults to sdkconfig, will override existing values
endif endif
$(call RunConf,conf-idf --olddefconfig) $(call RunConfGen)
# if neither defconfig or menuconfig are requested, use the GENCONFIG rule to # if neither defconfig or menuconfig are requested, use the GENCONFIG rule to
# ensure generated config files are up to date # ensure generated config files are up to date
$(SDKCONFIG_MAKEFILE) $(BUILD_DIR_BASE)/include/sdkconfig.h: $(KCONFIG_TOOL_DIR)/conf-idf $(SDKCONFIG) $(COMPONENT_KCONFIGS) $(COMPONENT_KCONFIGS_PROJBUILD) | $(call prereq_if_explicit,defconfig) $(call prereq_if_explicit,menuconfig) $(SDKCONFIG_MAKEFILE) $(BUILD_DIR_BASE)/include/sdkconfig.h: $(SDKCONFIG) $(COMPONENT_KCONFIGS) $(COMPONENT_KCONFIGS_PROJBUILD) | check_python_dependencies $(call prereq_if_explicit,defconfig) $(call prereq_if_explicit,menuconfig)
$(summary) GENCONFIG $(summary) GENCONFIG
ifdef BATCH_BUILD # can't prompt for new config values like on terminal $(call RunConfGen)
$(call RunConf,conf-idf --olddefconfig)
endif
$(call RunConf,conf-idf --silentoldconfig)
touch $(SDKCONFIG_MAKEFILE) $(BUILD_DIR_BASE)/include/sdkconfig.h # ensure newer than sdkconfig touch $(SDKCONFIG_MAKEFILE) $(BUILD_DIR_BASE)/include/sdkconfig.h # ensure newer than sdkconfig
else # "$(MAKE_RESTARTS)" != "" else # "$(MAKE_RESTARTS)" != ""

7
sdkconfig.rename Normal file
View file

@ -0,0 +1,7 @@
# sdkconfig replacement configurations for deprecated options formatted as
# CONFIG_DEPRECATED_OPTION CONFIG_NEW_OPTION
# SDK tool configuration
CONFIG_TOOLPREFIX CONFIG_SDK_TOOLPREFIX
CONFIG_PYTHON CONFIG_SDK_PYTHON
CONFIG_MAKE_WARN_UNDEFINED_VARIABLES CONFIG_SDK_MAKE_WARN_UNDEFINED_VARIABLES

View file

@ -310,6 +310,35 @@ function run_tests()
rm -rf esp32 rm -rf esp32
rm -rf mycomponents rm -rf mycomponents
print_status "Handling deprecated Kconfig options"
make clean > /dev/null;
rm -f sdkconfig.defaults;
rm -f sdkconfig;
echo "" > ${IDF_PATH}/sdkconfig.rename;
make defconfig > /dev/null;
echo "CONFIG_TEST_OLD_OPTION=y" >> sdkconfig;
echo "CONFIG_TEST_OLD_OPTION CONFIG_TEST_NEW_OPTION" >> ${IDF_PATH}/sdkconfig.rename;
echo -e "\n\
menu \"test\"\n\
config TEST_NEW_OPTION\n\
bool \"test\"\n\
default \"n\"\n\
help\n\
TEST_NEW_OPTION description\n\
endmenu\n" >> ${IDF_PATH}/Kconfig;
make defconfig > /dev/null;
grep "CONFIG_TEST_OLD_OPTION=y" sdkconfig || failure "CONFIG_TEST_OLD_OPTION should be in sdkconfig for backward compatibility"
grep "CONFIG_TEST_NEW_OPTION=y" sdkconfig || failure "CONFIG_TEST_NEW_OPTION should be now in sdkconfig"
grep "#define CONFIG_TEST_NEW_OPTION 1" build/include/sdkconfig.h || failure "sdkconfig.h should contain the new macro"
grep "#define CONFIG_TEST_OLD_OPTION CONFIG_TEST_NEW_OPTION" build/include/sdkconfig.h || failure "sdkconfig.h should contain the compatibility macro"
grep "CONFIG_TEST_OLD_OPTION=y" build/include/config/auto.conf || failure "CONFIG_TEST_OLD_OPTION should be in auto.conf for backward compatibility"
grep "CONFIG_TEST_NEW_OPTION=y" build/include/config/auto.conf || failure "CONFIG_TEST_NEW_OPTION should be now in auto.conf"
rm -f sdkconfig sdkconfig.defaults
pushd ${IDF_PATH}
git checkout -- sdkconfig.rename Kconfig
popd
make defconfig
print_status "All tests completed" print_status "All tests completed"
if [ -n "${FAILURES}" ]; then if [ -n "${FAILURES}" ]; then
echo "Some failures were detected:" echo "Some failures were detected:"

View file

@ -366,6 +366,35 @@ EOF
export PATH="$OLDPATH" export PATH="$OLDPATH"
rm ./python rm ./python
print_status "Handling deprecated Kconfig options"
idf.py clean > /dev/null;
rm -f sdkconfig.defaults;
rm -f sdkconfig;
echo "" > ${IDF_PATH}/sdkconfig.rename;
idf.py build > /dev/null;
echo "CONFIG_TEST_OLD_OPTION=y" >> sdkconfig;
echo "CONFIG_TEST_OLD_OPTION CONFIG_TEST_NEW_OPTION" >> ${IDF_PATH}/sdkconfig.rename;
echo -e "\n\
menu \"test\"\n\
config TEST_NEW_OPTION\n\
bool \"test\"\n\
default \"n\"\n\
help\n\
TEST_NEW_OPTION description\n\
endmenu\n" >> ${IDF_PATH}/Kconfig;
idf.py build > /dev/null;
grep "CONFIG_TEST_OLD_OPTION=y" sdkconfig || failure "CONFIG_TEST_OLD_OPTION should be in sdkconfig for backward compatibility"
grep "CONFIG_TEST_NEW_OPTION=y" sdkconfig || failure "CONFIG_TEST_NEW_OPTION should be now in sdkconfig"
grep "#define CONFIG_TEST_NEW_OPTION 1" build/config/sdkconfig.h || failure "sdkconfig.h should contain the new macro"
grep "#define CONFIG_TEST_OLD_OPTION CONFIG_TEST_NEW_OPTION" build/config/sdkconfig.h || failure "sdkconfig.h should contain the compatibility macro"
grep "set(CONFIG_TEST_OLD_OPTION \"y\")" build/config/sdkconfig.cmake || failure "CONFIG_TEST_OLD_OPTION should be in auto.conf for backward compatibility"
grep "set(CONFIG_TEST_NEW_OPTION \"y\")" build/config/sdkconfig.cmake || failure "CONFIG_TEST_NEW_OPTION should be now in auto.conf"
rm -f sdkconfig sdkconfig.defaults
pushd ${IDF_PATH}
git checkout -- sdkconfig.rename Kconfig
popd
idf.py build
print_status "All tests completed" print_status "All tests completed"
if [ -n "${FAILURES}" ]; then if [ -n "${FAILURES}" ]; then
echo "Some failures were detected:" echo "Some failures were detected:"

View file

@ -138,7 +138,11 @@ function(kconfig_process_config)
"IDF_TARGET=${IDF_TARGET}" "IDF_TARGET=${IDF_TARGET}"
${MCONF} ${ROOT_KCONFIG} ${MCONF} ${ROOT_KCONFIG}
VERBATIM VERBATIM
USES_TERMINAL) USES_TERMINAL
# additional run of confgen esures that the deprecated options will be inserted into sdkconfig (for backward
# compatibility)
COMMAND ${confgen_basecommand} --env "IDF_TARGET=${IDF_TARGET}" --output config ${SDKCONFIG}
)
# Custom target to run confserver.py from the build tool # Custom target to run confserver.py from the build tool
add_custom_target(confserver add_custom_target(confserver
@ -191,4 +195,4 @@ function(kconfig_process_config)
ADDITIONAL_MAKE_CLEAN_FILES ADDITIONAL_MAKE_CLEAN_FILES
"${SDKCONFIG_HEADER}" "${SDKCONFIG_CMAKE}") "${SDKCONFIG_HEADER}" "${SDKCONFIG_CMAKE}")
endfunction() endfunction()

View file

@ -22,12 +22,13 @@
# limitations under the License. # limitations under the License.
from __future__ import print_function from __future__ import print_function
import argparse import argparse
import sys import fnmatch
import json
import os import os
import os.path import os.path
import tempfile
import json
import re import re
import sys
import tempfile
import gen_kconfig_doc import gen_kconfig_doc
import kconfiglib import kconfiglib
@ -38,6 +39,108 @@ if "IDF_CMAKE" not in os.environ:
os.environ["IDF_CMAKE"] = "" os.environ["IDF_CMAKE"] = ""
class DeprecatedOptions(object):
_REN_FILE = 'sdkconfig.rename'
_DEP_OP_BEGIN = '# Deprecated options for backward compatibility'
_DEP_OP_END = '# End of deprecated options'
_RE_DEP_OP_BEGIN = re.compile(_DEP_OP_BEGIN)
_RE_DEP_OP_END = re.compile(_DEP_OP_END)
def __init__(self, config_prefix, path_rename_files):
self.config_prefix = config_prefix
# r_dic maps deprecated options to new options; rev_r_dic maps in the opposite direction
self.r_dic, self.rev_r_dic = self._parse_replacements(path_rename_files)
# note the '=' at the end of regex for not getting partial match of configs
self._RE_CONFIG = re.compile(r'{}(\w+)='.format(self.config_prefix))
def _parse_replacements(self, repl_dir):
rep_dic = {}
rev_rep_dic = {}
for root, dirnames, filenames in os.walk(repl_dir):
for filename in fnmatch.filter(filenames, self._REN_FILE):
rep_path = os.path.join(root, filename)
with open(rep_path) as f_rep:
for line_number, line in enumerate(f_rep, start=1):
sp_line = line.split()
if len(sp_line) == 0 or sp_line[0].startswith('#'):
# empty line or comment
continue
if len(sp_line) != 2 or not all(x.startswith(self.config_prefix) for x in sp_line):
raise RuntimeError('Syntax error in {} (line {})'.format(rep_path, line_number))
if sp_line[0] in rep_dic:
raise RuntimeError('Error in {} (line {}): Replacement {} exist for {} and new '
'replacement {} is defined'.format(rep_path, line_number,
rep_dic[sp_line[0]], sp_line[0],
sp_line[1]))
(dep_opt, new_opt) = (x.lstrip(self.config_prefix) for x in sp_line)
rep_dic[dep_opt] = new_opt
rev_rep_dic[new_opt] = dep_opt
return rep_dic, rev_rep_dic
def get_deprecated_option(self, new_option):
return self.rev_r_dic.get(new_option, None)
def get_new_option(self, deprecated_option):
return self.r_dic.get(deprecated_option, None)
def replace(self, sdkconfig_in, sdkconfig_out):
replace_enabled = True
with open(sdkconfig_in, 'r') as f_in, open(sdkconfig_out, 'w') as f_out:
for line_num, line in enumerate(f_in, start=1):
if self._RE_DEP_OP_BEGIN.search(line):
replace_enabled = False
elif self._RE_DEP_OP_END.search(line):
replace_enabled = True
elif replace_enabled:
m = self._RE_CONFIG.search(line)
if m and m.group(1) in self.r_dic:
depr_opt = self.config_prefix + m.group(1)
new_opt = self.config_prefix + self.r_dic[m.group(1)]
line = line.replace(depr_opt, new_opt)
print('{}:{} {} was replaced with {}'.format(sdkconfig_in, line_num, depr_opt, new_opt))
f_out.write(line)
def append_doc(self, config, path_output):
if len(self.r_dic) > 0:
with open(path_output, 'a') as f_o:
header = 'Deprecated options and their replacements'
f_o.write('{}\n{}\n\n'.format(header, '-' * len(header)))
for key in sorted(self.r_dic):
f_o.write('- {}{}: :ref:`{}{}`\n'.format(config.config_prefix, key,
config.config_prefix, self.r_dic[key]))
def append_config(self, config, path_output):
tmp_list = []
def append_config_node_process(node):
item = node.item
if isinstance(item, kconfiglib.Symbol) and item.env_var is None:
if item.name in self.rev_r_dic:
c_string = item.config_string
if c_string:
tmp_list.append(c_string.replace(self.config_prefix + item.name,
self.config_prefix + self.rev_r_dic[item.name]))
config.walk_menu(append_config_node_process)
if len(tmp_list) > 0:
with open(path_output, 'a') as f_o:
f_o.write('\n{}\n'.format(self._DEP_OP_BEGIN))
f_o.writelines(tmp_list)
f_o.write('{}\n'.format(self._DEP_OP_END))
def append_header(self, config, path_output):
if len(self.r_dic) > 0:
with open(path_output, 'a') as f_o:
f_o.write('\n/* List of deprecated options */\n')
for dep_opt in sorted(self.r_dic):
new_opt = self.r_dic[dep_opt]
f_o.write('#define {}{} {}{}\n'.format(self.config_prefix, dep_opt, self.config_prefix, new_opt))
def main(): def main():
parser = argparse.ArgumentParser(description='confgen.py v%s - Config Generation Tool' % __version__, prog=os.path.basename(sys.argv[0])) parser = argparse.ArgumentParser(description='confgen.py v%s - Config Generation Tool' % __version__, prog=os.path.basename(sys.argv[0]))
@ -94,16 +197,30 @@ def main():
raise RuntimeError("Defaults file not found: %s" % name) raise RuntimeError("Defaults file not found: %s" % name)
config.load_config(name, replace=False) config.load_config(name, replace=False)
deprecated_options = DeprecatedOptions(config.config_prefix, path_rename_files=os.environ["IDF_PATH"])
# If config file previously exists, load it # If config file previously exists, load it
if args.config and os.path.exists(args.config): if args.config and os.path.exists(args.config):
config.load_config(args.config, replace=False) # ... but replace deprecated options before that
with tempfile.NamedTemporaryFile(prefix="confgen_tmp", delete=False) as f:
temp_file = f.name
try:
deprecated_options.replace(sdkconfig_in=args.config, sdkconfig_out=temp_file)
config.load_config(temp_file, replace=False)
update_if_changed(temp_file, args.config)
finally:
try:
os.remove(temp_file)
except OSError:
pass
# Output the files specified in the arguments # Output the files specified in the arguments
for output_type, filename in args.output: for output_type, filename in args.output:
temp_file = tempfile.mktemp(prefix="confgen_tmp") with tempfile.NamedTemporaryFile(prefix="confgen_tmp", delete=False) as f:
temp_file = f.name
try: try:
output_function = OUTPUT_FORMATS[output_type] output_function = OUTPUT_FORMATS[output_type]
output_function(config, temp_file) output_function(deprecated_options, config, temp_file)
update_if_changed(temp_file, filename) update_if_changed(temp_file, filename)
finally: finally:
try: try:
@ -112,16 +229,56 @@ def main():
pass pass
def write_config(config, filename): def write_config(deprecated_options, config, filename):
CONFIG_HEADING = """# CONFIG_HEADING = """#
# Automatically generated file. DO NOT EDIT. # Automatically generated file. DO NOT EDIT.
# Espressif IoT Development Framework (ESP-IDF) Project Configuration # Espressif IoT Development Framework (ESP-IDF) Project Configuration
# #
""" """
config.write_config(filename, header=CONFIG_HEADING) config.write_config(filename, header=CONFIG_HEADING)
deprecated_options.append_config(config, filename)
def write_header(config, filename): def write_makefile(deprecated_options, config, filename):
CONFIG_HEADING = """#
# Automatically generated file. DO NOT EDIT.
# Espressif IoT Development Framework (ESP-IDF) Project Makefile Configuration
#
"""
with open(filename, "w") as f:
tmp_dep_lines = []
f.write(CONFIG_HEADING)
def get_makefile_config_string(name, value, orig_type):
if orig_type in (kconfiglib.BOOL, kconfiglib.TRISTATE):
return "{}{}={}\n".format(config.config_prefix, name, '' if value == 'n' else value)
elif orig_type in (kconfiglib.INT, kconfiglib.HEX):
return "{}{}={}\n".format(config.config_prefix, name, value)
elif orig_type == kconfiglib.STRING:
return '{}{}="{}"\n'.format(config.config_prefix, name, kconfiglib.escape(value))
else:
raise RuntimeError('{}{}: unknown type {}'.format(config.config_prefix, name, orig_type))
def write_makefile_node(node):
item = node.item
if isinstance(item, kconfiglib.Symbol) and item.env_var is None:
# item.config_string cannot be used because it ignores hidden config items
val = item.str_value
f.write(get_makefile_config_string(item.name, val, item.orig_type))
dep_opt = deprecated_options.get_deprecated_option(item.name)
if dep_opt:
# the same string but with the deprecated name
tmp_dep_lines.append(get_makefile_config_string(dep_opt, val, item.orig_type))
config.walk_menu(write_makefile_node, True)
if len(tmp_dep_lines) > 0:
f.write('\n# List of deprecated options\n')
f.writelines(tmp_dep_lines)
def write_header(deprecated_options, config, filename):
CONFIG_HEADING = """/* CONFIG_HEADING = """/*
* Automatically generated file. DO NOT EDIT. * Automatically generated file. DO NOT EDIT.
* Espressif IoT Development Framework (ESP-IDF) Configuration Header * Espressif IoT Development Framework (ESP-IDF) Configuration Header
@ -129,10 +286,12 @@ def write_header(config, filename):
#pragma once #pragma once
""" """
config.write_autoconf(filename, header=CONFIG_HEADING) config.write_autoconf(filename, header=CONFIG_HEADING)
deprecated_options.append_header(config, filename)
def write_cmake(config, filename): def write_cmake(deprecated_options, config, filename):
with open(filename, "w") as f: with open(filename, "w") as f:
tmp_dep_list = []
write = f.write write = f.write
prefix = config.config_prefix prefix = config.config_prefix
@ -155,8 +314,15 @@ def write_cmake(config, filename):
val = "" # write unset values as empty variables val = "" # write unset values as empty variables
write("set({}{} \"{}\")\n".format( write("set({}{} \"{}\")\n".format(
prefix, sym.name, val)) prefix, sym.name, val))
dep_opt = deprecated_options.get_deprecated_option(sym.name)
if dep_opt:
tmp_dep_list.append("set({}{} \"{}\")\n".format(prefix, dep_opt, val))
config.walk_menu(write_node) config.walk_menu(write_node)
if len(tmp_dep_list) > 0:
write('\n# List of deprecated options for backward compatibility\n')
f.writelines(tmp_dep_list)
def get_json_values(config): def get_json_values(config):
config_dict = {} config_dict = {}
@ -179,7 +345,7 @@ def get_json_values(config):
return config_dict return config_dict
def write_json(config, filename): def write_json(deprecated_options, config, filename):
config_dict = get_json_values(config) config_dict = get_json_values(config)
with open(filename, "w") as f: with open(filename, "w") as f:
json.dump(config_dict, f, indent=4, sort_keys=True) json.dump(config_dict, f, indent=4, sort_keys=True)
@ -209,7 +375,7 @@ def get_menu_node_id(node):
return result return result
def write_json_menus(config, filename): def write_json_menus(deprecated_options, config, filename):
existing_ids = set() existing_ids = set()
result = [] # root level items result = [] # root level items
node_lookup = {} # lookup from MenuNode to an item in result node_lookup = {} # lookup from MenuNode to an item in result
@ -298,6 +464,11 @@ def write_json_menus(config, filename):
f.write(json.dumps(result, sort_keys=True, indent=4)) f.write(json.dumps(result, sort_keys=True, indent=4))
def write_docs(deprecated_options, config, filename):
gen_kconfig_doc.write_docs(config, filename)
deprecated_options.append_doc(config, filename)
def update_if_changed(source, destination): def update_if_changed(source, destination):
with open(source, "r") as f: with open(source, "r") as f:
source_contents = f.read() source_contents = f.read()
@ -313,9 +484,10 @@ def update_if_changed(source, destination):
OUTPUT_FORMATS = {"config": write_config, OUTPUT_FORMATS = {"config": write_config,
"makefile": write_makefile, # only used with make in order to generate auto.conf
"header": write_header, "header": write_header,
"cmake": write_cmake, "cmake": write_cmake,
"docs": gen_kconfig_doc.write_docs, "docs": write_docs,
"json": write_json, "json": write_json,
"json_menus": write_json_menus, "json_menus": write_json_menus,
} }

View file

@ -5,11 +5,12 @@
# #
from __future__ import print_function from __future__ import print_function
import argparse import argparse
import confgen
import json import json
import kconfiglib import kconfiglib
import os import os
import sys import sys
import confgen import tempfile
from confgen import FatalError, __version__ from confgen import FatalError, __version__
# Min/Max supported protocol versions # Min/Max supported protocol versions
@ -58,6 +59,13 @@ def main():
def run_server(kconfig, sdkconfig, default_version=MAX_PROTOCOL_VERSION): def run_server(kconfig, sdkconfig, default_version=MAX_PROTOCOL_VERSION):
config = kconfiglib.Kconfig(kconfig) config = kconfiglib.Kconfig(kconfig)
deprecated_options = confgen.DeprecatedOptions(config.config_prefix, path_rename_files=os.environ["IDF_PATH"])
with tempfile.NamedTemporaryFile(mode='w+b') as f_o:
with open(sdkconfig, mode='rb') as f_i:
f_o.write(f_i.read())
f_o.flush()
f_o.seek(0)
deprecated_options.replace(sdkconfig_in=f_o.name, sdkconfig_out=sdkconfig)
config.load_config(sdkconfig) config.load_config(sdkconfig)
print("Server running, waiting for requests on stdin...", file=sys.stderr) print("Server running, waiting for requests on stdin...", file=sys.stderr)
@ -111,7 +119,7 @@ def run_server(kconfig, sdkconfig, default_version=MAX_PROTOCOL_VERSION):
else: else:
sdkconfig = req["save"] sdkconfig = req["save"]
error = handle_request(config, req) error = handle_request(deprecated_options, config, req)
after = confgen.get_json_values(config) after = confgen.get_json_values(config)
after_ranges = get_ranges(config) after_ranges = get_ranges(config)
@ -136,7 +144,7 @@ def run_server(kconfig, sdkconfig, default_version=MAX_PROTOCOL_VERSION):
print("\n") print("\n")
def handle_request(config, req): def handle_request(deprecated_options, config, req):
if "version" not in req: if "version" not in req:
return ["All requests must have a 'version'"] return ["All requests must have a 'version'"]
@ -161,7 +169,7 @@ def handle_request(config, req):
if "save" in req: if "save" in req:
try: try:
print("Saving config to %s..." % req["save"], file=sys.stderr) print("Saving config to %s..." % req["save"], file=sys.stderr)
confgen.write_config(config, req["save"]) confgen.write_config(deprecated_options, config, req["save"])
except Exception as e: except Exception as e:
error += ["Failed to save to %s: %s" % (req["save"], e)] error += ["Failed to save to %s: %s" % (req["save"], e)]

View file

@ -1,9 +1,9 @@
# #
# SDK tool configuration # SDK tool configuration
# #
CONFIG_TOOLPREFIX="xtensa-esp32-elf-" CONFIG_SDK_TOOLPREFIX="xtensa-esp32-elf-"
CONFIG_PYTHON="python" CONFIG_SDK_PYTHON="python"
CONFIG_MAKE_WARN_UNDEFINED_VARIABLES=y CONFIG_SDK_MAKE_WARN_UNDEFINED_VARIABLES=y
# #
# Bootloader config # Bootloader config