فهرست منبع

Rename deprecated Kconfig options in a backward compatible way

Roland Dobai 6 سال پیش
والد
کامیت
23ee93ea76

+ 3 - 3
Kconfig

@@ -25,14 +25,14 @@ mainmenu "Espressif IoT Development Framework Configuration"
 
 
     menu "SDK tool configuration"
-        config TOOLPREFIX
+        config SDK_TOOLPREFIX
             string "Compiler toolchain path/prefix"
             default "xtensa-esp32-elf-"
             help
                 The prefix/path that is used to call the toolchain. The default setting assumes
                 a crosstool-ng gcc setup that is in your PATH.
 
-        config PYTHON
+        config SDK_PYTHON
             string "Python 2 interpreter"
             depends on !IDF_CMAKE
             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
                 or CMake-based builds.)
 
-        config MAKE_WARN_UNDEFINED_VARIABLES
+        config SDK_MAKE_WARN_UNDEFINED_VARIABLES
             bool "'make' warns on undefined variables"
             default "y"
             help

+ 2 - 2
components/esptool_py/Makefile.projbuild

@@ -8,7 +8,7 @@ ESPFLASHSIZE ?= $(CONFIG_ESPTOOLPY_FLASHSIZE)
 
 CONFIG_ESPTOOLPY_COMPRESSED ?=
 
-PYTHON ?= $(call dequote,$(CONFIG_PYTHON))
+PYTHON ?= $(call dequote,$(CONFIG_SDK_PYTHON))
 
 # two commands that can be used from other components
 # 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 ?=
 
-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
 	$(summary) MONITOR

+ 1 - 1
examples/system/gcov/Makefile

@@ -7,7 +7,7 @@ PROJECT_NAME := gcov_example
 
 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
 
 lcov-report:

+ 2 - 2
examples/system/gcov/README.md

@@ -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`:
 
 ```
-GCOV := $(call dequote,$(CONFIG_TOOLPREFIX))gcov
+GCOV := $(call dequote,$(CONFIG_SDK_TOOLPREFIX))gcov
 REPORT_DIR := $(BUILD_DIR_BASE)/coverage_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.
-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).

+ 2 - 2
make/common.mk

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

+ 9 - 9
make/project.mk

@@ -471,13 +471,13 @@ export CFLAGS CPPFLAGS CXXFLAGS ARFLAGS
 
 # Set target compiler. Defaults to whatever the user has
 # configured as prefix + ye olde gcc commands
-CC := $(call dequote,$(CONFIG_TOOLPREFIX))gcc
-CXX := $(call dequote,$(CONFIG_TOOLPREFIX))c++
-LD := $(call dequote,$(CONFIG_TOOLPREFIX))ld
-AR := $(call dequote,$(CONFIG_TOOLPREFIX))ar
-OBJCOPY := $(call dequote,$(CONFIG_TOOLPREFIX))objcopy
-OBJDUMP := $(call dequote,$(CONFIG_TOOLPREFIX))objdump
-SIZE := $(call dequote,$(CONFIG_TOOLPREFIX))size
+CC := $(call dequote,$(CONFIG_SDK_TOOLPREFIX))gcc
+CXX := $(call dequote,$(CONFIG_SDK_TOOLPREFIX))c++
+LD := $(call dequote,$(CONFIG_SDK_TOOLPREFIX))ld
+AR := $(call dequote,$(CONFIG_SDK_TOOLPREFIX))ar
+OBJCOPY := $(call dequote,$(CONFIG_SDK_TOOLPREFIX))objcopy
+OBJDUMP := $(call dequote,$(CONFIG_SDK_TOOLPREFIX))objdump
+SIZE := $(call dequote,$(CONFIG_SDK_TOOLPREFIX))size
 export CC CXX LD AR OBJCOPY OBJDUMP SIZE
 
 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
 #     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
-ifdef CONFIG_TOOLPREFIX
+ifdef CONFIG_SDK_TOOLPREFIX
 ifndef MAKE_RESTARTS
 
 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 #MAKE_RESTARTS
-endif #CONFIG_TOOLPREFIX
+endif #CONFIG_SDK_TOOLPREFIX
 
 #####################################################################
 endif #CONFIG_IDF_TARGET

+ 25 - 8
make/project_config.mk

@@ -42,8 +42,24 @@ $(SDKCONFIG): defconfig
 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.
 # $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
 	mkdir -p $(BUILD_DIR_BASE)/include/config
 	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
 # the prerequisite's own recipe.
 
-menuconfig: $(KCONFIG_TOOL_DIR)/mconf-idf
+menuconfig: $(KCONFIG_TOOL_DIR)/mconf-idf | check_python_dependencies
 	$(summary) MENUCONFIG
 ifdef BATCH_BUILD
 	@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."
 	@exit 1
 else
+	$(call RunConfGen)
+	# RunConfGen before mconf-idf ensures that deprecated options won't be ignored (they've got renamed)
 	$(call RunConf,mconf-idf)
+	# RunConfGen after mconf-idf ensures that deprecated options are appended to $(SDKCONFIG) for backward compatibility
+	$(call RunConfGen)
 endif
 
 # defconfig creates a default config, based on SDKCONFIG_DEFAULTS if present
-defconfig: $(KCONFIG_TOOL_DIR)/conf-idf
+defconfig: | check_python_dependencies
 	$(summary) DEFCONFIG
 ifneq ("$(wildcard $(SDKCONFIG_DEFAULTS))","")
 	cat $(SDKCONFIG_DEFAULTS) >> $(SDKCONFIG)  # append defaults to sdkconfig, will override existing values
 endif
