feat: Consume root-managed components from IDF Component Manager

This commit is contained in:
Daniel Paul
2026-08-18 20:51:54 +08:00
parent ab6a455b1a
commit b764f073ac
12 changed files with 194 additions and 53 deletions
@@ -2,15 +2,21 @@
# SPDX-License-Identifier: Apache-2.0
import json
import os.path
import subprocess
import textwrap
from pathlib import Path
import pytest
from test_build_system_helpers import EXT_IDF_PATH
from test_build_system_helpers import EnvDict
from test_build_system_helpers import IdfPyFunc
from test_build_system_helpers import replace_in_file
def _install_root_components(env: EnvDict) -> None:
subprocess.run(['compote', 'cooking', 'stock'], check=True, env=env)
def test_dependency_lock(idf_py: IdfPyFunc, test_app_copy: Path) -> None:
replace_in_file(
test_app_copy / 'CMakeLists.txt',
@@ -202,3 +208,102 @@ class TestOptionalDependencyWithKconfig:
data = json.load(open(test_app_copy / 'build' / 'project_description.json'))
assert ['example__cmp'] == data['build_component_info']['foo']['priv_reqs']
assert ['espressif__mdns'] == data['build_component_info']['foo']['reqs']
@pytest.mark.revert_later(['tools/idf_extra_components.yml'])
class TestIdfRootDependency:
@pytest.fixture(autouse=True)
def _clean_root_managed(self, clean_root_managed_components: None) -> None:
pass
def test_basic_build(self, idf_py: IdfPyFunc, test_app_copy: Path, default_idf_env: EnvDict) -> None:
with open(os.path.join(EXT_IDF_PATH, 'tools', 'idf_extra_components.yml'), 'w') as fw:
fw.write(
textwrap.dedent("""
dependencies:
espressif/mdns: "*"
""")
)
_install_root_components(default_idf_env)
replace_in_file(
(test_app_copy / 'main' / 'build_test_app.c'),
'// placeholder_before_main',
'#include "mdns.h"',
)
# Intentional dependency on the cmake-level name of the managed component because
# idf_extra_components.yml installs espressif/mdns and we verify REQUIRES pulls
# espressif__mdns into the build — not something application code should do.
replace_in_file(
(test_app_copy / 'main' / 'CMakeLists.txt'),
'# placeholder_inside_idf_component_register',
'REQUIRES espressif__mdns',
)
idf_py('build')
def test_build_only_when_required(self, idf_py: IdfPyFunc, test_app_copy: Path, default_idf_env: EnvDict) -> None:
with open(os.path.join(EXT_IDF_PATH, 'tools', 'idf_extra_components.yml'), 'w') as fw:
fw.write(
textwrap.dedent("""
dependencies:
espressif/mdns: "*"
example/cmp: "*"
""")
)
_install_root_components(default_idf_env)
idf_py('reconfigure')
data = json.load(open(test_app_copy / 'build' / 'project_description.json'))
assert 'espressif__mdns' not in data['build_components']
assert 'example__cmp' not in data['build_components']
# Intentional dependency on the cmake-level name of the managed component because
# we assert espressif__mdns enters build_components only after REQUIRES — not
# something application code should do.
replace_in_file(
(test_app_copy / 'main' / 'CMakeLists.txt'),
'# placeholder_inside_idf_component_register',
'REQUIRES espressif__mdns',
)
idf_py('reconfigure')
data = json.load(open(test_app_copy / 'build' / 'project_description.json'))
assert 'espressif__mdns' in data['build_components']
assert 'example__cmp' not in data['build_components']
def test_cleanup_unused(self, idf_py: IdfPyFunc, test_app_copy: Path, default_idf_env: EnvDict) -> None:
with open(os.path.join(EXT_IDF_PATH, 'tools', 'idf_extra_components.yml'), 'w') as fw:
fw.write(
textwrap.dedent("""
dependencies:
espressif/mdns: "*"
""")
)
_install_root_components(default_idf_env)
idf_py('reconfigure')
data = json.load(open(test_app_copy / 'build' / 'project_description.json'))
assert 'espressif__mdns' in data['all_component_info']
with open(os.path.join(EXT_IDF_PATH, 'tools', 'idf_extra_components.yml'), 'w') as fw:
fw.write(
textwrap.dedent("""
dependencies:
espressif/led_strip: "*"
example/cmp: "*"
""")
)
_install_root_components(default_idf_env)
idf_py('reconfigure')
data = json.load(open(test_app_copy / 'build' / 'project_description.json'))
assert 'espressif__led_strip' in data['all_component_info']
assert 'example__cmp' in data['all_component_info']
assert 'espressif__mdns' not in data['all_component_info']