-
Notifications
You must be signed in to change notification settings - Fork 8.2k
Zephyr sysbuild / multi image #40555
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b1d1c24
32a28ef
a0665bf
1a71ce8
f655493
86dda45
4ec16a3
b719e15
70e05e2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,17 +12,21 @@ | |
| from west import log | ||
| from west.configuration import config | ||
| from zcmake import DEFAULT_CMAKE_GENERATOR, run_cmake, run_build, CMakeCache | ||
| from build_helpers import is_zephyr_build, find_build_dir, \ | ||
| from build_helpers import is_zephyr_build, find_build_dir, load_domains, \ | ||
| FIND_BUILD_DIR_DESCRIPTION | ||
|
|
||
| from zephyr_ext_common import Forceable | ||
|
|
||
| _ARG_SEPARATOR = '--' | ||
|
|
||
| SYSBUILD_PROJ_DIR = pathlib.Path(__file__).resolve().parent.parent.parent \ | ||
| / pathlib.Path('share/sysbuild') | ||
|
|
||
| BUILD_USAGE = '''\ | ||
| west build [-h] [-b BOARD[@REV]]] [-d BUILD_DIR] | ||
| [-t TARGET] [-p {auto, always, never}] [-c] [--cmake-only] | ||
| [-n] [-o BUILD_OPT] [-f] | ||
| [--sysbuild | --no-sysbuild] | ||
| [source_dir] -- [cmake_opt [cmake_opt ...]] | ||
| ''' | ||
|
|
||
|
|
@@ -111,6 +115,9 @@ def do_add_parser(self, parser_adder): | |
| help='force a cmake run') | ||
| group.add_argument('--cmake-only', action='store_true', | ||
| help="just run cmake; don't build (implies -c)") | ||
| group.add_argument('--domain', action='append', | ||
| help='''execute build tool (make or ninja) only for | ||
| given domain''') | ||
| group.add_argument('-t', '--target', | ||
| help='''run build system target TARGET | ||
| (try "-t usage")''') | ||
|
|
@@ -124,6 +131,13 @@ def do_add_parser(self, parser_adder): | |
| dest='dry_run', action='store_true', | ||
| help="just print build commands; don't run them") | ||
|
|
||
| group = parser.add_mutually_exclusive_group() | ||
| group.add_argument('--sysbuild', action='store_true', | ||
| help='''create multi domain build system''') | ||
| group.add_argument('--no-sysbuild', action='store_true', | ||
| help='''do not create multi domain build system | ||
| (default)''') | ||
|
|
||
| group = parser.add_argument_group('pristine builds', | ||
| PRISTINE_DESCRIPTION) | ||
| group.add_argument('-p', '--pristine', choices=['auto', 'always', | ||
|
|
@@ -190,8 +204,9 @@ def do_run(self, args, remainder): | |
|
|
||
| self._sanity_check() | ||
| self._update_cache() | ||
| self.domains = load_domains(self.build_dir) | ||
|
|
||
| self._run_build(args.target) | ||
| self._run_build(args.target, args.domain) | ||
|
|
||
| def _find_board(self): | ||
| board, origin = None, None | ||
|
|
@@ -357,9 +372,14 @@ def _sanity_check(self): | |
| # CMake configuration phase. | ||
| self.run_cmake = True | ||
|
|
||
| cached_app = self.cmake_cache.get('APPLICATION_SOURCE_DIR') | ||
| log.dbg('APPLICATION_SOURCE_DIR:', cached_app, | ||
| level=log.VERBOSE_EXTREME) | ||
| cached_proj = self.cmake_cache.get('APPLICATION_SOURCE_DIR') | ||
| cached_app = self.cmake_cache.get('APP_DIR') | ||
| # if APP_DIR is None but APPLICATION_SOURCE_DIR is set, that indicates | ||
| # an older build folder, this still requires pristine. | ||
| if cached_app is None and cached_proj: | ||
| cached_app = cached_proj | ||
|
|
||
| log.dbg('APP_DIR:', cached_app, level=log.VERBOSE_EXTREME) | ||
| source_abs = (os.path.abspath(self.args.source_dir) | ||
| if self.args.source_dir else None) | ||
| cached_abs = os.path.abspath(cached_app) if cached_app else None | ||
|
|
@@ -445,6 +465,14 @@ def _run_cmake(self, board, origin, cmake_opts): | |
| if user_args: | ||
| cmake_opts.extend(shlex.split(user_args)) | ||
|
|
||
| config_sysbuild = config_getboolean('sysbuild', False) | ||
|
||
| if self.args.sysbuild or (config_sysbuild and not self.args.no_sysbuild): | ||
| cmake_opts.extend(['-S{}'.format(SYSBUILD_PROJ_DIR), | ||
| '-DAPP_DIR:PATH={}'.format(self.source_dir)]) | ||
| else: | ||
| # self.args.no_sysbuild == True or config sysbuild False | ||
| cmake_opts.extend(['-S{}'.format(self.source_dir)]) | ||
|
|
||
| # Invoke CMake from the current working directory using the | ||
| # -S and -B options (officially introduced in CMake 3.13.0). | ||
| # This is important because users expect invocations like this | ||
|
|
@@ -453,7 +481,6 @@ def _run_cmake(self, board, origin, cmake_opts): | |
| # west build -- -DOVERLAY_CONFIG=relative-path.conf | ||
| final_cmake_args = ['-DWEST_PYTHON={}'.format(sys.executable), | ||
| '-B{}'.format(self.build_dir), | ||
| '-S{}'.format(self.source_dir), | ||
| '-G{}'.format(config_get('generator', | ||
| DEFAULT_CMAKE_GENERATOR))] | ||
| if cmake_opts: | ||
|
|
@@ -476,7 +503,7 @@ def _run_pristine(self): | |
| '-P', cache['ZEPHYR_BASE'] + '/cmake/pristine.cmake'] | ||
| run_cmake(cmake_args, cwd=self.build_dir, dry_run=self.args.dry_run) | ||
|
|
||
| def _run_build(self, target): | ||
| def _run_build(self, target, domain): | ||
| if target: | ||
| _banner('running target {}'.format(target)) | ||
| elif self.run_cmake: | ||
|
|
@@ -488,8 +515,23 @@ def _run_build(self, target): | |
| if self.args.verbose: | ||
| self._append_verbose_args(extra_args, | ||
| not bool(self.args.build_opt)) | ||
| run_build(self.build_dir, extra_args=extra_args, | ||
| dry_run=self.args.dry_run) | ||
|
|
||
| domains = load_domains(self.build_dir) | ||
| build_dir_list = [] | ||
|
|
||
| if domain is None: | ||
| # If no domain is specified, we just build top build dir as that | ||
| # will build all domains. | ||
| build_dir_list = [domains.get_top_build_dir()] | ||
| else: | ||
| _banner('building domain(s): {}'.format(' '.join(domain))) | ||
| domain_list = domains.get_domains(domain) | ||
| for d in domain_list: | ||
| build_dir_list.append(d.build_dir) | ||
|
|
||
| for b in build_dir_list: | ||
| run_build(b, extra_args=extra_args, | ||
| dry_run=self.args.dry_run) | ||
|
|
||
| def _append_verbose_args(self, extra_args, add_dashes): | ||
| # These hacks are only needed for CMake versions earlier than | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,139 @@ | ||
| # 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 | ||
| from west import log | ||
|
|
||
| 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 | ||
| ''' | ||
|
|
||
| schema = yaml.safe_load(DOMAINS_SCHEMA) | ||
|
|
||
|
|
||
| class Domains: | ||
|
|
||
| def __init__(self, data): | ||
| self._domains = [] | ||
| self._domain_names = [] | ||
| self._domain_default = [] | ||
|
|
||
| self._build_dir = data.get('build_dir') | ||
| domain_list = data.get('domains') | ||
| if not domain_list: | ||
| log.wrn("no domains defined; this probably won't work") | ||
|
|
||
| for d in domain_list: | ||
| domain = Domain(d['name'], d['build_dir']) | ||
| self._domains.append(domain) | ||
| self._domain_names.append(domain.name) | ||
| if domain.name == data['default']: | ||
| self._default_domain = domain | ||
|
|
||
| @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: | ||
| log.die(f'domains.yaml file not found: {domains_file}') | ||
|
|
||
| try: | ||
| pykwalify.core.Core(source_data=domains, schema_data=schema)\ | ||
| .validate() | ||
| except pykwalify.errors.SchemaError: | ||
| log.die(f'ERROR: Malformed yaml in file: {domains_file}') | ||
|
|
||
| return Domains(domains) | ||
|
|
||
| @staticmethod | ||
| def from_data(domains_data): | ||
| '''Load domains from domains dictionary. | ||
| ''' | ||
| return Domains(domains_data) | ||
|
|
||
| def get_domains(self, names=None): | ||
| ret = [] | ||
|
|
||
| if not names: | ||
| return self._domains | ||
|
|
||
| for n in names: | ||
| found = False | ||
| for d in self._domains: | ||
| if n == d.name: | ||
| ret.append(d) | ||
| found = True | ||
| break | ||
| # Getting here means the domain was not found. | ||
| # Todo: throw an error. | ||
| if not found: | ||
| log.die(f'domain {n} not found, ' | ||
| f'valid domains are:', *self._domain_names) | ||
| 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 |
Uh oh!
There was an error while loading. Please reload this page.