The recent support for BUILD_ONLY images was implemented by excluding them from `domains.yaml`, in order to crudely prevent them from being picked up by `west flash`. Arguably, this is incorrect or unexpected, because the sysbuild documentation defines a "domain" as: Every Zephyr CMake build system managed by sysbuild. Another consequence is that, given a build-only `<image>`, this makes it impossible to pass `--domain <image>` to `west flash`, `west debug`, and ironically `west build`. To fix that, `domains.yaml` should again represent all domains, and the build-only ones should be indicated in another way. Enter `flash_order`: a new top-level key in the domains YAML schema. It contains the default sequence of images used by `west flash`, where the build-only images are excluded, and the order is influenced by `sysbuild_add_dependencies()`. Signed-off-by: Grzegorz Swiderski <grzegorz.swiderski@nordicsemi.no>
147 lines
3.7 KiB
Python
147 lines
3.7 KiB
Python
# Copyright (c) 2022 Nordic Semiconductor ASA
|
|
#
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
'''Domain handling for west extension commands.
|
|
|
|
This provides parsing of domains yaml file and creation of objects of the
|
|
Domain class.
|
|
'''
|
|
|
|
import yaml
|
|
import pykwalify.core
|
|
import logging
|
|
|
|
DOMAINS_SCHEMA = '''
|
|
## A pykwalify schema for basic validation of the structure of a
|
|
## domains YAML file.
|
|
##
|
|
# The domains.yaml file is a simple list of domains from a multi image build
|
|
# along with the default domain to use.
|
|
type: map
|
|
mapping:
|
|
default:
|
|
required: true
|
|
type: str
|
|
build_dir:
|
|
required: true
|
|
type: str
|
|
domains:
|
|
required: false
|
|
type: seq
|
|
sequence:
|
|
- type: map
|
|
mapping:
|
|
name:
|
|
required: true
|
|
type: str
|
|
build_dir:
|
|
required: true
|
|
type: str
|
|
flash_order:
|
|
required: false
|
|
type: seq
|
|
sequence:
|
|
- type: str
|
|
'''
|
|
|
|
schema = yaml.safe_load(DOMAINS_SCHEMA)
|
|
logger = logging.getLogger('build_helpers')
|
|
# Configure simple logging backend.
|
|
formatter = logging.Formatter('%(name)s - %(levelname)s - %(message)s')
|
|
handler = logging.StreamHandler()
|
|
handler.setFormatter(formatter)
|
|
logger.addHandler(handler)
|
|
|
|
|
|
class Domains:
|
|
|
|
def __init__(self, data):
|
|
self._build_dir = data.get('build_dir')
|
|
domain_list = data.get('domains') or []
|
|
if not domain_list:
|
|
logger.warning("no domains defined; this probably won't work")
|
|
|
|
self._domains = {
|
|
d['name']: Domain(d['name'], d['build_dir'])
|
|
for d in domain_list
|
|
}
|
|
self._default_domain = self._domains.get(data['default'])
|
|
|
|
domains_flash_order = data.get('flash_order') or []
|
|
self._flash_order = list(map(self._domains.get, domains_flash_order))
|
|
|
|
@staticmethod
|
|
def from_file(domains_file):
|
|
'''Load domains from domains.yaml.
|
|
|
|
Exception raised:
|
|
- ``FileNotFoundError`` if the domains file is not found.
|
|
'''
|
|
try:
|
|
with open(domains_file, 'r') as f:
|
|
domains = yaml.safe_load(f.read())
|
|
except FileNotFoundError:
|
|
logger.critical(f'domains.yaml file not found: {domains_file}')
|
|
exit(1)
|
|
|
|
try:
|
|
pykwalify.core.Core(source_data=domains, schema_data=schema)\
|
|
.validate()
|
|
except pykwalify.errors.SchemaError:
|
|
logger.critical(f'ERROR: Malformed yaml in file: {domains_file}')
|
|
exit(1)
|
|
|
|
return Domains(domains)
|
|
|
|
@staticmethod
|
|
def from_data(domains_data):
|
|
'''Load domains from domains dictionary.
|
|
'''
|
|
return Domains(domains_data)
|
|
|
|
def get_domains(self, names=None, default_flash_order=False):
|
|
ret = []
|
|
|
|
if not names:
|
|
if default_flash_order:
|
|
return self._flash_order
|
|
return list(self._domains.values())
|
|
|
|
for n in names:
|
|
found = self._domains.get(n)
|
|
if not found:
|
|
logger.critical(f'domain {n} not found, '
|
|
f'valid domains are: {", ".join(self._domains)}')
|
|
exit(1)
|
|
ret.append(found)
|
|
return ret
|
|
|
|
def get_default_domain(self):
|
|
return self._default_domain
|
|
|
|
def get_top_build_dir(self):
|
|
return self._build_dir
|
|
|
|
|
|
class Domain:
|
|
|
|
def __init__(self, name, build_dir):
|
|
self.name = name
|
|
self.build_dir = build_dir
|
|
|
|
@property
|
|
def name(self):
|
|
return self._name
|
|
|
|
@name.setter
|
|
def name(self, value):
|
|
self._name = value
|
|
|
|
@property
|
|
def build_dir(self):
|
|
return self._build_dir
|
|
|
|
@build_dir.setter
|
|
def build_dir(self, value):
|
|
self._build_dir = value
|