mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-03 03:31:41 +03:00
fix(cmakev2/manager): seed known_components for namespace rewrite
When a component's manifest declared a managed dep `<ns>/<name>` and the project had a local `components/<name>` shadowing it, configure failed with `IDF: Failed to resolve component '<ns>__<name>'`. cmakev1 does a project-wide injection so the manager's _choose_component sees every component name in known_components and rewrites the namespaced dep to its locally-shadowing short name. cmakev2 invokes the manager per component with a single-component requirements file, so known_components has only one entry and the rewrite cannot fire -- `<ns>__<name>` is written verbatim into MANAGED_REQUIRES and the force-include at component.cmake:995 aborts. Seed the per-component requirements file with one __COMPONENT_SOURCE entry per discovered component so handle_project_requirements() builds the same known_components list cmakev1 produces. The seeded entries are inert on the cmake side -- the __component_set_property shim ignores __COMPONENT_SOURCE -- they exist purely to feed the manager's rewrite. Add a regression test in tools/test_build_system/buildv2/test_component.py. Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
# SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
import json
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
@@ -297,3 +298,53 @@ def test_idf_component_set_get_property_apis(idf_py: IdfPyFunc) -> None:
|
||||
assert 'LIB=' in result and len(result.split('LIB=')[1].split('\n')[0]) > 0, (
|
||||
'idf_component_get_property should retrieve COMPONENT_LIB'
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures('test_app_copy')
|
||||
def test_local_component_shadows_managed_dep_in_manifest(idf_py: IdfPyFunc) -> None:
|
||||
"""A component's manifest declares `<ns>/<name>` while the project has a
|
||||
local `components/<name>` that shadows it. The dep must resolve to the
|
||||
local short-named component rather than failing with
|
||||
`Failed to resolve component '<ns>__<name>'`.
|
||||
|
||||
Regression test for the cmakev2 per-component injection path that lost
|
||||
the project-wide context _choose_component needs to rewrite a manifest-
|
||||
declared namespaced dep to its locally-shadowing short name. The fix
|
||||
seeds the per-component requirements file with one entry per discovered
|
||||
component so known_components matches what cmakev1's project-wide
|
||||
injection produces.
|
||||
"""
|
||||
logging.info('Testing local component shadows manifest-declared managed dep')
|
||||
|
||||
# Local shadow named `lvgl`.
|
||||
(Path('components/lvgl')).mkdir(parents=True)
|
||||
(Path('components/lvgl/CMakeLists.txt')).write_text('idf_component_register(SRCS "lvgl_stub.c" INCLUDE_DIRS ".")\n')
|
||||
(Path('components/lvgl/lvgl_stub.c')).write_text('void lvgl_local_stub(void) {}\n')
|
||||
|
||||
# A second local component whose manifest declares the namespaced dep.
|
||||
# override_path keeps the component manager offline by pointing the dep
|
||||
# at the local lvgl directory.
|
||||
(Path('components/consumer')).mkdir(parents=True)
|
||||
(Path('components/consumer/CMakeLists.txt')).write_text(
|
||||
'idf_component_register(SRCS "consumer.c" INCLUDE_DIRS ".")\n'
|
||||
)
|
||||
(Path('components/consumer/consumer.c')).write_text('void consumer_stub(void) {}\n')
|
||||
(Path('components/consumer/idf_component.yml')).write_text(
|
||||
'dependencies:\n idf: ">=5.0"\n lvgl/lvgl:\n version: "*"\n override_path: "../lvgl"\n'
|
||||
)
|
||||
|
||||
# Force consumer into the build via main (cmakev2 only builds required components).
|
||||
replace_in_file(
|
||||
'main/CMakeLists.txt',
|
||||
'# placeholder_inside_idf_component_register',
|
||||
'PRIV_REQUIRES consumer',
|
||||
)
|
||||
|
||||
# Without the fix this fails with "Failed to resolve component 'lvgl__lvgl'".
|
||||
idf_py('reconfigure')
|
||||
|
||||
with open('build/project_description.json') as f:
|
||||
data = json.load(f)
|
||||
paths = data.get('build_component_paths', [])
|
||||
assert any(p.endswith('/components/lvgl') for p in paths), f'local lvgl not in build_component_paths: {paths}'
|
||||
assert not any('lvgl__lvgl' in p for p in paths), f'managed lvgl__lvgl should not be in build: {paths}'
|
||||
|
||||
Reference in New Issue
Block a user