mconf: Group all options per subproject and align all groups

Also hide value of yielding subproject options to make it clear the
value must be set on the main project.
pull/6071/head
Xavier Claessens 5 years ago committed by Jussi Pakkanen
parent b626978dc6
commit 88e77e69bc
  1. 187
      mesonbuild/mconf.py

@ -43,6 +43,13 @@ class Conf:
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.has_choices = False
self.all_subprojects = set()
self.yielding_options = set()
if os.path.isdir(os.path.join(self.build_dir, 'meson-private')):
self.build = build.load(self.build_dir)
@ -79,71 +86,89 @@ class Conf:
# are erased when Meson is executed the next time, i.e. when
# Ninja is run.
def print_aligned(self, arr):
if not arr:
return
def print_aligned(self):
col_widths = (max([len(i) for i in self.name_col], default=0),
max([len(i) for i in self.value_col], default=0),
max([len(i) for i in self.choices_col], default=0))
titles = {'name': 'Option', 'descr': 'Description', 'value': 'Current Value', 'choices': 'Possible Values'}
if self.default_values_only:
titles['value'] = 'Default Value'
name_col = [titles['name'], '-' * len(titles['name'])]
value_col = [titles['value'], '-' * len(titles['value'])]
choices_col = [titles['choices'], '-' * len(titles['choices'])]
descr_col = [titles['descr'], '-' * len(titles['descr'])]
choices_found = False
for opt in arr:
name_col.append(opt['name'])
descr_col.append(opt['descr'])
if isinstance(opt['value'], list):
value_col.append('[{0}]'.format(', '.join(make_lower_case(opt['value']))))
else:
value_col.append(make_lower_case(opt['value']))
if opt['choices']:
choices_found = True
if isinstance(opt['choices'], list):
choices_list = make_lower_case(opt['choices'])
current = '['
while choices_list:
i = choices_list.pop(0)
if len(current) + len(i) >= self.max_choices_line_length:
choices_col.append(current + ',')
name_col.append('')
value_col.append('')
descr_col.append('')
current = ' '
if len(current) > 1:
current += ', '
current += i
choices_col.append(current + ']')
else:
choices_col.append(make_lower_case(opt['choices']))
for line in zip(self.name_col, self.value_col, self.choices_col, self.descr_col):
if self.has_choices:
print('{0:{width[0]}} {1:{width[1]}} {2:{width[2]}} {3}'.format(*line, width=col_widths))
else:
choices_col.append('')
print('{0:{width[0]}} {1:{width[1]}} {3}'.format(*line, width=col_widths))
col_widths = (max([len(i) for i in name_col], default=0),
max([len(i) for i in value_col], default=0),
max([len(i) for i in choices_col], default=0),
max([len(i) for i in descr_col], default=0))
def split_options_per_subproject(self, options):
result = {}
for k, o in options.items():
subproject = ''
if ':' in k:
subproject, optname = k.split(':')
if o.yielding and optname in options:
self.yielding_options.add(k)
self.all_subprojects.add(subproject)
result.setdefault(subproject, {})[k] = o
return result
for line in zip(name_col, value_col, choices_col, descr_col):
if choices_found:
print(' {0:{width[0]}} {1:{width[1]}} {2:{width[2]}} {3:{width[3]}}'.format(*line, width=col_widths))
def _add_line(self, name, value, choices, descr):
self.name_col.append(' ' * self.print_margin + name)
self.value_col.append(value)
self.choices_col.append(choices)
self.descr_col.append(descr)
def add_option(self, name, descr, value, choices):
if isinstance(value, list):
value = '[{0}]'.format(', '.join(make_lower_case(value)))
else:
value = make_lower_case(value)
if choices:
self.has_choices = True
if isinstance(choices, list):
choices_list = make_lower_case(choices)
current = '['
while choices_list:
i = choices_list.pop(0)
if len(current) + len(i) >= self.max_choices_line_length:
self._add_line(name, value, current + ',', descr)
name = ''
value = ''
descr = ''
current = ' '
if len(current) > 1:
current += ', '
current += i
choices = current + ']'
else:
print(' {0:{width[0]}} {1:{width[1]}} {3:{width[3]}}'.format(*line, width=col_widths))
choices = make_lower_case(choices)
else:
choices = ''
self._add_line(name, value, choices, descr)
def add_title(self, title):
titles = {'descr': 'Description', 'value': 'Current Value', 'choices': 'Possible Values'}
if self.default_values_only:
titles['value'] = 'Default Value'
self._add_line('', '', '', '')
self._add_line(title, titles['value'], titles['choices'], titles['descr'])
self._add_line('-' * len(title), '-' * len(titles['value']), '-' * len(titles['choices']), '-' * len(titles['descr']))
def add_section(self, section):
self.print_margin = 0
self._add_line('', '', '', '')
self._add_line(section + ':', '', '', '')
self.print_margin = 2
def print_options(self, title, options):
print('\n{}:'.format(title))
if not options:
print(' No {}\n'.format(title.lower()))
arr = []
return
if title:
self.add_title(title)
for k, o in sorted(options.items()):
d = o.description
v = o.printable_value()
c = o.choices
arr.append({'name': k, 'descr': d, 'value': v, 'choices': c})
self.print_aligned(arr)
printable_value = o.printable_value()
if k in self.yielding_options:
printable_value = '<inherited from main project>'
self.add_option(k, o.description, printable_value, o.choices)
def print_conf(self):
def print_default_values_warning():
@ -180,26 +205,44 @@ class Conf:
test_options = {k: o for k, o in self.coredata.builtins.items() if k in test_option_names}
core_options = {k: o for k, o in self.coredata.builtins.items() if k in core_option_names}
self.print_options('Core options', core_options)
if self.default_values_only or self.build.environment.is_cross_build():
self.print_options('Core options (for host machine)', self.coredata.builtins_per_machine.host)
self.print_options(
'Core options (for build machine)',
{'build.' + k: o for k, o in self.coredata.builtins_per_machine.build.items()})
else:
self.print_options('Core options', self.coredata.builtins_per_machine.host)
def insert_build_prefix(k):
idx = k.find(':')
if idx < 0:
return 'build.' + k
return k[:idx + 1] + 'build.' + k[idx + 1:]
core_options = self.split_options_per_subproject(core_options)
host_compiler_options = self.split_options_per_subproject(self.coredata.compiler_options.host)
build_compiler_options = self.split_options_per_subproject({insert_build_prefix(k): o for k, o in self.coredata.compiler_options.build.items()})
project_options = self.split_options_per_subproject(self.coredata.user_options)
show_build_options = self.default_values_only or self.build.environment.is_cross_build()
self.add_section('Main project options')
self.print_options('Core options', core_options[''])
self.print_options('', self.coredata.builtins_per_machine.host)
if show_build_options:
self.print_options('', {insert_build_prefix(k): o for k, o in self.coredata.builtins_per_machine.build.items()})
self.print_options('Backend options', self.coredata.backend_options)
self.print_options('Base options', self.coredata.base_options)
if self.default_values_only or self.build.environment.is_cross_build():
self.print_options('Compiler options (for host machine)', self.coredata.compiler_options.host)
self.print_options(
'Compiler options (for build machine)',
{'build.' + k: o for k, o in self.coredata.compiler_options.build.items()})
else:
self.print_options('Compiler options', self.coredata.compiler_options.host)
self.print_options('Compiler options', host_compiler_options[''])
if show_build_options:
self.print_options('', build_compiler_options[''])
self.print_options('Directories', dir_options)
self.print_options('Project options', self.coredata.user_options)
self.print_options('Testing options', test_options)
self.print_options('Project options', project_options[''])
for subproject in sorted(self.all_subprojects):
if subproject == '':
continue
self.add_section('Subproject ' + subproject)
if subproject in core_options:
self.print_options('Core options', core_options[subproject])
if subproject in host_compiler_options:
self.print_options('Compiler options', host_compiler_options[subproject])
if subproject in build_compiler_options and show_build_options:
self.print_options('', build_compiler_options[subproject])
if subproject in project_options:
self.print_options('Project options', project_options[subproject])
self.print_aligned()
# Print the warning twice so that the user shouldn't be able to miss it
if self.default_values_only:

Loading…
Cancel
Save