Răsfoiți Sursa

kconfig: Fix generation of hex outputs for Make & CMake

And add tests for hex output formatting in all output formats.

Previously, Make & CMake outputs only formatted hex values with the 0x prefix
if they had the 0x prefix in the sdkconfig file. Now this prefix is always
applied.

Closes https://github.com/espressif/vscode-esp-idf-extension/issues/83
Angus Gratton 5 ani în urmă
părinte
comite
16e14104f7

+ 18 - 7
tools/kconfig_new/confgen.py

@@ -355,14 +355,24 @@ def write_makefile(deprecated_options, config, filename):
 
         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)
+                value = '' if value == 'n' else value
+            elif orig_type == kconfiglib.INT:
+                try:
+                    value = int(value)
+                except ValueError:
+                    value = ""
+            elif orig_type == kconfiglib.HEX:
+                try:
+                    value = hex(int(value, 16))  # ensure 0x prefix
+                except ValueError:
+                    value = ""
             elif orig_type == kconfiglib.STRING:
-                return '{}{}="{}"\n'.format(config.config_prefix, name, kconfiglib.escape(value))
+                value = '"{}"'.format(kconfiglib.escape(value))
             else:
                 raise RuntimeError('{}{}: unknown type {}'.format(config.config_prefix, name, orig_type))
 
+            return '{}{}={}\n'.format(config.config_prefix, name, value)
+
         def write_makefile_node(node):
             item = node.item
             if isinstance(item, kconfiglib.Symbol) and item.env_var is None:
@@ -419,13 +429,14 @@ def write_cmake(deprecated_options, config, filename):
                     val = ""  # write unset values as empty variables
                 elif sym.orig_type == kconfiglib.STRING:
                     val = kconfiglib.escape(val)
-                write("set({}{} \"{}\")\n".format(
-                    prefix, sym.name, val))
+                elif sym.orig_type == kconfiglib.HEX:
+                    val = hex(int(val, 16))  # ensure 0x prefix
+                write('set({}{} "{}")\n'.format(prefix, sym.name, val))
 
                 configs_list.append(prefix + sym.name)
                 dep_opt = deprecated_options.get_deprecated_option(sym.name)
                 if dep_opt:
-                    tmp_dep_list.append("set({}{} \"{}\")\n".format(prefix, dep_opt, val))
+                    tmp_dep_list.append('set({}{} "{}")\n'.format(prefix, dep_opt, val))
                     configs_list.append(prefix + dep_opt)
 
         for n in config.node_iter():

+ 45 - 5
tools/kconfig_new/test/confgen/test_confgen.py

@@ -25,7 +25,7 @@ class ConfgenBaseTestCase(unittest.TestCase):
             # Python 2 fallback
             regex_func = self.assertRegexpMatches
         finally:
-            self.functions['regex'] = regex_func
+            self.functions['regex'] = lambda instance, s, expr: regex_func(instance, expr, s)  # reverse args order
 
     def setUp(self):
         with tempfile.NamedTemporaryFile(prefix='test_confgen_', delete=False) as f:
@@ -47,6 +47,16 @@ class ConfgenBaseTestCase(unittest.TestCase):
         subprocess.check_call(call_args)
 
     def invoke_and_test(self, in_text, out_text, test='in'):
+        """
+        Main utility function for testing confgen:
+
+        - Runs confgen via invoke_confgen(), using output method pre-set in test class setup
+        - in_text is the Kconfig file input content
+        - out_text is some expected output from confgen
+        - 'test' can be any function key from self.functions dict (see above). Default is 'in' to test if
+          out_text is a substring of the full confgen output.
+        """
+
         with tempfile.NamedTemporaryFile(mode='w+', prefix='test_confgen_', delete=False) as f:
             self.addCleanup(os.remove, f.name)
             f.write(textwrap.dedent(in_text))
@@ -58,10 +68,12 @@ class ConfgenBaseTestCase(unittest.TestCase):
         with open(self.output_file) as f_result:
             result = f_result.read()
 
-        if test == 'regex':  # need to reverse the argument order
-            self.functions[test](self, result, out_text)
-        else:
-            self.functions[test](self, textwrap.dedent(out_text), result)
+        try:
+            out_text = textwrap.dedent(out_text)
+        except TypeError:
+            pass  # probably a regex
+
+        self.functions[test](self, out_text, result)
 
 
 class CmakeTestCase(ConfgenBaseTestCase):
@@ -77,6 +89,10 @@ class CmakeTestCase(ConfgenBaseTestCase):
             default "\\\\~!@#$%^&*()\\\""
         """, 'set(CONFIG_PASSWORD "\\\\~!@#$%^&*()\\\"")')
 
+    def testHexPrefix(self):
+        self.invoke_and_test(HEXPREFIX_KCONFIG, 'set(CONFIG_HEX_NOPREFIX "0x33")')
+        self.invoke_and_test(HEXPREFIX_KCONFIG, 'set(CONFIG_HEX_PREFIX "0x77")')
+
 
 class JsonTestCase(ConfgenBaseTestCase):
     @classmethod
@@ -91,6 +107,11 @@ class JsonTestCase(ConfgenBaseTestCase):
             default "\\\\~!@#$%^&*()\\\""
         """, '"PASSWORD": "\\\\~!@#$%^&*()\\\""')
 
+    def testHexPrefix(self):
+        # hex values come out as integers in JSON, due to no hex type
+        self.invoke_and_test(HEXPREFIX_KCONFIG, '"HEX_NOPREFIX": %d' % 0x33)
+        self.invoke_and_test(HEXPREFIX_KCONFIG, '"HEX_PREFIX": %d' % 0x77)
+
 
 class JsonMenuTestCase(ConfgenBaseTestCase):
     @classmethod
@@ -168,6 +189,10 @@ class MakefileTestCase(ConfgenBaseTestCase):
         with open(os.path.join(os.environ['IDF_PATH'], 'Kconfig')) as f:
             self.invoke_and_test(f.read(), 'CONFIG_IDF_TARGET="esp32"')
 
+    def testHexPrefix(self):
+        self.invoke_and_test(HEXPREFIX_KCONFIG, 'CONFIG_HEX_NOPREFIX=0x33')
+        self.invoke_and_test(HEXPREFIX_KCONFIG, 'CONFIG_HEX_PREFIX=0x77')
+
 
 class HeaderTestCase(ConfgenBaseTestCase):
     @classmethod
@@ -182,6 +207,10 @@ class HeaderTestCase(ConfgenBaseTestCase):
             default "\\\\~!@#$%^&*()\\\""
         """, '#define CONFIG_PASSWORD "\\\\~!@#$%^&*()\\\""')
 
+    def testHexPrefix(self):
+        self.invoke_and_test(HEXPREFIX_KCONFIG, '#define CONFIG_HEX_NOPREFIX 0x33')
+        self.invoke_and_test(HEXPREFIX_KCONFIG, '#define CONFIG_HEX_PREFIX 0x77')
+
 
 class DocsTestCase(ConfgenBaseTestCase):
     @classmethod
@@ -230,5 +259,16 @@ class DocsTestCase(ConfgenBaseTestCase):
         """)  # this is more readable than regex
 
 
+# Used by multiple testHexPrefix() test cases to verify correct hex output for each format
+HEXPREFIX_KCONFIG = """
+config HEX_NOPREFIX
+hex "Hex Item default no prefix"
+default 33
+
+config HEX_PREFIX
+hex "Hex Item default prefix"
+default 0x77
+"""
+
 if __name__ == "__main__":
     unittest.main()