# Copyright (c) 2018 Foundries.io
#
# SPDX-License-Identifier: Apache-2.0

import argparse
import contextlib
import os
import pathlib
import shlex
import sys

import yaml
from build_helpers import FIND_BUILD_DIR_DESCRIPTION, find_build_dir, is_zephyr_build, load_domains
from west.commands import Verbosity
from west.configuration import config
from west.util import WestNotFound, west_topdir
from west.version import __version__
from zcmake import DEFAULT_CMAKE_GENERATOR, CMakeCache, run_build, run_cmake
from zephyr_ext_common import Forceable

_ARG_SEPARATOR = '--'

SYSBUILD_PROJ_DIR = pathlib.Path(__file__).resolve().parent.parent.parent \
                    / pathlib.Path('share/sysbuild')

BUILD_INFO_LOG = 'build_info.yml'

BUILD_USAGE = '''\
west build [-h] [-b BOARD[@REV]]] [-d BUILD_DIR]
           [-S SNIPPET] [--shield SHIELD]
           [-t TARGET] [-p {auto, always, never}] [-c] [--cmake-only]
           [-n] [-o BUILD_OPT] [-f]
           [--sysbuild | --no-sysbuild] [--domain DOMAIN]
           [--extra-conf FILE.conf]
           [--extra-dtc-overlay FILE.overlay]
           [source_dir] -- [cmake_opt [cmake_opt ...]]
'''

BUILD_DESCRIPTION = f'''\
Convenience wrapper for building Zephyr applications.

{FIND_BUILD_DIR_DESCRIPTION}

positional arguments:
  source_dir            application source directory
  cmake_opt             extra options to pass to cmake; implies -c
                        (these must come after "--" as shown above)
'''

PRISTINE_DESCRIPTION = """\
A "pristine" build directory is empty. The -p option controls
whether the build directory is made pristine before the build
is done. A bare '--pristine' with no value is the same as
--pristine=always. Setting --pristine=auto uses heuristics to
guess if a pristine build may be necessary."""

def config_get(option, fallback):
    return config.get('build', option, fallback=fallback)

def config_getboolean(option, fallback):
    return config.getboolean('build', option, fallback=fallback)

class AlwaysIfMissing(argparse.Action):

    def __call__(self, parser, namespace, values, option_string=None):
        setattr(namespace, self.dest, values or 'always')

