def do_subproject(self, dirname: str, method: str, kwargs):
    (disabled, required, feature) = extract_required_kwarg(kwargs, self.subproject)
    if disabled:
        mlog.log('Subproject', mlog.bold(dirname), ':', 'skipped: feature', mlog.bold(feature), 'disabled')
        return self.disabled_subproject(dirname, disabled_feature=feature)
    default_options = mesonlib.stringlistify(kwargs.get('default_options', []))
    default_options = coredata.create_options_dict(default_options)
    if (dirname == ''):
        raise InterpreterException('Subproject dir name must not be empty.')
    if (dirname[0] == '.'):
        raise InterpreterException('Subproject dir name must not start with a period.')
    if ('..' in dirname):
        raise InterpreterException('Subproject name must not contain a ".." path segment.')
    if os.path.isabs(dirname):
        raise InterpreterException('Subproject name must not be an absolute path.')
    if has_path_sep(dirname):
        mlog.warning('Subproject name has a path separator. This may cause unexpected behaviour.', location=self.current_node)
    if (dirname in self.subproject_stack):
        fullstack = (self.subproject_stack + [dirname])
        incpath = ' => '.join(fullstack)
        raise InvalidCode(('Recursive include of subprojects: %s.' % incpath))
    if (dirname in self.subprojects):
        subproject = self.subprojects[dirname]
        if (required and (not subproject.found())):
            raise InterpreterException(('Subproject "%s/%s" required but not found.' % (self.subproject_dir, dirname)))
        return subproject
    subproject_dir_abs = os.path.join(self.environment.get_source_dir(), self.subproject_dir)
    r = wrap.Resolver(subproject_dir_abs, self.coredata.get_builtin_option('wrap_mode'))
    try:
        resolved = r.resolve(dirname, method)
    except wrap.WrapException as e:
        subprojdir = os.path.join(self.subproject_dir, r.directory)
        if isinstance(e, wrap.WrapNotFoundException):
            self.print_nested_info(dirname)
        if (not required):
            mlog.log(e)
            mlog.log('Subproject ', mlog.bold(subprojdir), 'is buildable:', mlog.red('NO'), '(disabling)')
            return self.disabled_subproject(dirname, exception=e)
        raise e
    subdir = os.path.join(self.subproject_dir, resolved)
    subdir_abs = os.path.join(subproject_dir_abs, resolved)
    os.makedirs(os.path.join(self.build.environment.get_build_dir(), subdir), exist_ok=True)
    self.global_args_frozen = True
    mlog.log()
    with mlog.nested():
        mlog.log('Executing subproject', mlog.bold(dirname), 'method', mlog.bold(method), '\n')
    try:
        if (method == 'meson'):
            return self._do_subproject_meson(dirname, subdir, default_options, kwargs)
        elif (method == 'cmake'):
            return self._do_subproject_cmake(dirname, subdir, subdir_abs, default_options, kwargs)
        else:
            raise InterpreterException('The method {} is invalid for the subproject {}'.format(method, dirname))
    except InvalidCode:
        raise
    except Exception as e:
        if (not required):
            with mlog.nested():
                mlog.exception(e, prefix=mlog.yellow('Exception:'))
            mlog.log('\nSubproject', mlog.bold(dirname), 'is buildable:', mlog.red('NO'), '(disabling)')
            return self.disabled_subproject(dirname, exception=e)
        raise e
def do_subproject(self, dirname: str, method: str, kwargs):
    (disabled, required, feature) = extract_required_kwarg(kwargs, self.subproject)
    if disabled:
        mlog.log('Subproject', mlog.bold(dirname), ':', 'skipped: feature', mlog.bold(feature), 'disabled')
        return self.disabled_subproject(dirname, disabled_feature=feature)
    default_options = mesonlib.stringlistify(kwargs.get('default_options', []))
    default_options = coredata.create_options_dict(default_options)
    if (dirname == ):
        raise InterpreterException('Subproject dir name must not be empty.')
    if (dirname[0] == '.'):
        raise InterpreterException('Subproject dir name must not start with a period.')
    if ('..' in dirname):
        raise InterpreterException('Subproject name must not contain a ".." path segment.')
    if os.path.isabs(dirname):
        raise InterpreterException('Subproject name must not be an absolute path.')
    if has_path_sep(dirname):
        mlog.warning('Subproject name has a path separator. This may cause unexpected behaviour.', location=self.current_node)
    if (dirname in self.subproject_stack):
        fullstack = (self.subproject_stack + [dirname])
        incpath = ' => '.join(fullstack)
        raise InvalidCode(('Recursive include of subprojects: %s.' % incpath))
    if (dirname in self.subprojects):
        subproject = self.subprojects[dirname]
        if (required and (not subproject.found())):
            raise InterpreterException(('Subproject "%s/%s" required but not found.' % (self.subproject_dir, dirname)))
        return subproject
    subproject_dir_abs = os.path.join(self.environment.get_source_dir(), self.subproject_dir)
    r = wrap.Resolver(subproject_dir_abs, self.coredata.get_builtin_option('wrap_mode'))
    try:
        resolved = r.resolve(dirname, method)
    except wrap.WrapException as e:
        subprojdir = os.path.join(self.subproject_dir, r.directory)
        if isinstance(e, wrap.WrapNotFoundException):
            self.print_nested_info(dirname)
        if (not required):
            mlog.log(e)
            mlog.log('Subproject ', mlog.bold(subprojdir), 'is buildable:', mlog.red('NO'), '(disabling)')
            return self.disabled_subproject(dirname, exception=e)
        raise e
    subdir = os.path.join(self.subproject_dir, resolved)
    subdir_abs = os.path.join(subproject_dir_abs, resolved)
    os.makedirs(os.path.join(self.build.environment.get_build_dir(), subdir), exist_ok=True)
    self.global_args_frozen = True
    mlog.log()
    with mlog.nested():
        mlog.log('Executing subproject', mlog.bold(dirname), 'method', mlog.bold(method), '\n')
    try:
        if (method == 'meson'):
            return self._do_subproject_meson(dirname, subdir, default_options, kwargs)
        elif (method == 'cmake'):
            return self._do_subproject_cmake(dirname, subdir, subdir_abs, default_options, kwargs)
        else:
            raise InterpreterException('The method {} is invalid for the subproject {}'.format(method, dirname))
    except InvalidCode:
        raise
    except Exception as e:
        if (not required):
            with mlog.nested():
                mlog.exception(e, prefix=mlog.yellow('Exception:'))
            mlog.log('\nSubproject', mlog.bold(dirname), 'is buildable:', mlog.red('NO'), '(disabling)')
            return self.disabled_subproject(dirname, exception=e)
        raise e