Esempio n. 1
0
def find_build_dir(dir, **kwargs):
    '''Heuristic for finding a build directory.

    The default build directory is computed by reading the build.dir-fmt
    configuration option, defaulting to DEFAULT_BUILD_DIR if not set. It might
    be None if the build.dir-fmt configuration option is set but cannot be
    resolved.
    If the given argument is truthy, it is returned. Otherwise, if
    the default build folder is a build directory, it is returned.
    Next, if the current working directory is a build directory, it is
    returned. Finally, the default build directory is returned (may be None).
    '''

    if dir:
        build_dir = dir
    else:
        cwd = os.getcwd()
        default = config.get('build', 'dir-fmt', fallback=DEFAULT_BUILD_DIR)
        try:
            default = _resolve_build_dir(default, cwd, **kwargs)
            log.dbg('config dir-fmt: {}'.format(default),
                    level=log.VERBOSE_EXTREME)
        except KeyError:
            default = None
        if default and is_zephyr_build(default):
            build_dir = default
        elif is_zephyr_build(cwd):
            build_dir = cwd
        else:
            build_dir = default
    log.dbg('build dir: {}'.format(build_dir), level=log.VERBOSE_EXTREME)
    if build_dir:
        return os.path.abspath(build_dir)
    else:
        return None
Esempio n. 2
0
    def do_run(self, args, user_args):
        # manifest.path is not supposed to be set during init, thus clear it
        # for the session and update it to correct location when complete.
        if config.get('manifest', 'path', fallback=None) is not None:
            config.remove_option('manifest', 'path')

        manifest_file = os.path.join(args.local or args.cache, 'west.yml')

        projects = Manifest.from_file(manifest_file).projects
        manifest_project = projects[MANIFEST_PROJECT_INDEX]

        if args.local is not None:
            rel_manifest = os.path.relpath(args.local, util.west_topdir())
            update_config('manifest', 'path', rel_manifest)
        else:
            if manifest_project.path == '':
                url_path = urlparse(args.manifest_url).path
                manifest_project.path = posixpath.basename(url_path)
                manifest_project.abspath = os.path.realpath(
                    os.path.join(util.west_topdir(), manifest_project.path))
                manifest_project.name = manifest_project.path

            shutil.move(args.cache, manifest_project.abspath)
            update_config('manifest', 'path', manifest_project.path)

        for project in projects:
            if project.path == 'zephyr':
                update_config('zephyr', 'base', project.path)
Esempio n. 3
0
    def getConfig(self, name):
        """Gets a configuration for a command
        :param self:
            Self
        :param name:
            The name of the configuration to get

        :return None:
            Configuration not found
        :return String:
            The configurtion's value
        """

        # We'll let them qualify namespaces with ':' in their provided name,
        # but we need to split off any namespaces and combine with our uber
        # namespace; and provide the final configuration option name as a
        # standalone string
        fields = name.split(".")

        namespace = Command.ConfigPrefix

        if len(fields) > 1:
            namespace += ":{}".format(fields[0])
            option = fields[1]
        else:
            option = fields[0]

        return config.get(namespace, option, fallback=None)
Esempio n. 4
0
def manifest_path():
    '''Return the path to the manifest file.

    Raises WestNotFound if called from outside of a west working directory.'''
    try:
        return os.path.join(util.west_topdir(), config.get('manifest', 'path'),
                            'west.yml')
    except (configparser.NoOptionError, configparser.NoSectionError) as e:
        raise MalformedConfig('missing key: \'{}\' in west config file'.format(
            e.args[0])) from e
Esempio n. 5
0
 def fetch_strategy(self, args):
     cfg = config.get('update', 'fetch', fallback=None)
     if cfg is not None and cfg not in ('always', 'smart'):
         log.wrn(f'ignoring invalid config update.fetch={cfg}; '
                 'choices: always, smart')
         cfg = None
     if args.fetch_strategy:
         return args.fetch_strategy
     elif cfg:
         return cfg
     else:
         return 'smart'
Esempio n. 6
0
def load_runners_yaml(path, args):
    # Load runners.yaml using its location in the CMake cache,
    # allowing a command line override for the cache file location.

    try:
        with open(path, 'r') as f:
            config = yaml.safe_load(f.read())
    except FileNotFoundError:
        log.die(f'runners.yaml file not found: {path}')

    if not config.get('runners'):
        log.wrn(f'no pre-configured runners in {path}; '
                "this probably won't work")

    return config