class Build(Forceable):

    def __init__(self):
        super().__init__(
            'build',
            # Keep this in sync with the string in west-commands.yml.
            'compile a Zephyr application',
            BUILD_DESCRIPTION,
            accepts_unknown_args=True)

        self.source_dir = None
        '''Source directory for the build, or None on error.'''

        self.build_dir = None
        '''Final build directory used to run the build, or None on error.'''

        self.created_build_dir = False
        '''True if the build directory was created; False otherwise.'''

        self.run_cmake = False
        '''True if CMake was run; False otherwise.

        Note: this only describes CMake runs done by this command. The
        build system generated by CMake may also update itself due to
        internal logic.'''

        self.cmake_cache = None
        '''Final parsed CMake cache for the build, or None on error.'''

    def _banner(self, msg):
        self.inf('-- west build: ' + msg, colorize=True)

    def do_add_parser(self, parser_adder):
        parser = parser_adder.add_parser(
            self.name,
            help=self.help,
            formatter_class=argparse.RawDescriptionHelpFormatter,
            description=self.description,
            usage=BUILD_USAGE)

        # Remember to update west-completion.bash if you add or remove
        # flags

        parser.add_argument('-b', '--board',
                        help='board to build for with optional board revision')
        # Hidden option for backwards compatibility
        parser.add_argument('-s', '--source-dir', help=argparse.SUPPRESS)
        parser.add_argument('-d', '--build-dir',
                            help='build directory to create or use')
        self.add_force_arg(parser)

        group = parser.add_argument_group('cmake and build tool')
        group.add_argument('-c', '--cmake', action='store_true',
                           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")''')
        group.add_argument('-T', '--test-item',
                           help='''Build based on test data in testcase.yaml
                           or sample.yaml. If source directory is not used
                           an argument has to be defined as
                           SOURCE_PATH/TEST_NAME.
                           E.g. samples/hello_world/sample.basic.helloworld.
                           If source directory is passed
                           then "TEST_NAME" is enough.''')
        group.add_argument('-o', '--build-opt', default=[], action='append',
                           help='''options to pass to the build tool
                           (make or ninja); may be given more than once''')
        group.add_argument('-n', '--just-print', '--dry-run', '--recon',
                            dest='dry_run', action='store_true',
                            help="just print build commands; don't run them")
        group.add_argument('-S', '--snippet', dest='snippets', metavar='SNIPPET',
                           action='append', default=[],
                           help='''add the argument to SNIPPET; may be given
                           multiple times. Forces CMake to run again if given.
                           Do not use this option with manually specified
                           -DSNIPPET... cmake arguments: the results are
                           undefined''')
        group.add_argument('--shield', dest='shields', metavar='SHIELD',
                           action='append', default=[],
                           help='''add the argument to SHIELD; may be given
                           multiple times. Forces CMake to run again if given.
                           Do not use this option with manually specified
                           -DSHIELD... cmake arguments: the results are
                           undefined''')
        group.add_argument('--extra-conf', dest='extra_conf_files', metavar='EXTRA_CONF_FILE',
                           action='append', default=[],
                           help='''add the argument to EXTRA_CONF_FILE; may be given
                           multiple times. Forces CMake to run again if given.
                           Do not use this option with manually specified
                           -DEXTRA_CONF_FILE... cmake arguments: the results are
                           undefined''')
        group.add_argument('--extra-dtc-overlay', dest='extra_dtc_overlay_files',
                           metavar='EXTRA_DTC_OVERLAY_FILE', action='append', default=[],
                           help='''add the argument to EXTRA_DTC_OVERLAY_FILE; may be given
                           multiple times. Forces CMake to run again if given.
                           Do not use this option with manually specified
                           -DEXTRA_DTC_OVERLAY_FILE... cmake arguments: the results are
                           undefined''')

        group.add_argument('--sysbuild', action=argparse.BooleanOptionalAction,
                           help='''create multi domain build system or disable it (default)''')

        group = parser.add_argument_group('pristine builds',
                                          PRISTINE_DESCRIPTION)
        group.add_argument('-p', '--pristine', choices=['auto', 'always',
                            'never'], action=AlwaysIfMissing, nargs='?',
                            help='pristine build folder setting')

        return parser

    def do_run(self, args, remainder):
        self.args = args        # Avoid having to pass them around
        self.config_board = config_get('board', None)
        self.dbg(f'args: {args} remainder: {remainder}',
                level=Verbosity.DBG_EXTREME)
        # Store legacy -s option locally
        source_dir = self.args.source_dir
        self._parse_remainder(remainder)

        if source_dir:
            if self.args.source_dir:
                self.die(
                    f"source directory specified twice:({source_dir} and {self.args.source_dir})")
            self.args.source_dir = source_dir
        self.dbg(f'source_dir: {self.args.source_dir} cmake_opts: {self.args.cmake_opts}',
                level=Verbosity.DBG_EXTREME)
        self._sanity_precheck()
        self._setup_build_dir()

        if args.pristine is not None:
            pristine = args.pristine
        else:
            # Load the pristine={auto, always, never} configuration value
            pristine = config_get('pristine', 'never')
            if pristine not in ['auto', 'always', 'never']:
                self.wrn(
                    f'treating unknown build.pristine value "{pristine}" as "never"')
                pristine = 'never'
        self.auto_pristine = pristine == 'auto'

        self.dbg(f'pristine: {pristine} auto_pristine: {self.auto_pristine}',
                level=Verbosity.DBG_MORE)
        if is_zephyr_build(self.build_dir):
            if pristine == 'always':
                self._run_pristine()
                self.run_cmake = True
            else:
                self._update_cache()
                if (self.args.cmake or self.args.cmake_opts or
                        self.args.cmake_only or self.args.snippets or
                        self.args.shields or self.args.extra_conf_files or
                        self.args.extra_dtc_overlay_files):
                    self.run_cmake = True
        else:
            self.run_cmake = True

        self.source_dir = self._find_source_dir()
        self._sanity_check()

        build_info_path = self.build_dir
        build_info_file = os.path.join(build_info_path, BUILD_INFO_LOG)
        west_workspace = west_topdir(self.source_dir)
        if not os.path.exists(build_info_path):
            os.makedirs(build_info_path)
        if not os.path.exists(build_info_file):
            build_command = {'west': {'command': ' '.join(sys.argv[:]),
                                     'topdir': str(west_workspace),
                                     'version': str(__version__)}}
            try:
                with open(build_info_file, "w") as f:
                    yaml.dump(build_command, f, default_flow_style=False)
            except Exception as e:
                self.wrn(f'Failed to create info file: {build_info_file},', e)

        board, origin = self._find_board()

        # Parse testcase.yaml or sample.yaml files for additional options.
        if self.args.test_item:
            # we get path + testitem
            item = os.path.basename(self.args.test_item)
            if self.args.source_dir:
                test_path = self.args.source_dir
            else:
                test_path = os.path.dirname(self.args.test_item)
            if test_path and os.path.exists(test_path):
                self.args.source_dir = test_path
                if not self._parse_test_item(item, board):
                    self.die("No test metadata found")
            else:
                self.die("test item path does not exist")

        self._run_cmake(board, origin, self.args.cmake_opts)
        if args.cmake_only:
            return

        self._sanity_check()
        self._update_cache()
        self.domains = load_domains(self.build_dir)

        self._run_build(args.target, args.domain)

    def _find_board(self):
        board, origin = None, None
        if self.cmake_cache:
            board, origin = (self.cmake_cache.get('CACHED_BOARD'),
                             'CMakeCache.txt')

            # A malformed CMake cache may exist, but not have a board.
            # This happens if there's a build error from a previous run.
            if board is not None:
                return (board, origin)

        if getattr(self.args, 'board', None):
            board, origin = self.args.board, 'command line'
        elif 'BOARD' in os.environ:
            board, origin = os.environ['BOARD'], 'env'
        elif getattr(self, 'config_board', None):
            board, origin = self.config_board, 'configfile'
        return board, origin

    def _parse_remainder(self, remainder):
        self.args.source_dir = None
        self.args.cmake_opts = None

        try:
            # Only one source_dir is allowed, as the first positional arg
            if remainder[0] != _ARG_SEPARATOR:
                self.args.source_dir = remainder[0]
                remainder = remainder[1:]
            # Only the first argument separator is consumed, the rest are
            # passed on to CMake
            if remainder[0] == _ARG_SEPARATOR:
                remainder = remainder[1:]
            if remainder:
                self.args.cmake_opts = remainder
        except IndexError:
            pass

    def _parse_extra_entry(self, arg, board):
        equals = arg.find('=')
        colon = arg.rfind(':', 0, equals)
        if colon != -1:
            elem = arg.split(':')
            if elem[0] != 'platform':
                # conditional configs other than platform
                # (xxx:yyy:CONFIG_FOO=bar) are not supported by 'west build'
                self.wrn(f'"west build" does not support conditional config "{arg}". Add '
                         f'"-D{arg[colon+1:]}" to the supplied CMake arguments if desired.')
                return None
            elif elem[1] not in board:
                return None
            return elem[2]
        else:
            return arg

    def _parse_test_item(self, test_item, board):
        found_test_metadata = False
        for yp in ['sample.yaml', 'testcase.yaml']:
            yf = os.path.join(self.args.source_dir, yp)
            if not os.path.exists(yf):
                continue
            found_test_metadata = True
            with open(yf) as stream:
                try:
                    y = yaml.safe_load(stream)
                except yaml.YAMLError as exc:
                    self.die(exc)
            common = y.get('common')
            tests = y.get('tests')
            if not tests:
                self.die(f"No tests found in {yf}")
            if test_item not in tests:
                self.die(f"Test item {test_item} not found in {yf}")
            item = tests.get(test_item)

            sysbuild = False
            extra_dtc_overlay_files = []
            extra_overlay_confs = []
            extra_conf_files = []
            required_snippets = []
            for section in [common, item]:
                if not section:
                    continue
                sysbuild = section.get('sysbuild', sysbuild)
                for data in [
                        'extra_args',
                        'extra_configs',
                        'extra_conf_files',
                        'extra_overlay_confs',
                        'extra_dtc_overlay_files',
                        'required_snippets'
                        ]:
                    extra = section.get(data)
                    if not extra:
                        continue
                    if isinstance(extra, str):
                        arg_list = extra.split(" ")
                    else:
                        arg_list = extra

                    if data == 'extra_configs':
                        args = []
                        for arg in arg_list:
                            entry = self._parse_extra_entry(arg, board)
                            if entry is not None:
                                args.append("-D{}".format(entry.replace('"', '\"')))
                    elif data == 'extra_args':
                        # Retain quotes around config options
                        config_options = [arg for arg in arg_list if arg.startswith("CONFIG_")]
                        non_config_option_candidates = [
                            arg for arg in arg_list if not arg.startswith("CONFIG_")
                        ]
                        args = ["-D{}".format(a.replace('"', '\"')) for a in config_options]

                        non_config_options = []
                        for arg in non_config_option_candidates:
                            entry = self._parse_extra_entry(arg, board)
                            if entry is not None:
                                non_config_options.append(entry)

                        args.extend([
                            "-D{}".format(arg.replace('"', '')) for arg in non_config_options
                        ])
                    elif data == 'extra_conf_files':
                        extra_conf_files.extend(arg_list)
                        continue
                    elif data == 'extra_overlay_confs':
                        extra_overlay_confs.extend(arg_list)
                        continue
                    elif data == 'extra_dtc_overlay_files':
                        extra_dtc_overlay_files.extend(arg_list)
                        continue
                    elif data == 'required_snippets':
                        required_snippets.extend(arg_list)
                        continue

                    if self.args.cmake_opts:
                        self.args.cmake_opts.extend(args)
                    else:
                        self.args.cmake_opts = args

            self.args.sysbuild = sysbuild

        if found_test_metadata:
            args = []
            if extra_conf_files:
                args.append(f"CONF_FILE=\"{';'.join(extra_conf_files)}\"")

            if extra_dtc_overlay_files:
                args.append(f"DTC_OVERLAY_FILE=\"{';'.join(extra_dtc_overlay_files)}\"")

            if extra_overlay_confs:
                args.append(f"OVERLAY_CONFIG=\"{';'.join(extra_overlay_confs)}\"")

            if required_snippets:
                args.append(f"SNIPPET=\"{';'.join(required_snippets)}\"")

            # Build the final argument list
            args_expanded = ["-D{}".format(a.replace('"', '')) for a in args]

            if self.args.cmake_opts:
                self.args.cmake_opts.extend(args_expanded)
            else:
                self.args.cmake_opts = args_expanded

        return found_test_metadata

    def _sanity_precheck(self):
        app = self.args.source_dir
        if app:
            self.check_force(
                os.path.isdir(app),
                f'source directory {app} does not exist')
            self.check_force(
                'CMakeLists.txt' in os.listdir(app),
                f"{app} doesn't contain a CMakeLists.txt")

    def _update_cache(self):
        with contextlib.suppress(FileNotFoundError):
            self.cmake_cache = CMakeCache.from_build_dir(self.build_dir)

    def _get_dir_fmt_context(self):
        # Return a dictionary of build attributes which are used while
        # substituting the placeholders in the build.dir-fmt format string.
        source_dir = pathlib.Path(self._find_source_dir())
        app = source_dir.name
        board, _ = self._find_board()
        try:
            west_top_dir = west_topdir(source_dir)
        except WestNotFound:
            west_top_dir = pathlib.Path.cwd()
        context = {
            "west_topdir": str(west_top_dir),
            "source_dir": str(source_dir),
            "app": app,
            "board": board,
        }
        if source_dir.is_relative_to(west_top_dir):
            context['source_dir_workspace'] = str(source_dir.relative_to(west_top_dir))
        else:
            context['source_dir_workspace'] = str(source_dir.relative_to(source_dir.anchor))
        self.dbg(f'dir-fmt context: {context}', level=Verbosity.DBG_EXTREME)
        return context

    def _setup_build_dir(self):
        # Initialize build_dir and created_build_dir attributes.
        # If we created the build directory, we must run CMake.
        self.dbg('setting up build directory', level=Verbosity.DBG_EXTREME)
        # The CMake Cache has not been loaded yet, so this is safe

        context = self._get_dir_fmt_context()
        build_dir = find_build_dir(self.args.build_dir, **context)
        if not build_dir:
            self.die('Unable to determine a default build folder. Check '
                    'your build.dir-fmt configuration option')

        if os.path.exists(build_dir):
            if not os.path.isdir(build_dir):
                self.die(f'build directory {build_dir} exists and is not a directory')
        else:
            os.makedirs(build_dir, exist_ok=False)
            self.created_build_dir = True
            self.run_cmake = True

        self.build_dir = build_dir

    def _find_source_dir(self):
        # Initialize source_dir attribute, either from command line argument,
        # implicitly from the build directory's CMake cache, or using the
        # default (current working directory).
        self.dbg('setting up source directory', level=Verbosity.DBG_EXTREME)
        if self.args.source_dir:
            source_dir = self.args.source_dir
        elif self.cmake_cache:
            source_dir = self.cmake_cache.get('APP_DIR')

            if not source_dir:
                source_dir = self.cmake_cache.get('APPLICATION_SOURCE_DIR')

            if not source_dir:
                source_dir = self.cmake_cache.get('CMAKE_HOME_DIRECTORY')

            if not source_dir:
                # This really ought to be there. The build directory
                # must be corrupted somehow. Let's see what we can do.
                self.die('build directory', self.build_dir,
                        'CMake cache has no CMAKE_HOME_DIRECTORY;',
                        'please give a source_dir')
        else:
            source_dir = os.getcwd()
        return os.path.abspath(source_dir)

    def _sanity_check_source_dir(self):
        if self.source_dir == self.build_dir:
            # There's no forcing this.
            self.die(f'source and build directory {self.source_dir} cannot be the same; '
                    f'use --build-dir {self.build_dir} to specify a build directory')

        srcrel = os.path.relpath(self.source_dir)
        self.check_force(
            not is_zephyr_build(self.source_dir),
            f'it looks like {srcrel} is a build directory: '
            f'did you mean --build-dir {srcrel} instead?')
        self.check_force(
            'CMakeLists.txt' in os.listdir(self.source_dir),
            f'source directory "{srcrel}" does not contain '
            'a CMakeLists.txt; is this really what you '
            'want to build? (Use -s SOURCE_DIR to specify '
            'the application source directory)')

    def _sanity_check(self):
        # Sanity check the build configuration.
        # Side effect: may update cmake_cache attribute.
        self.dbg('sanity checking the build', level=Verbosity.DBG_EXTREME)
        self._sanity_check_source_dir()

        if not self.cmake_cache:
            return          # That's all we can check without a cache.

        if "CMAKE_PROJECT_NAME" not in self.cmake_cache:
            # This happens sometimes when a build system is not
            # completely generated due to an error during the
            # CMake configuration phase.
            self.run_cmake = True

        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

        self.dbg('APP_DIR:', cached_app, level=Verbosity.DBG_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

        self.dbg('pristine:', self.auto_pristine, level=Verbosity.DBG_EXTREME)

        # If the build directory specifies a source app, make sure it's
        # consistent with --source-dir.
        apps_mismatched = (source_abs and cached_abs and
            pathlib.Path(source_abs).resolve() != pathlib.Path(cached_abs).resolve())

        self.check_force(
            not apps_mismatched or self.auto_pristine,
            f'Build directory "{self.build_dir}" is for application "{cached_abs}", but source '
            f'directory "{source_abs}" was specified; please clean it, use --pristine, '
            'or use --build-dir to set another build directory')

        if apps_mismatched:
            self.run_cmake = True  # If they insist, we need to re-run cmake.

        # If CACHED_BOARD is not defined, we need some other way to
        # find the board.
        cached_board = self.cmake_cache.get('CACHED_BOARD')
        self.dbg('CACHED_BOARD:', cached_board, level=Verbosity.DBG_EXTREME)
        # If apps_mismatched and self.auto_pristine are true, we will
        # run pristine on the build, invalidating the cached
        # board. In that case, we need some way of getting the board.
        self.check_force((cached_board and
                          not (apps_mismatched and self.auto_pristine))
                         or self.args.board or self.config_board or
                         os.environ.get('BOARD'),
                         'Cached board not defined, please provide it '
                         '(provide --board, set default with '
                         '"west config build.board <BOARD>", or set '
                         'BOARD in the environment)')

        # Check consistency between cached board and --board.
        boards_mismatched = (self.args.board and cached_board and
                             self.args.board != cached_board)
        self.check_force(
            not boards_mismatched or self.auto_pristine,
            f'Build directory {self.build_dir} targets board {cached_board}, '
            f'but board {self.args.board} was specified. '
            '(Clean the directory, use --pristine, or use --build-dir to '
            'specify a different one.)')

        if self.auto_pristine and (apps_mismatched or boards_mismatched):
            self._run_pristine()
            self.cmake_cache = None
            self.dbg('run_cmake:', True, level=Verbosity.DBG_EXTREME)
            self.run_cmake = True

            # Tricky corner-case: The user has not specified a build folder but
            # there was one in the CMake cache. Since this is going to be
            # invalidated, reset to CWD and re-run the basic tests.
            if ((boards_mismatched and not apps_mismatched) and
                    (not source_abs and cached_abs)):
                self.source_dir = self._find_source_dir()
                self._sanity_check_source_dir()

    def _run_cmake(self, board, origin, cmake_opts):
        if board is None and config_getboolean('board_warn', True):
            self.wrn('This looks like a fresh build and BOARD is unknown;',
                    "so it probably won't work. To fix, use",
                    '--board=<your-board>.')
            self.inf('Note: to silence the above message, run',
                    "'west config build.board_warn false'")

        if not self.run_cmake:
            return

        cmake_env = None

        self._banner('generating a build system')

        if board is not None and origin != 'CMakeCache.txt':
            cmake_opts = [f'-DBOARD={board}']
        else:
            cmake_opts = []
        if self.args.cmake_opts:
            cmake_opts.extend(self.args.cmake_opts)
        if self.args.snippets:
            cmake_opts.append(f'-DSNIPPET={";".join(self.args.snippets)}')
        if self.args.shields:
            cmake_opts.append(f'-DSHIELD={";".join(self.args.shields)}')
        if self.args.extra_conf_files:
            cmake_opts.append(f'-DEXTRA_CONF_FILE={";".join(self.args.extra_conf_files)}')
        if self.args.extra_dtc_overlay_files:
            cmake_opts.append(
                f'-DEXTRA_DTC_OVERLAY_FILE='
                f'{";".join(self.args.extra_dtc_overlay_files)}'
            )

        user_args = config_get('cmake-args', None)
        if user_args:
            cmake_opts.extend(shlex.split(user_args))

        config_sysbuild = config_getboolean('sysbuild', False)
        if self.args.sysbuild is True or (config_sysbuild and self.args.sysbuild is not False):
            cmake_opts.extend([f'-S{SYSBUILD_PROJ_DIR}'])
            cmake_env = os.environ.copy()
            cmake_env["APP_DIR"] = str(self.source_dir)
        else:
            # self.args.sysbuild == False or config sysbuild False
            cmake_opts.extend([f'-S{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
        # to Just Work:
        #
        # west build -- -DOVERLAY_CONFIG=relative-path.conf
        final_cmake_args = [f'-DWEST_PYTHON={pathlib.Path(sys.executable).as_posix()}',
                            f'-B{self.build_dir}',
                            f'-G{config_get("generator", DEFAULT_CMAKE_GENERATOR)}']
        if cmake_opts:
            final_cmake_args.extend(cmake_opts)
        run_cmake(final_cmake_args, dry_run=self.args.dry_run, env=cmake_env)

    def _run_pristine(self):
        self._banner(f'making build dir {self.build_dir} pristine')
        if not is_zephyr_build(self.build_dir):
            self.die('Refusing to run pristine on a folder that is not a '
                     'Zephyr build system')

        cache = CMakeCache.from_build_dir(self.build_dir)

        app_src_dir = cache.get('APPLICATION_SOURCE_DIR')
        app_bin_dir = cache.get('APPLICATION_BINARY_DIR')

        cmake_args = [f'-DBINARY_DIR={app_bin_dir}',
                      f'-DSOURCE_DIR={app_src_dir}',
                      '-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, domain):
        if target:
            self._banner(f'running target {target}')
        elif self.run_cmake:
            self._banner('building application')
        extra_args = ['--target', target] if target else []
        if self.args.build_opt:
            extra_args.append('--')
            extra_args.extend(self.args.build_opt)
        if self.args.verbose:
            self._append_verbose_args(extra_args,
                                      not bool(self.args.build_opt))

        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:
            self._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
        # 3.14. When Zephyr's minimum version is at least that, we can
        # drop this nonsense and just run "cmake --build BUILD -v".
        self._update_cache()
        if not self.cmake_cache:
            return
        generator = self.cmake_cache.get('CMAKE_GENERATOR')
        if not generator:
            return
        # Substring matching is for things like "Eclipse CDT4 - Ninja".
        if 'Ninja' in generator:
            if add_dashes:
                extra_args.append('--')
            extra_args.append('-v')
        elif generator == 'Unix Makefiles':
            if add_dashes:
                extra_args.append('--')
            extra_args.append('VERBOSE=1')
