Quellcode durchsuchen

feat(hints): use all_component_info from project_description.json

Currently the component_requirements hint module does not work
as expected if the component list for a project is trimmed down.
With the new "all_component_info" dictionary info in project_description.json,
the module can produce hints even if cmake's COMPONENTS variable is
set.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
Frantisek Hrbata vor 2 Jahren
Ursprung
Commit
64d82b54bc

+ 4 - 4
tools/idf_py_actions/hint_modules/component_requirements.py

@@ -58,7 +58,7 @@ def generate_hint(output: str) -> Optional[str]:
     # find the source_component that contains the source file
     found_source_component_name = None
     found_source_component_info = None
-    for component_name, component_info in proj_desc['build_component_info'].items():
+    for component_name, component_info in proj_desc['all_component_info'].items():
         # look if the source_filename is within a component directory, not only
         # at component_info['sources'], because the missing file may be included
         # from header file, which is not present in component_info['sources']
@@ -86,7 +86,7 @@ def generate_hint(output: str) -> Optional[str]:
         original_file_match = ORIGINAL_FILE_RE.match(lines[-2])
         if original_file_match:
             original_filename = _get_absolute_path(original_file_match.group(1), proj_desc['build_dir'])
-            for component_name, component_info in proj_desc['build_component_info'].items():
+            for component_name, component_info in proj_desc['all_component_info'].items():
                 component_dir = os.path.normpath(component_info['dir'])
                 if original_filename.startswith(component_dir):
                     found_original_component_name = component_name
@@ -100,7 +100,7 @@ def generate_hint(output: str) -> Optional[str]:
 
     # look for the header file in the public include directories of all components
     found_dep_component_names = []
-    for candidate_component_name, candidate_component_info in proj_desc['build_component_info'].items():
+    for candidate_component_name, candidate_component_info in proj_desc['all_component_info'].items():
         if candidate_component_name == found_source_component_name:
             # skip the component that contains the source file
             continue
@@ -117,7 +117,7 @@ def generate_hint(output: str) -> Optional[str]:
         # directories if we can find the missing header there and notify user about possible
         # missing entry in INCLUDE_DIRS.
         candidate_component_include_dirs = []
-        for component_name, component_info in proj_desc['build_component_info'].items():
+        for component_name, component_info in proj_desc['all_component_info'].items():
             component_dir = os.path.normpath(component_info['dir'])
             for root, _, _ in os.walk(component_dir):
                 full_path = os.path.normpath(os.path.join(root, missing_header))

+ 29 - 0
tools/test_idf_py/test_hints.py

@@ -171,5 +171,34 @@ class TestNestedModuleComponentRequirements(unittest.TestCase):
         self.tmpdir.cleanup()
 
 
+class TestTrimmedModuleComponentRequirements(unittest.TestCase):
+    def setUp(self) -> None:
+        # Set up a dummy project with a trimmed down list of components and main component.
+        # The main component includes "esp_http_client.h", but the esp_http_client
+        # component is not added to main's requirements.
+        self.tmpdir = tempfile.TemporaryDirectory()
+        self.tmpdirpath = Path(self.tmpdir.name)
+
+        self.projectdir = self.tmpdirpath / 'project'
+        self.projectdir.mkdir(parents=True)
+        (self.projectdir / 'CMakeLists.txt').write_text((
+            'cmake_minimum_required(VERSION 3.16)\n'
+            'set(COMPONENTS main)\n'
+            'include($ENV{IDF_PATH}/tools/cmake/project.cmake)\n'
+            'project(foo)'))
+
+        maindir = self.projectdir / 'main'
+        maindir.mkdir()
+        (maindir / 'CMakeLists.txt').write_text('idf_component_register(SRCS "foo.c")')
+        (maindir / 'foo.c').write_text('#include "esp_http_client.h"\nvoid app_main(){}')
+
+    def test_trimmed_component_requirements(self) -> None:
+        output = run_idf(['app'], self.projectdir)
+        self.assertIn('To fix this, add esp_http_client to PRIV_REQUIRES list of idf_component_register call in', output)
+
+    def tearDown(self) -> None:
+        self.tmpdir.cleanup()
+
+
 if __name__ == '__main__':
     unittest.main()