|
|
|
@ -32,6 +32,9 @@ from .mesonlib import MachineChoice, OptionKey |
|
|
|
|
if T.TYPE_CHECKING: |
|
|
|
|
import argparse |
|
|
|
|
|
|
|
|
|
# cannot be TV_Loggable, because non-ansidecorators do direct string concat |
|
|
|
|
LOGLINE = T.Union[str, mlog.AnsiDecorator] |
|
|
|
|
|
|
|
|
|
def add_arguments(parser: 'argparse.ArgumentParser') -> None: |
|
|
|
|
coredata.register_builtin_arguments(parser) |
|
|
|
|
parser.add_argument('builddir', nargs='?', default='.') |
|
|
|
@ -40,7 +43,7 @@ def add_arguments(parser: 'argparse.ArgumentParser') -> None: |
|
|
|
|
parser.add_argument('--no-pager', action='store_false', dest='pager', |
|
|
|
|
help='Do not redirect output to a pager') |
|
|
|
|
|
|
|
|
|
def stringify(val: T.Any) -> T.Union[str, T.List[T.Any]]: # T.Any because of recursion... |
|
|
|
|
def stringify(val: T.Any) -> str: |
|
|
|
|
if isinstance(val, bool): |
|
|
|
|
return str(val).lower() |
|
|
|
|
elif isinstance(val, list): |
|
|
|
@ -57,16 +60,16 @@ class ConfException(mesonlib.MesonException): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Conf: |
|
|
|
|
def __init__(self, build_dir): |
|
|
|
|
def __init__(self, build_dir: str): |
|
|
|
|
self.build_dir = os.path.abspath(os.path.realpath(build_dir)) |
|
|
|
|
if 'meson.build' in [os.path.basename(self.build_dir), self.build_dir]: |
|
|
|
|
self.build_dir = os.path.dirname(self.build_dir) |
|
|
|
|
self.build = None |
|
|
|
|
self.max_choices_line_length = 60 |
|
|
|
|
self.name_col = [] |
|
|
|
|
self.value_col = [] |
|
|
|
|
self.choices_col = [] |
|
|
|
|
self.descr_col = [] |
|
|
|
|
self.name_col: T.List[LOGLINE] = [] |
|
|
|
|
self.value_col: T.List[LOGLINE] = [] |
|
|
|
|
self.choices_col: T.List[LOGLINE] = [] |
|
|
|
|
self.descr_col: T.List[LOGLINE] = [] |
|
|
|
|
self.all_subprojects: T.Set[str] = set() |
|
|
|
|
|
|
|
|
|
if os.path.isdir(os.path.join(self.build_dir, 'meson-private')): |
|
|
|
@ -85,13 +88,13 @@ class Conf: |
|
|
|
|
else: |
|
|
|
|
raise ConfException(f'Directory {build_dir} is neither a Meson build directory nor a project source directory.') |
|
|
|
|
|
|
|
|
|
def clear_cache(self): |
|
|
|
|
def clear_cache(self) -> None: |
|
|
|
|
self.coredata.clear_cache() |
|
|
|
|
|
|
|
|
|
def set_options(self, options) -> bool: |
|
|
|
|
def set_options(self, options: T.Dict[OptionKey, str]) -> bool: |
|
|
|
|
return self.coredata.set_options(options) |
|
|
|
|
|
|
|
|
|
def save(self): |
|
|
|
|
def save(self) -> None: |
|
|
|
|
# Do nothing when using introspection |
|
|
|
|
if self.default_values_only: |
|
|
|
|
return |
|
|
|
@ -127,12 +130,16 @@ class Conf: |
|
|
|
|
mlog.log(line[0]) |
|
|
|
|
continue |
|
|
|
|
|
|
|
|
|
def wrap_text(text, width): |
|
|
|
|
def wrap_text(text: LOGLINE, width: int) -> mlog.TV_LoggableList: |
|
|
|
|
raw = text.text if isinstance(text, mlog.AnsiDecorator) else text |
|
|
|
|
indent = ' ' if raw.startswith('[') else '' |
|
|
|
|
wrapped = textwrap.wrap(raw, width, subsequent_indent=indent) |
|
|
|
|
wrapped_ = textwrap.wrap(raw, width, subsequent_indent=indent) |
|
|
|
|
# We cast this because https://github.com/python/mypy/issues/1965 |
|
|
|
|
# mlog.TV_LoggableList does not provide __len__ for stringprotocol |
|
|
|
|
if isinstance(text, mlog.AnsiDecorator): |
|
|
|
|
wrapped = [mlog.AnsiDecorator(i, text.code) for i in wrapped] |
|
|
|
|
wrapped = T.cast('T.List[LOGLINE]', [mlog.AnsiDecorator(i, text.code) for i in wrapped_]) |
|
|
|
|
else: |
|
|
|
|
wrapped = T.cast('T.List[LOGLINE]', wrapped_) |
|
|
|
|
# Add padding here to get even rows, as `textwrap.wrap()` will |
|
|
|
|
# only shorten, not lengthen each item |
|
|
|
|
return [str(i) + ' ' * (width - len(i)) for i in wrapped] |
|
|
|
@ -149,15 +156,15 @@ class Conf: |
|
|
|
|
items = [l[i] if l[i] else ' ' * four_column[i] for i in range(4)] |
|
|
|
|
mlog.log(*items) |
|
|
|
|
|
|
|
|
|
def split_options_per_subproject(self, options: 'coredata.KeyedOptionDictType') -> T.Dict[str, 'coredata.KeyedOptionDictType']: |
|
|
|
|
result: T.Dict[str, 'coredata.KeyedOptionDictType'] = {} |
|
|
|
|
def split_options_per_subproject(self, options: 'coredata.KeyedOptionDictType') -> T.Dict[str, 'coredata.MutableKeyedOptionDictType']: |
|
|
|
|
result: T.Dict[str, 'coredata.MutableKeyedOptionDictType'] = {} |
|
|
|
|
for k, o in options.items(): |
|
|
|
|
if k.subproject: |
|
|
|
|
self.all_subprojects.add(k.subproject) |
|
|
|
|
result.setdefault(k.subproject, {})[k] = o |
|
|
|
|
return result |
|
|
|
|
|
|
|
|
|
def _add_line(self, name, value, choices, descr) -> None: |
|
|
|
|
def _add_line(self, name: LOGLINE, value: LOGLINE, choices: LOGLINE, descr: LOGLINE) -> None: |
|
|
|
|
if isinstance(name, mlog.AnsiDecorator): |
|
|
|
|
name.text = ' ' * self.print_margin + name.text |
|
|
|
|
else: |
|
|
|
@ -167,21 +174,21 @@ class Conf: |
|
|
|
|
self.choices_col.append(choices) |
|
|
|
|
self.descr_col.append(descr) |
|
|
|
|
|
|
|
|
|
def add_option(self, name, descr, value, choices): |
|
|
|
|
def add_option(self, name: str, descr: str, value: T.Any, choices: T.Any) -> None: |
|
|
|
|
value = stringify(value) |
|
|
|
|
choices = stringify(choices) |
|
|
|
|
self._add_line(mlog.green(name), mlog.yellow(value), mlog.blue(choices), descr) |
|
|
|
|
|
|
|
|
|
def add_title(self, title): |
|
|
|
|
title = mlog.cyan(title) |
|
|
|
|
def add_title(self, title: str) -> None: |
|
|
|
|
newtitle = mlog.cyan(title) |
|
|
|
|
descr = mlog.cyan('Description') |
|
|
|
|
value = mlog.cyan('Default Value' if self.default_values_only else 'Current Value') |
|
|
|
|
choices = mlog.cyan('Possible Values') |
|
|
|
|
self._add_line('', '', '', '') |
|
|
|
|
self._add_line(title, value, choices, descr) |
|
|
|
|
self._add_line('-' * len(title), '-' * len(value), '-' * len(choices), '-' * len(descr)) |
|
|
|
|
self._add_line(newtitle, value, choices, descr) |
|
|
|
|
self._add_line('-' * len(newtitle), '-' * len(value), '-' * len(choices), '-' * len(descr)) |
|
|
|
|
|
|
|
|
|
def add_section(self, section): |
|
|
|
|
def add_section(self, section: str) -> None: |
|
|
|
|
self.print_margin = 0 |
|
|
|
|
self._add_line('', '', '', '') |
|
|
|
|
self._add_line(mlog.normal_yellow(section + ':'), '', '', '') |
|
|
|
@ -202,11 +209,11 @@ class Conf: |
|
|
|
|
printable_value = auto.printable_value() |
|
|
|
|
self.add_option(str(root), o.description, printable_value, o.choices) |
|
|
|
|
|
|
|
|
|
def print_conf(self, pager: bool): |
|
|
|
|
def print_conf(self, pager: bool) -> None: |
|
|
|
|
if pager: |
|
|
|
|
mlog.start_pager() |
|
|
|
|
|
|
|
|
|
def print_default_values_warning(): |
|
|
|
|
def print_default_values_warning() -> None: |
|
|
|
|
mlog.warning('The source directory instead of the build directory was specified.') |
|
|
|
|
mlog.warning('Only the default values for the project are printed.') |
|
|
|
|
|
|
|
|
@ -223,10 +230,10 @@ class Conf: |
|
|
|
|
test_option_names = {OptionKey('errorlogs'), |
|
|
|
|
OptionKey('stdsplit')} |
|
|
|
|
|
|
|
|
|
dir_options: 'coredata.KeyedOptionDictType' = {} |
|
|
|
|
test_options: 'coredata.KeyedOptionDictType' = {} |
|
|
|
|
core_options: 'coredata.KeyedOptionDictType' = {} |
|
|
|
|
module_options: T.Dict[str, 'coredata.KeyedOptionDictType'] = collections.defaultdict(dict) |
|
|
|
|
dir_options: 'coredata.MutableKeyedOptionDictType' = {} |
|
|
|
|
test_options: 'coredata.MutableKeyedOptionDictType' = {} |
|
|
|
|
core_options: 'coredata.MutableKeyedOptionDictType' = {} |
|
|
|
|
module_options: T.Dict[str, 'coredata.MutableKeyedOptionDictType'] = collections.defaultdict(dict) |
|
|
|
|
for k, v in self.coredata.options.items(): |
|
|
|
|
if k in dir_option_names: |
|
|
|
|
dir_options[k] = v |
|
|
|
@ -285,7 +292,7 @@ class Conf: |
|
|
|
|
|
|
|
|
|
self.print_nondefault_buildtype_options() |
|
|
|
|
|
|
|
|
|
def print_nondefault_buildtype_options(self): |
|
|
|
|
def print_nondefault_buildtype_options(self) -> None: |
|
|
|
|
mismatching = self.coredata.get_nondefault_buildtype_args() |
|
|
|
|
if not mismatching: |
|
|
|
|
return |
|
|
|
@ -294,7 +301,7 @@ class Conf: |
|
|
|
|
for m in mismatching: |
|
|
|
|
mlog.log(f'{m[0]:21}{m[1]:10}{m[2]:10}') |
|
|
|
|
|
|
|
|
|
def run(options): |
|
|
|
|
def run(options: argparse.Namespace) -> int: |
|
|
|
|
coredata.parse_cmd_line_options(options) |
|
|
|
|
builddir = os.path.abspath(os.path.realpath(options.builddir)) |
|
|
|
|
print_only = not options.cmd_line_options and not options.clearcache |
|
|
|
|