From d778a371ac3eb0bdb2bfde84d753722b576d5f14 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 4 Apr 2019 13:32:55 -0700 Subject: coredata: Add an object to abstract builtins Currently the builtins are stored as lists, then there are a mess of functions which take said lists, check what the type of the first thing is, and then extract data from various points in the list based on that. This is stupid. This is what structs/classes are for. --- mesonbuild/coredata.py | 115 ++++++++++++++++++++++++++++--------------------- 1 file changed, 67 insertions(+), 48 deletions(-) (limited to 'mesonbuild') diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 01db635..9002fd9 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -26,6 +26,7 @@ from .wrap import WrapMode import ast import argparse import configparser +from typing import Optional, Any, TypeVar, Generic, Type version = '0.50.999' backendlist = ['ninja', 'vs', 'vs2010', 'vs2015', 'vs2017', 'xcode'] @@ -335,11 +336,8 @@ class CoreData: def init_builtins(self): # Create builtin options with default values self.builtins = {} - prefix = get_builtin_option_default('prefix') - for key in get_builtin_options(): - value = get_builtin_option_default(key, prefix) - args = [key] + builtin_options[key][1:-1] + [value] - self.builtins[key] = builtin_options[key][0](*args) + for key, opt in builtin_options.items(): + self.builtins[key] = opt.init_option(key) def init_backend_options(self, backend_name): if backend_name == 'ninja': @@ -664,25 +662,24 @@ def is_builtin_option(optname): def get_builtin_option_choices(optname): if is_builtin_option(optname): - if builtin_options[optname][0] == UserComboOption: - return builtin_options[optname][2] - elif builtin_options[optname][0] == UserBooleanOption: + b = builtin_options[optname] + if b.opt_type is UserBooleanOption: return [True, False] - elif builtin_options[optname][0] == UserFeatureOption: + elif b.opt_type is UserFeatureOption: return UserFeatureOption.static_choices else: - return None + return b.choices else: raise RuntimeError('Tried to get the supported values for an unknown builtin option \'%s\'.' % optname) def get_builtin_option_description(optname): if is_builtin_option(optname): - return builtin_options[optname][1] + return builtin_options[optname].description else: raise RuntimeError('Tried to get the description for an unknown builtin option \'%s\'.' % optname) def get_builtin_option_action(optname): - default = builtin_options[optname][2] + default = builtin_options[optname].default if default is True: return 'store_false' elif default is False: @@ -692,15 +689,13 @@ def get_builtin_option_action(optname): def get_builtin_option_default(optname, prefix=''): if is_builtin_option(optname): o = builtin_options[optname] - if o[0] == UserComboOption: - return o[3] - if o[0] == UserIntegerOption: - return o[4] + if o.opt_type in [UserComboOption, UserIntegerOption]: + return o.default try: return builtin_dir_noprefix_options[optname][prefix] except KeyError: pass - return o[2] + return o.default else: raise RuntimeError('Tried to get the default value for an unknown builtin option \'%s\'.' % optname) @@ -757,38 +752,62 @@ def parse_cmd_line_options(args): args.cmd_line_options[name] = value delattr(args, name) + +_U = TypeVar('_U', bound=UserOption) + +class BuiltinOption(Generic[_U]): + + """Class for a builtin option type. + + Currently doesn't support UserIntegerOption, or a few other cases. + """ + + def __init__(self, opt_type: Type[_U], description: str, default: Any, yielding: Optional[bool] = None, *, + choices: Any = None): + self.opt_type = opt_type + self.description = description + self.default = default + self.choices = choices + self.yielding = yielding + + def init_option(self, name: str) -> _U: + """Create an instance of opt_type and return it.""" + keywords = {'yielding': self.yielding, 'value': self.default} + if self.choices: + keywords['choices'] = self.choices + return self.opt_type(name, self.description, **keywords) + + builtin_options = { - 'buildtype': [UserComboOption, 'Build type to use', ['plain', 'debug', 'debugoptimized', 'release', 'minsize', 'custom'], 'debug'], - 'strip': [UserBooleanOption, 'Strip targets on install', False], - 'unity': [UserComboOption, 'Unity build', ['on', 'off', 'subprojects'], 'off'], - 'prefix': [UserStringOption, 'Installation prefix', default_prefix()], - 'libdir': [UserStringOption, 'Library directory', default_libdir()], - 'libexecdir': [UserStringOption, 'Library executable directory', default_libexecdir()], - 'bindir': [UserStringOption, 'Executable directory', 'bin'], - 'sbindir': [UserStringOption, 'System executable directory', 'sbin'], - 'includedir': [UserStringOption, 'Header file directory', 'include'], - 'datadir': [UserStringOption, 'Data file directory', 'share'], - 'mandir': [UserStringOption, 'Manual page directory', 'share/man'], - 'infodir': [UserStringOption, 'Info page directory', 'share/info'], - 'localedir': [UserStringOption, 'Locale data directory', 'share/locale'], - 'sysconfdir': [UserStringOption, 'Sysconf data directory', 'etc'], - 'localstatedir': [UserStringOption, 'Localstate data directory', 'var'], - 'sharedstatedir': [UserStringOption, 'Architecture-independent data directory', 'com'], - 'werror': [UserBooleanOption, 'Treat warnings as errors', False], - 'warning_level': [UserComboOption, 'Compiler warning level to use', ['0', '1', '2', '3'], '1'], - 'layout': [UserComboOption, 'Build directory layout', ['mirror', 'flat'], 'mirror'], - 'default_library': [UserComboOption, 'Default library type', ['shared', 'static', 'both'], 'shared'], - 'backend': [UserComboOption, 'Backend to use', backendlist, 'ninja'], - 'stdsplit': [UserBooleanOption, 'Split stdout and stderr in test logs', True], - 'errorlogs': [UserBooleanOption, "Whether to print the logs from failing tests", True], - 'install_umask': [UserUmaskOption, 'Default umask to apply on permissions of installed files', '022'], - 'auto_features': [UserFeatureOption, "Override value of all 'auto' features", 'auto'], - 'optimization': [UserComboOption, 'Optimization level', ['0', 'g', '1', '2', '3', 's'], '0'], - 'debug': [UserBooleanOption, 'Debug', True], - 'wrap_mode': [UserComboOption, 'Wrap mode', ['default', - 'nofallback', - 'nodownload', - 'forcefallback'], 'default'], + 'buildtype': BuiltinOption(UserComboOption, 'Build type to use', 'debug', + choices=['plain', 'debug', 'debugoptimized', 'release', 'minsize', 'custom']), + 'strip': BuiltinOption(UserBooleanOption, 'Strip targets on install', False), + 'unity': BuiltinOption(UserComboOption, 'Unity build', 'off', choices=['on', 'off', 'subprojects']), + 'prefix': BuiltinOption(UserStringOption, 'Installation prefix', default_prefix()), + 'libdir': BuiltinOption(UserStringOption, 'Library directory', default_libdir()), + 'libexecdir': BuiltinOption(UserStringOption, 'Library executable directory', default_libexecdir()), + 'bindir': BuiltinOption(UserStringOption, 'Executable directory', 'bin'), + 'sbindir': BuiltinOption(UserStringOption, 'System executable directory', 'sbin'), + 'includedir': BuiltinOption(UserStringOption, 'Header file directory', 'include'), + 'datadir': BuiltinOption(UserStringOption, 'Data file directory', 'share'), + 'mandir': BuiltinOption(UserStringOption, 'Manual page directory', 'share/man'), + 'infodir': BuiltinOption(UserStringOption, 'Info page directory', 'share/info'), + 'localedir': BuiltinOption(UserStringOption, 'Locale data directory', 'share/locale'), + 'sysconfdir': BuiltinOption(UserStringOption, 'Sysconf data directory', 'etc'), + 'localstatedir': BuiltinOption(UserStringOption, 'Localstate data directory', 'var'), + 'sharedstatedir': BuiltinOption(UserStringOption, 'Architecture-independent data directory', 'com'), + 'werror': BuiltinOption(UserBooleanOption, 'Treat warnings as errors', False), + 'warning_level': BuiltinOption(UserComboOption, 'Compiler warning level to use', '1', choices=['0', '1', '2', '3']), + 'layout': BuiltinOption(UserComboOption, 'Build directory layout', 'mirror', choices=['mirror', 'flat']), + 'default_library': BuiltinOption(UserComboOption, 'Default library type', 'shared', choices=['shared', 'static', 'both']), + 'backend': BuiltinOption(UserComboOption, 'Backend to use', 'ninja', choices=backendlist), + 'stdsplit': BuiltinOption(UserBooleanOption, 'Split stdout and stderr in test logs', True), + 'errorlogs': BuiltinOption(UserBooleanOption, "Whether to print the logs from failing tests", True), + 'install_umask': BuiltinOption(UserUmaskOption, 'Default umask to apply on permissions of installed files', '022'), + 'auto_features': BuiltinOption(UserFeatureOption, "Override value of all 'auto' features", 'auto'), + 'optimization': BuiltinOption(UserComboOption, 'Optimization level', '0', choices=['0', 'g', '1', '2', '3', 's']), + 'debug': BuiltinOption(UserBooleanOption, 'Debug', True), + 'wrap_mode': BuiltinOption(UserComboOption, 'Wrap mode', 'default', choices=['default', 'nofallback', 'nodownload', 'forcefallback']), } # Special prefix-dependent defaults for installation directories that reside in -- cgit v1.1 From c6060d795cfc9084505123bbb4004ccb112f0de3 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 4 Apr 2019 13:35:43 -0700 Subject: coredata: remove get_builtin_options This returns a list out of th keys of a dict. In both cases of use remaining though it's used for checking membership, checking for list membership, lists are O(n) lookup, while dicts are O(1), so removing the abstraction reduces typing and improves performance. --- mesonbuild/coredata.py | 7 ++----- mesonbuild/optinterpreter.py | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) (limited to 'mesonbuild') diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 9002fd9..97094fb 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -508,7 +508,7 @@ class CoreData: if subproject: if not k.startswith(subproject + ':'): continue - elif k not in get_builtin_options(): + elif k not in builtin_options: if ':' in k: continue if optinterpreter.is_invalid_name(k): @@ -654,11 +654,8 @@ def save(obj, build_dir): os.replace(tempfilename, filename) return filename -def get_builtin_options(): - return list(builtin_options.keys()) - def is_builtin_option(optname): - return optname in get_builtin_options() + return optname in builtin_options def get_builtin_option_choices(optname): if is_builtin_option(optname): diff --git a/mesonbuild/optinterpreter.py b/mesonbuild/optinterpreter.py index 85f6897..2d60d10 100644 --- a/mesonbuild/optinterpreter.py +++ b/mesonbuild/optinterpreter.py @@ -20,7 +20,7 @@ from . import coredata from . import mesonlib from . import compilers -forbidden_option_names = coredata.get_builtin_options() +forbidden_option_names = set(coredata.builtin_options.keys()) forbidden_prefixes = [lang + '_' for lang in compilers.all_languages] + ['b_', 'backend_'] reserved_prefixes = ['cross_'] -- cgit v1.1 From f8fcc7174d2c36d1fa1c91be52990ce600d806de Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 4 Apr 2019 13:38:57 -0700 Subject: coredata: Remove is_builtin_option This is a silly abstraction at this point. --- mesonbuild/coredata.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'mesonbuild') diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 97094fb..347af14 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -654,11 +654,8 @@ def save(obj, build_dir): os.replace(tempfilename, filename) return filename -def is_builtin_option(optname): - return optname in builtin_options - def get_builtin_option_choices(optname): - if is_builtin_option(optname): + if optname in builtin_options: b = builtin_options[optname] if b.opt_type is UserBooleanOption: return [True, False] @@ -670,7 +667,7 @@ def get_builtin_option_choices(optname): raise RuntimeError('Tried to get the supported values for an unknown builtin option \'%s\'.' % optname) def get_builtin_option_description(optname): - if is_builtin_option(optname): + if optname in builtin_options: return builtin_options[optname].description else: raise RuntimeError('Tried to get the description for an unknown builtin option \'%s\'.' % optname) @@ -684,7 +681,7 @@ def get_builtin_option_action(optname): return None def get_builtin_option_default(optname, prefix=''): - if is_builtin_option(optname): + if optname in builtin_options: o = builtin_options[optname] if o.opt_type in [UserComboOption, UserIntegerOption]: return o.default -- cgit v1.1 From 6940848f0bc9820d8f32667e4d0f9b73b68d2003 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 4 Apr 2019 13:51:26 -0700 Subject: coredata: Move argparse action getterin into BuiltinOption class --- mesonbuild/coredata.py | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'mesonbuild') diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 347af14..180f7e5 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -672,14 +672,6 @@ def get_builtin_option_description(optname): else: raise RuntimeError('Tried to get the description for an unknown builtin option \'%s\'.' % optname) -def get_builtin_option_action(optname): - default = builtin_options[optname].default - if default is True: - return 'store_false' - elif default is False: - return 'store_true' - return None - def get_builtin_option_default(optname, prefix=''): if optname in builtin_options: o = builtin_options[optname] @@ -700,9 +692,15 @@ def get_builtin_option_cmdline_name(name): return '--' + name.replace('_', '-') def add_builtin_argument(p, name): + try: + builtin = builtin_options[name] + except KeyError: + raise RuntimeError('Tried to get attribute of unknown builtin option "{}"'.format(name)) + kwargs = {} + c = get_builtin_option_choices(name) - b = get_builtin_option_action(name) + b = builtin.argparse_action() h = get_builtin_option_description(name) if not b: h = h.rstrip('.') + ' (default: %s).' % get_builtin_option_default(name) @@ -771,6 +769,13 @@ class BuiltinOption(Generic[_U]): keywords['choices'] = self.choices return self.opt_type(name, self.description, **keywords) + def argparse_action(self) -> Optional[str]: + if self.default is True: + return 'store_false' + elif self.default is False: + return 'store_true' + return None + builtin_options = { 'buildtype': BuiltinOption(UserComboOption, 'Build type to use', 'debug', -- cgit v1.1 From 1e5496d1ba949bdb9422e6c476014e079320f788 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 4 Apr 2019 13:52:33 -0700 Subject: coredata: Remove get_builtin_option_description Since the attribute is always accessible from a BuiltinOptions instance we don't need a special function for this. --- mesonbuild/coredata.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'mesonbuild') diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 180f7e5..9fa1317 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -666,12 +666,6 @@ def get_builtin_option_choices(optname): else: raise RuntimeError('Tried to get the supported values for an unknown builtin option \'%s\'.' % optname) -def get_builtin_option_description(optname): - if optname in builtin_options: - return builtin_options[optname].description - else: - raise RuntimeError('Tried to get the description for an unknown builtin option \'%s\'.' % optname) - def get_builtin_option_default(optname, prefix=''): if optname in builtin_options: o = builtin_options[optname] @@ -701,7 +695,7 @@ def add_builtin_argument(p, name): c = get_builtin_option_choices(name) b = builtin.argparse_action() - h = get_builtin_option_description(name) + h = builtin.description if not b: h = h.rstrip('.') + ' (default: %s).' % get_builtin_option_default(name) else: -- cgit v1.1 From 5aa2219f50685b24e933960455cd279dd7af801d Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 4 Apr 2019 13:55:17 -0700 Subject: coredata: pull get_builtin_option_choices into BuiltinOption We can remove some guards here since we know the object will have certain attributes. --- mesonbuild/coredata.py | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) (limited to 'mesonbuild') diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 9fa1317..a662ce5 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -654,18 +654,6 @@ def save(obj, build_dir): os.replace(tempfilename, filename) return filename -def get_builtin_option_choices(optname): - if optname in builtin_options: - b = builtin_options[optname] - if b.opt_type is UserBooleanOption: - return [True, False] - elif b.opt_type is UserFeatureOption: - return UserFeatureOption.static_choices - else: - return b.choices - else: - raise RuntimeError('Tried to get the supported values for an unknown builtin option \'%s\'.' % optname) - def get_builtin_option_default(optname, prefix=''): if optname in builtin_options: o = builtin_options[optname] @@ -693,7 +681,7 @@ def add_builtin_argument(p, name): kwargs = {} - c = get_builtin_option_choices(name) + c = builtin.argparse_choices() b = builtin.argparse_action() h = builtin.description if not b: @@ -770,6 +758,13 @@ class BuiltinOption(Generic[_U]): return 'store_true' return None + def argparse_choices(self) -> Any: + if self.opt_type is UserBooleanOption: + return [True, False] + elif self.opt_type is UserFeatureOption: + return UserFeatureOption.static_choices + return self.choices + builtin_options = { 'buildtype': BuiltinOption(UserComboOption, 'Build type to use', 'debug', -- cgit v1.1 From c3cb966631358ccb7e761c96c22b70ed631ff4de Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 4 Apr 2019 14:13:57 -0700 Subject: coredata: merge get_builtin_option_default in to BuiltinOption --- mesonbuild/coredata.py | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) (limited to 'mesonbuild') diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index a662ce5..69ac6a4 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -460,7 +460,7 @@ class CoreData: self.builtins['prefix'].set_value(prefix) for key in builtin_dir_noprefix_options: if key not in options: - self.builtins[key].set_value(get_builtin_option_default(key, prefix)) + self.builtins[key].set_value(builtin_options[key].prefixed_default(key, prefix)) unknown_options = [] for k, v in options.items(): @@ -654,19 +654,6 @@ def save(obj, build_dir): os.replace(tempfilename, filename) return filename -def get_builtin_option_default(optname, prefix=''): - if optname in builtin_options: - o = builtin_options[optname] - if o.opt_type in [UserComboOption, UserIntegerOption]: - return o.default - try: - return builtin_dir_noprefix_options[optname][prefix] - except KeyError: - pass - return o.default - else: - raise RuntimeError('Tried to get the default value for an unknown builtin option \'%s\'.' % optname) - def get_builtin_option_cmdline_name(name): if name == 'warning_level': return '--warnlevel' @@ -685,7 +672,7 @@ def add_builtin_argument(p, name): b = builtin.argparse_action() h = builtin.description if not b: - h = h.rstrip('.') + ' (default: %s).' % get_builtin_option_default(name) + h = '{} (default: {}).'.format(h.rstrip('.'), builtin.prefixed_default(name)) else: kwargs['action'] = b if c and not b: @@ -765,6 +752,15 @@ class BuiltinOption(Generic[_U]): return UserFeatureOption.static_choices return self.choices + def prefixed_default(self, name: str, prefix: str = '') -> Any: + if self.opt_type in [UserComboOption, UserIntegerOption]: + return self.default + try: + return builtin_dir_noprefix_options[name][prefix] + except KeyError: + pass + return self.default + builtin_options = { 'buildtype': BuiltinOption(UserComboOption, 'Build type to use', 'debug', -- cgit v1.1 From 1d7eda5fc8aef2938c9f66058fe706d98c32fa62 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 4 Apr 2019 14:25:09 -0700 Subject: coredata: Merge get_builtin_option_cmdline_name into BuiltinOption --- mesonbuild/coredata.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'mesonbuild') diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 69ac6a4..84e6136 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -654,12 +654,6 @@ def save(obj, build_dir): os.replace(tempfilename, filename) return filename -def get_builtin_option_cmdline_name(name): - if name == 'warning_level': - return '--warnlevel' - else: - return '--' + name.replace('_', '-') - def add_builtin_argument(p, name): try: builtin = builtin_options[name] @@ -680,7 +674,7 @@ def add_builtin_argument(p, name): kwargs['default'] = argparse.SUPPRESS kwargs['dest'] = name - cmdline_name = get_builtin_option_cmdline_name(name) + cmdline_name = builtin.argparse_name_to_arg(name) p.add_argument(cmdline_name, help=h, **kwargs) def register_builtin_arguments(parser): @@ -707,7 +701,7 @@ def parse_cmd_line_options(args): value = getattr(args, name, None) if value is not None: if name in args.cmd_line_options: - cmdline_name = get_builtin_option_cmdline_name(name) + cmdline_name = BuiltinOption.argparse_name_to_arg(name) raise MesonException( 'Got argument {0} as both -D{0} and {1}. Pick one.'.format(name, cmdline_name)) args.cmd_line_options[name] = value @@ -752,6 +746,13 @@ class BuiltinOption(Generic[_U]): return UserFeatureOption.static_choices return self.choices + @staticmethod + def argparse_name_to_arg(name: str) -> str: + if name == 'warning_level': + return '--warnlevel' + else: + return '--' + name.replace('_', '-') + def prefixed_default(self, name: str, prefix: str = '') -> Any: if self.opt_type in [UserComboOption, UserIntegerOption]: return self.default -- cgit v1.1 From 863de725990a944380df6ecf79b43f1a51718489 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 4 Apr 2019 14:17:52 -0700 Subject: coredata: Fold add_builtin_argument into BuiltinOption It really is a method of the BuiltinOption class, not a standalone function. --- mesonbuild/coredata.py | 48 ++++++++++++++++++++++-------------------------- 1 file changed, 22 insertions(+), 26 deletions(-) (limited to 'mesonbuild') diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 84e6136..fc2ab88 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -654,32 +654,10 @@ def save(obj, build_dir): os.replace(tempfilename, filename) return filename -def add_builtin_argument(p, name): - try: - builtin = builtin_options[name] - except KeyError: - raise RuntimeError('Tried to get attribute of unknown builtin option "{}"'.format(name)) - - kwargs = {} - - c = builtin.argparse_choices() - b = builtin.argparse_action() - h = builtin.description - if not b: - h = '{} (default: {}).'.format(h.rstrip('.'), builtin.prefixed_default(name)) - else: - kwargs['action'] = b - if c and not b: - kwargs['choices'] = c - kwargs['default'] = argparse.SUPPRESS - kwargs['dest'] = name - - cmdline_name = builtin.argparse_name_to_arg(name) - p.add_argument(cmdline_name, help=h, **kwargs) def register_builtin_arguments(parser): - for n in builtin_options: - add_builtin_argument(parser, n) + for n, b in builtin_options.items(): + b.add_to_argparse(n, parser) parser.add_argument('-D', action='append', dest='projectoptions', default=[], metavar="option", help='Set the value of an option, can be used several times to set multiple options.') @@ -732,14 +710,14 @@ class BuiltinOption(Generic[_U]): keywords['choices'] = self.choices return self.opt_type(name, self.description, **keywords) - def argparse_action(self) -> Optional[str]: + def _argparse_action(self) -> Optional[str]: if self.default is True: return 'store_false' elif self.default is False: return 'store_true' return None - def argparse_choices(self) -> Any: + def _argparse_choices(self) -> Any: if self.opt_type is UserBooleanOption: return [True, False] elif self.opt_type is UserFeatureOption: @@ -762,6 +740,24 @@ class BuiltinOption(Generic[_U]): pass return self.default + def add_to_argparse(self, name: str, parser: argparse.ArgumentParser) -> None: + kwargs = {} + + c = self._argparse_choices() + b = self._argparse_action() + h = self.description + if not b: + h = '{} (default: {}).'.format(h.rstrip('.'), self.prefixed_default(name)) + else: + kwargs['action'] = b + if c and not b: + kwargs['choices'] = c + kwargs['default'] = argparse.SUPPRESS + kwargs['dest'] = name + + cmdline_name = self.argparse_name_to_arg(name) + parser.add_argument(cmdline_name, help=h, **kwargs) + builtin_options = { 'buildtype': BuiltinOption(UserComboOption, 'Build type to use', 'debug', -- cgit v1.1 From 05ad69a1c7f98b82278916e29964c153c8f39390 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 5 Apr 2019 09:20:53 -0700 Subject: optinterpreter: Add type annotations to is_invalid_name --- mesonbuild/optinterpreter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mesonbuild') diff --git a/mesonbuild/optinterpreter.py b/mesonbuild/optinterpreter.py index 2d60d10..5bddbc8 100644 --- a/mesonbuild/optinterpreter.py +++ b/mesonbuild/optinterpreter.py @@ -24,7 +24,7 @@ forbidden_option_names = set(coredata.builtin_options.keys()) forbidden_prefixes = [lang + '_' for lang in compilers.all_languages] + ['b_', 'backend_'] reserved_prefixes = ['cross_'] -def is_invalid_name(name): +def is_invalid_name(name: str) -> bool: if name in forbidden_option_names: return True pref = name.split('_')[0] + '_' -- cgit v1.1 From 068c3bf60ab04b7803b3bbe57f069a412d9186d3 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 5 Apr 2019 09:22:13 -0700 Subject: optinterpreter: Add a log argument to is_invalid_name Since we're adding arguments that use the cross_ prefix but are valid we don't want to print "warning invalid argument name!", as that will confuse people by virtue of being wrong. --- mesonbuild/optinterpreter.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'mesonbuild') diff --git a/mesonbuild/optinterpreter.py b/mesonbuild/optinterpreter.py index 5bddbc8..e64ed4e 100644 --- a/mesonbuild/optinterpreter.py +++ b/mesonbuild/optinterpreter.py @@ -24,15 +24,16 @@ forbidden_option_names = set(coredata.builtin_options.keys()) forbidden_prefixes = [lang + '_' for lang in compilers.all_languages] + ['b_', 'backend_'] reserved_prefixes = ['cross_'] -def is_invalid_name(name: str) -> bool: +def is_invalid_name(name: str, *, log: bool = True) -> bool: if name in forbidden_option_names: return True pref = name.split('_')[0] + '_' if pref in forbidden_prefixes: return True if pref in reserved_prefixes: - from . import mlog - mlog.deprecation('Option uses prefix "%s", which is reserved for Meson. This will become an error in the future.' % pref) + if log: + from . import mlog + mlog.deprecation('Option uses prefix "%s", which is reserved for Meson. This will become an error in the future.' % pref) return False class OptionException(mesonlib.MesonException): -- cgit v1.1 From 5ce0d9fbbb7c2e009d179c77c6904326fe569fb3 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Fri, 5 Apr 2019 09:23:51 -0700 Subject: coredata: Don't log warnings about reserved prefixes --- mesonbuild/coredata.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'mesonbuild') diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index fc2ab88..2666bb9 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -493,7 +493,7 @@ class CoreData: from . import optinterpreter for k, v in default_options.items(): if subproject: - if optinterpreter.is_invalid_name(k): + if optinterpreter.is_invalid_name(k, log=False): continue k = subproject + ':' + k env.cmd_line_options.setdefault(k, v) @@ -511,7 +511,7 @@ class CoreData: elif k not in builtin_options: if ':' in k: continue - if optinterpreter.is_invalid_name(k): + if optinterpreter.is_invalid_name(k, log=False): continue options[k] = v -- cgit v1.1 From 569e646e1e3556fb5fdb7c4fb012a30145c7145d Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Tue, 12 Feb 2019 15:51:46 -0800 Subject: dependencies: Add command line option for pkg_config_path This creates a new command line option to store pkg_config_path into, and store the environment variable into that option. Currently this works like the environment variable, for both cross and native targets. --- mesonbuild/coredata.py | 8 +++++++- mesonbuild/dependencies/base.py | 11 ++++++++--- mesonbuild/msetup.py | 8 -------- 3 files changed, 15 insertions(+), 12 deletions(-) (limited to 'mesonbuild') diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 2666bb9..034f86a 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -270,7 +270,6 @@ class CoreData: self.cross_compilers = OrderedDict() self.deps = OrderedDict() # Only to print a warning if it changes between Meson invocations. - self.pkgconf_envvar = os.environ.get('PKG_CONFIG_PATH', '') self.config_files = self.__load_config_files(options.native_file) self.libdir_cross_fixup() @@ -504,6 +503,12 @@ class CoreData: # languages and setting the backend (builtin options must be set first # to know which backend we'll use). options = {} + + # Some options default to environment variables if they are + # unset, set those now. These will either be overwritten + # below, or they won't. + options['pkg_config_path'] = os.environ.get('PKG_CONFIG_PATH', '').split(':') + for k, v in env.cmd_line_options.items(): if subproject: if not k.startswith(subproject + ':'): @@ -789,6 +794,7 @@ builtin_options = { 'optimization': BuiltinOption(UserComboOption, 'Optimization level', '0', choices=['0', 'g', '1', '2', '3', 's']), 'debug': BuiltinOption(UserBooleanOption, 'Debug', True), 'wrap_mode': BuiltinOption(UserComboOption, 'Wrap mode', 'default', choices=['default', 'nofallback', 'nodownload', 'forcefallback']), + 'pkg_config_path': BuiltinOption(UserArrayOption, 'List of additional paths for pkg-config to search', []), } # Special prefix-dependent defaults for installation directories that reside in diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index af4b13f..94a6a6b 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -609,11 +609,16 @@ class PkgConfigDependency(ExternalDependency): return rc, out def _call_pkgbin(self, args, env=None): + # Always copy the environment since we're going to modify it + # with pkg-config variables if env is None: - fenv = env - env = os.environ + env = os.environ.copy() else: - fenv = frozenset(env.items()) + env = env.copy() + + extra_paths = self.env.coredata.get_builtin_option('pkg_config_path') + env['PKG_CONFIG_PATH'] = ':'.join([p for p in extra_paths]) + fenv = frozenset(env.items()) targs = tuple(args) cache = PkgConfigDependency.pkgbin_cache if (self.pkgbin, targs, fenv) not in cache: diff --git a/mesonbuild/msetup.py b/mesonbuild/msetup.py index 6e8ca83..ef0511d 100644 --- a/mesonbuild/msetup.py +++ b/mesonbuild/msetup.py @@ -149,13 +149,6 @@ class MesonApp: sys.exit(1) return src_dir, build_dir - def check_pkgconfig_envvar(self, env): - curvar = os.environ.get('PKG_CONFIG_PATH', '') - if curvar != env.coredata.pkgconf_envvar: - mlog.warning('PKG_CONFIG_PATH has changed between invocations from "%s" to "%s".' % - (env.coredata.pkgconf_envvar, curvar)) - env.coredata.pkgconf_envvar = curvar - def generate(self): env = environment.Environment(self.source_dir, self.build_dir, self.options) mlog.initialize(env.get_log_dir(), self.options.fatal_warnings) @@ -169,7 +162,6 @@ class MesonApp: mlog.debug('Main binary:', sys.executable) mlog.debug('Python system:', platform.system()) mlog.log(mlog.bold('The Meson build system')) - self.check_pkgconfig_envvar(env) mlog.log('Version:', coredata.version) mlog.log('Source dir:', mlog.bold(self.source_dir)) mlog.log('Build dir:', mlog.bold(self.build_dir)) -- cgit v1.1 From 377b652b93c8961bdcb266ba4254a15b28f2c5be Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 4 Apr 2019 14:37:57 -0700 Subject: coredata: Add ability to mark options as having separate cross values Currently this only marks the pkg_config_path flag, but it could be used to mark any of these values as having separate values for cross and native builds, assuming that the necessary plumbing is done. --- mesonbuild/coredata.py | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) (limited to 'mesonbuild') diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 034f86a..739f6e7 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -337,6 +337,8 @@ class CoreData: self.builtins = {} for key, opt in builtin_options.items(): self.builtins[key] = opt.init_option(key) + if opt.separate_cross: + self.builtins['cross_' + key] = opt.init_option(key) def init_backend_options(self, backend_name): if backend_name == 'ninja': @@ -680,15 +682,19 @@ def parse_cmd_line_options(args): args.cmd_line_options = create_options_dict(args.projectoptions) # Merge builtin options set with --option into the dict. - for name in builtin_options: - value = getattr(args, name, None) - if value is not None: - if name in args.cmd_line_options: - cmdline_name = BuiltinOption.argparse_name_to_arg(name) - raise MesonException( - 'Got argument {0} as both -D{0} and {1}. Pick one.'.format(name, cmdline_name)) - args.cmd_line_options[name] = value - delattr(args, name) + for name, builtin in builtin_options.items(): + names = [name] + if builtin.separate_cross: + names.append('cross_' + name) + for name in names: + value = getattr(args, name, None) + if value is not None: + if name in args.cmd_line_options: + cmdline_name = BuiltinOption.argparse_name_to_arg(name) + raise MesonException( + 'Got argument {0} as both -D{0} and {1}. Pick one.'.format(name, cmdline_name)) + args.cmd_line_options[name] = value + delattr(args, name) _U = TypeVar('_U', bound=UserOption) @@ -701,12 +707,13 @@ class BuiltinOption(Generic[_U]): """ def __init__(self, opt_type: Type[_U], description: str, default: Any, yielding: Optional[bool] = None, *, - choices: Any = None): + choices: Any = None, separate_cross: bool = False): self.opt_type = opt_type self.description = description self.default = default self.choices = choices self.yielding = yielding + self.separate_cross = separate_cross def init_option(self, name: str) -> _U: """Create an instance of opt_type and return it.""" @@ -762,6 +769,9 @@ class BuiltinOption(Generic[_U]): cmdline_name = self.argparse_name_to_arg(name) parser.add_argument(cmdline_name, help=h, **kwargs) + if self.separate_cross: + kwargs['dest'] = 'cross_' + name + parser.add_argument(self.argparse_name_to_arg('cross_' + name), help=h + ' (for host in cross compiles)', **kwargs) builtin_options = { @@ -794,7 +804,7 @@ builtin_options = { 'optimization': BuiltinOption(UserComboOption, 'Optimization level', '0', choices=['0', 'g', '1', '2', '3', 's']), 'debug': BuiltinOption(UserBooleanOption, 'Debug', True), 'wrap_mode': BuiltinOption(UserComboOption, 'Wrap mode', 'default', choices=['default', 'nofallback', 'nodownload', 'forcefallback']), - 'pkg_config_path': BuiltinOption(UserArrayOption, 'List of additional paths for pkg-config to search', []), + 'pkg_config_path': BuiltinOption(UserArrayOption, 'List of additional paths for pkg-config to search', [], separate_cross=True), } # Special prefix-dependent defaults for installation directories that reside in -- cgit v1.1 From 91b2475e30d7659dad24eb35b47e4d098c716792 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Thu, 4 Apr 2019 15:48:54 -0700 Subject: dependencies/pkg-config: Add support for different cross_flags --- mesonbuild/dependencies/base.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'mesonbuild') diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py index 94a6a6b..1787f1f 100644 --- a/mesonbuild/dependencies/base.py +++ b/mesonbuild/dependencies/base.py @@ -616,7 +616,10 @@ class PkgConfigDependency(ExternalDependency): else: env = env.copy() - extra_paths = self.env.coredata.get_builtin_option('pkg_config_path') + if self.want_cross: + extra_paths = self.env.coredata.get_builtin_option('cross_pkg_config_path') + else: + extra_paths = self.env.coredata.get_builtin_option('pkg_config_path') env['PKG_CONFIG_PATH'] = ':'.join([p for p in extra_paths]) fenv = frozenset(env.items()) targs = tuple(args) -- cgit v1.1