From 29b3d640f15c9d664da1615bacefd67342645283 Mon Sep 17 00:00:00 2001 From: Jamie Smith Date: Sat, 1 Nov 2025 19:09:12 -0700 Subject: [PATCH 01/21] Start on using pydantic schemas. mbed_lib.json schema working! --- cmsis/device/rtos/mbed_lib.json | 1 - connectivity/FEATURE_BLE/mbed_lib.json | 1 - .../FEATURE_BLE/TARGET_STM32WB/mbed_lib.json | 3 +- .../lora/COMPONENT_SX126X/mbed_lib.json | 1 - .../lora/COMPONENT_SX1272/mbed_lib.json | 1 - .../lora/COMPONENT_SX1276/mbed_lib.json | 1 - .../drivers/lora/TARGET_STM32WL/mbed_lib.json | 1 - connectivity/lorawan/mbed_lib.json | 1 - .../nanostack/mbed-mesh-api/mbed_lib.json | 1 - connectivity/nanostack/mbed_lib.json | 3 +- .../mbed_lib.json | 1 - .../sal-stack-nanostack/mbed_lib.json | 1 - connectivity/netsocket/mbed_lib.json5 | 1 - events/mbed_lib.json | 1 - .../cy_rtos_rtx_adapter/mbed_lib.json | 5 +- .../TARGET_MBED_PSA_SRV/mbed_lib.json | 11 +- platform/bare_metal/mbed_lib.json | 3 +- platform/mbed-trace/mbed_lib.json | 2 +- rtos/mbed_lib.json | 5 +- storage/filesystem/mbed_lib.json | 5 +- .../kv_config/filesystem_no_rbp/mbed_lib.json | 38 ---- .../kvstore/kvstore_global_api/mbed_lib.json | 3 +- tools/pyproject.toml | 7 +- .../_internal/config/assemble_build_config.py | 2 +- .../build/_internal/config/config.py | 3 +- .../build/_internal/config/schemas.py | 132 +++++++++++++ .../build/_internal/config/source.py | 179 ++++++++++++++++-- tools/python/mbed_tools/lib/json_helpers.py | 20 +- 28 files changed, 328 insertions(+), 105 deletions(-) delete mode 100644 storage/kvstore/kv_config/filesystem_no_rbp/mbed_lib.json create mode 100644 tools/python/mbed_tools/build/_internal/config/schemas.py diff --git a/cmsis/device/rtos/mbed_lib.json b/cmsis/device/rtos/mbed_lib.json index e9a70296984..338dfcb14e0 100644 --- a/cmsis/device/rtos/mbed_lib.json +++ b/cmsis/device/rtos/mbed_lib.json @@ -1,7 +1,6 @@ { "name": "rtos", "config": { - "present": 1, "main-thread-stack-size": { "help": "The size of the main thread's stack", "value": 4096 diff --git a/connectivity/FEATURE_BLE/mbed_lib.json b/connectivity/FEATURE_BLE/mbed_lib.json index 2d1b11ef40d..e6398909770 100644 --- a/connectivity/FEATURE_BLE/mbed_lib.json +++ b/connectivity/FEATURE_BLE/mbed_lib.json @@ -1,6 +1,5 @@ { "name": "ble", - "requires": ["ble-api-implementation"], "config": { "present": 1, "ble-role-observer": { diff --git a/connectivity/drivers/ble/FEATURE_BLE/TARGET_STM32WB/mbed_lib.json b/connectivity/drivers/ble/FEATURE_BLE/TARGET_STM32WB/mbed_lib.json index 13d17bcf083..b0c80f5002a 100644 --- a/connectivity/drivers/ble/FEATURE_BLE/TARGET_STM32WB/mbed_lib.json +++ b/connectivity/drivers/ble/FEATURE_BLE/TARGET_STM32WB/mbed_lib.json @@ -1,4 +1,3 @@ { - "name": "cordio-stm32wb", - "requires": ["cordio", "ble"] + "name": "cordio-stm32wb" } diff --git a/connectivity/drivers/lora/COMPONENT_SX126X/mbed_lib.json b/connectivity/drivers/lora/COMPONENT_SX126X/mbed_lib.json index 5e068ea0525..fbee95cf4a6 100644 --- a/connectivity/drivers/lora/COMPONENT_SX126X/mbed_lib.json +++ b/connectivity/drivers/lora/COMPONENT_SX126X/mbed_lib.json @@ -1,6 +1,5 @@ { "name": "SX126X-lora-driver", - "requires": ["lora"], "config": { "spi-frequency": { "help": "SPI frequency, Default: 16 MHz", diff --git a/connectivity/drivers/lora/COMPONENT_SX1272/mbed_lib.json b/connectivity/drivers/lora/COMPONENT_SX1272/mbed_lib.json index 824c71ee964..7182de340aa 100644 --- a/connectivity/drivers/lora/COMPONENT_SX1272/mbed_lib.json +++ b/connectivity/drivers/lora/COMPONENT_SX1272/mbed_lib.json @@ -1,6 +1,5 @@ { "name": "sx1272-lora-driver", - "requires": ["lora"], "config": { "spi-frequency": { "help": "SPI frequency, Default: 8 MHz", diff --git a/connectivity/drivers/lora/COMPONENT_SX1276/mbed_lib.json b/connectivity/drivers/lora/COMPONENT_SX1276/mbed_lib.json index 82bbf8a02df..0033945bece 100644 --- a/connectivity/drivers/lora/COMPONENT_SX1276/mbed_lib.json +++ b/connectivity/drivers/lora/COMPONENT_SX1276/mbed_lib.json @@ -1,6 +1,5 @@ { "name": "sx1276-lora-driver", - "requires": ["lora"], "config": { "spi-frequency": { "help": "SPI frequency, Default: 8 MHz", diff --git a/connectivity/drivers/lora/TARGET_STM32WL/mbed_lib.json b/connectivity/drivers/lora/TARGET_STM32WL/mbed_lib.json index e8faccd63ed..4389f908eec 100644 --- a/connectivity/drivers/lora/TARGET_STM32WL/mbed_lib.json +++ b/connectivity/drivers/lora/TARGET_STM32WL/mbed_lib.json @@ -1,6 +1,5 @@ { "name": "stm32wl-lora-driver", - "requires": ["lora"], "config": { "buffer-size": { "help": "Max. buffer size the radio can handle, Default: 255 B", diff --git a/connectivity/lorawan/mbed_lib.json b/connectivity/lorawan/mbed_lib.json index 576f4092afd..d8e0bbff7bc 100644 --- a/connectivity/lorawan/mbed_lib.json +++ b/connectivity/lorawan/mbed_lib.json @@ -1,6 +1,5 @@ { "name": "lora", - "requires": ["mbedtls", "events"], "config": { "phy": { "help": "LoRa PHY region: EU868, AS923, AU915, CN470, CN779, EU433, IN865, KR920, US915", diff --git a/connectivity/nanostack/mbed-mesh-api/mbed_lib.json b/connectivity/nanostack/mbed-mesh-api/mbed_lib.json index e053940ec26..871f41d5000 100644 --- a/connectivity/nanostack/mbed-mesh-api/mbed_lib.json +++ b/connectivity/nanostack/mbed-mesh-api/mbed_lib.json @@ -1,6 +1,5 @@ { "name": "mbed-mesh-api", - "requires": ["nanostack"], "config": { "heap-size": { "help": "Nanostack's heap size [bytes: 0-4294967295]", diff --git a/connectivity/nanostack/mbed_lib.json b/connectivity/nanostack/mbed_lib.json index 2761bfd407c..5c9a05cd6b3 100644 --- a/connectivity/nanostack/mbed_lib.json +++ b/connectivity/nanostack/mbed_lib.json @@ -1,4 +1,3 @@ { - "name": "nanostack-interface", - "requires": ["nanostack"] + "name": "nanostack-interface" } diff --git a/connectivity/nanostack/sal-stack-nanostack-eventloop/mbed_lib.json b/connectivity/nanostack/sal-stack-nanostack-eventloop/mbed_lib.json index 25a93630146..a56cdb50306 100644 --- a/connectivity/nanostack/sal-stack-nanostack-eventloop/mbed_lib.json +++ b/connectivity/nanostack/sal-stack-nanostack-eventloop/mbed_lib.json @@ -1,6 +1,5 @@ { "name": "nanostack-eventloop", - "requires": ["nanostack-hal"], "config": { "use_platform_tick_timer": { "help": "Use platform provided low resolution tick timer for eventloop", diff --git a/connectivity/nanostack/sal-stack-nanostack/mbed_lib.json b/connectivity/nanostack/sal-stack-nanostack/mbed_lib.json index ce65c8a038a..c397fa2075a 100644 --- a/connectivity/nanostack/sal-stack-nanostack/mbed_lib.json +++ b/connectivity/nanostack/sal-stack-nanostack/mbed_lib.json @@ -1,6 +1,5 @@ { "name": "nanostack", - "requires": ["nanostack-eventloop", "coap-service"], "config": { "configuration": { "help": "Build time configuration. Refer to Handbook for valid values. Default: full stack", diff --git a/connectivity/netsocket/mbed_lib.json5 b/connectivity/netsocket/mbed_lib.json5 index bc2f091410c..3efa3cc9f64 100644 --- a/connectivity/netsocket/mbed_lib.json5 +++ b/connectivity/netsocket/mbed_lib.json5 @@ -1,7 +1,6 @@ { "name": "nsapi", "config": { - "present": 1, "add-event-listener-return-change": { "help": "Updates the add_event_listener to return a nsapi_error_t value which can indicate allocation failure. See documents for more details.", "value": 0 diff --git a/events/mbed_lib.json b/events/mbed_lib.json index cf9f6594038..2c19bbe254d 100644 --- a/events/mbed_lib.json +++ b/events/mbed_lib.json @@ -1,7 +1,6 @@ { "name": "events", "config": { - "present": 1, "shared-stacksize": { "help": "Stack size (bytes) for shared event queue thread", "value": 2048 diff --git a/features/frameworks/cy_rtos_rtx_adapter/mbed_lib.json b/features/frameworks/cy_rtos_rtx_adapter/mbed_lib.json index ad5352e440c..8b010b98701 100644 --- a/features/frameworks/cy_rtos_rtx_adapter/mbed_lib.json +++ b/features/frameworks/cy_rtos_rtx_adapter/mbed_lib.json @@ -1,6 +1,3 @@ { - "name": "cy_psoc6csp_rtos", - "config": { - "present": 1 - } + "name": "cy_psoc6csp_rtos" } diff --git a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbed_lib.json b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbed_lib.json index e8e50477234..d575d571f0e 100644 --- a/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbed_lib.json +++ b/platform/FEATURE_EXPERIMENTAL_API/FEATURE_PSA/TARGET_MBED_PSA_SRV/mbed_lib.json @@ -1,12 +1,3 @@ { - "name": "psa-services", - "requires": [ - "drivers", - "platform", - "mbedtls", - "storage", - "flashiap-block-device", - "kv-global-api", - "storage_tdb_internal" - ] + "name": "psa-services" } diff --git a/platform/bare_metal/mbed_lib.json b/platform/bare_metal/mbed_lib.json index e85a309c2f2..7bacdab6b2e 100644 --- a/platform/bare_metal/mbed_lib.json +++ b/platform/bare_metal/mbed_lib.json @@ -1,4 +1,3 @@ { - "name": "bare-metal", - "requires": ["platform", "drivers", "rtos-api", "mbed-trace", "blockdevice"] + "name": "bare-metal" } diff --git a/platform/mbed-trace/mbed_lib.json b/platform/mbed-trace/mbed_lib.json index 6a078dc8066..4c7e8b7c333 100644 --- a/platform/mbed-trace/mbed_lib.json +++ b/platform/mbed-trace/mbed_lib.json @@ -20,7 +20,7 @@ }, "color-theme": { "help": "Set color theme. 0 for readable, 1 for unobtrusive.", - "options": [0, 1], + "accepted_values": [0, 1], "macro_name": "MBED_TRACE_COLOR_THEME", "value": 0 }, diff --git a/rtos/mbed_lib.json b/rtos/mbed_lib.json index 43fb3abb77b..d7fb31e5c3f 100644 --- a/rtos/mbed_lib.json +++ b/rtos/mbed_lib.json @@ -1,6 +1,3 @@ { - "name": "rtos-api", - "config": { - "present": 1 - } + "name": "rtos-api" } diff --git a/storage/filesystem/mbed_lib.json b/storage/filesystem/mbed_lib.json index e53bc85fe23..3c8aaf77331 100644 --- a/storage/filesystem/mbed_lib.json +++ b/storage/filesystem/mbed_lib.json @@ -1,6 +1,3 @@ { - "name": "filesystem", - "config": { - "present": 1 - } + "name": "filesystem" } diff --git a/storage/kvstore/kv_config/filesystem_no_rbp/mbed_lib.json b/storage/kvstore/kv_config/filesystem_no_rbp/mbed_lib.json deleted file mode 100644 index d75560099c6..00000000000 --- a/storage/kvstore/kv_config/filesystem_no_rbp/mbed_lib.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "name": "storage_filesystem_no_rbp", - "config": { - "WARNING": { - "help": "DEPRECATION WARNING: storage_filesystem_no_rbp does not work and will be removed in the future", - "value": null - }, - "filesystem": { - "help": "Options are default, FAT or LITTLE. If default value the filesystem is chosen by the blockdevice type", - "value": "default" - }, - "blockdevice": { - "help": "Options are default, SPIF, DATAFLASH, QSPIF, SD or other. If default the block device will be chosen by the defined component. If other, override get_other_blockdevice() to support block device out of Mbed OS tree.", - "value": "default" - }, - "external_size": { - "help": "Size in bytes of the external block device, if default the maximum size available is used.", - "value": "0" - }, - "external_base_address": { - "help": "The default will set start address to address 0", - "value": "0" - }, - "mount_point": { - "help": "Where to mount the filesystem.", - "value": "kv" - }, - "folder_path": { - "help": "Path for the working directory where the FileSystemStore stores the data", - "value": "kvstore" - } - }, - "target_overrides": { - "CY_EXTERNAL_WIFI_FW": { - "blockdevice": "other" - } - } -} diff --git a/storage/kvstore/kvstore_global_api/mbed_lib.json b/storage/kvstore/kvstore_global_api/mbed_lib.json index b44d08c2e6b..7facc6b0dc8 100644 --- a/storage/kvstore/kvstore_global_api/mbed_lib.json +++ b/storage/kvstore/kvstore_global_api/mbed_lib.json @@ -1,4 +1,3 @@ { - "name": "kv-global-api", - "requires": ["kvstore"] + "name": "kv-global-api" } diff --git a/tools/pyproject.toml b/tools/pyproject.toml index 6e1b0ec7c97..f7eb1b61433 100644 --- a/tools/pyproject.toml +++ b/tools/pyproject.toml @@ -27,9 +27,14 @@ dependencies = [ "typing-extensions", "pyserial", "appdirs", - "pyjson5>=1.6", "humanize>=4.9.0", "setuptools>=64.0", + "pydantic>=2.5", # note: 2.5 is the last version that supports python3.7 + + # We need two JSON5 parsers because 'json5' is slow as hell, but 'pyjson5' has completely inscrutable + # error messages when parsing fails. Combining them produces a decent experience. + "pyjson5>=1.6", + "json5>=0.10", # Needed for downloading CMSIS MCU descriptions "cmsis-pack-manager>=0.5.0", 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 79e2bd360e1..c7d6595914a 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 @@ -84,7 +84,7 @@ def _assemble_config_from_sources( while previous_filter_data != current_filter_data: filtered_files = _filter_files(mbed_lib_files, current_filter_data) for config_file in filtered_files: - config.update(source.from_file(config_file, target_filters=current_filter_data.labels)) + config.update(source.from_mbed_lib_json_file(config_file, target_filters=current_filter_data.labels)) # Remove any mbed_lib files we've already visited from the list so we don't parse them multiple times. mbed_lib_files.remove(config_file) diff --git a/tools/python/mbed_tools/build/_internal/config/config.py b/tools/python/mbed_tools/build/_internal/config/config.py index 5fd5fcea6f0..76e405823f1 100644 --- a/tools/python/mbed_tools/build/_internal/config/config.py +++ b/tools/python/mbed_tools/build/_internal/config/config.py @@ -53,7 +53,7 @@ def _handle_overrides(self, overrides: Iterable[Override]) -> None: _apply_override(self.data, override) continue - setting = next( + setting: ConfigSetting = next( filter( lambda x: x.name == override.name and x.namespace == override.namespace, self.data.get(CONFIG_SECTION, []), @@ -81,6 +81,7 @@ def _handle_overrides(self, overrides: Iterable[Override]) -> None: ) else: setting.value = override.value + setting.check_value() def _update_config_section(self, config_settings: List[ConfigSetting]) -> None: for setting in config_settings: diff --git a/tools/python/mbed_tools/build/_internal/config/schemas.py b/tools/python/mbed_tools/build/_internal/config/schemas.py new file mode 100644 index 00000000000..674efb4d16e --- /dev/null +++ b/tools/python/mbed_tools/build/_internal/config/schemas.py @@ -0,0 +1,132 @@ +# +# Copyright (c) 2025 Jamie Smith +# SPDX-License-Identifier: Apache-2.0 +# + +""" +Pydantic schemas for Mbed OS JSON config files. +""" + +from __future__ import annotations + +from typing import Union, Self + +from pydantic import BaseModel, Field, model_validator + +ConfigSettingValue = Union[int | float | bool | str | None] + + +class ConfigEntryDetails(BaseModel): + """ + Details for an entry in a JSON file's 'config' section. This defines the attributes of a configurable setting + for a library, target, or application. + """ + + macro_name: str | None = None + """ + Name of the macro that this setting shall generate. If unset, defaults to + 'MBED_CONF__' + """ + + value: ConfigSettingValue = None + """ Default value for this setting when not overridden. """ + + help: str | None = None + """ Documentation associated with this setting. """ + + accepted_values: list[ConfigSettingValue] | None = None + """ + Enumeration of legal values for this setting. A warning will be issued if the setting is set to + a value not in this list. + """ + + value_max: int | float | None = None + """ + For integer or floating point values, this gives the maximum allowed value. + """ + + value_min: int | float | None = None + """ + For integer or floating point values, this gives the minimum allowed value. + """ + + @model_validator(mode="after") + def verify_max_min(self) -> Self: + if self.accepted_values is not None and (self.value_max is not None or self.value_min is not None): + raise ValueError("May not specify both 'accepted_values' and 'value_min'/'value_max' at the same time!") + + if self.value_max is not None and self.value_min is not None: + if self.value_max < self.value_min: + raise ValueError("value_max cannot be less than value_min!") + + return self + + +class MbedLibJSON(BaseModel): + """ + Schema for an mbed_lib.json5 config file. + This type of config file provides information about a library (inside or outside the Mbed OS source tree) + to the Mbed configuration system. + """ + + name: str + """ + The name of this library. This is also considered the 'namespace' and will be prepended to all + configuration settings generated by this file. + """ + + config: dict[str, ConfigSettingValue | ConfigEntryDetails] = Field(default_factory=dict) + """ + Configuration items for this library. These can be defined directly as "name": default value, or as + "name": {details...} (see _ConfigEntryDetails above). Using details is recommended as it allows + adding documentation for the setting. + + By convention, the name used for a configuration setting should be in skewer-case and should not contain + periods, underscores, or uppercase letters. + """ + + macros: list[str] | None = None + """ + List of macros to unconditionally define when this lib is included, in "NAME" or "NAME=VALUE" format. + """ + + overrides: dict[str, ConfigSettingValue] = Field(default_factory=dict) + """ + List of overrides to unconditionally apply when this lib is included. + + Overrides take the form "[.]": and cause the value of the given config + setting to be changed to the given value. If the namespace is omitted, it will be set to the current + namespace. + + Note that in mbed_lib.json files, only settings defined in the current file or in the 'app' namespace + (mbed_app.json) can be overridden. + + Override priority is defined as first mbed_app.json5, then mbed_lib.json5 files, then targets.json5. + So, for example, an override defined in mbed_app.json5 supersedes any other overrides of that + same setting. + + Override order between different mbed_lib.json5 files is not currently defined but should not matter + because they cannot override settings from targets.json5 or other mbed_lib.json5 files. + """ + + target_overrides: dict[str, dict[str, ConfigSettingValue]] = Field(default_factory=dict) + """ + List of overrides applied based on target labels. This is similar to the "overrides" section, + but allows applying the override only if the target has a specific label. Labels generally + come from the names of the target and its parents, but targets can also add extra ones. + For example: + + "target_overrides": { + "MIMXRT105X": { + "some-setting": some-value + } + } + + would apply the override only for targets in the MIMXRT105X target family. + + The magic target label "*" is always true and is equivalent to using the "overrides" section. + + Also note that the override priority between different sections within target_overrides, and between + target_overrides and overrides, is not currently defined. So, if you override the same setting in both, + results may not be what you expect. + """ diff --git a/tools/python/mbed_tools/build/_internal/config/source.py b/tools/python/mbed_tools/build/_internal/config/source.py index f0b538b8da5..5d2aada193d 100644 --- a/tools/python/mbed_tools/build/_internal/config/source.py +++ b/tools/python/mbed_tools/build/_internal/config/source.py @@ -8,12 +8,16 @@ import pathlib from dataclasses import dataclass -from typing import Iterable, Any, Optional, List +from typing import Iterable, Any, Optional, List, Literal + +import pydantic from mbed_tools.lib.json_helpers import decode_json_file from mbed_tools.build.exceptions import InvalidConfigOverride from mbed_tools.lib.python_helpers import flatten_nested +from . import schemas + logger = logging.getLogger(__name__) @@ -61,6 +65,118 @@ def prepare( return data +def _check_config_name(file_path: pathlib.Path, config_name: str) -> None: + """ + Issue a warning if a config name is not recommended to be used. + """ + if config_name.lower() != config_name: + logger.warning( + f"Config setting '{config_name}' in file {file_path} contains uppercase letters. This style is not recommended." + ) + if "." in config_name: + logger.warning( + f"Config setting '{config_name}' in file {file_path} contains a period. This style is not recommended as it may cause confusion with the config namespace name." + ) + if "_" in config_name: + logger.warning( + f"Config setting '{config_name}' in file {file_path} contains an underscore. This style is not recommended as it may cause confusion (config names should be in skewer-case). Underscores will be replaced by hyphens when Mbed processes JSON settings." + ) + + +def from_mbed_lib_json_file( + mbed_lib_json_path: pathlib.Path, target_filters: Iterable[str] +) -> dict[str, list | str | dict]: + """ + Prepare a config source for entry into the Config object. + + Extracts config and override settings from an mbed_lib.json file. + + Args: + mbed_lib_json_path: Path to mbed_lib.json file + target_filters: List of filter string used when extracting data from target_overrides section of the config + data. + + Returns: + Prepared config source. + """ + + # Load JSON file using schema + try: + mbed_lib = schemas.MbedLibJSON.model_validate(decode_json_file(mbed_lib_json_path), extra="forbid", strict=True) + except pydantic.ValidationError as ex: + logger.error(f"{mbed_lib_json_path!s} did not validate against the schema for mbed_lib.json5!") + raise ex + + config_source = {} + + # Process config settings + if len(mbed_lib.config) > 0: + settings = [] + for config_name, item in mbed_lib.config.items(): + # If the config item is about a certain component or feature + # being present, avoid adding it to the mbed_config.cmake + # configuration file. Instead, applications should depend on + # the feature or component with target_link_libraries() and the + # component's CMake file (in the Mbed OS repo) will create + # any necessary macros or definitions. + if config_name == "present": + logger.warning( + f"Legacy 'present' entry in config file {mbed_lib_json_path}. This was for the Mbed CLI 1 " + f"build system only and is now ignored." + ) + continue + + _check_config_name(mbed_lib_json_path, config_name) + + # Remove all underscores in the setting name and replace with hyphens, as this makes settings harder to get wrong + config_name = config_name.replace("_", "-") + + logger.debug("Extracting config setting from '%s': '%s'='%s'", mbed_lib.name, config_name, item) + if isinstance(item, schemas.ConfigEntryDetails): + setting = ConfigSetting( + namespace=mbed_lib.name, + name=config_name, + macro_name=item.macro_name, + help_text=item.help, + value=item.value, + accepted_values=set(item.accepted_values) if item.accepted_values is not None else None, + value_max=item.value_max, + value_min=item.value_min, + ) + else: + setting = ConfigSetting( + namespace=mbed_lib.name, + name=config_name, + macro_name=None, + help_text=None, + value=item, + accepted_values=None, + value_max=None, + value_min=None, + ) + settings.append(setting) + + config_source["settings"] = settings + + # Process macros + if mbed_lib.macros is not None and len(mbed_lib.macros) > 0: + config_source["macros"] = set(mbed_lib.macros) + + # Process overrides + if len(mbed_lib.overrides) > 0: + config_source["overrides"] = _extract_overrides(mbed_lib.namespace, mbed_lib.overrides) + + # Process target overrides + if len(mbed_lib.target_overrides) > 0: + target_overrides = _extract_target_overrides( + mbed_lib.name, mbed_lib.target_overrides, target_filters if target_filters is not None else [] + ) + + config_source["overrides"] = config_source.get("overrides", []) + target_overrides + + return config_source + + @dataclass class ConfigSetting: """Representation of a config setting. @@ -70,13 +186,35 @@ class ConfigSetting: namespace: str name: str - value: Any + value: schemas.ConfigSettingValue help_text: Optional[str] = None macro_name: Optional[str] = None + accepted_values: set[schemas.ConfigSettingValue] | None = None + value_max: int | float | None = None + value_min: int | float | None = None def __post_init__(self) -> None: """Convert the value to a set if applicable.""" self.value = _sanitise_value(self.value) + self.check_value() + + def check_value(self): + """Issue a warning if the value does not appear to be valid.""" + if self.accepted_values is not None: + if self.value not in self.accepted_values: + logger.warning( + f"Value set for {self.namespace}.{self.name} ({self.value}) does not appear to be valid. Valid values are {self.accepted_values!r}" + ) + if self.value_max is not None: + if self.value > self.value_max: + logger.warning( + f"Value set for {self.namespace}.{self.name} ({self.value}) does not appear to be valid. Cannot be greater than {self.value_max}" + ) + if self.value_min is not None: + if self.value < self.value_min: + logger.warning( + f"Value set for {self.namespace}.{self.name} ({self.value}) does not appear to be valid. Cannot be less than {self.value_min}" + ) @dataclass @@ -88,8 +226,8 @@ class Override: namespace: str name: str - value: Any - modifier: Optional[str] = None + value: schemas.ConfigSettingValue + modifier: Optional[Literal["add", "remove"]] = None def __post_init__(self) -> None: """Parse modifiers and convert list values to sets.""" @@ -128,31 +266,38 @@ def _extract_config_settings(namespace: str, config_data: dict) -> List[ConfigSe def _extract_target_overrides( - namespace: str, override_data: dict, allowed_target_labels: Iterable[str] + namespace: str, + target_override_data: dict[str, dict[str, schemas.ConfigSettingValue]], + allowed_target_labels: Iterable[str], ) -> List[Override]: valid_target_data = dict() - for target_type in override_data: + for target_type in target_override_data: if target_type == "*" or target_type in allowed_target_labels: - valid_target_data.update(override_data[target_type]) + valid_target_data.update(target_override_data[target_type]) return _extract_overrides(namespace, valid_target_data) -def _extract_overrides(namespace: str, override_data: dict) -> List[Override]: +def _extract_overrides(namespace: str, override_data: dict[str, schemas.ConfigSettingValue]) -> List[Override]: overrides = [] for name, value in override_data.items(): - try: - override_namespace, override_name = name.split(".") - if override_namespace and override_namespace not in [namespace, "target"] and namespace != "app": - raise InvalidConfigOverride( - "It is only possible to override config settings defined in an mbed_lib.json from mbed_app.json. " - f"An override was defined by the lib `{namespace}` that attempts to override " - f"`{override_namespace}.{override_name}`." - ) - except ValueError: + split_results = name.split(".", maxsplit=1) + if len(split_results) == 2: + override_namespace, override_name = split_results + else: override_namespace = namespace override_name = name + # Remove all underscores in the setting name and replace with hyphens, as this makes settings harder to get wrong + override_name = override_name.replace("_", "-") + + if override_namespace not in {namespace, "target"} and namespace != "app": + raise InvalidConfigOverride( + "It is only possible to override config settings defined in an mbed_lib.json from mbed_app.json. " + f"An override was defined by the lib `{namespace}` that attempts to override " + f"`{override_namespace}.{override_name}`." + ) + overrides.append(Override(namespace=override_namespace, name=override_name, value=value)) return overrides diff --git a/tools/python/mbed_tools/lib/json_helpers.py b/tools/python/mbed_tools/lib/json_helpers.py index ef6f9f85489..a3b4a7d2f3d 100644 --- a/tools/python/mbed_tools/lib/json_helpers.py +++ b/tools/python/mbed_tools/lib/json_helpers.py @@ -6,6 +6,7 @@ import json import pyjson5 +import json5 import logging from pathlib import Path @@ -24,12 +25,23 @@ def decode_json_file(path: Path) -> Any: logger.error(f"Failed to decode JSON data in the file located at '{path}'") raise elif path.suffix == ".json5": + logger.debug(f"Loading JSON file {path}") try: - logger.debug(f"Loading JSON file {path}") with path.open() as json_file: return pyjson5.decode_io(json_file) - except ValueError: - logger.error(f"Failed to decode JSON data in the file located at '{path}'") - raise + except pyjson5.Json5Exception as ex: + # Parsing failed. pyjson5 produces completely useless error messages, so reparse the file with + # json5 for a better one (slow!). + try: + with path.open() as json_file: + parsed_file = json5.load(json_file) + logger.warning( + f"JSON5 file {path} could not be decoded with pyjson5 but was decodable with" + f"json5. Error from pyjson5 was: {ex!s}" + ) + return parsed_file + except ValueError as json5_ex: + logger.error(f"Failed to decode JSON5 data in the file located at '{path}': {json5_ex!s}") + raise json5_ex from None else: raise ValueError(f"Unknown JSON file extension {path.suffix}") From 4ead8813414c16d33c38238a8c71f055ae517b52 Mon Sep 17 00:00:00 2001 From: Jamie Smith Date: Sun, 2 Nov 2025 16:06:39 -0800 Subject: [PATCH 02/21] Start on schema for targets.json5 --- TESTS/configs/greentea_baremetal.json5 | 10 +- targets/targets.json5 | 324 +----------------- .../_internal/config/assemble_build_config.py | 30 +- .../build/_internal/config/schemas.py | 257 +++++++++++++- .../mbed_tools/build/_internal/find_files.py | 21 -- tools/python/mbed_tools/build/config.py | 14 + .../accumulating_attribute_parser.py | 5 +- .../test_accumulating_attribute_parser.py | 10 +- tools/run_python_tests.sh | 18 +- 9 files changed, 302 insertions(+), 387 deletions(-) diff --git a/TESTS/configs/greentea_baremetal.json5 b/TESTS/configs/greentea_baremetal.json5 index ab0eb3fa57d..6689a1c3ea4 100644 --- a/TESTS/configs/greentea_baremetal.json5 +++ b/TESTS/configs/greentea_baremetal.json5 @@ -1,11 +1,9 @@ { - "target_overrides": { - "*": { - "target.c_lib": "small", - "target.application-profile": "bare-metal" - } - }, "overrides": { + "target.c_lib": "small", + + "target.application-profile": "bare-metal", + // Enable Mbed Stats tests "platform.all-stats-enabled": 1, diff --git a/targets/targets.json5 b/targets/targets.json5 index 2ee76604d1f..649c508b8e5 100644 --- a/targets/targets.json5 +++ b/targets/targets.json5 @@ -1,21 +1,15 @@ { "Target": { "core": null, - "trustzone": false, - "default_toolchain": "ARM", - "supported_toolchains": null, "extra_labels": [], "supported_form_factors": [], "components": [], - "is_disk_virtual": false, "macros": [], "device_has": [], "features": [], "detect_code": [], "public": false, "c_lib": "std", - "bootloader_supported": false, - "static_memory_defines": true, "printf_lib": "minimal-printf", "supported_c_libs": { "arm": [ @@ -179,9 +173,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "core": "Cortex-M4", "default_toolchain": "uARM", "public": false, - "supported_toolchains": [ - "uARM" - ], "default_lib": "small", "detect_code": [ "9992" @@ -193,9 +184,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", ], "core": "Cortex-M4", "public": false, - "supported_toolchains": [ - "ARM" - ], "detect_code": [ "9993" ] @@ -207,9 +195,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "core": "Cortex-M4F", "default_toolchain": "uARM", "public": false, - "supported_toolchains": [ - "uARM" - ], "default_lib": "small", "detect_code": [ "9990" @@ -221,9 +206,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", ], "core": "Cortex-M4F", "public": false, - "supported_toolchains": [ - "ARM" - ], "detect_code": [ "9991" ] @@ -235,9 +217,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "Target" ], "core": "Cortex-M4F", - "supported_toolchains": [ - "GCC_ARM" - ], "macros": [ "__ADUCM4050__", "EV_COG_AD4050LZ" @@ -269,7 +248,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "release_versions": [ "5" ], - "bootloader_supported": true, "supported_application_profiles" : ["full", "bare-metal"], "supported_c_libs": { "arm": [ @@ -288,9 +266,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "Target" ], "core": "Cortex-M3", - "supported_toolchains": [ - "GCC_ARM" - ], "macros": [ "__ADUCM3029__", "EV_COG_AD3029LZ" @@ -322,7 +297,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "release_versions": [ "5" ], - "bootloader_supported": true, "supported_application_profiles" : ["full", "bare-metal"], "supported_c_libs": { "arm": [ @@ -352,7 +326,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "LPCTarget" ], "core": "Cortex-M0", - "default_toolchain": "ARM", "extra_labels": [ "NXP", "LPC11XX_11CXX", @@ -362,9 +335,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "CMSIS_VECTAB_VIRTUAL", "CMSIS_VECTAB_VIRTUAL_HEADER_FILE=\"cmsis_nvic.h\"" ], - "supported_toolchains": [ - "GCC_ARM" - ], "device_has": [ "ANALOGIN", "I2C", @@ -416,9 +386,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "LPC17XX", "NXP_EMAC" ], - "supported_toolchains": [ - "GCC_ARM" - ], "macros_add": [ "MBED_SPLIT_HEAP" ], @@ -451,7 +418,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "release_versions": [ "5" ], - "bootloader_supported": true, "config": { "us-ticker-timer": { "help": "Chooses which timer (0-3) to use for us_ticker.c", @@ -542,10 +508,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "Freescale", "KLXX" ], - "is_disk_virtual": true, - "supported_toolchains": [ - "GCC_ARM" - ], "inherits": [ "Target" ], @@ -597,16 +559,9 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "KLXX", "FLASH_CMSIS_ALGO" ], - "is_disk_virtual": true, - "supported_toolchains": [ - "GCC_ARM" - ], "inherits": [ "Target" ], - "detect_code": [ - "0220" - ], "device_has": [ "USTICKER", "ANALOGIN", @@ -628,7 +583,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "5" ], "device_name": "MKL46Z256VLL4", - "bootloader_supported": true, "supported_c_libs": { "arm": [ "std", @@ -646,9 +600,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", }, "MCU_K22F512": { "core": "Cortex-M4F", - "supported_toolchains": [ - "GCC_ARM" - ], "extra_labels": [ "Freescale", "MCUXpresso_MCUS", @@ -659,7 +610,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "KPSDK_MCUS", "KPSDK_CODE" ], - "is_disk_virtual": true, "public": false, "macros": [ "CPU_MK22FN512VLH12", @@ -669,9 +619,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "inherits": [ "Target" ], - "detect_code": [ - "0231" - ], "device_has": [ "USTICKER", "LPTICKER", @@ -721,9 +668,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "extra_labels_add": [ "FRDM" ], - "detect_code": [ - "0231" - ], "image_url": "https://www.nxp.com/assets/images/en/dev-board-image/FRDM-K22F-ANGLE.jpg" }, "KL43Z": { @@ -731,9 +675,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "ARDUINO" ], "core": "Cortex-M0+", - "supported_toolchains": [ - "GCC_ARM" - ], "extra_labels": [ "Freescale", "MCUXpresso_MCUS", @@ -744,13 +685,9 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "CPU_MKL43Z256VLH4", "FSL_RTOS_MBED" ], - "is_disk_virtual": true, "inherits": [ "Target" ], - "detect_code": [ - "0262" - ], "device_has": [ "USTICKER", "LPTICKER", @@ -795,9 +732,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "ARDUINO_UNO" ], "core": "Cortex-M0+", - "supported_toolchains": [ - "GCC_ARM" - ], "extra_labels": [ "Freescale", "MCUXpresso_MCUS", @@ -805,7 +739,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "FRDM", "FRAMEWORK_5_3_3" ], - "is_disk_virtual": true, "macros": [ "CPU_MKW41Z512VHT4", "FSL_RTOS_MBED", @@ -814,9 +747,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "inherits": [ "Target" ], - "detect_code": [ - "0201" - ], "device_has": [ "USTICKER", "LPTICKER", @@ -842,7 +772,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "5" ], "device_name": "MKW41Z512xxx4", - "bootloader_supported": true, "overrides": { "network-default-interface-type": "MESH" }, @@ -850,9 +779,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", }, "MCU_K64F": { "core": "Cortex-M4F", - "supported_toolchains": [ - "GCC_ARM" - ], "extra_labels_add": [ "Freescale", "MCUXpresso_MCUS", @@ -902,7 +828,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "5" ], "device_name": "MK64FN1M0xxx12", - "bootloader_supported": true, "overrides": { "network-default-interface-type": "ETHERNET" }, @@ -935,13 +860,9 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "extra_labels_add": [ "FRDM" ], - "is_disk_virtual": true, "inherits": [ "MCU_K64F" ], - "detect_code": [ - "0240" - ], "image_url": "https://mm.digikey.com/Volume0/opasdata/d220001/medias/images/407/MFG_FRDM-K64F.JPG" }, "SDT64B": { @@ -952,18 +873,12 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "K64F" ], "supported_form_factors": [], - "detect_code": [ - "3105" - ], "image_url": "https://os.mbed.com/media/cache/platforms/SDT64B_size.png.250x250_q85.png" }, "HEXIWEAR": { "inherits": [ "MCU_K64F" ], - "detect_code": [ - "0214" - ], "image_url": "https://os.mbed.com/media/cache/platforms/Hexiwear_Platform_Image_19Ja2aX_pNSWsjb.png.250x250_q85.png", }, "K66F": { // AKA FRDM-K66F @@ -974,9 +889,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "SD", ], "core": "Cortex-M4F", - "supported_toolchains": [ - "GCC_ARM" - ], "extra_labels_add": [ "Freescale", "MCUXpresso_MCUS", @@ -984,7 +896,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "FRDM", "Freescale_EMAC" ], - "is_disk_virtual": true, "macros_add": [ "CPU_MK66FN2M0VMD18", "FSL_RTOS_MBED", @@ -994,9 +905,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "inherits": [ "PSA_V7_M" ], - "detect_code": [ - "0311" - ], "device_has_add": [ "USTICKER", "LPTICKER", @@ -1024,7 +932,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "5" ], "device_name": "MK66FN2M0xxx18", - "bootloader_supported": true, "overrides": { "network-default-interface-type": "ETHERNET" }, @@ -1054,16 +961,12 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "SPIF", ], "core": "Cortex-M4F", - "supported_toolchains": [ - "GCC_ARM" - ], "extra_labels": [ "Freescale", "MCUXpresso_MCUS", "KSDK2_MCUS", "FRDM" ], - "is_disk_virtual": true, "macros": [ "CPU_MK82FN256VDC15", "FSL_RTOS_MBED", @@ -1072,9 +975,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "inherits": [ "Target" ], - "detect_code": [ - "0217" - ], "device_has": [ "USTICKER", "LPTICKER", @@ -1127,9 +1027,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "extra_labels": [ "STM" ], - "supported_toolchains": [ - "GCC_ARM" - ], "supported_c_libs": { "arm": [ "std", @@ -1151,7 +1048,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "USE_HAL_DRIVER", "USE_FULL_LL_DRIVER" ], - "bootloader_supported": true, "config": { "lse_available": { "help": "Define if a Low Speed External xtal (LSE) is available on the board (0 = No, 1 = Yes). If Yes, the LSE will be used to clock the RTC, LPUART, ... otherwise the Low Speed Internal clock (LSI) will be used", @@ -1295,9 +1191,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "supported_form_factors": [ "ARDUINO_UNO" ], - "detect_code": [ - "0755" - ], "device_name": "STM32F070RBTx", "image_url": "https://www.st.com/bin/ecommerce/api/image.PF261500.en.feature-description-include-personalized-no-cpn-medium.jpg" }, @@ -1324,9 +1217,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "supported_form_factors": [ "ARDUINO_UNO" ], - "detect_code": [ - "0730" - ], "device_name": "STM32F072RBTx", "image_url": "https://www.st.com/bin/ecommerce/api/image.PF261500.en.feature-description-include-personalized-no-cpn-medium.jpg" }, @@ -1353,9 +1243,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "supported_form_factors": [ "ARDUINO_UNO" ], - "detect_code": [ - "0750" - ], "device_name": "STM32F091RCTx", "image_url": "https://www.st.com/bin/ecommerce/api/image.PF261500.en.feature-description-include-personalized-no-cpn-medium.jpg" }, @@ -1419,9 +1306,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "supported_form_factors": [ "ARDUINO_UNO" ], - "detect_code": [ - "0700" - ], "device_name": "STM32F103RB", "image_url": "https://www.st.com/bin/ecommerce/api/image.PF259875.en.feature-description-include-personalized-no-cpn-medium.jpg" }, @@ -1545,9 +1429,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "macro_name": "STM32_D11_SPI_ETHERNET_PIN" } }, - "detect_code": [ - "0835" - ], "device_has_add": [ "USBDEVICE" ], @@ -1627,9 +1508,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "clock_source": "USE_PLL_HSI", "lse_available": 0 }, - "detect_code": [ - "0775" - ], "device_name": "STM32F303K8Tx", "image_url": "https://www.st.com/bin/ecommerce/api/image.PF262544.en.feature-description-include-personalized-no-cpn-medium.jpg" }, @@ -1673,9 +1551,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "supported_form_factors": [ "ARDUINO_UNO" ], - "detect_code": [ - "0745" - ], "device_name": "STM32F303RETx", "image_url": "https://www.st.com/bin/ecommerce/api/image.PF260945.en.feature-description-include-personalized-no-cpn-medium.jpg" }, @@ -1686,9 +1561,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "supported_form_factors": [ "ARDUINO_UNO" ], - "detect_code": [ - "0747" - ], "device_has_add": [ "USBDEVICE" ], @@ -1755,9 +1627,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "supported_form_factors": [ "ARDUINO_UNO" ], - "detect_code": [ - "0720" - ], "device_name": "STM32F401RETx", "image_url": "https://www.st.com/bin/ecommerce/api/image.PF260000.en.feature-description-include-personalized-no-cpn-medium.jpg" }, @@ -1803,9 +1672,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "lse_available": 0, "network-default-interface-type": "ETHERNET" }, - "detect_code": [ - "9011" - ], "image_url": "https://mm.digikey.com/Volume0/opasdata/d220001/medias/images/1881/MFG_102110014.jpg" }, "MCU_STM32F411xE": { @@ -1827,9 +1693,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "supported_form_factors": [ "ARDUINO_UNO" ], - "detect_code": [ - "0740" - ], "device_name": "STM32F411RETx", "image_url": "https://www.st.com/bin/ecommerce/api/image.PF260945.en.feature-description-include-personalized-no-cpn-medium.jpg" }, @@ -1851,9 +1714,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "LPTICKER" ], "device_name": "STM32F411RETx", - "detect_code": [ - "0454" - ], "components_add": [ "TELIT_HE910" ], @@ -1874,9 +1734,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "SERIAL_FC" ], "device_name": "STM32F411RETx", - "detect_code": [ - "0320" - ], "image_url": "https://mm.digikey.com/Volume0/opasdata/d220001/medias/images/1290/MTDOT-868-X1P-SMA-1.jpg" }, "BLACKPILL_F411CE": { @@ -1892,10 +1749,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "device_has_add": [ "USBDEVICE" ], - "bootloader_supported": true, - "detect_code": [ - "0740" - ], "device_name": "STM32F411CEYx", "image_url": "https://user-images.githubusercontent.com/1301112/69389644-eb5fb080-0ccc-11ea-8002-67d3db851250.png" }, @@ -3460,9 +3313,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "inherits": [ "MCU_STM32H723xG" ], - "supported_toolchains": [ - "GCC_ARM" - ], "extra_labels_add": [ "STM32H723ZG" ], @@ -5412,9 +5262,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", // See here for details: https://github.com/mbed-ce/mbed-os/wiki/MCU-Info-Page:-MIMXRT105x-and-106x "MIMXRT105X": { "core": "Cortex-M7FD", - "supported_toolchains": [ - "GCC_ARM" - ], "supported_application_profiles": [ "full", "bare-metal" @@ -5531,7 +5378,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "startup": true } }, - "bootloader_supported": true, "device_name": "MIMXRT1052DVL6A", "image_url": "https://www.nxp.com/assets/images/en/dev-board-image/IMX_RT1050-EVKB_TOP-LR.jpg" }, @@ -5679,9 +5525,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "ARDUINO_UNO" ], "core": "Cortex-M7FD", - "supported_toolchains": [ - "GCC_ARM" - ], "extra_labels": [ "NXP", "MCUXpresso_MCUS", @@ -5689,7 +5532,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "MIMXRT1170", "IMX" ], - "is_disk_virtual": true, "macros": [ "CPU_MIMXRT1176DVMAA_cm7", "FSL_RTOS_MBED", @@ -5747,9 +5589,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "ARDUINO" ], "core": "Cortex-M4F", - "supported_toolchains": [ - "GCC_ARM" - ], "extra_labels": [ "NXP", "MCUXpresso_MCUS", @@ -5757,7 +5596,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "LPCXpresso", "LPC" ], - "is_disk_virtual": true, "macros": [ "CPU_LPC54114J256BD64_cm4", "FSL_RTOS_MBED", @@ -5812,16 +5650,12 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", }, "MCU_LPC546XX": { "core": "Cortex-M4F", - "supported_toolchains": [ - "GCC_ARM" - ], "extra_labels": [ "NXP", "MCUXpresso_MCUS", "LPC", "NXP_EMAC" ], - "is_disk_virtual": true, "public": false, "macros": [ "CPU_LPC54628J512ET180", @@ -5956,9 +5790,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "ARM_MPS2_Target" ], "core": "Cortex-M0", - "supported_toolchains": [ - "GCC_ARM" - ], "extra_labels": [ "ARM_SSG", "MPS2", @@ -5996,9 +5827,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "ARM_MPS2_Target" ], "core": "Cortex-M0+", - "supported_toolchains": [ - "GCC_ARM" - ], "extra_labels": [ "ARM_SSG", "MPS2", @@ -6034,9 +5862,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "ARM_MPS2_Target" ], "core": "Cortex-M3", - "supported_toolchains": [ - "GCC_ARM" - ], "extra_labels": [ "ARM_SSG", "MPS2", @@ -6073,9 +5898,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "ARM_MPS2_Target" ], "core": "Cortex-M4F", - "supported_toolchains": [ - "GCC_ARM" - ], "extra_labels": [ "ARM_SSG", "MPS2", @@ -6112,9 +5934,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "ARM_MPS2_Target" ], "core": "Cortex-M7FD", - "supported_toolchains": [ - "GCC_ARM" - ], "extra_labels": [ "ARM_SSG", "MPS2", @@ -6172,9 +5991,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "ARM_IOTSS_Target" ], "core": "Cortex-M3", - "supported_toolchains": [ - "GCC_ARM" - ], "components_add": [ "SMSC9220" ], @@ -6230,9 +6046,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "5" ], "core": "Cortex-M33-NS", - "supported_toolchains": [ - "GCC_ARM" - ], "device_has_add": [ "INTERRUPTIN", "I2C", @@ -6286,9 +6099,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "5" ], "core": "Cortex-M33-NS", - "supported_toolchains": [ - "GCC_ARM" - ], "device_has_add": [ "INTERRUPTIN", "I2C", @@ -6340,9 +6150,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", ], "public": false, "core": "Cortex-A9", - "supported_toolchains": [ - "GCC_ARM" - ], "extra_labels": [ "RENESAS", "RZ_A1XX" @@ -6411,7 +6218,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "5" ], "device_name": "R7S72100", - "bootloader_supported": true, // 8MB serial flash on the board "memory_banks": { "EXT_FLASH": { @@ -6466,7 +6272,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "5" ], "device_name": "R7S72103", - "bootloader_supported": true, "memory_banks": { "EXT_FLASH": { "access": { @@ -6500,7 +6305,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "inherits": ["Target"], "public": false, "core": "Cortex-A9", - "supported_toolchains": ["GCC_ARM"], "extra_labels": ["RENESAS", "RZ_A2XX"], "device_has": [ "SLEEP", @@ -6545,7 +6349,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "device_has_add": ["EMAC","FLASH"], "release_versions": ["5"], "device_name": "R7S921053", - "bootloader_supported": true, // 16MiB OSPI flash on PCB "memory_banks": { @@ -6589,9 +6392,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "Maxim", "MAX32620C" ], - "supported_toolchains": [ - "GCC_ARM" - ], "device_has": [ "ANALOGIN", "FLASH", @@ -6658,9 +6458,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "Maxim", "MAX32625" ], - "supported_toolchains": [ - "GCC_ARM" - ], "device_has": [ "ANALOGIN", "I2C", @@ -6717,7 +6514,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "inherits": [ "MAX32625_BASE" ], - "bootloader_supported": true, // Reserve the first 64k of flash for the bootloader "memory_bank_config": { @@ -6749,9 +6545,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "Maxim", "MAX32630" ], - "supported_toolchains": [ - "GCC_ARM" - ], "components_add": [ "SD" ], @@ -6807,9 +6600,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "Maxim", "MAX32660" ], - "supported_toolchains": [ - "GCC_ARM" - ], "device_has": [ "SERIAL", "SERIAL_FC", @@ -6885,9 +6675,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "Maxim", "MAX32670" ], - "supported_toolchains": [ - "GCC_ARM" - ], "device_has": [ "SERIAL", "SERIAL_FC", @@ -6959,10 +6746,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "inherits": [ "MAX32670" ], - "bootloader_supported": true, - "detect_code": [ - "0351" - ], "image_url": "https://os.mbed.com/media/cache/platforms/xDot_Developer_Kit_with_xdot.png.250x250_q85.png" }, @@ -7038,7 +6821,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "macro_name": "HFRCO_FREQUENCY" } }, - "bootloader_supported": true, "supported_c_libs": { "arm": [ "std", @@ -7078,9 +6860,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "macros_add": [ "EFM32GG990F1024" ], - "supported_toolchains": [ - "GCC_ARM" - ], "release_versions": [ "5" ], @@ -7139,9 +6918,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "macros_add": [ "EFR32MG12P332F1024GL125" ], - "supported_toolchains": [ - "GCC_ARM" - ], "release_versions": [ "5" ], @@ -7191,9 +6967,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "macros_add": [ "EFM32GG11B820F2048GL192" ], - "supported_toolchains": [ - "GCC_ARM" - ], "release_versions": [ "5" ], @@ -7305,16 +7078,11 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "value": 32 } }, - "is_disk_virtual": true, - "supported_toolchains": [ - "GCC_ARM" - ], "public": false, "detect_code": [ "1101" ], "program_cycle_s": 6, - "bootloader_supported": true, "supported_application_profiles" : ["full", "bare-metal"], "supported_c_libs": { "arm": [ @@ -7501,16 +7269,11 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "5" ], "device_name": "nRF52840_xxAA", - "is_disk_virtual": true, - "supported_toolchains": [ - "GCC_ARM" - ], "public": false, "detect_code": [ "1101" ], "program_cycle_s": 6, - "bootloader_supported": true, "supported_application_profiles" : ["full", "bare-metal"], "supported_c_libs": { "arm": [ @@ -7645,17 +7408,12 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", // Nuvoton Targets ------------------------------------------------------------------------------------------------- "NUMAKER_PFM_NUC472": { "core": "Cortex-M4F", - "default_toolchain": "ARM", "extra_labels": [ "NUVOTON", "NUC472", "FLASH_CMSIS_ALGO", "NUVOTON_EMAC" ], - "is_disk_virtual": true, - "supported_toolchains": [ - "GCC_ARM" - ], "config": { "hxt-present": { "help": "High-speed external crystal oscillator HXT is present", @@ -7735,7 +7493,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", ] ], "device_name": "NUC472HI8AE", - "bootloader_supported": true, "overrides": { "hxt-present": false, "lxt-present": true, @@ -7781,7 +7538,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", }, "NUMAKER_PFM_M453": { "core": "Cortex-M4F", - "default_toolchain": "ARM", "extra_labels": [ "NUVOTON", "M451", @@ -7789,10 +7545,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "NUMAKER_PFM_M453", "FLASH_CMSIS_ALGO" ], - "is_disk_virtual": true, - "supported_toolchains": [ - "GCC_ARM" - ], "config": { "hxt-present": { "help": "High-speed external crystal oscillator HXT is present", @@ -7888,7 +7640,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", ] ], "device_name": "M453VG6AE", - "bootloader_supported": true, "overrides": { "hxt-present": false, "lxt-present": true, @@ -7902,16 +7653,11 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", }, "NUMAKER_PFM_NANO130": { "core": "Cortex-M0", - "default_toolchain": "ARM", "extra_labels": [ "NUVOTON", "NANO100", "NANO130KE3BN" ], - "is_disk_virtual": true, - "supported_toolchains": [ - "GCC_ARM" - ], "config": { "hxt-present": { "help": "High-speed external crystal oscillator HXT is present", @@ -8016,7 +7762,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", }, "MCU_M460": { "core": "Cortex-M4F", - "default_toolchain": "ARM", "public": false, "extra_labels": [ "NUVOTON", @@ -8024,10 +7769,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "FLASH_CMSIS_ALGO", "NUVOTON_EMAC" ], - "is_disk_virtual": true, - "supported_toolchains": [ - "GCC_ARM" - ], "config": { "hxt-present": { "help": "High-speed external crystal oscillator HXT is present", @@ -8150,7 +7891,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", 4096 ] ], - "bootloader_supported": true, "overrides": { "deep-sleep-latency": 1, "tickless-from-us-ticker": true @@ -8221,7 +7961,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", }, "MCU_M480": { "core": "Cortex-M4F", - "default_toolchain": "ARM", "public": false, "extra_labels": [ "NUVOTON", @@ -8229,10 +7968,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "FLASH_CMSIS_ALGO", "NUVOTON_EMAC" ], - "is_disk_virtual": true, - "supported_toolchains": [ - "GCC_ARM" - ], "config": { "hxt-present": { "help": "High-speed external crystal oscillator HXT is present", @@ -8340,7 +8075,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", 4096 ] ], - "bootloader_supported": true, "overrides": { "deep-sleep-latency": 1, "tickless-from-us-ticker": true @@ -8420,9 +8154,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "public": false, "core": "Cortex-M23-NS", "default_toolchain": "ARMC6", - "supported_toolchains": [ - "GCC_ARM" - ], "features_add": [ "EXPERIMENTAL_API" ], @@ -8434,7 +8165,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "CMSIS_NVIC_VIRTUAL", "LPTICKER_DELAY_TICKS=4" ], - "is_disk_virtual": true, "config": { "hxt-present": { "help": "High-speed external crystal oscillator HXT is present", @@ -8523,7 +8253,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", 2048 ] ], - "bootloader_supported": true, "forced_reset_timeout": 5, "supported_application_profiles": [ "full", "bare-metal" @@ -8596,8 +8325,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "MCU_M251": { "core": "Cortex-M23", "public": false, - "trustzone": false, - "is_disk_virtual": true, "default_toolchain": "ARMC6", "extra_labels": [ "NUVOTON", @@ -8607,9 +8334,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "macros_add": [ "LPTICKER_DELAY_TICKS=4" ], - "supported_toolchains": [ - "GCC_ARM" - ], "config": { "hxt-present": { "help": "High-speed external crystal oscillator HXT is present", @@ -8711,7 +8435,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", 512 ] ], - "bootloader_supported": true, "supported_c_libs": { "arm": [ "std", @@ -8758,10 +8481,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "macros": [ "LPTICKER_DELAY_TICKS=4" ], - "is_disk_virtual": true, - "supported_toolchains": [ - "GCC_ARM" - ], "config": { "hxt-present": { "help": "High-speed external crystal oscillator HXT is present", @@ -8857,7 +8576,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", 2048 ] ], - "bootloader_supported": true, "overrides": { "hxt-present": false, "lxt-present": true, @@ -8921,9 +8639,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "MBED_PSA_SRV" ], "public": false, - "supported_toolchains": [ - "GCC_ARM" - ], "OUTPUT_EXT": "elf", "device_has": [ "AACI", @@ -9041,9 +8756,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "COMPONENT_CAT1A=1", ], "default_toolchain": "GCC_ARM", - "supported_toolchains": [ - "GCC_ARM" - ], "core": "Cortex-M4F", "OUTPUT_EXT": "hex", "device_has_add": [ @@ -9170,7 +8882,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "detect_code": [ "1901" ], - "bootloader_supported": false, "sectors": [ [ 268435456, @@ -9309,7 +9020,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "detect_code": [ "1900" ], - "bootloader_supported": false, "sectors": [ [ 268435456, @@ -9358,7 +9068,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", 512 ] ], - "bootloader_supported": false, "image_url": "https://os.mbed.com/media/cache/platforms/SS2_3797_with_out_USB_cable.jpg.250x250_q85.jpg" }, "CYW9P62S1_43438EVB_01": { // AKA CYW9P62S1-43438EVB-01 PSoC 62S1 Wi-Fi BT Pioneer Kit @@ -9400,7 +9109,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "detect_code": [ "1900" ], - "bootloader_supported": false, "sectors": [ [ 268435456, @@ -9591,9 +9299,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "S1SBP6A": { // AKA Samsung Bio-Processor S1SBP6A "inherits": ["Target"], "core": "Cortex-M4F", - "supported_toolchains": [ - "GCC_ARM" - ], "default_toolchain": "GCC_ARM", "extra_labels": [ "Samsung", @@ -9636,9 +9341,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "core": "Cortex-M4F", "features": ["BLE"], "default_toolchain": "GCC_ARM", - "supported_toolchains": [ - "GCC_ARM" - ], "public": false, "extra_labels": [ "Ambiq_Micro", @@ -9730,16 +9432,12 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "Target" ], "core": "Cortex-M4F", - "is_disk_virtual": true, "extra_labels": [ "TOSHIBA" ], "macros": [ "__TMPM46B__" ], - "supported_toolchains": [ - "GCC_ARM" - ], "device_has": [ "USTICKER", "ANALOGIN", @@ -9769,7 +9467,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "release_versions": [ "5" ], - "bootloader_supported": true, "supported_application_profiles" : ["full", "bare-metal"], "supported_c_libs": { "arm": [ @@ -9788,16 +9485,12 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "Target" ], "core": "Cortex-M4F", - "is_disk_virtual": true, "extra_labels": [ "TOSHIBA" ], "macros": [ "__TMPM4G9__" ], - "supported_toolchains": [ - "GCC_ARM" - ], "device_has": [ "ANALOGIN", "ANALOGOUT", @@ -9828,7 +9521,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "release_versions": [ "5" ], - "bootloader_supported": true, "supported_application_profiles" : ["full", "bare-metal"], "supported_c_libs": { "arm": [ @@ -9852,10 +9544,8 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "TMPM4KN": { // AKA TMPM-M4KN-SBK from ESP Co. "inherits": ["Target"], "core": "Cortex-M4F", - "is_disk_virtual": true, "extra_labels": ["TOSHIBA"], "macros": ["__TMPM4KN__"], - "supported_toolchains": ["GCC_ARM"], "device_has": [ "ANALOGIN", "INTERRUPTIN", @@ -9878,7 +9568,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "device_name": "TMPM4KNFYAFG", "detect_code": ["7020"], "release_versions": ["5"], - "bootloader_supported": true, "supported_application_profiles" : ["full"], "supported_c_libs": { "arm": [ @@ -9895,16 +9584,12 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "Target" ], "core": "Cortex-M4F", - "is_disk_virtual": true, "extra_labels": [ "TOSHIBA" ], "macros": [ "TMPM4NR" ], - "supported_toolchains": [ - "GCC_ARM" - ], "device_has": [ "ANALOGIN", "ANALOGOUT", @@ -9935,7 +9620,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "release_versions": [ "5" ], - "bootloader_supported": true, "supported_c_libs": { "arm": [ "std", @@ -9953,16 +9637,12 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "Target" ], "core": "Cortex-M4F", - "is_disk_virtual": true, "extra_labels": [ "TOSHIBA" ], "macros": [ "__TMPM4GR__" ], - "supported_toolchains": [ - "GCC_ARM" - ], "device_has": [ "ANALOGIN", "ANALOGOUT", @@ -9993,8 +9673,7 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "release_versions": [ "5" ], - "bootloader_supported": true, - "supported_c_libs": { + "supported_c_libs": { "arm": [ "std", "small" @@ -10010,7 +9689,6 @@ mode is recommended for target MCUs with small amounts of flash and RAM.", "public": false, "inherits": ["Target"], "core": "Cortex-M0+", - "supported_toolchains": ["GCC_ARM"], "supported_application_profiles": [ "full", "bare-metal" ], 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 c7d6595914a..5f8161181cd 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 @@ -15,7 +15,7 @@ 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 +from mbed_tools.build._internal.find_files import LabelFilter, filter_files, find_files def assemble_config(target_attributes: dict, program: MbedProgram) -> Config: @@ -41,10 +41,12 @@ def assemble_config(target_attributes: dict, program: MbedProgram) -> Config: mbed_lib_files.update(find_files("mbed_lib.json", path.absolute().resolve())) mbed_lib_files.update(find_files("mbed_lib.json5", path.absolute().resolve())) - config = _assemble_config_from_sources(target_attributes, list(mbed_lib_files), program.files.app_config_file) + config, used_mbed_lib_files = _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) + config.json_sources.extend(used_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) @@ -67,7 +69,7 @@ def make_relative_if_possible(path: Path): def _assemble_config_from_sources( target_attributes: dict, mbed_lib_files: List[Path], mbed_app_file: Optional[Path] = None -) -> Config: +) -> tuple[Config, list[Path]]: config = Config(source.prepare(target_attributes, source_name="target")) previous_filter_data = None app_data = None @@ -80,22 +82,19 @@ def _assemble_config_from_sources( ) _get_app_filter_labels(app_data, config) - current_filter_data = FileFilterData.from_config(config) - while previous_filter_data != current_filter_data: - filtered_files = _filter_files(mbed_lib_files, current_filter_data) - for config_file in filtered_files: - config.update(source.from_mbed_lib_json_file(config_file, target_filters=current_filter_data.labels)) - # Remove any mbed_lib files we've already visited from the list so we don't parse them multiple times. - mbed_lib_files.remove(config_file) - - previous_filter_data = current_filter_data - current_filter_data = FileFilterData.from_config(config) + # Process mbed_lib.json files according to the filter. + filter_data = FileFilterData.from_config(config) + filtered_files = list(_filter_files(mbed_lib_files, filter_data)) + for config_file in filtered_files: + config.update(source.from_mbed_lib_json_file(config_file, target_filters=filter_data.labels)) + # Remove any mbed_lib files we've already visited from the list so we don't parse them multiple times. + mbed_lib_files.remove(config_file) # Apply mbed_app.json data last so config parameters are overriden in the correct order. if app_data: config.update(app_data) - return config + return config, filtered_files def _get_app_filter_labels(mbed_app_data: dict, config: Config) -> None: @@ -135,6 +134,5 @@ def _filter_files(files: Iterable[Path], filter_data: FileFilterData) -> Iterabl LabelFilter("TARGET", filter_data.labels), LabelFilter("FEATURE", filter_data.features), LabelFilter("COMPONENT", filter_data.components), - RequiresFilter(filter_data.requires), ) return filter_files(files, filters) diff --git a/tools/python/mbed_tools/build/_internal/config/schemas.py b/tools/python/mbed_tools/build/_internal/config/schemas.py index 674efb4d16e..6d6a7f51e96 100644 --- a/tools/python/mbed_tools/build/_internal/config/schemas.py +++ b/tools/python/mbed_tools/build/_internal/config/schemas.py @@ -9,7 +9,7 @@ from __future__ import annotations -from typing import Union, Self +from typing import Union, Self, Literal from pydantic import BaseModel, Field, model_validator @@ -62,17 +62,10 @@ def verify_max_min(self) -> Self: return self -class MbedLibJSON(BaseModel): +class BaseJSONConfig(BaseModel): """ - Schema for an mbed_lib.json5 config file. - This type of config file provides information about a library (inside or outside the Mbed OS source tree) - to the Mbed configuration system. - """ - - name: str - """ - The name of this library. This is also considered the 'namespace' and will be prepended to all - configuration settings generated by this file. + Base schema for JSON config files. This schema applies to mbed_app.json5 and mbed_lib.json5, + as well as each entry in targets.json5 """ config: dict[str, ConfigSettingValue | ConfigEntryDetails] = Field(default_factory=dict) @@ -83,11 +76,15 @@ class MbedLibJSON(BaseModel): By convention, the name used for a configuration setting should be in skewer-case and should not contain periods, underscores, or uppercase letters. + + In target JSON, this is a merging attribute. """ macros: list[str] | None = None """ List of macros to unconditionally define when this lib is included, in "NAME" or "NAME=VALUE" format. + + In target JSON, this is an accumulating attribute. """ overrides: dict[str, ConfigSettingValue] = Field(default_factory=dict) @@ -107,6 +104,22 @@ class MbedLibJSON(BaseModel): Override order between different mbed_lib.json5 files is not currently defined but should not matter because they cannot override settings from targets.json5 or other mbed_lib.json5 files. + + In target JSON, this is a merging attribute. + """ + + +class MbedLibJSON(BaseJSONConfig): + """ + Schema for an mbed_lib.json5 config file. + This type of config file provides information about a library (inside or outside the Mbed OS source tree) + to the Mbed configuration system. + """ + + name: str + """ + The name of this library. This is also considered the 'namespace' and will be prepended to all + configuration settings generated by this file. """ target_overrides: dict[str, dict[str, ConfigSettingValue]] = Field(default_factory=dict) @@ -130,3 +143,225 @@ class MbedLibJSON(BaseModel): target_overrides and overrides, is not currently defined. So, if you override the same setting in both, results may not be what you expect. """ + + +class TargetJSON(BaseJSONConfig): + """ + Schema for one entry in targets.json5. + """ + + inherits: list[str] = Field(default_factory=list) + """ + Parent target(s) to inherit this target's attributes from. + + Multiple parent targets are allowed, but be careful as the inheritance tree is flattened into a list before + being processed, which can cause some possibly unexpected behavior. See below for more details. + + In the Mbed target configuration language, each attribute has one of three behaviors with respect to inheritance: + "overriding", "merging", and "accumulating". + + Overriding attributes are the simplest, and work like regular inheritance in programming: the value of the attribute + from the "closest" ancestor is used, and all other values are discarded. + + To determine the attribute's value, the inheritance tree is flattened into a list using a depth-first traversal + that visits the first parent of each target first. For example, the inheritance tree diagram for target "A" below: + + D E + | | + B C + |_____| + | + A + + Would give us an inheritance order of [A, B, D, C, E]. Then, the overriding attribute's value would be taken + from the first target in this list to contain the attribute. + + Merging attributes work similarly but are all of dict type. With merging attributes, the dicts are merged + together with only elements with the same keys overriding based on the order above. + + Accumulating attributes, on the other hand, work very differently. These are all of list type, and have + three forms: "", "_add", and "_remove". Using the first of those forms (the base form) + gives the attribute its initial value, and the second and third forms remove the attribute from parent targets. + + UNLIKE overriding and merging attributes, accumulating attributes use a breadth-first search to flatten + the inheritance hierarchy. (why? no idea! -Jamie). For example, an inheritance tree diagram for the target "A" below + + D E + | | + B C + |_____| + | + A + + Would give us an inheritance order of [A, B, C, D, E]. To process this, the first occurance of the bare + attribute name in the above list is found, and then we work backwards towards target A processing "_add" and + "_remove" directives until the full set of values is built up. + + *note:* Based on my current understanding of this code, if no parent target defines the attribute in base form, + then the child targets cannot add to the value using "_add" - the config system will simply treat the attribute as + not existing. This seems like a potential source of bugs, but I don't want to change it for fear of + breaking something. -Jamie + """ + + public: bool = True + """ + Whether this target is intended for user use and can be passed as a target when building Mbed. + Set this to false for targets that are incomplete and intended to be inherited from other targets. + + This attribute is not affected by inheritance and always defaults to true unless set to false for + each individual target. + """ + + core: str | None = None + """ + Name of the CPU core used by this target. This gets set into the MBED_CPU_CORE CMake variable and + is used to select the correct compile flags. + + This is an overriding attribute. + """ + + supported_form_factors: list[Literal["ARDUINO_UNO", "PMOD", "STMOD"]] + """ + Form factors that this board supports. + Form factors provide a standard electrical interface with standardized pin locations and functions for + add-on boards. Enabling a form factor enables its standard pin names. + See https://web.archive.org/web/20240620001521/https://os.mbed.com/docs/mbed-os/v6.16/porting/standard-pin-names.html + + This is an overriding attribute. + """ + + macros_add: list[str] = Field(default_factory=list) + """ + Macros to add (see "macros"). + Using this attribute adds macros to the set defined by parent target(s), rather than overwriting it. + + This is a merging attribute in its add form. + """ + + macros_remove: list[str] = Field(default_factory=list) + """ + Macros to remove (see "macros"). + Using this attribute removes macros from the set defined by parent target(s), rather than overwriting it. + + This is a merging attribute in its remove form. + + Note that this specific attribute has some special behavior, in that the value after the "=" in the macro + definition can be ignored when finding matches to remove. So if the parent target adds a macro "FOO=7", then + doing "macros_remove": ["FOO"] in a child target is enough to remove it. + """ + + extra_labels: list[str] = Field(default_factory=list) + """ + Additional labels to add for this target and targets that inherit from it. + Labels are added to the `MBED_TARGET_LABELS` list in CMake, and become compile definitions + in the format `TARGET_