Esempio n. 7
0
def manifest_path():
    '''Return the path to the manifest file.

    Raises: WestNotFound if called from outside of a west working directory,
    MalformedConfig if the configuration file is missing a manifest.path key,
    and FileNotFoundError if the manifest.path file doesn't exist.'''
    try:
        ret = os.path.join(util.west_topdir(), config.get('manifest', 'path'),
                           'west.yml')
    except (configparser.NoOptionError, configparser.NoSectionError) as e:
        raise MalformedConfig('no "manifest.path" config option is set') from e
    # It's kind of annoying to manually instantiate a FileNotFoundError.
    # This seems to be the best way.
    if not os.path.isfile(ret):
        raise OSError(errno.ENOENT, os.strerror(errno.ENOENT), ret)
    return ret
Esempio n. 8
0
def _update_west(rebase, keep_descendants):
    _banner('self-updating west:')
    with _error_context(_FAILED_UPDATE_MSG):
        project = _west_project()
        old_sha = _sha(project, 'HEAD')
        _update(project, rebase, keep_descendants)

        if config.get('zephyr', 'base', fallback=None) is None:
            for proj in _all_projects():
                if proj.path == 'zephyr':
                    update_config('zephyr', 'base', proj.path)
                    break

        if old_sha != _sha(project, 'HEAD'):
            _msg(project.format('{name}: updated to {revision} (from {url}).'))

            # Signal self-update, which will cause a restart. This is a bit
            # nicer than doing the restart here, as callers will have a
            # chance to flush file buffers, etc.
            raise WestUpdated()
Esempio n. 9
0
def get_build_dir(args, die_if_none=True):
    # Get the build directory for the given argument list and environment.
    if args.build_dir:
        return args.build_dir

    guess = config.get('build', 'guess-dir', fallback='never')
    guess = guess == 'runners'
    dir = find_build_dir(None, guess)

    if dir and is_zephyr_build(dir):
        return dir
    elif die_if_none:
        msg = '--build-dir was not given, '
        if dir:
            msg = msg + 'and neither {} nor {} are zephyr build directories.'
        else:
            msg = msg + ('{} is not a build directory and the default build '
                         'directory cannot be determined. Check your '
                         'build.dir-fmt configuration option')
        log.die(msg.format(getcwd(), dir))
    else:
        return None
Esempio n. 10
0
    def do_run(self, args, ignored):
        if self.topdir:
            zb = os.environ.get('ZEPHYR_BASE')
            if zb:
                msg = textwrap.dedent('''
                Note:
                    In your environment, ZEPHYR_BASE is set to:
                    {}

                    This forces west to search for an installation there.
                    Try unsetting ZEPHYR_BASE and re-running this command.'''.
                                      format(zb))
            else:
                msg = ''
            log.die('already initialized in {}, aborting.{}'.format(
                self.topdir, msg))

        if args.local and (args.manifest_url or args.manifest_rev):
            log.die('-l cannot be combined with -m or --mr')

        if shutil.which('git') is None:
            log.die("can't find git; install it or ensure it's on your PATH")

        # west.manifest will try to read manifest.path and use it when
        # parsing the manifest. Clear it out for now so we can parse
        # the manifest without it; local() or bootstrap() will set it
        # properly.
        if config.get('manifest', 'path', fallback=None) is not None:
            config.remove_option('manifest', 'path')
        if args.local:
            projects, manifest_dir = self.local(args)
        else:
            projects, manifest_dir = self.bootstrap(args)

        self.fixup_zephyr_base(projects)

        log.banner('Initialized. Now run "west update" inside {}.'.format(
            self.topdir))
Esempio n. 11
0
    def do_run(self, args, ignored):
        if self.topdir:
            log.die('already in an installation ({}), aborting'.
                    format(self.topdir))

        if shutil.which('git') is None:
            log.die("can't find git; install it or ensure it's on your PATH")

        # west.manifest will try to read manifest.path and use it when
        # parsing the manifest. Clear it out for now so we can parse
        # the manifest without it; local() or bootstrap() will set it
        # properly.
        if config.get('manifest', 'path', fallback=None) is not None:
            config.remove_option('manifest', 'path')
        if args.local:
            projects, manifest_dir = self.local(args)
        else:
            projects, manifest_dir = self.bootstrap(args)

        self.fixup_zephyr_base(projects)

        _banner('Initialized. Now run "west update" inside {}.'.
                format(self.topdir))
