diff --git a/tools/cmake/mbed_generate_configuration.cmake b/tools/cmake/mbed_generate_configuration.cmake index 17b5593f12..2cbb6633e7 100644 --- a/tools/cmake/mbed_generate_configuration.cmake +++ b/tools/cmake/mbed_generate_configuration.cmake @@ -27,58 +27,44 @@ else() endif() set(MBED_INTERNAL_LAST_MBED_TARGET "${MBED_TARGET}" CACHE INTERNAL "Previous mbed target this dir was configured with" FORCE) -# Convert all relative paths to absolute paths, rooted at CMAKE_SOURCE_DIR. -# This makes sure that they are interpreted the same way everywhere. -get_filename_component(MBED_APP_JSON_PATH "${MBED_APP_JSON_PATH}" ABSOLUTE BASE_DIR ${CMAKE_SOURCE_DIR}) -get_filename_component(CUSTOM_TARGETS_JSON_PATH "${CUSTOM_TARGETS_JSON_PATH}" ABSOLUTE BASE_DIR ${CMAKE_SOURCE_DIR}) - -# Make it so that if mbed_app.json or custom_targets.json are modified, CMake is rerun. -set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${MBED_APP_JSON_PATH}) -if(EXISTS "${CUSTOM_TARGETS_JSON_PATH}" AND (NOT IS_DIRECTORY "${CUSTOM_TARGETS_JSON_PATH}")) - set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${CUSTOM_TARGETS_JSON_PATH}) -endif() - -# Check if mbed_app.json was modified -# Note: if the path is an empty string, get_filename_component(ABSOLUTE) will convert it to a directory, -# so we have to verify that the path we have is a file, not a dir. -if(EXISTS "${MBED_APP_JSON_PATH}" AND (NOT IS_DIRECTORY "${MBED_APP_JSON_PATH}")) - file(TIMESTAMP "${MBED_APP_JSON_PATH}" MBED_APP_JSON_TIMESTAMP "%s" UTC) -else() - set(MBED_APP_JSON_TIMESTAMP "") -endif() - -if(NOT MBED_NEED_TO_RECONFIGURE) - if(NOT "${MBED_INTERNAL_LAST_MBED_APP_JSON_TIMESTAMP}" STREQUAL "${MBED_APP_JSON_TIMESTAMP}") - message(STATUS "Mbed: mbed_app.json modified, regenerating configs...") - set(MBED_NEED_TO_RECONFIGURE TRUE) - endif() -endif() -set(MBED_INTERNAL_LAST_MBED_APP_JSON_TIMESTAMP "${MBED_APP_JSON_TIMESTAMP}" CACHE INTERNAL "Previous UTC modification timestamp for mbed_app.json" FORCE) - -# Check if custom_targets.json was modified -if(EXISTS "${CUSTOM_TARGETS_JSON_PATH}" AND (NOT IS_DIRECTORY "${CUSTOM_TARGETS_JSON_PATH}")) - file(TIMESTAMP "${CUSTOM_TARGETS_JSON_PATH}" CUSTOM_TARGETS_JSON_TIMESTAMP "%s" UTC) -else() - set(CUSTOM_TARGETS_JSON_TIMESTAMP "") -endif() - -if(NOT MBED_NEED_TO_RECONFIGURE) - if(NOT "${MBED_INTERNAL_LAST_CUSTOM_TARGETS_JSON_TIMESTAMP}" STREQUAL "${CUSTOM_TARGETS_JSON_TIMESTAMP}") - message(STATUS "Mbed: custom_targets.json modified, regenerating configs...") - set(MBED_NEED_TO_RECONFIGURE TRUE) - endif() -endif() - -set(MBED_INTERNAL_LAST_CUSTOM_TARGETS_JSON_TIMESTAMP "${CUSTOM_TARGETS_JSON_TIMESTAMP}" CACHE INTERNAL "Previous UTC modification timestamp for custom_targets.json" FORCE) - # Check if the include file is missing (e.g. because a previous attempt to generate it failed) if(NOT EXISTS ${CMAKE_CURRENT_BINARY_DIR}/mbed_config.cmake) if(NOT MBED_NEED_TO_RECONFIGURE) message(STATUS "Mbed: mbed_config.cmake not found, regenerating configs...") set(MBED_NEED_TO_RECONFIGURE TRUE) endif() +else() + # Include the old version of mbed_config.cmake to get the MBED_CONFIG_JSON_SOURCE_FILES variable used below + include(${CMAKE_CURRENT_BINARY_DIR}/mbed_config.cmake) endif() +# Check timestamps on all JSON files used to generate the Mbed configuration +if(NOT MBED_NEED_TO_RECONFIGURE) + file(TIMESTAMP ${CMAKE_CURRENT_BINARY_DIR}/mbed_config.cmake MBED_CONFIG_CMAKE_TIMESTAMP "%s" UTC) + + foreach(CONFIG_JSON ${MBED_CONFIG_JSON_SOURCE_FILES}) + get_filename_component(CONFIG_JSON_ABSPATH ${CONFIG_JSON} ABSOLUTE) + + if(NOT EXISTS ${CONFIG_JSON_ABSPATH}) + message(STATUS "Mbed: ${CONFIG_JSON} deleted or renamed, regenerating configs...") + set(MBED_NEED_TO_RECONFIGURE TRUE) + break() + endif() + + file(TIMESTAMP ${CONFIG_JSON_ABSPATH} CONFIG_JSON_TIMESTAMP "%s" UTC) + if(${CONFIG_JSON_TIMESTAMP} GREATER ${MBED_CONFIG_CMAKE_TIMESTAMP}) + message(STATUS "Mbed: ${CONFIG_JSON} modified, regenerating configs...") + set(MBED_NEED_TO_RECONFIGURE TRUE) + break() + endif() + endforeach() +endif() + +# Convert all relative paths to absolute paths, rooted at CMAKE_SOURCE_DIR. +# This makes sure that they are interpreted the same way everywhere. +get_filename_component(MBED_APP_JSON_PATH "${MBED_APP_JSON_PATH}" ABSOLUTE BASE_DIR ${CMAKE_SOURCE_DIR}) +get_filename_component(CUSTOM_TARGETS_JSON_PATH "${CUSTOM_TARGETS_JSON_PATH}" ABSOLUTE BASE_DIR ${CMAKE_SOURCE_DIR}) + if(MBED_NEED_TO_RECONFIGURE) # Generate mbed_config.cmake for this target if(EXISTS "${MBED_APP_JSON_PATH}" AND (NOT IS_DIRECTORY "${MBED_APP_JSON_PATH}")) @@ -98,7 +84,7 @@ if(MBED_NEED_TO_RECONFIGURE) set(MBEDTOOLS_CONFIGURE_COMMAND ${Python3_EXECUTABLE} -m mbed_tools.cli.main - -v # without -v, warnings (e.g. "you have tried to override a nonexistent parameter") do not get printed + -v -v # without at least -v, warnings (e.g. "you have tried to override a nonexistent parameter") do not get printed configure -t GCC_ARM # GCC_ARM is currently the only supported toolchain -m "${MBED_TARGET}" @@ -126,4 +112,7 @@ if(MBED_NEED_TO_RECONFIGURE) endif() # Include the generated config file -include(${CMAKE_CURRENT_BINARY_DIR}/mbed_config.cmake) \ No newline at end of file +include(${CMAKE_CURRENT_BINARY_DIR}/mbed_config.cmake) + +# Make it so that if any config JSON files are modified, CMake is rerun. +set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${MBED_CONFIG_JSON_SOURCE_FILES}) \ No newline at end of file diff --git a/tools/python/mbed_tools/build/_internal/cmake_file.py b/tools/python/mbed_tools/build/_internal/cmake_file.py index d6b550bffc..90f5df9826 100644 --- a/tools/python/mbed_tools/build/_internal/cmake_file.py +++ b/tools/python/mbed_tools/build/_internal/cmake_file.py @@ -30,7 +30,11 @@ def render_mbed_config_cmake_template(config: Config, toolchain_name: str, targe env.filters["to_hex"] = to_hex template = env.get_template(TEMPLATE_NAME) config["supported_c_libs"] = [x for x in config["supported_c_libs"][toolchain_name.lower()]] - context = {"target_name": target_name, "toolchain_name": toolchain_name, **config} + + context = {"target_name": target_name, + "toolchain_name": toolchain_name, + "json_sources": config.json_sources, + **config} return template.render(context) diff --git a/tools/python/mbed_tools/build/_internal/config/assemble_build_config.py b/tools/python/mbed_tools/build/_internal/config/assemble_build_config.py index 834dc6989c..34d4e7f106 100644 --- a/tools/python/mbed_tools/build/_internal/config/assemble_build_config.py +++ b/tools/python/mbed_tools/build/_internal/config/assemble_build_config.py @@ -9,12 +9,15 @@ from dataclasses import dataclass from pathlib import Path from typing import Iterable, List, Optional, Set +from setuptools.build_meta import build_editable + +from mbed_tools.project import MbedProgram from mbed_tools.build._internal.config.config import Config from mbed_tools.build._internal.config import source from mbed_tools.build._internal.find_files import LabelFilter, RequiresFilter, filter_files, find_files -def assemble_config(target_attributes: dict, search_paths: Iterable[Path], mbed_app_file: Optional[Path]) -> Config: +def assemble_config(target_attributes: dict, program: MbedProgram) -> Config: """Assemble config for given target and program directory. Mbed library and application specific config parameters are parsed from mbed_lib.json and mbed_app.json files @@ -29,16 +32,36 @@ def assemble_config(target_attributes: dict, search_paths: Iterable[Path], mbed_ Args: target_attributes: Mapping of target specific config parameters. - search_paths: Iterable of paths to search for mbed_lib.json files. - mbed_app_file: The path to mbed_app.json. This can be None. + program: MbedProgram to build the config for """ mbed_lib_files: Set[Path] = set() - for path in search_paths: + for path in [program.root, program.mbed_os.root]: mbed_lib_files.update(find_files("mbed_lib.json", path.absolute().resolve())) mbed_lib_files.update(find_files("mbed_lib.json5", path.absolute().resolve())) - return _assemble_config_from_sources(target_attributes, list(mbed_lib_files), mbed_app_file) + config = _assemble_config_from_sources(target_attributes, list(mbed_lib_files), program.files.app_config_file) + + # Set up the config source path list using the path to every JSON + config.json_sources.extend(mbed_lib_files) + if program.files.app_config_file is not None: + config.json_sources.append(program.files.app_config_file) + config.json_sources.append(program.mbed_os.targets_json_file) + config.json_sources.append(program.mbed_os.cmsis_mcu_descriptions_json_file) + if program.files.custom_targets_json.exists(): + config.json_sources.append(program.files.custom_targets_json) + + # Make all JSON sources relative paths to the program root + def make_relative_if_possible(path: Path): + # Sadly, Pathlib did not gain a better way to do this until newer python versions. + try: + return path.relative_to(program.root) + except ValueError: + return path + + config.json_sources = [make_relative_if_possible(program.root) for json_source in config.json_sources] + + return config def _assemble_config_from_sources( diff --git a/tools/python/mbed_tools/build/_internal/config/config.py b/tools/python/mbed_tools/build/_internal/config/config.py index 946bb74a25..ef10ee0fb9 100644 --- a/tools/python/mbed_tools/build/_internal/config/config.py +++ b/tools/python/mbed_tools/build/_internal/config/config.py @@ -7,6 +7,7 @@ import logging from collections import UserDict from typing import Any, Iterable, Hashable, List +import pathlib from mbed_tools.build._internal.config.source import Override, ConfigSetting @@ -21,6 +22,11 @@ class Config(UserDict): Applies overrides, appends macros, and updates config settings. """ + # List of JSON files used to create this config. Dumped to CMake at the end of configuration + # so that it can regenerate configuration if the JSONs change. + # All paths will be relative to the Mbed program root directory, or absolute if outside said directory. + json_sources: List[pathlib.Path] = [] + def __setitem__(self, key: Hashable, item: Any) -> None: """Set an item based on its key.""" if key == CONFIG_SECTION: diff --git a/tools/python/mbed_tools/build/_internal/templates/mbed_config.tmpl b/tools/python/mbed_tools/build/_internal/templates/mbed_config.tmpl index f358225a2a..384f387bbc 100644 --- a/tools/python/mbed_tools/build/_internal/templates/mbed_config.tmpl +++ b/tools/python/mbed_tools/build/_internal/templates/mbed_config.tmpl @@ -6,13 +6,19 @@ include_guard(GLOBAL) -set(MBED_TOOLCHAIN "{{toolchain_name}}" CACHE STRING "") -set(MBED_TARGET "{{target_name}}" CACHE STRING "") -set(MBED_CPU_CORE "{{core}}" CACHE STRING "") -set(MBED_C_LIB "{{c_lib}}" CACHE STRING "") -set(MBED_PRINTF_LIB "{{printf_lib}}" CACHE STRING "") -set(MBED_OUTPUT_EXT "{{OUTPUT_EXT}}" CACHE STRING "") -set(MBED_GREENTEA_TEST_RESET_TIMEOUT "{{forced_reset_timeout}}" CACHE STRING "") +set(MBED_TOOLCHAIN "{{toolchain_name}}") +set(MBED_CPU_CORE "{{core}}") +set(MBED_C_LIB "{{c_lib}}") +set(MBED_PRINTF_LIB "{{printf_lib}}") +set(MBED_OUTPUT_EXT "{{OUTPUT_EXT}}") +set(MBED_GREENTEA_TEST_RESET_TIMEOUT "{{forced_reset_timeout}}") + +# JSON files used to generate this config. If any of these change, the Python config generation +# scripts must be rerun. +set(MBED_CONFIG_JSON_SOURCE_FILES {% for json_source in json_sources | sort %} + "{{json_source.as_posix()}}" +{%- endfor %} +) list(APPEND MBED_TARGET_SUPPORTED_C_LIBS {% for supported_c_lib in supported_c_libs %} {{supported_c_lib}} diff --git a/tools/python/mbed_tools/build/config.py b/tools/python/mbed_tools/build/config.py index 7c3b7e61a9..e0303c4b47 100644 --- a/tools/python/mbed_tools/build/config.py +++ b/tools/python/mbed_tools/build/config.py @@ -38,7 +38,7 @@ def generate_config(target_name: str, toolchain: str, program: MbedProgram) -> T target_build_attributes = get_target_by_name(target_name, targets_data) incorporate_memory_bank_data_from_cmsis(target_build_attributes, program) config = assemble_config( - target_build_attributes, [program.root, program.mbed_os.root], program.files.app_config_file + target_build_attributes, program ) # Process memory banks and save JSON data for other tools (e.g. memap) to use diff --git a/tools/python/mbed_tools/cli/build.py b/tools/python/mbed_tools/cli/build.py deleted file mode 100644 index 60d2e06db7..0000000000 --- a/tools/python/mbed_tools/cli/build.py +++ /dev/null @@ -1,140 +0,0 @@ -# -# Copyright (c) 2020-2021 Arm Limited and Contributors. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 -# -"""Command to build/compile an Mbed project using CMake.""" -import os -import pathlib -import shutil - -from typing import Optional, Tuple - -import click - -from mbed_tools.build import build_project, generate_build_system, generate_config, flash_binary -from mbed_tools.devices import find_connected_device, find_all_connected_devices -from mbed_tools.project import MbedProgram -from mbed_tools.sterm import terminal - - -@click.command(name="compile", help="Build an Mbed project.") -@click.option( - "-t", - "--toolchain", - type=click.Choice(["ARM", "GCC_ARM"], case_sensitive=False), - required=True, - help="The toolchain you are using to build your app.", -) -@click.option("-m", "--mbed-target", required=True, help="A build target for an Mbed-enabled device, e.g. K64F.") -@click.option("-b", "--profile", default="develop", help="The build type (release, develop or debug).") -@click.option("-c", "--clean", is_flag=True, default=False, help="Perform a clean build.") -@click.option( - "-p", - "--program-path", - default=os.getcwd(), - help="Path to local Mbed program. By default it is the current working directory.", -) -@click.option( - "--mbed-os-path", type=click.Path(), default=None, help="Path to local Mbed OS directory.", -) -@click.option( - "--custom-targets-json", type=click.Path(), default=None, help="Path to custom_targets.json.", -) -@click.option( - "--app-config", type=click.Path(), default=None, help="Path to application configuration file.", -) -@click.option( - "-f", "--flash", is_flag=True, default=False, help="Flash the binary onto a device", -) -@click.option( - "-s", "--sterm", is_flag=True, default=False, help="Launch a serial terminal to the device.", -) -@click.option( - "--baudrate", - default=9600, - show_default=True, - help="Change the serial baud rate (ignored unless --sterm is also given).", -) -def build( - program_path: str, - profile: str, - toolchain: str, - mbed_target: str, - clean: bool, - flash: bool, - sterm: bool, - baudrate: int, - mbed_os_path: str, - custom_targets_json: str, - app_config: str, -) -> None: - """Configure and build an Mbed project using CMake and Ninja. - - If the CMake configuration step has already been run previously (i.e a CMake build tree exists), then just try to - build the project immediately using Ninja. - - Args: - program_path: Path to the Mbed project. - mbed_os_path: The path to the local Mbed OS directory. - profile: The Mbed build profile (debug, develop or release). - custom_targets_json: Path to custom_targets.json. - toolchain: The toolchain to use for the build. - mbed_target: The name of the Mbed target to build for. - app_config: the path to the application configuration file - clean: Perform a clean build. - flash: Flash the binary onto a device. - sterm: Open a serial terminal to the connected target. - baudrate: Change the serial baud rate (ignored unless --sterm is also given). - """ - mbed_target, target_id = _get_target_id(mbed_target) - - cmake_build_subdir = pathlib.Path(mbed_target.upper(), profile.lower(), toolchain.upper()) - if mbed_os_path is None: - program = MbedProgram.from_existing(pathlib.Path(program_path), cmake_build_subdir) - else: - program = MbedProgram.from_existing(pathlib.Path(program_path), cmake_build_subdir, pathlib.Path(mbed_os_path)) - build_tree = program.files.cmake_build_dir - if clean and build_tree.exists(): - shutil.rmtree(build_tree) - - click.echo("Configuring project and generating build system...") - if custom_targets_json is not None: - program.files.custom_targets_json = pathlib.Path(custom_targets_json) - if app_config is not None: - program.files.app_config_file = pathlib.Path(app_config) - config, _ = generate_config(mbed_target.upper(), toolchain, program) - generate_build_system(program.root, build_tree, profile) - - click.echo("Building Mbed project...") - build_project(build_tree) - - if flash or sterm: - if target_id is not None or sterm: - devices = [find_connected_device(mbed_target, target_id)] - else: - devices = find_all_connected_devices(mbed_target) - - if flash: - for dev in devices: - hex_file = "OUTPUT_EXT" in config and config["OUTPUT_EXT"] == "hex" - flashed_path = flash_binary(dev.mount_points[0].resolve(), program.root, build_tree, mbed_target, hex_file) - click.echo(f"Copied {str(flashed_path.resolve())} to {len(devices)} device(s).") - - if sterm: - dev = devices[0] - if dev.serial_port is None: - raise click.ClickException( - f"The connected device {dev.mbed_board.board_name} does not have an associated serial port." - " Reconnect the device and try again." - ) - - terminal.run(dev.serial_port, baudrate) - - -def _get_target_id(target: str) -> Tuple[str, Optional[int]]: - if "[" in target: - target_name, target_id = target.replace("]", "").split("[", maxsplit=1) - if target_id.isdigit() and int(target_id) >= 0: - return (target_name, int(target_id)) - raise click.ClickException("When using the format mbed-target[ID], ID must be a positive integer or 0.") - return (target, None) diff --git a/tools/python/mbed_tools/cli/configure.py b/tools/python/mbed_tools/cli/configure.py index 24b49d81c3..016b7dbfcc 100644 --- a/tools/python/mbed_tools/cli/configure.py +++ b/tools/python/mbed_tools/cli/configure.py @@ -25,8 +25,10 @@ from mbed_tools.build import generate_config help="The toolchain you are using to build your app.", ) @click.option("-m", "--mbed-target", required=True, help="A build target for an Mbed-enabled device, eg. K64F") -@click.option("-b", "--profile", default="develop", help="The build type (release, develop or debug).") -@click.option("-o", "--output-dir", type=click.Path(), default=None, help="Path to output directory.") +@click.option("-o", "--output-dir", + type=click.Path(path_type=pathlib.Path), + required=True, + help="Path to output directory (CMake binary dir)") @click.option( "-p", "--program-path", @@ -43,10 +45,9 @@ from mbed_tools.build import generate_config def configure( toolchain: str, mbed_target: str, - profile: str, program_path: str, mbed_os_path: str, - output_dir: str, + output_dir: pathlib.Path, custom_targets_json: str, app_config: str ) -> None: @@ -63,21 +64,17 @@ def configure( custom_targets_json: the path to custom_targets.json toolchain: the toolchain you are using (eg. GCC_ARM, ARM) mbed_target: the target you are building for (eg. K64F) - profile: The Mbed build profile (debug, develop or release). program_path: the path to the local Mbed program mbed_os_path: the path to the local Mbed OS directory output_dir: the path to the output directory app_config: the path to the application configuration file """ - cmake_build_subdir = pathlib.Path(mbed_target.upper(), profile.lower(), toolchain.upper()) if mbed_os_path is None: - program = MbedProgram.from_existing(pathlib.Path(program_path), cmake_build_subdir) + program = MbedProgram.from_existing(pathlib.Path(program_path), output_dir) else: - program = MbedProgram.from_existing(pathlib.Path(program_path), cmake_build_subdir, pathlib.Path(mbed_os_path)) + program = MbedProgram.from_existing(pathlib.Path(program_path), output_dir, pathlib.Path(mbed_os_path).resolve()) if custom_targets_json is not None: program.files.custom_targets_json = pathlib.Path(custom_targets_json) - if output_dir is not None: - program.files.cmake_build_dir = pathlib.Path(output_dir) if app_config is not None: program.files.app_config_file = pathlib.Path(app_config) diff --git a/tools/python/mbed_tools/cli/main.py b/tools/python/mbed_tools/cli/main.py index c7a32bb0db..5ab21fc329 100644 --- a/tools/python/mbed_tools/cli/main.py +++ b/tools/python/mbed_tools/cli/main.py @@ -15,7 +15,6 @@ from mbed_tools.lib.logging import set_log_level, MbedToolsHandler from mbed_tools.cli.configure import configure from mbed_tools.cli.list_connected_devices import list_connected_devices from mbed_tools.cli.project_management import new, import_, deploy -from mbed_tools.cli.build import build from mbed_tools.cli.sterm import sterm from mbed_tools.cli.cmsis_mcu_descr import cmsis_mcu_descr @@ -78,7 +77,6 @@ cli.add_command(list_connected_devices, "detect") cli.add_command(new, "new") cli.add_command(deploy, "deploy") cli.add_command(import_, "import") -cli.add_command(build, "compile") cli.add_command(sterm, "sterm") cli.add_command(cmsis_mcu_descr) diff --git a/tools/python/mbed_tools/cli/sterm.py b/tools/python/mbed_tools/cli/sterm.py index 30ab31c54c..ec40861b92 100644 --- a/tools/python/mbed_tools/cli/sterm.py +++ b/tools/python/mbed_tools/cli/sterm.py @@ -3,16 +3,24 @@ # SPDX-License-Identifier: Apache-2.0 # """Command to launch a serial terminal to a connected Mbed device.""" -from typing import Any, Optional +from typing import Any, Optional, Tuple import click -from mbed_tools.cli.build import _get_target_id from mbed_tools.devices import find_connected_device, get_connected_devices from mbed_tools.devices.exceptions import MbedDevicesError from mbed_tools.sterm import terminal +def _get_target_id(target: str) -> Tuple[str, Optional[int]]: + if "[" in target: + target_name, target_id = target.replace("]", "").split("[", maxsplit=1) + if target_id.isdigit() and int(target_id) >= 0: + return (target_name, int(target_id)) + raise click.ClickException("When using the format mbed-target[ID], ID must be a positive integer or 0.") + return (target, None) + + @click.command( help="Open a serial terminal to a connected Mbed Enabled device, or connect to a user-specified COM port." ) diff --git a/tools/python/mbed_tools/project/_internal/project_data.py b/tools/python/mbed_tools/project/_internal/project_data.py index e8873b97c1..952521659c 100644 --- a/tools/python/mbed_tools/project/_internal/project_data.py +++ b/tools/python/mbed_tools/project/_internal/project_data.py @@ -99,12 +99,12 @@ class MbedProgramFiles: ) @classmethod - def from_existing(cls, root_path: Path, build_subdir: Path) -> "MbedProgramFiles": + def from_existing(cls, root_path: Path, build_dir: Path) -> "MbedProgramFiles": """Create MbedProgramFiles from a directory containing an existing program. Args: root_path: The path containing the MbedProgramFiles. - build_subdir: The subdirectory of BUILD_DIR to use for CMake build. + build_dir: The directory to use for CMake build. """ app_config: Optional[Path] = None if (root_path / APP_CONFIG_FILE_NAME_JSON5).exists(): @@ -126,13 +126,12 @@ class MbedProgramFiles: cmakelists_file = root_path / CMAKELISTS_FILE_NAME if not cmakelists_file.exists(): logger.warning("No CMakeLists.txt found in the program root.") - cmake_build_dir = root_path / BUILD_DIR / build_subdir return cls( app_config_file=app_config, mbed_os_ref=mbed_os_file, cmakelists_file=cmakelists_file, - cmake_build_dir=cmake_build_dir, + cmake_build_dir=build_dir, custom_targets_json=custom_targets_json, ) diff --git a/tools/python/mbed_tools/project/mbed_program.py b/tools/python/mbed_tools/project/mbed_program.py index c3a95362fe..cca36f356f 100644 --- a/tools/python/mbed_tools/project/mbed_program.py +++ b/tools/python/mbed_tools/project/mbed_program.py @@ -4,6 +4,7 @@ # """Mbed Program abstraction layer.""" import logging +import pathlib from pathlib import Path from typing import Dict @@ -29,7 +30,7 @@ class MbedProgram: * A collection of references to external libraries, defined in .lib files located in the program source tree """ - def __init__(self, program_files: MbedProgramFiles, mbed_os: MbedOS) -> None: + def __init__(self, program_files: MbedProgramFiles, mbed_os: MbedOS, root_path: pathlib.Path) -> None: """Initialise the program attributes. Args: @@ -37,7 +38,7 @@ class MbedProgram: mbed_os: An instance of `MbedOS` holding paths to locations in the local copy of the Mbed OS source. """ self.files = program_files - self.root = self.files.mbed_os_ref.parent + self.root = root_path self.mbed_os = mbed_os @classmethod @@ -63,17 +64,17 @@ class MbedProgram: program_files = MbedProgramFiles.from_new(dir_path) logger.info(f"Creating git repository for the Mbed program '{dir_path}'") mbed_os = MbedOS.from_new(dir_path / MBED_OS_DIR_NAME) - return cls(program_files, mbed_os) + return cls(program_files, mbed_os, dir_path) @classmethod def from_existing( - cls, dir_path: Path, build_subdir: Path, mbed_os_path: Path = None, check_mbed_os: bool = True, + cls, dir_path: Path, build_dir: Path, mbed_os_path: Path = None, check_mbed_os: bool = True, ) -> "MbedProgram": """Create an MbedProgram from an existing program directory. Args: dir_path: Directory containing an Mbed program. - build_subdir: The subdirectory for the CMake build tree. + build_dir: The directory for the CMake build tree. mbed_os_path: Directory containing Mbed OS. check_mbed_os: If True causes an exception to be raised if the Mbed OS source directory does not exist. @@ -88,7 +89,7 @@ class MbedProgram: program_root = dir_path logger.info(f"Found existing Mbed program at path '{program_root}'") - program = MbedProgramFiles.from_existing(program_root, build_subdir) + program = MbedProgramFiles.from_existing(program_root, build_dir) try: mbed_os = MbedOS.from_existing(mbed_os_path, check_mbed_os) @@ -98,7 +99,7 @@ class MbedProgram: "\nYou may need to resolve the mbed-os.lib reference. You can do this by performing a `deploy`." ) - return cls(program, mbed_os) + return cls(program, mbed_os, program_root) def parse_url(name_or_url: str) -> Dict[str, str]: diff --git a/tools/python/python_tests/mbed_tools/cli/test_build.py b/tools/python/python_tests/mbed_tools/cli/test_build.py deleted file mode 100644 index bb6b70aa96..0000000000 --- a/tools/python/python_tests/mbed_tools/cli/test_build.py +++ /dev/null @@ -1,338 +0,0 @@ -# -# Copyright (c) 2020-2021 Arm Limited and Contributors. All rights reserved. -# SPDX-License-Identifier: Apache-2.0 -# -import contextlib -import os -import pathlib - -from tempfile import TemporaryDirectory -from unittest import TestCase, mock - -from click.testing import CliRunner - -import sys -print(sys.path) - -from mbed_tools.cli.build import build -from mbed_tools.project._internal.project_data import BUILD_DIR -from mbed_tools.build.config import CMAKE_CONFIG_FILE - - -DEFAULT_BUILD_ARGS = ["-t", "GCC_ARM", "-m", "K64F"] -DEFAULT_BUILD_SUBDIR = pathlib.Path("K64F", "develop", "GCC_ARM") - - -@contextlib.contextmanager -def mock_project_directory( - program, mbed_config_exists=False, build_tree_exists=False, build_subdir=DEFAULT_BUILD_SUBDIR -): - with TemporaryDirectory() as tmp_dir: - root = pathlib.Path(tmp_dir, "test-project") - root.mkdir() - program.root = root - program.files.cmake_build_dir = root / BUILD_DIR / build_subdir - program.files.cmake_config_file = root / BUILD_DIR / build_subdir / CMAKE_CONFIG_FILE - if mbed_config_exists: - program.files.cmake_config_file.parent.mkdir(exist_ok=True, parents=True) - program.files.cmake_config_file.touch(exist_ok=True) - - if build_tree_exists: - program.files.cmake_build_dir.mkdir(exist_ok=True, parents=True) - - yield - - -@mock.patch("mbed_tools.cli.build.generate_build_system") -@mock.patch("mbed_tools.cli.build.build_project") -@mock.patch("mbed_tools.cli.build.MbedProgram") -@mock.patch("mbed_tools.cli.build.generate_config") -class TestBuildCommand(TestCase): - def test_searches_for_mbed_program_at_default_project_path( - self, generate_config, mbed_program, build_project, generate_build_system - ): - runner = CliRunner() - runner.invoke(build, DEFAULT_BUILD_ARGS) - - mbed_program.from_existing.assert_called_once_with(pathlib.Path(os.getcwd()), DEFAULT_BUILD_SUBDIR) - - def test_searches_for_mbed_program_at_user_defined_project_root( - self, generate_config, mbed_program, build_project, generate_build_system - ): - project_path = "my-blinky" - - runner = CliRunner() - runner.invoke(build, ["-p", project_path, *DEFAULT_BUILD_ARGS]) - - mbed_program.from_existing.assert_called_once_with(pathlib.Path(project_path), DEFAULT_BUILD_SUBDIR) - - def test_calls_generate_build_system_if_build_tree_nonexistent( - self, generate_config, mbed_program, build_project, generate_build_system - ): - program = mbed_program.from_existing() - with mock_project_directory(program, mbed_config_exists=True, build_tree_exists=False): - generate_config.return_value = [mock.MagicMock(), mock.MagicMock()] - - runner = CliRunner() - runner.invoke(build, DEFAULT_BUILD_ARGS) - - generate_build_system.assert_called_once_with(program.root, program.files.cmake_build_dir, "develop") - - def test_generate_config_called_if_config_script_nonexistent( - self, generate_config, mbed_program, build_project, generate_build_system - ): - program = mbed_program.from_existing() - with mock_project_directory( - program, mbed_config_exists=False, build_subdir=pathlib.Path("K64F", "develop", "GCC_ARM") - ): - target = "k64f" - toolchain = "gcc_arm" - - runner = CliRunner() - runner.invoke(build, ["-t", toolchain, "-m", target]) - - generate_config.assert_called_once_with(target.upper(), toolchain.upper(), program) - - def test_raises_if_gen_config_toolchain_not_passed_when_required( - self, generate_config, mbed_program, build_project, generate_build_system - ): - program = mbed_program.from_existing() - with mock_project_directory(program, mbed_config_exists=False): - target = "k64f" - - runner = CliRunner() - result = runner.invoke(build, ["-m", target]) - - self.assertIsNotNone(result.exception) - self.assertRegex(result.output, "--toolchain") - - def test_raises_if_gen_config_target_not_passed_when_required( - self, generate_config, mbed_program, build_project, generate_build_system - ): - program = mbed_program.from_existing() - with mock_project_directory(program, mbed_config_exists=False): - toolchain = "gcc_arm" - - runner = CliRunner() - result = runner.invoke(build, ["-t", toolchain]) - - self.assertIsNotNone(result.exception) - self.assertRegex(result.output, "--mbed-target") - - def test_raises_if_target_identifier_not_int( - self, generate_config, mbed_program, build_project, generate_build_system - ): - target = "K64F[foo]" - - result = CliRunner().invoke(build, ["-m", target, "-t", "gcc_arm"]) - self.assertIsNotNone(result.exception) - self.assertRegex(result.output, "ID") - - def test_raises_if_target_identifier_negative( - self, generate_config, mbed_program, build_project, generate_build_system - ): - target = "K64F[-1]" - - result = CliRunner().invoke(build, ["-m", target, "-t", "gcc_arm"]) - self.assertIsNotNone(result.exception) - self.assertRegex(result.output, "ID") - - def test_build_system_regenerated_when_mbed_os_path_passed( - self, generate_config, mbed_program, build_project, generate_build_system - ): - program = mbed_program.from_existing() - with mock_project_directory( - program, - mbed_config_exists=True, - build_tree_exists=True, - build_subdir=pathlib.Path("K64F", "develop", "GCC_ARM"), - ): - generate_config.return_value = [mock.MagicMock(), mock.MagicMock()] - - toolchain = "gcc_arm" - target = "k64f" - mbed_os_path = "./extern/mbed-os" - - runner = CliRunner() - runner.invoke(build, ["-t", toolchain, "-m", target, "--mbed-os-path", mbed_os_path]) - - generate_config.assert_called_once_with(target.upper(), toolchain.upper(), program) - generate_build_system.assert_called_once_with(program.root, program.files.cmake_build_dir, "develop") - - def test_custom_targets_location_used_when_passed( - self, generate_config, mbed_program, build_project, generate_build_system - ): - program = mbed_program.from_existing() - with mock_project_directory(program, mbed_config_exists=True, build_tree_exists=True): - toolchain = "gcc_arm" - target = "k64f" - custom_targets_json_path = pathlib.Path("custom", "custom_targets.json") - - runner = CliRunner() - runner.invoke(build, ["-t", toolchain, "-m", target, "--custom-targets-json", custom_targets_json_path]) - - generate_config.assert_called_once_with(target.upper(), toolchain.upper(), program) - self.assertEqual(program.files.custom_targets_json, custom_targets_json_path) - - def test_app_config_used_when_passed( - self, generate_config, mbed_program, build_project, generate_build_system - ): - program = mbed_program.from_existing() - with mock_project_directory(program, mbed_config_exists=True, build_tree_exists=True): - toolchain = "gcc_arm" - target = "k64f" - app_config_path = pathlib.Path("alternative_config.json") - - runner = CliRunner() - runner.invoke(build, ["-t", toolchain, "-m", target, "--app-config", app_config_path]) - - generate_config.assert_called_once_with(target.upper(), toolchain.upper(), program) - self.assertEqual(program.files.app_config_file, app_config_path) - - def test_profile_used_when_passed( - self, generate_config, mbed_program, build_project, generate_build_system - ): - program = mbed_program.from_existing() - mbed_program.reset_mock() # clear call count from previous line - - with mock_project_directory(program, mbed_config_exists=True, build_tree_exists=True): - generate_config.return_value = [mock.MagicMock(), mock.MagicMock()] - - toolchain = "gcc_arm" - target = "k64f" - profile = "release" - - runner = CliRunner() - runner.invoke(build, ["-t", toolchain, "-m", target, "--profile", profile]) - - mbed_program.from_existing.assert_called_once_with( - pathlib.Path(os.getcwd()), - pathlib.Path(target.upper(), profile, toolchain.upper()) - ) - generate_config.assert_called_once_with(target.upper(), toolchain.upper(), program) - generate_build_system.assert_called_once_with(program.root, program.files.cmake_build_dir, profile) - - def test_build_folder_removed_when_clean_flag_passed( - self, generate_config, mbed_program, build_project, generate_build_system - ): - program = mbed_program.from_existing() - with mock_project_directory( - program, - mbed_config_exists=True, - build_tree_exists=True, - build_subdir=pathlib.Path("K64F", "develop", "GCC_ARM"), - ): - generate_config.return_value = [mock.MagicMock(), mock.MagicMock()] - - toolchain = "gcc_arm" - target = "k64f" - - runner = CliRunner() - runner.invoke(build, ["-t", toolchain, "-m", target, "-c"]) - - generate_config.assert_called_once_with(target.upper(), toolchain.upper(), program) - generate_build_system.assert_called_once_with(program.root, program.files.cmake_build_dir, "develop") - self.assertFalse(program.files.cmake_build_dir.exists()) - - @mock.patch("mbed_tools.cli.build.flash_binary") - @mock.patch("mbed_tools.cli.build.find_all_connected_devices") - def test_build_flash_options_bin_target( - self, - mock_find_devices, - flash_binary, - generate_config, - mbed_program, - build_project, - generate_build_system, - ): - # A target with bin images does not need OUTPUT_EXT defined - generate_config.return_value = [mock.MagicMock(), mock.MagicMock()] - mock_find_devices.return_value = [mock.MagicMock()] - runner = CliRunner() - runner.invoke(build, ["--flash", *DEFAULT_BUILD_ARGS]) - call_args = flash_binary.call_args - args, kwargs = call_args - flash_binary.assert_called_once_with(args[0], args[1], args[2], args[3], False) - - @mock.patch("mbed_tools.cli.build.flash_binary") - @mock.patch("mbed_tools.cli.build.find_all_connected_devices") - def test_build_flash_options_hex_target( - self, - mock_find_devices, - flash_binary, - generate_config, - mbed_program, - build_project, - generate_build_system, - ): - generate_config.return_value = [{"OUTPUT_EXT": "hex"}, mock.MagicMock()] - mock_find_devices.return_value = [mock.MagicMock()] - runner = CliRunner() - runner.invoke(build, ["--flash", *DEFAULT_BUILD_ARGS]) - call_args = flash_binary.call_args - args, kwargs = call_args - flash_binary.assert_called_once_with(args[0], args[1], args[2], args[3], True) - - @mock.patch("mbed_tools.cli.build.flash_binary") - @mock.patch("mbed_tools.cli.build.find_all_connected_devices") - def test_build_flash_both_two_devices( - self, - mock_find_devices, - flash_binary, - generate_config, - mbed_program, - build_project, - generate_build_system, - ): - generate_config.return_value = [mock.MagicMock(), mock.MagicMock()] - mock_find_devices.return_value = [mock.MagicMock(), mock.MagicMock()] - runner = CliRunner() - runner.invoke(build, ["--flash", *DEFAULT_BUILD_ARGS]) - self.assertEqual(flash_binary.call_count, 2) - - @mock.patch("mbed_tools.cli.build.flash_binary") - @mock.patch("mbed_tools.cli.build.find_connected_device") - def test_build_flash_only_identifier_device( - self, - mock_find_device, - flash_binary, - generate_config, - mbed_program, - build_project, - generate_build_system, - ): - generate_config.return_value = [mock.MagicMock(), mock.MagicMock()] - mock_find_device.return_value = mock.MagicMock() - runner = CliRunner() - runner.invoke(build, ["--flash", "-m", "K64F[1]", "-t", "GCC_ARM"]) - self.assertEqual(flash_binary.call_count, 1) - - @mock.patch("mbed_tools.cli.build.terminal") - @mock.patch("mbed_tools.cli.build.find_connected_device") - def test_sterm_is_started_when_flag_passed( - self, mock_find_device, mock_terminal, generate_config, mbed_program, build_project, generate_build_system - ): - target = "K64F" - serial_port = "tty.k64f" - baud = 115200 - mock_find_device.return_value = mock.Mock(serial_port=serial_port) - generate_config.return_value = [mock.MagicMock(), mock.MagicMock()] - - CliRunner().invoke(build, ["-m", target, "-t", "gcc_arm", "--sterm", "--baudrate", baud]) - - mock_find_device.assert_called_once_with(target, None) - mock_terminal.run.assert_called_once_with(serial_port, baud) - - @mock.patch("mbed_tools.cli.build.terminal") - @mock.patch("mbed_tools.cli.build.find_connected_device") - def test_raises_if_device_does_not_have_serial_port_and_sterm_flag_given( - self, mock_find_device, mock_terminal, generate_config, mbed_program, build_project, generate_build_system - ): - target = "K64F" - serial_port = None - mock_find_device.return_value = mock.Mock(serial_port=serial_port) - generate_config.return_value = [mock.MagicMock(), mock.MagicMock()] - - output = CliRunner().invoke(build, ["-m", target, "-t", "gcc_arm", "--sterm"]) - self.assertEqual(type(output.exception), SystemExit) - mock_terminal.assert_not_called() diff --git a/tools/python/python_tests/mbed_tools/cli/test_configure.py b/tools/python/python_tests/mbed_tools/cli/test_configure.py index 0483e99c01..43ade6acb1 100644 --- a/tools/python/python_tests/mbed_tools/cli/test_configure.py +++ b/tools/python/python_tests/mbed_tools/cli/test_configure.py @@ -15,14 +15,14 @@ class TestConfigureCommand(TestCase): @mock.patch("mbed_tools.cli.configure.generate_config") @mock.patch("mbed_tools.cli.configure.MbedProgram") def test_generate_config_called_with_correct_arguments(self, program, generate_config): - CliRunner().invoke(configure, ["-m", "k64f", "-t", "gcc_arm"]) + CliRunner().invoke(configure, ["-m", "k64f", "-t", "gcc_arm", "-o", "some_output_dir"]) generate_config.assert_called_once_with("K64F", "GCC_ARM", program.from_existing()) @mock.patch("mbed_tools.cli.configure.generate_config") @mock.patch("mbed_tools.cli.configure.MbedProgram") def test_generate_config_called_with_mbed_os_path(self, program, generate_config): - CliRunner().invoke(configure, ["-m", "k64f", "-t", "gcc_arm", "--mbed-os-path", "./extern/mbed-os"]) + CliRunner().invoke(configure, ["-m", "k64f", "-t", "gcc_arm", "--mbed-os-path", "./extern/mbed-os", "-o", "some_output_dir"]) generate_config.assert_called_once_with("K64F", "GCC_ARM", program.from_existing()) @@ -32,29 +32,19 @@ class TestConfigureCommand(TestCase): program = program.from_existing() custom_targets_json_path = pathlib.Path("custom", "custom_targets.json") CliRunner().invoke( - configure, ["-t", "gcc_arm", "-m", "k64f", "--custom-targets-json", custom_targets_json_path] + configure, ["-t", "gcc_arm", "-m", "k64f", "--custom-targets-json", custom_targets_json_path, "-o", "some_output_dir"] ) generate_config.assert_called_once_with("K64F", "GCC_ARM", program) self.assertEqual(program.files.custom_targets_json, custom_targets_json_path) - @mock.patch("mbed_tools.cli.configure.generate_config") - @mock.patch("mbed_tools.cli.configure.MbedProgram") - def test_custom_output_directory_used_when_passed(self, program, generate_config): - program = program.from_existing() - output_dir = pathlib.Path("build") - CliRunner().invoke(configure, ["-t", "gcc_arm", "-m", "k64f", "-o", output_dir]) - - generate_config.assert_called_once_with("K64F", "GCC_ARM", program) - self.assertEqual(program.files.cmake_build_dir, output_dir) - @mock.patch("mbed_tools.cli.configure.generate_config") @mock.patch("mbed_tools.cli.configure.MbedProgram") def test_app_config_used_when_passed(self, program, generate_config): program = program.from_existing() app_config_path = pathlib.Path("alternative_config.json") CliRunner().invoke( - configure, ["-t", "gcc_arm", "-m", "k64f", "--app-config", app_config_path] + configure, ["-t", "gcc_arm", "-m", "k64f", "--app-config", app_config_path, "-o", "some_output_dir"] ) generate_config.assert_called_once_with("K64F", "GCC_ARM", program) @@ -62,20 +52,19 @@ class TestConfigureCommand(TestCase): @mock.patch("mbed_tools.cli.configure.generate_config") @mock.patch("mbed_tools.cli.configure.MbedProgram") - def test_profile_used_when_passed(self, program, generate_config): + def test_output_dir_passed(self, program, generate_config): test_program = program.from_existing() program.reset_mock() # clear call count from previous line toolchain = "gcc_arm" target = "k64f" - profile = "release" CliRunner().invoke( - configure, ["-t", toolchain, "-m", target, "--profile", profile] + configure, ["-t", toolchain, "-m", target, "-o", "some_output_dir"] ) program.from_existing.assert_called_once_with( pathlib.Path("."), - pathlib.Path(target.upper(), profile, toolchain.upper()) + pathlib.Path("some_output_dir") ) generate_config.assert_called_once_with("K64F", "GCC_ARM", test_program) diff --git a/tools/python/python_tests/mbed_tools/project/test_mbed_program.py b/tools/python/python_tests/mbed_tools/project/test_mbed_program.py index 50eb17cbf4..69945d10f0 100644 --- a/tools/python/python_tests/mbed_tools/project/test_mbed_program.py +++ b/tools/python/python_tests/mbed_tools/project/test_mbed_program.py @@ -10,7 +10,7 @@ import pytest from mbed_tools.project import MbedProgram from mbed_tools.project.exceptions import ExistingProgram, ProgramNotFound, MbedOSNotFound from mbed_tools.project.mbed_program import _find_program_root, parse_url -from mbed_tools.project._internal.project_data import MbedProgramFiles +from mbed_tools.project._internal.project_data import MbedProgramFiles, BUILD_DIR from python_tests.mbed_tools.project.factories import make_mbed_program_files, make_mbed_os_files @@ -40,7 +40,7 @@ class TestInitialiseProgram: program = from_new_set_target_toolchain(program_root) - assert program.files == MbedProgramFiles.from_existing(program_root, DEFAULT_BUILD_SUBDIR) + assert program.files == MbedProgramFiles.from_existing(program_root, program_root / BUILD_DIR / DEFAULT_BUILD_SUBDIR) def test_from_new_local_dir_generates_valid_program_creating_directory_in_cwd(self, tmp_path): old_cwd = os.getcwd() @@ -52,7 +52,7 @@ class TestInitialiseProgram: program = from_new_set_target_toolchain(program_root) - assert program.files == MbedProgramFiles.from_existing(program_root, DEFAULT_BUILD_SUBDIR) + assert program.files == MbedProgramFiles.from_existing(program_root, program_root / BUILD_DIR / DEFAULT_BUILD_SUBDIR) finally: os.chdir(old_cwd) @@ -64,7 +64,7 @@ class TestInitialiseProgram: program = from_new_set_target_toolchain(program_root) - assert program.files == MbedProgramFiles.from_existing(program_root, DEFAULT_BUILD_SUBDIR) + assert program.files == MbedProgramFiles.from_existing(program_root, program_root / BUILD_DIR / DEFAULT_BUILD_SUBDIR) def test_from_existing_raises_if_path_is_not_a_program(self, tmp_path): fs_root = pathlib.Path(tmp_path, "foo") @@ -72,21 +72,21 @@ class TestInitialiseProgram: program_root = fs_root / "programfoo" with pytest.raises(ProgramNotFound): - MbedProgram.from_existing(program_root, DEFAULT_BUILD_SUBDIR) + MbedProgram.from_existing(program_root, program_root / BUILD_DIR / DEFAULT_BUILD_SUBDIR) def test_from_existing_raises_if_no_mbed_os_dir_found_and_check_mbed_os_is_true(self, tmp_path): fs_root = pathlib.Path(tmp_path, "foo") make_mbed_program_files(fs_root) with pytest.raises(MbedOSNotFound): - MbedProgram.from_existing(fs_root, DEFAULT_BUILD_SUBDIR, check_mbed_os=True) + MbedProgram.from_existing(fs_root, fs_root / BUILD_DIR / DEFAULT_BUILD_SUBDIR, check_mbed_os=True) def test_from_existing_returns_valid_program(self, tmp_path): fs_root = pathlib.Path(tmp_path, "foo") make_mbed_program_files(fs_root) make_mbed_os_files(fs_root / "mbed-os") - program = MbedProgram.from_existing(fs_root, DEFAULT_BUILD_SUBDIR) + program = MbedProgram.from_existing(fs_root, fs_root / BUILD_DIR / DEFAULT_BUILD_SUBDIR) assert program.files.app_config_file.exists() assert program.mbed_os.root.exists() @@ -98,7 +98,7 @@ class TestInitialiseProgram: make_mbed_program_files(fs_root) make_mbed_os_files(mbed_os_path) - program = MbedProgram.from_existing(fs_root, DEFAULT_BUILD_SUBDIR, mbed_os_path) + program = MbedProgram.from_existing(fs_root, fs_root / BUILD_DIR / DEFAULT_BUILD_SUBDIR, mbed_os_path) assert program.files.app_config_file.exists() assert program.mbed_os.root.exists() diff --git a/tools/python/python_tests/mbed_tools/regression/test_configure.py b/tools/python/python_tests/mbed_tools/regression/test_configure.py index 859bea9705..eabb93111f 100644 --- a/tools/python/python_tests/mbed_tools/regression/test_configure.py +++ b/tools/python/python_tests/mbed_tools/regression/test_configure.py @@ -53,8 +53,9 @@ class TestConfigureRegression(TestCase): pathlib.Path(tmpDirPath / "mbed-os" / "targets").mkdir() pathlib.Path(tmpDirPath / "mbed-os" / "targets" / "targets.json5").write_text(target_json) pathlib.Path(tmpDirPath / "mbed-os" / "targets" / "cmsis_mcu_descriptions.json5").write_text("{}") + pathlib.Path(tmpDirPath / "cmake-build-debug").mkdir() result = CliRunner().invoke( - configure, ["-m", "Target", "-t", "gcc_arm", "-p", tmpDir], catch_exceptions=False + configure, ["-m", "Target", "-t", "gcc_arm", "-p", tmpDir, "-o", str(tmpDirPath / "cmake-build-debug")], catch_exceptions=False ) self.assertIn("mbed_config.cmake has been generated and written to", result.output)