Merge branch 'fix/failing_custom_cmake_host_win' into 'master'

fix(Tools): failing test_build_custom_cmake_project (Win, MacOS runners)

Closes IDF-12682

See merge request espressif/esp-idf!37932
This commit is contained in:
Marek Fiala
2025-04-16 16:01:23 +08:00
3 changed files with 78 additions and 32 deletions

View File

@@ -90,3 +90,5 @@
- windows - windows
specific_rules: specific_rules:
- if-schedule-test-build-system-windows - if-schedule-test-build-system-windows
patterns:
- build_system

View File

@@ -408,6 +408,8 @@
when: never when: never
- <<: *if-schedule-test-build-system-windows - <<: *if-schedule-test-build-system-windows
- <<: *if-label-windows - <<: *if-label-windows
- <<: *if-dev-push
changes: *patterns-build_system
.rules:test:host_test: .rules:test:host_test:
rules: rules:

View File

@@ -4,70 +4,112 @@ import logging
import os import os
import re import re
import shutil import shutil
import sys
from pathlib import Path from pathlib import Path
from test_build_system_helpers import append_to_file import pytest
from test_build_system_helpers import EnvDict from test_build_system_helpers import EnvDict
from test_build_system_helpers import file_contains
from test_build_system_helpers import IdfPyFunc from test_build_system_helpers import IdfPyFunc
from test_build_system_helpers import append_to_file
from test_build_system_helpers import file_contains
from test_build_system_helpers import run_cmake 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
# 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
@pytest.mark.usefixtures('idf_copy')
def test_build_custom_cmake_project(test_app_copy: Path) -> None: def test_build_custom_cmake_project(test_app_copy: Path) -> None:
# Test is compatible with any target. Random targets in the list are selected for performance reasons # 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'])
for target in ['esp32','esp32c2','esp32c3','esp32c6','esp32h2','esp32p4','esp32s2','esp32s3']: 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}') logging.info(f'Test build ESP-IDF as a library to a custom CMake projects for {target}')
run_cmake_and_build(str(idf_path / 'examples' / 'build_system' / 'cmake' / 'idf_as_lib'), '-G', 'Ninja', run_cmake_and_build(
'-DCMAKE_TOOLCHAIN_FILE={}'.format(idf_path / 'tools' / 'cmake' / f'toolchain-{target}.cmake'), f'-DTARGET={target}') str(idf_path / 'examples' / 'build_system' / 'cmake' / 'idf_as_lib'),
'-G',
'Ninja',
'-DCMAKE_TOOLCHAIN_FILE={}'.format(idf_path / 'tools' / 'cmake' / f'toolchain-{target}.cmake'),
f'-DTARGET={target}',
)
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')
os.remove(idf_path / 'examples' / 'build_system' / 'cmake' / 'idf_as_lib' / 'sdkconfig')
logging.info(f'Test build ESP-IDF as a library to a custom CMake projects for host')
@pytest.mark.skipif(
sys.platform == 'win32',
reason='On Win project is not buildable without system compiler on the host machine. (Win CI runners)',
)
@pytest.mark.usefixtures('idf_copy')
@pytest.mark.usefixtures('test_app_copy')
def test_build_custom_cmake_project_host() -> None:
logging.info('Test build ESP-IDF as a library to a custom CMake projects for host')
idf_path = Path(os.environ['IDF_PATH'])
run_cmake_and_build(str(idf_path / 'examples' / 'build_system' / 'cmake' / 'idf_as_lib'), '-G', 'Ninja') run_cmake_and_build(str(idf_path / 'examples' / 'build_system' / 'cmake' / 'idf_as_lib'), '-G', 'Ninja')
def test_build_cmake_library_psram_workaround(test_app_copy: Path) -> None: def test_build_cmake_library_psram_workaround(test_app_copy: Path) -> None:
logging.info('Building a project with CMake library imported and PSRAM workaround, all files compile with workaround') logging.info(
'Building a project with CMake library imported and PSRAM workaround, all files compile with workaround'
)
idf_path = Path(os.environ['IDF_PATH']) idf_path = Path(os.environ['IDF_PATH'])
(test_app_copy / 'sdkconfig.defaults').write_text('\n'.join(['CONFIG_SPIRAM=y', (test_app_copy / 'sdkconfig.defaults').write_text(
'CONFIG_SPIRAM_CACHE_WORKAROUND=y'])) '\n'.join(['CONFIG_SPIRAM=y', 'CONFIG_SPIRAM_CACHE_WORKAROUND=y'])
run_cmake('-G', 'Ninja', '-DCOMPONENTS=main;esp_psram', )
'-DSDKCONFIG_DEFAULTS={}'.format(test_app_copy / 'sdkconfig.defaults'), run_cmake(
str(idf_path / 'examples' / 'build_system' / 'cmake' / 'import_lib')) '-G',
'Ninja',
'-DCOMPONENTS=main;esp_psram',
'-DSDKCONFIG_DEFAULTS={}'.format(test_app_copy / 'sdkconfig.defaults'),
str(idf_path / 'examples' / 'build_system' / 'cmake' / 'import_lib'),
)
with open((test_app_copy / 'build' / 'compile_commands.json'), 'r', encoding='utf-8') as f: with open((test_app_copy / 'build' / 'compile_commands.json'), 'r', encoding='utf-8') as f:
data = f.read() data = f.read()
res = re.findall(r'.*\"command\".*', data) res = re.findall(r'.*\"command\".*', data)
for r in res: for r in res:
assert 'mfix-esp32-psram-cache-issue' in r, 'All commands in compile_commands.json should use PSRAM cache workaround' assert 'mfix-esp32-psram-cache-issue' in r, (
'All commands in compile_commands.json should use PSRAM cache workaround'
)
def test_build_cmake_library_psram_strategies(idf_py: IdfPyFunc, test_app_copy: Path) -> None: def test_build_cmake_library_psram_strategies(idf_py: IdfPyFunc, test_app_copy: Path) -> None:
for strategy in ['DUPLDST', 'NOPS', 'MEMW']: for strategy in ['DUPLDST', 'NOPS', 'MEMW']:
logging.info(f'Test for external libraries in custom CMake projects with PSRAM strategy {strategy}') logging.info(f'Test for external libraries in custom CMake projects with PSRAM strategy {strategy}')
(test_app_copy / 'sdkconfig.defaults').write_text('\n'.join(['CONFIG_SPIRAM=y', (test_app_copy / 'sdkconfig.defaults').write_text(
f'CONFIG_SPIRAM_CACHE_WORKAROUND_STRATEGY_{strategy}=y', '\n'.join(
'CONFIG_SPIRAM_CACHE_WORKAROUND=y'])) [
'CONFIG_SPIRAM=y',
f'CONFIG_SPIRAM_CACHE_WORKAROUND_STRATEGY_{strategy}=y',
'CONFIG_SPIRAM_CACHE_WORKAROUND=y',
]
)
)
idf_py('reconfigure') idf_py('reconfigure')
with open((test_app_copy / 'build' / 'compile_commands.json'), 'r', encoding='utf-8') as f: with open((test_app_copy / 'build' / 'compile_commands.json'), 'r', encoding='utf-8') as f:
data = f.read() data = f.read()
res = re.findall(r'.*\"command\".*', data) res = re.findall(r'.*\"command\".*', data)
for r in res: for r in res:
assert f'mfix-esp32-psram-cache-strategy={strategy.lower()}' in r, ('All commands in compile_commands.json ' assert f'mfix-esp32-psram-cache-strategy={strategy.lower()}' in r, (
'should use PSRAM cache workaround strategy') 'All commands in compile_commands.json should use PSRAM cache workaround strategy'
)
(test_app_copy / 'sdkconfig').unlink() (test_app_copy / 'sdkconfig').unlink()
def test_defaults_unspecified_build_args(idf_copy: Path) -> None: def test_defaults_unspecified_build_args(idf_copy: Path) -> None:
logging.info('Defaults set properly for unspecified idf_build_process args') logging.info('Defaults set properly for unspecified idf_build_process args')
idf_as_lib_path = idf_copy / 'examples' / 'build_system' / 'cmake' / 'idf_as_lib' idf_as_lib_path = idf_copy / 'examples' / 'build_system' / 'cmake' / 'idf_as_lib'
append_to_file(idf_as_lib_path / 'CMakeLists.txt', '\n'.join(['idf_build_get_property(project_dir PROJECT_DIR)', append_to_file(
'message("Project directory: ${project_dir}")'])) idf_as_lib_path / 'CMakeLists.txt',
ret = run_cmake('..', '-G', 'Ninja', '\n'.join(['idf_build_get_property(project_dir PROJECT_DIR)', 'message("Project directory: ${project_dir}")']),
'-DCMAKE_TOOLCHAIN_FILE={}'.format(str(idf_copy / 'tools' / 'cmake' / 'toolchain-esp32.cmake')), )
'-DTARGET=esp32', ret = run_cmake(
workdir=idf_as_lib_path) '..',
'-G',
'Ninja',
'-DCMAKE_TOOLCHAIN_FILE={}'.format(str(idf_copy / 'tools' / 'cmake' / 'toolchain-esp32.cmake')),
'-DTARGET=esp32',
workdir=idf_as_lib_path,
)
assert 'Project directory: {}'.format(str(idf_as_lib_path.as_posix())) in ret.stderr assert 'Project directory: {}'.format(str(idf_as_lib_path.as_posix())) in ret.stderr
@@ -77,14 +119,14 @@ def test_build_example_on_host(default_idf_env: EnvDict) -> None:
idf_as_lib_path = Path(idf_path, 'examples', 'build_system', 'cmake', 'idf_as_lib') idf_as_lib_path = Path(idf_path, 'examples', 'build_system', 'cmake', 'idf_as_lib')
try: try:
target = 'esp32' target = 'esp32'
run_cmake('..', run_cmake(
f'-DCMAKE_TOOLCHAIN_FILE={idf_path}/tools/cmake/toolchain-{target}.cmake', '..',
f'-DTARGET={target}', f'-DCMAKE_TOOLCHAIN_FILE={idf_path}/tools/cmake/toolchain-{target}.cmake',
'-GNinja', f'-DTARGET={target}',
workdir=idf_as_lib_path) '-GNinja',
workdir=idf_as_lib_path,
)
run_cmake('--build', run_cmake('--build', '.', workdir=idf_as_lib_path)
'.',
workdir=idf_as_lib_path)
finally: finally:
shutil.rmtree(idf_as_lib_path / 'build', ignore_errors=True) shutil.rmtree(idf_as_lib_path / 'build', ignore_errors=True)