Esempio n. 12
0
def config_get(option, fallback):
    return config.get('build', option, fallback=fallback)
Esempio n. 13
0
    def _load(self, data, sections):
        # Initialize this instance's fields from values given in the
        # manifest data, which must be validated according to the schema.
        if 'west' in sections:
            west = data.get('west', {})

            url = west.get('url') or WEST_URL_DEFAULT
            revision = west.get('revision') or WEST_REV_DEFAULT

            self.west_project = SpecialProject('west',
                                               url=url,
                                               revision=revision,
                                               path=os.path.join(
                                                   '.west', 'west'))

        # Next is the manifest section
        if 'manifest' not in sections:
            return

        projects = []
        project_abspaths = set()

        manifest = data.get('manifest')

        path = config.get('manifest', 'path', fallback=None)

        self_tag = manifest.get('self')
        if path is None:
            path = self_tag.get('path') if self_tag else ''
        west_commands = self_tag.get('west-commands') if self_tag else None

        project = SpecialProject(path, path=path, west_commands=west_commands)
        projects.insert(MANIFEST_PROJECT_INDEX, project)

        # Map from each remote's name onto that remote's data in the manifest.
        remotes = tuple(
            Remote(r['name'], r['url-base']) for r in manifest['remotes'])
        remotes_dict = {r.name: r for r in remotes}

        # Get any defaults out of the manifest.
        #
        # md = manifest defaults (dictionary with values parsed from
        # the manifest)
        md = manifest.get('defaults', dict())
        mdrem = md.get('remote')
        if mdrem:
            # The default remote name, if provided, must refer to a
            # well-defined remote.
            if mdrem not in remotes_dict:
                self._malformed(
                    'default remote {} is not defined'.format(mdrem))
            default_remote = remotes_dict[mdrem]
            default_remote_name = mdrem
        else:
            default_remote = None
            default_remote_name = None
        defaults = Defaults(remote=default_remote, revision=md.get('revision'))

        # mp = manifest project (dictionary with values parsed from
        # the manifest)
        for mp in manifest['projects']:
            # Validate the project name.
            name = mp['name']
            if name == 'west':
                self._malformed('the name "west" is reserved and cannot '
                                'be used to name a manifest project')

            # Validate the project remote.
            remote_name = mp.get('remote', default_remote_name)
            if remote_name is None:
                self._malformed(
                    'project {} does not specify a remote'.format(name))
            if remote_name not in remotes_dict:
                self._malformed('project {} remote {} is not defined'.format(
                    name, remote_name))

            # Create the project instance for final checking.
            project = Project(name,
                              remotes_dict[remote_name],
                              defaults,
                              path=mp.get('path'),
                              clone_depth=mp.get('clone-depth'),
                              revision=mp.get('revision'),
                              west_commands=mp.get('west-commands'))

            # Two projects cannot have the same path. We use absolute
            # paths to check for collisions to ensure paths are
            # normalized (e.g. for case-insensitive file systems or
            # in cases like on Windows where / or \ may serve as a
            # path component separator).
            if project.abspath in project_abspaths:
                self._malformed('project {} path {} is already in use'.format(
                    project.name, project.path))

            project_abspaths.add(project.abspath)
            projects.append(project)

        self.defaults = defaults
        self.remotes = remotes
        self._remotes_dict = remotes_dict
        self.projects = tuple(projects)
