forked from espressif/esp-idf
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>
This commit is contained in:
@ -58,7 +58,7 @@ def generate_hint(output: str) -> Optional[str]:
|
|||||||
# find the source_component that contains the source file
|
# find the source_component that contains the source file
|
||||||
found_source_component_name = None
|
found_source_component_name = None
|
||||||
found_source_component_info = 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
|
# look if the source_filename is within a component directory, not only
|
||||||
# at component_info['sources'], because the missing file may be included
|
# at component_info['sources'], because the missing file may be included
|
||||||
# from header file, which is not present in component_info['sources']
|
# 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])
|
original_file_match = ORIGINAL_FILE_RE.match(lines[-2])
|
||||||
if original_file_match:
|
if original_file_match:
|
||||||
original_filename = _get_absolute_path(original_file_match.group(1), proj_desc['build_dir'])
|
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'])
|
component_dir = os.path.normpath(component_info['dir'])
|
||||||
if original_filename.startswith(component_dir):
|
if original_filename.startswith(component_dir):
|
||||||
found_original_component_name = component_name
|
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
|
# look for the header file in the public include directories of all components
|
||||||
found_dep_component_names = []
|
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:
|
if candidate_component_name == found_source_component_name:
|
||||||
# skip the component that contains the source file
|
# skip the component that contains the source file
|
||||||
continue
|
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
|
# directories if we can find the missing header there and notify user about possible
|
||||||
# missing entry in INCLUDE_DIRS.
|
# missing entry in INCLUDE_DIRS.
|
||||||
candidate_component_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'])
|
component_dir = os.path.normpath(component_info['dir'])
|
||||||
for root, _, _ in os.walk(component_dir):
|
for root, _, _ in os.walk(component_dir):
|
||||||
full_path = os.path.normpath(os.path.join(root, missing_header))
|
full_path = os.path.normpath(os.path.join(root, missing_header))
|
||||||
|
@ -171,5 +171,34 @@ class TestNestedModuleComponentRequirements(unittest.TestCase):
|
|||||||
self.tmpdir.cleanup()
|
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__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
Reference in New Issue
Block a user