zephyr/scripts/pylib/build_helpers/domains.py

129 lines
3.4 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.
'''
from dataclasses import dataclass
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: true
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, domains_yaml):
try:
data = yaml.safe_load(domains_yaml)
pykwalify.core.Core(source_data=data,
schema_data=schema).validate()
except (yaml.YAMLError, pykwalify.errors.SchemaError):
logger.critical(f'malformed domains.yaml')
exit(1)
self._build_dir = data['build_dir']
self._domains = {
d['name']: Domain(d['name'], d['build_dir'])
for d in data['domains']
}
# In the YAML data, the values for "default" and "flash_order"
# must not name any domains that aren't listed under "domains".
# Now that self._domains has been initialized, we can leverage
# the common checks in self.get_domain to verify this.
self._default_domain = self.get_domain(data['default'])
self._flash_order = self.get_domains(data.get('flash_order', []))
@staticmethod
def from_file(domains_file):
'''Load domains from a domains.yaml file.
'''
try:
with open(domains_file, 'r') as f:
domains_yaml = f.read()
except FileNotFoundError:
logger.critical(f'domains.yaml file not found: {domains_file}')
exit(1)
return Domains(domains_yaml)
@staticmethod
def from_yaml(domains_yaml):
'''Load domains from a string with YAML contents.
'''
return Domains(domains_yaml)
def get_domains(self, names=None, default_flash_order=False):
if names is None:
if default_flash_order:
return self._flash_order
return list(self._domains.values())
return list(map(self.get_domain, names))
def get_domain(self, name):
found = self._domains.get(name)
if not found:
logger.critical(f'domain "{name}" not found, '
f'valid domains are: {", ".join(self._domains)}')
exit(1)
return found
def get_default_domain(self):
return self._default_domain
def get_top_build_dir(self):
return self._build_dir
@dataclass
class Domain:
name: str
build_dir: str