diff --git a/.gitlab/ci/test-win.yml b/.gitlab/ci/test-win.yml index a3a2c3950f..59f0166e5a 100644 --- a/.gitlab/ci/test-win.yml +++ b/.gitlab/ci/test-win.yml @@ -146,7 +146,7 @@ pytest_buildv2_system_win: extends: - .test_build_system_template_win - .rules:labels:buildv2 - parallel: 2 + parallel: 10 needs: - job: manual_gate optional: true diff --git a/tools/test_build_system/conftest.py b/tools/test_build_system/conftest.py index 6720a2abe7..1640e84774 100644 --- a/tools/test_build_system/conftest.py +++ b/tools/test_build_system/conftest.py @@ -47,7 +47,8 @@ def _create_idf_copy_via_worktree(path_from: Path, path_to: Path) -> str: """ 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})') subprocess.run( diff --git a/tools/test_build_system/test_build.py b/tools/test_build_system/test_build.py index 2f88c97f12..ef6f0d1c79 100644 --- a/tools/test_build_system/test_build.py +++ b/tools/test_build_system/test_build.py @@ -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 import logging 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 get_idf_build_env 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 @@ -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: logging.info('Moving BUILD_DIR_BASE out of tree') alt_build_dir = func_work_dir / 'alt_build' - try: - idf_py('-B', str(alt_build_dir), 'build') - assert os.listdir(alt_build_dir) != [], 'No files found in new build directory!' - default_build_dir = test_app_copy / 'build' - if default_build_dir.exists(): - assert os.listdir(default_build_dir) == [], ( - f'Some files were incorrectly put into the default build directory: {default_build_dir}' - ) - except Exception: - raise - else: - shutil.rmtree(alt_build_dir) + # Use reconfigure instead of full build - we're testing directory placement, not compilation + idf_py('-B', str(alt_build_dir), 'reconfigure') + assert os.listdir(alt_build_dir) != [], 'No files found in new build directory!' + assert (alt_build_dir / 'CMakeCache.txt').exists(), 'CMakeCache.txt not found in alt build directory!' + default_build_dir = test_app_copy / 'build' + if default_build_dir.exists(): + assert os.listdir(default_build_dir) == [], ( + f'Some files were incorrectly put into the default build directory: {default_build_dir}' + ) + shutil.rmtree(alt_build_dir) logging.info('BUILD_DIR_BASE inside default build directory') 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 (build_subdir_inside_build_dir / 'CMakeCache.txt').exists(), 'CMakeCache.txt not found in subdirectory!' @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: + # 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']) env = get_idf_build_env(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}') - run_cmake_and_build('-G', 'Ninja', '..', f'-DIDF_PATH={idf_path}', env=env) - assert_built(BOOTLOADER_BINS + APP_BINS + PARTITION_BIN) - idf_py('fullclean') + run_cmake('-G', 'Ninja', '..', f'-DIDF_PATH={idf_path}', env=env) + assert (build_dir / 'CMakeCache.txt').exists(), 'CMake configuration failed' + shutil.rmtree(build_dir) - logging.info('Can build with IDF_PATH unset and inferred by cmake when Kconfig needs it to be set') - # working with already changed CMakeLists.txt + logging.info('Can configure with IDF_PATH unset and inferred by cmake when Kconfig needs it to be set') kconfig_file = test_app_copy / '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) - assert_built(BOOTLOADER_BINS + APP_BINS + PARTITION_BIN) - kconfig_file.unlink() # remove file to not affect following sub-test - idf_py('fullclean') + run_cmake('-G', 'Ninja', '..', f'-DIDF_PATH={idf_path}', env=env) + assert (build_dir / 'CMakeCache.txt').exists(), 'CMake configuration failed' + kconfig_file.unlink() + shutil.rmtree(build_dir) - logging.info('Can build 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 + logging.info('Can configure with IDF_PATH unset and inferred by build system') 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) - assert_built(BOOTLOADER_BINS + APP_BINS + PARTITION_BIN) + run_cmake('-G', 'Ninja', '-D', f'ci_idf_path={idf_path}', '..', env=env) + assert (build_dir / 'CMakeCache.txt').exists(), 'CMake configuration failed' def test_build_skdconfig_phy_init_data(idf_py: IdfPyFunc, test_app_copy: Path) -> None: diff --git a/tools/test_build_system/test_cmake.py b/tools/test_build_system/test_cmake.py index 5c881c803c..2917babe40 100644 --- a/tools/test_build_system/test_cmake.py +++ b/tools/test_build_system/test_cmake.py @@ -19,11 +19,10 @@ from test_build_system_helpers import run_cmake_and_build 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 -# tested in a isolated test case, but that would mean doing idf_copy each time, and copying takes most of the time +# This test verifies ESP-IDF can be used as a library in custom CMake projects. +# We use cmake configure only (not full build) and test representative targets from each arch. @pytest.mark.usefixtures('idf_copy') 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']) is_buildv2 = request.config.getoption('buildv2', False) 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'] target_var = 'TARGET' - for target in ['esp32', 'esp32c2', 'esp32c3', 'esp32c6', 'esp32h2', 'esp32p4', 'esp32s2', 'esp32s3']: - logging.info(f'Test build ESP-IDF as a library to a custom CMake projects for {target}') - run_cmake_and_build( + # Test representative targets: Xtensa (esp32), RISC-V (esp32c3), and newest (esp32p4) + for target in ['esp32', 'esp32c3', 'esp32p4']: + 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), *base_cmake_args, '-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"') shutil.rmtree(test_app_copy / 'build') - sdkconfig_path = idf_as_lib_path / 'sdkconfig' - if sdkconfig_path.exists(): - os.remove(sdkconfig_path) + sdkconfig = idf_as_lib_path / 'sdkconfig' + if sdkconfig.exists(): + sdkconfig.unlink() @pytest.mark.skipif( diff --git a/tools/test_build_system/test_spaces.py b/tools/test_build_system/test_spaces.py index 8ef2895031..438bb4853b 100644 --- a/tools/test_build_system/test_spaces.py +++ b/tools/test_build_system/test_spaces.py @@ -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: logging.info(f'Running test spaces bundle 4 in {test_app_copy}') (test_app_copy / 'sdkconfig').write_text('CONFIG_APP_REPRODUCIBLE_BUILD=y') - idf_py('reconfigure') + idf_py('build') (test_app_copy / 'sdkconfig').unlink() idf_py('set-target', 'esp32s2')