-	$(call RunConf,conf-idf --olddefconfig)
+	$(call RunConfGen)
 
 # if neither defconfig or menuconfig are requested, use the GENCONFIG rule to
 # 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
-ifdef BATCH_BUILD  # can't prompt for new config values like on terminal
-	$(call RunConf,conf-idf --olddefconfig)
-endif
-	$(call RunConf,conf-idf --silentoldconfig)
+	$(call RunConfGen)
 	touch $(SDKCONFIG_MAKEFILE) $(BUILD_DIR_BASE)/include/sdkconfig.h  # ensure newer than sdkconfig
 
 else  # "$(MAKE_RESTARTS)" != ""

+ 7 - 0
sdkconfig.rename

@@ -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

+ 29 - 0
tools/ci/test_build_system.sh

@@ -310,6 +310,35 @@ function run_tests()
     rm -rf esp32
     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"
     if [ -n "${FAILURES}" ]; then
         echo "Some failures were detected:"

+ 29 - 0
tools/ci/test_build_system_cmake.sh

@@ -366,6 +366,35 @@ EOF
     export PATH="$OLDPATH"
     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"
     if [ -n "${FAILURES}" ]; then
         echo "Some failures were detected:"

+ 6 - 2
tools/cmake/kconfig.cmake

@@ -138,7 +138,11 @@ function(kconfig_process_config)
         "IDF_TARGET=${IDF_TARGET}"
         ${MCONF} ${ROOT_KCONFIG}
         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
     add_custom_target(confserver
@@ -191,4 +195,4 @@ function(kconfig_process_config)
         ADDITIONAL_MAKE_CLEAN_FILES
         "${SDKCONFIG_HEADER}" "${SDKCONFIG_CMAKE}")
 
-endfunction()
+endfunction()

+ 184 - 12
tools/kconfig_new/confgen.py

@@ -22,12 +22,13 @@
 # limitations under the License.
 from __future__ import print_function
 import argparse
-import sys
+import fnmatch
+import json
 import os
 import os.path
-import tempfile
-import json
 import re
+import sys
+import tempfile
 
 import gen_kconfig_doc
 import kconfiglib
@@ -38,6 +39,108 @@ if "IDF_CMAKE" not in os.environ:
     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():
     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)
             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 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
     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:
             output_function = OUTPUT_FORMATS[output_type]
-            output_function(config, temp_file)
+            output_function(deprecated_options, config, temp_file)
             update_if_changed(temp_file, filename)
         finally:
             try:
@@ -112,16 +229,56 @@ def main():
                 pass
 
 
-def write_config(config, filename):
+def write_config(deprecated_options, config, filename):
     CONFIG_HEADING = """#
 # Automatically generated file. DO NOT EDIT.
 # Espressif IoT Development Framework (ESP-IDF) Project Configuration
 #
 """
     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 = """/*
  * Automatically generated file. DO NOT EDIT.
  * Espressif IoT Development Framework (ESP-IDF) Configuration Header
@@ -129,10 +286,12 @@ def write_header(config, filename):
 #pragma once
 """
     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:
+        tmp_dep_list = []
         write = f.write
         prefix = config.config_prefix
 
@@ -155,8 +314,15 @@ def write_cmake(config, filename):
                     val = ""  # write unset values as empty variables
                 write("set({}{} \"{}\")\n".format(
                     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)
 
+        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):
     config_dict = {}
@@ -179,7 +345,7 @@ def get_json_values(config):
     return config_dict
 
 
-def write_json(config, filename):
+def write_json(deprecated_options, config, filename):
     config_dict = get_json_values(config)
     with open(filename, "w") as f:
         json.dump(config_dict, f, indent=4, sort_keys=True)
@@ -209,7 +375,7 @@ def get_menu_node_id(node):
     return result
 
 
-def write_json_menus(config, filename):
+def write_json_menus(deprecated_options, config, filename):
     existing_ids = set()
     result = []  # root level items
     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))
 
 
+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):
     with open(source, "r") as f:
         source_contents = f.read()
@@ -313,9 +484,10 @@ def update_if_changed(source, destination):
 
 
 OUTPUT_FORMATS = {"config": write_config,
+                  "makefile": write_makefile,  # only used with make in order to generate auto.conf
                   "header": write_header,
                   "cmake": write_cmake,
-                  "docs": gen_kconfig_doc.write_docs,
+                  "docs": write_docs,
                   "json": write_json,
                   "json_menus": write_json_menus,
                   }

+ 12 - 4
tools/kconfig_new/confserver.py

@@ -5,11 +5,12 @@
 #
 from __future__ import print_function
 import argparse
+import confgen
 import json
 import kconfiglib
 import os
 import sys
-import confgen
+import tempfile
 from confgen import FatalError, __version__
 
 # Min/Max supported protocol versions
@@ -58,6 +59,13 @@ def main():
 
 def run_server(kconfig, sdkconfig, default_version=MAX_PROTOCOL_VERSION):
     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)
 
     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:
                 sdkconfig = req["save"]
 
-        error = handle_request(config, req)
+        error = handle_request(deprecated_options, config, req)
 
         after = confgen.get_json_values(config)
         after_ranges = get_ranges(config)
@@ -136,7 +144,7 @@ def run_server(kconfig, sdkconfig, default_version=MAX_PROTOCOL_VERSION):
         print("\n")
 
 
-def handle_request(config, req):
+def handle_request(deprecated_options, config, req):
     if "version" not in req:
         return ["All requests must have a 'version'"]
 
@@ -161,7 +169,7 @@ def handle_request(config, req):
     if "save" in req:
         try:
             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:
             error += ["Failed to save to %s: %s" % (req["save"], e)]
 

+ 3 - 3
tools/ldgen/samples/sdkconfig

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