Esempio n. 14
0
    def _load(self, data):
        # Initialize this instance's fields from values given in the
        # manifest data, which must be validated according to the schema.
        projects = []
        project_names = set()
        project_abspaths = set()

        manifest = data.get('manifest')

        path = config.get('manifest', 'path', fallback=None)

        self_tag = manifest.get('self')
        if path is None:
            path = self_tag.get('path') if self_tag else ''

        # Both are named "self.path" depending on where you look at.
        if path and self.path:
            realpath = os.path.dirname(self.path)
            realdir = os.path.basename(realpath)
            if realdir not in [os.path.basename(path), 'manifest-tmp']:
                raise MalformedManifest("""Manifest self.path is '{}' \
but located in directory '{}'""".format(path, realpath))

        west_commands = self_tag.get('west-commands') if self_tag else None

        project = ManifestProject(path=path, west_commands=west_commands)
        projects.insert(MANIFEST_PROJECT_INDEX, project)

        # Map from each remote's name onto that remote's data in the manifest.
        remotes = tuple(
            Remote(r['name'], r['url-base'])
            for r in manifest.get('remotes', []))
        remotes_dict = {r.name: r for r in remotes}

        # Get any defaults out of the manifest.
        #
        # md = manifest defaults (dictionary with values parsed from
        # the manifest)
        md = manifest.get('defaults', dict())
        mdrem = md.get('remote')
        if mdrem:
            # The default remote name, if provided, must refer to a
            # well-defined remote.
            if mdrem not in remotes_dict:
                self._malformed(
                    'default remote {} is not defined'.format(mdrem))
            default_remote = remotes_dict[mdrem]
            default_remote_name = mdrem
        else:
            default_remote = None
            default_remote_name = None
        defaults = Defaults(remote=default_remote, revision=md.get('revision'))

        # mp = manifest project (dictionary with values parsed from
        # the manifest)
        for mp in manifest['projects']:
            # Validate the project name.
            name = mp['name']

            # Validate the project remote or URL.
            remote_name = mp.get('remote', default_remote_name)
            url = mp.get('url')
            if remote_name is None and url is None:
                self._malformed(
                    'project {} does not specify a remote or URL'.format(name))
            if remote_name:
                if remote_name not in remotes_dict:
                    self._malformed(
                        'project {} remote {} is not defined'.format(
                            name, remote_name))
                remote = remotes_dict[remote_name]
            else:
                remote = None

            # Create the project instance for final checking.
            try:
                project = Project(name,
                                  defaults,
                                  path=mp.get('path'),
                                  clone_depth=mp.get('clone-depth'),
                                  revision=mp.get('revision'),
                                  west_commands=mp.get('west-commands'),
                                  remote=remote,
                                  url=url)
            except ValueError as ve:
                self._malformed(ve.args[0])

            # Project names must be unique.
            if project.name in project_names:
                self._malformed('project name {} is already used'.format(
                    project.name))
            # Two projects cannot have the same path. We use absolute
            # paths to check for collisions to ensure paths are
            # normalized (e.g. for case-insensitive file systems or
            # in cases like on Windows where / or \ may serve as a
            # path component separator).
            if project.abspath in project_abspaths:
                self._malformed('project {} path {} is already in use'.format(
                    project.name, project.path))

            project_names.add(project.name)
            project_abspaths.add(project.abspath)
            projects.append(project)

        self.defaults = defaults
        self.remotes = remotes
        self._remotes_dict = remotes_dict
        self.projects = tuple(projects)
Esempio n. 15
0
    def do_run(self, args, remainder):
        self.args = args        # Avoid having to pass them around
        log.dbg('args: {} remainder: {}'.format(args, remainder,
                                                level=log.VERBOSE_EXTREME))
        # Store legacy -s option locally
        source_dir = self.args.source_dir
        self._parse_remainder(remainder)
        if source_dir:
            if self.args.source_dir:
                log.die("source directory specified twice:({} and {})".format(
                                            source_dir, self.args.source_dir))
            self.args.source_dir = source_dir
        log.dbg('source_dir: {} cmake_opts: {}'.format(self.args.source_dir,
                                                       self.args.cmake_opts))
        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('build', 'pristine', fallback='never')
            if pristine not in ['auto', 'always', 'never']:
                log.wrn('treating unknown build.pristine value "{}" as "never"'.
                        format(pristine))
                pristine = 'never'
        self.auto_pristine = (pristine == 'auto')

        log.dbg('pristine: {} auto_pristine: {}'.format(pristine,
                                                        self.auto_pristine))
        if is_zephyr_build(self.build_dir):
            if pristine == 'always':
                log.inf('Making build dir {} pristine'.format(self.build_dir))
                self._run_build('pristine')
                self.run_cmake = True
            else:
                self._update_cache()
                if self.args.cmake or self.args.cmake_opts:
                    self.run_cmake = True
        else:
            self.run_cmake = True
        self._setup_source_dir()
        self._sanity_check()

        log.inf('source directory: {}'.format(self.source_dir), colorize=True)
        log.inf('build directory: {}{}'.
                format(self.build_dir,
                       (' (created)' if self.created_build_dir
                        else '')),
                colorize=True)
        if self.cmake_cache:
            board = self.cmake_cache.get('CACHED_BOARD')
        elif self.args.board:
            board = self.args.board
        else:
            board = 'UNKNOWN'   # shouldn't happen
        log.inf('BOARD:', board, colorize=True)

        self._run_cmake(self.args.cmake_opts)
        self._sanity_check()
        self._update_cache()

        self._run_build(args.target)