ci(tools): Changed the approach of some build tests to cmake reconfigure

Where actually building the app is not needed cmake reconfigure was introduced instead.
This should be performance upgrade especially for Windows runners, where build is quite slow
This commit is contained in:
Jakub Kocka
2026-01-23 10:58:43 +01:00
parent 82cc3b55b6
commit 7551e82048
5 changed files with 43 additions and 40 deletions
+1 -1
View File
@@ -146,7 +146,7 @@ pytest_buildv2_system_win:
extends: extends:
- .test_build_system_template_win - .test_build_system_template_win
- .rules:labels:buildv2 - .rules:labels:buildv2
parallel: 2 parallel: 10
needs: needs:
- job: manual_gate - job: manual_gate
optional: true optional: true
+2 -1
View File
@@ -47,7 +47,8 @@ def _create_idf_copy_via_worktree(path_from: Path, path_to: Path) -> str:
""" """
import uuid import uuid
branch_name = f'test-worktree-{uuid.uuid4().hex[:8]}' timestamp = datetime.datetime.now().strftime('%H%M%S')
branch_name = f'test-worktree-{timestamp}-{uuid.uuid4().hex[:8]}'
logging.debug(f'creating git worktree at {path_to} (branch: {branch_name})') logging.debug(f'creating git worktree at {path_to} (branch: {branch_name})')
subprocess.run( subprocess.run(
+29 -28
View File
@@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD # SPDX-FileCopyrightText: 2022-2026 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0 # SPDX-License-Identifier: Apache-2.0
import logging import logging
import os import os
@@ -17,6 +17,7 @@ from test_build_system_helpers import append_to_file
from test_build_system_helpers import file_contains from test_build_system_helpers import file_contains
from test_build_system_helpers import get_idf_build_env from test_build_system_helpers import get_idf_build_env
from test_build_system_helpers import replace_in_file from test_build_system_helpers import replace_in_file
from test_build_system_helpers import run_cmake
from test_build_system_helpers import run_cmake_and_build from test_build_system_helpers import run_cmake_and_build
@@ -28,23 +29,22 @@ def assert_built(paths: list[str] | list[Path]) -> None:
def test_build_alternative_directories(idf_py: IdfPyFunc, func_work_dir: Path, test_app_copy: Path) -> None: def test_build_alternative_directories(idf_py: IdfPyFunc, func_work_dir: Path, test_app_copy: Path) -> None:
logging.info('Moving BUILD_DIR_BASE out of tree') logging.info('Moving BUILD_DIR_BASE out of tree')
alt_build_dir = func_work_dir / 'alt_build' alt_build_dir = func_work_dir / 'alt_build'
try: # Use reconfigure instead of full build - we're testing directory placement, not compilation
idf_py('-B', str(alt_build_dir), 'build') idf_py('-B', str(alt_build_dir), 'reconfigure')
assert os.listdir(alt_build_dir) != [], 'No files found in new build directory!' assert os.listdir(alt_build_dir) != [], 'No files found in new build directory!'
default_build_dir = test_app_copy / 'build' assert (alt_build_dir / 'CMakeCache.txt').exists(), 'CMakeCache.txt not found in alt build directory!'
if default_build_dir.exists(): default_build_dir = test_app_copy / 'build'
assert os.listdir(default_build_dir) == [], ( if default_build_dir.exists():
f'Some files were incorrectly put into the default build directory: {default_build_dir}' assert os.listdir(default_build_dir) == [], (
) f'Some files were incorrectly put into the default build directory: {default_build_dir}'
except Exception: )
raise shutil.rmtree(alt_build_dir)
else:
shutil.rmtree(alt_build_dir)
logging.info('BUILD_DIR_BASE inside default build directory') logging.info('BUILD_DIR_BASE inside default build directory')
build_subdir_inside_build_dir = default_build_dir / 'subdirectory' build_subdir_inside_build_dir = default_build_dir / 'subdirectory'
idf_py('-B', str(build_subdir_inside_build_dir), 'build') idf_py('-B', str(build_subdir_inside_build_dir), 'reconfigure')
assert os.listdir(build_subdir_inside_build_dir) != [], 'No files found in new build directory!' assert os.listdir(build_subdir_inside_build_dir) != [], 'No files found in new build directory!'
assert (build_subdir_inside_build_dir / 'CMakeCache.txt').exists(), 'CMakeCache.txt not found in subdirectory!'
@pytest.mark.usefixtures('test_app_copy') @pytest.mark.usefixtures('test_app_copy')
@@ -84,30 +84,31 @@ def test_build_with_generator_makefile(idf_py: IdfPyFunc) -> None:
def test_build_with_cmake_and_idf_path_unset(idf_py: IdfPyFunc, test_app_copy: Path) -> None: def test_build_with_cmake_and_idf_path_unset(idf_py: IdfPyFunc, test_app_copy: Path) -> None:
# This test verifies CMake configuration works with various IDF_PATH setups.
# We use run_cmake (configure only) instead of full builds for speed.
idf_path = Path(os.environ['IDF_PATH']) idf_path = Path(os.environ['IDF_PATH'])
env = get_idf_build_env(idf_path) env = get_idf_build_env(idf_path)
env.pop('IDF_PATH') env.pop('IDF_PATH')
build_dir = test_app_copy / 'build'
logging.info('Can build with IDF_PATH set via cmake cache not environment') logging.info('Can configure with IDF_PATH set via cmake cache not environment')
replace_in_file('CMakeLists.txt', 'ENV{IDF_PATH}', '{IDF_PATH}') replace_in_file('CMakeLists.txt', 'ENV{IDF_PATH}', '{IDF_PATH}')
run_cmake_and_build('-G', 'Ninja', '..', f'-DIDF_PATH={idf_path}', env=env) run_cmake('-G', 'Ninja', '..', f'-DIDF_PATH={idf_path}', env=env)
assert_built(BOOTLOADER_BINS + APP_BINS + PARTITION_BIN) assert (build_dir / 'CMakeCache.txt').exists(), 'CMake configuration failed'
idf_py('fullclean') shutil.rmtree(build_dir)
logging.info('Can build with IDF_PATH unset and inferred by cmake when Kconfig needs it to be set') logging.info('Can configure with IDF_PATH unset and inferred by cmake when Kconfig needs it to be set')
# working with already changed CMakeLists.txt
kconfig_file = test_app_copy / 'main' / 'Kconfig.projbuild' kconfig_file = test_app_copy / 'main' / 'Kconfig.projbuild'
kconfig_file.write_text('source "$IDF_PATH/examples/wifi/getting_started/station/main/Kconfig.projbuild"') kconfig_file.write_text('source "$IDF_PATH/examples/wifi/getting_started/station/main/Kconfig.projbuild"')
run_cmake_and_build('-G', 'Ninja', '..', f'-DIDF_PATH={idf_path}', env=env) run_cmake('-G', 'Ninja', '..', f'-DIDF_PATH={idf_path}', env=env)
assert_built(BOOTLOADER_BINS + APP_BINS + PARTITION_BIN) assert (build_dir / 'CMakeCache.txt').exists(), 'CMake configuration failed'
kconfig_file.unlink() # remove file to not affect following sub-test kconfig_file.unlink()
idf_py('fullclean') shutil.rmtree(build_dir)
logging.info('Can build with IDF_PATH unset and inferred by build system') logging.info('Can configure with IDF_PATH unset and inferred by build system')
# replacing {IDF_PATH} not ENV{IDF_PATH} since CMakeLists.txt was already changed in this test
replace_in_file('CMakeLists.txt', '{IDF_PATH}', '{ci_idf_path}') replace_in_file('CMakeLists.txt', '{IDF_PATH}', '{ci_idf_path}')
run_cmake_and_build('-G', 'Ninja', '-D', f'ci_idf_path={idf_path}', '..', env=env) run_cmake('-G', 'Ninja', '-D', f'ci_idf_path={idf_path}', '..', env=env)
assert_built(BOOTLOADER_BINS + APP_BINS + PARTITION_BIN) assert (build_dir / 'CMakeCache.txt').exists(), 'CMake configuration failed'
def test_build_skdconfig_phy_init_data(idf_py: IdfPyFunc, test_app_copy: Path) -> None: def test_build_skdconfig_phy_init_data(idf_py: IdfPyFunc, test_app_copy: Path) -> None:
+10 -9
View File
@@ -19,11 +19,10 @@ from test_build_system_helpers import run_cmake_and_build
from test_build_system_helpers import run_idf_py from test_build_system_helpers import run_idf_py
# This test checks multiple targets in one test function. It would be better to have each target # This test verifies ESP-IDF can be used as a library in custom CMake projects.
# tested in a isolated test case, but that would mean doing idf_copy each time, and copying takes most of the time # We use cmake configure only (not full build) and test representative targets from each arch.
@pytest.mark.usefixtures('idf_copy') @pytest.mark.usefixtures('idf_copy')
def test_build_custom_cmake_project(test_app_copy: Path, request: pytest.FixtureRequest) -> None: def test_build_custom_cmake_project(test_app_copy: Path, request: pytest.FixtureRequest) -> None:
# Test is compatible with any target. Random targets in the list are selected for performance reasons
idf_path = Path(os.environ['IDF_PATH']) idf_path = Path(os.environ['IDF_PATH'])
is_buildv2 = request.config.getoption('buildv2', False) is_buildv2 = request.config.getoption('buildv2', False)
if is_buildv2: if is_buildv2:
@@ -35,9 +34,11 @@ def test_build_custom_cmake_project(test_app_copy: Path, request: pytest.Fixture
base_cmake_args = ['-G', 'Ninja'] base_cmake_args = ['-G', 'Ninja']
target_var = 'TARGET' target_var = 'TARGET'
for target in ['esp32', 'esp32c2', 'esp32c3', 'esp32c6', 'esp32h2', 'esp32p4', 'esp32s2', 'esp32s3']: # Test representative targets: Xtensa (esp32), RISC-V (esp32c3), and newest (esp32p4)
logging.info(f'Test build ESP-IDF as a library to a custom CMake projects for {target}') for target in ['esp32', 'esp32c3', 'esp32p4']:
run_cmake_and_build( logging.info(f'Test CMake configuration of ESP-IDF as a library for {target}')
# Use run_cmake (configure only) - compile_commands.json is generated during configure
run_cmake(
str(idf_as_lib_path), str(idf_as_lib_path),
*base_cmake_args, *base_cmake_args,
'-DCMAKE_TOOLCHAIN_FILE={}'.format(idf_path / 'tools' / 'cmake' / f'toolchain-{target}.cmake'), '-DCMAKE_TOOLCHAIN_FILE={}'.format(idf_path / 'tools' / 'cmake' / f'toolchain-{target}.cmake'),
@@ -45,9 +46,9 @@ def test_build_custom_cmake_project(test_app_copy: Path, request: pytest.Fixture
) )
assert file_contains((test_app_copy / 'build' / 'compile_commands.json'), '"command"') assert file_contains((test_app_copy / 'build' / 'compile_commands.json'), '"command"')
shutil.rmtree(test_app_copy / 'build') shutil.rmtree(test_app_copy / 'build')
sdkconfig_path = idf_as_lib_path / 'sdkconfig' sdkconfig = idf_as_lib_path / 'sdkconfig'
if sdkconfig_path.exists(): if sdkconfig.exists():
os.remove(sdkconfig_path) sdkconfig.unlink()
@pytest.mark.skipif( @pytest.mark.skipif(
+1 -1
View File
@@ -82,7 +82,7 @@ def test_spaces_bundle3(idf_copy: Path) -> None:
def test_spaces_bundle4(dummy_: str, idf_py: IdfPyFunc, test_app_copy: Path) -> None: def test_spaces_bundle4(dummy_: str, idf_py: IdfPyFunc, test_app_copy: Path) -> None:
logging.info(f'Running test spaces bundle 4 in {test_app_copy}') logging.info(f'Running test spaces bundle 4 in {test_app_copy}')
(test_app_copy / 'sdkconfig').write_text('CONFIG_APP_REPRODUCIBLE_BUILD=y') (test_app_copy / 'sdkconfig').write_text('CONFIG_APP_REPRODUCIBLE_BUILD=y')
idf_py('reconfigure') idf_py('build')
(test_app_copy / 'sdkconfig').unlink() (test_app_copy / 'sdkconfig').unlink()
idf_py('set-target', 'esp32s2') idf_py('set-target', 'esp32s2')