diff options
| author | Jussi Pakkanen <jpakkane@gmail.com> | 2024-07-14 19:33:41 +0300 |
|---|---|---|
| committer | Jussi Pakkanen <jpakkane@gmail.com> | 2024-07-17 18:37:51 +0300 |
| commit | 6e200222957063819a00e3bf767ce28b7489c31f (patch) | |
| tree | 1c95bf865976905b83b4f7ae5c4a32edeb799f8b | |
| parent | 61c742fae9ec74e81b3bb3caf815cf49992fb93c (diff) | |
| download | meson-6e200222957063819a00e3bf767ce28b7489c31f.tar.gz | |
Remove module type from OptionKey.
| -rw-r--r-- | mesonbuild/coredata.py | 6 | ||||
| -rw-r--r-- | mesonbuild/mconf.py | 7 | ||||
| -rw-r--r-- | mesonbuild/modules/__init__.py | 10 | ||||
| -rw-r--r-- | mesonbuild/modules/pkgconfig.py | 2 | ||||
| -rw-r--r-- | mesonbuild/modules/python.py | 10 | ||||
| -rw-r--r-- | mesonbuild/options.py | 78 | ||||
| -rw-r--r-- | unittests/datatests.py | 4 |
7 files changed, 72 insertions, 45 deletions
diff --git a/mesonbuild/coredata.py b/mesonbuild/coredata.py index 8c797cdb8..f9d209913 100644 --- a/mesonbuild/coredata.py +++ b/mesonbuild/coredata.py @@ -422,7 +422,11 @@ class CoreData: value = opts_map.get_value(key.as_root()) else: value = None - opts_map.add_system_option(key, opt.init_option(key, value, options.default_prefix())) + if key.has_module_prefix(): + modulename = key.get_module_prefix() + opts_map.add_module_option(modulename, key, opt.init_option(key, value, options.default_prefix())) + else: + opts_map.add_system_option(key, opt.init_option(key, value, options.default_prefix())) def init_backend_options(self, backend_name: str) -> None: if backend_name == 'ninja': diff --git a/mesonbuild/mconf.py b/mesonbuild/mconf.py index bd54251bd..6cb64e1c4 100644 --- a/mesonbuild/mconf.py +++ b/mesonbuild/mconf.py @@ -272,12 +272,13 @@ class Conf: dir_options[k] = v elif k in test_option_names: test_options[k] = v - elif k.module: + elif k.has_module_prefix(): # Ignore module options if we did not use that module during # configuration. - if self.build and k.module not in self.build.modules: + modname = k.get_module_prefix() + if self.build and modname not in self.build.modules: continue - module_options[k.module][k] = v + module_options[modname][k] = v elif self.coredata.optstore.is_builtin_option(k): core_options[k] = v diff --git a/mesonbuild/modules/__init__.py b/mesonbuild/modules/__init__.py index 94d7e5da6..3fe4956c7 100644 --- a/mesonbuild/modules/__init__.py +++ b/mesonbuild/modules/__init__.py @@ -132,15 +132,13 @@ class ModuleState: self._interpreter.func_test(self.current_node, real_args, kwargs) def get_option(self, name: str, subproject: str = '', - machine: MachineChoice = MachineChoice.HOST, - module: T.Optional[str] = None) -> T.Union[T.List[str], str, int, bool]: - return self.environment.coredata.get_option(OptionKey(name, subproject, machine, module)) + machine: MachineChoice = MachineChoice.HOST) -> T.Union[T.List[str], str, int, bool]: + return self.environment.coredata.get_option(OptionKey(name, subproject, machine)) def is_user_defined_option(self, name: str, subproject: str = '', machine: MachineChoice = MachineChoice.HOST, - lang: T.Optional[str] = None, - module: T.Optional[str] = None) -> bool: - key = OptionKey(name, subproject, machine, module) + lang: T.Optional[str] = None) -> bool: + key = OptionKey(name, subproject, machine) return key in self._interpreter.user_defined_options.cmd_line_options def process_include_dirs(self, dirs: T.Iterable[T.Union[str, IncludeDirs]]) -> T.Iterable[IncludeDirs]: diff --git a/mesonbuild/modules/pkgconfig.py b/mesonbuild/modules/pkgconfig.py index d66c2a901..16c8c0798 100644 --- a/mesonbuild/modules/pkgconfig.py +++ b/mesonbuild/modules/pkgconfig.py @@ -703,7 +703,7 @@ class PkgConfigModule(NewExtensionModule): else: pkgroot = os.path.join(_as_str(state.environment.coredata.get_option(OptionKey('libdir'))), 'pkgconfig') pkgroot_name = os.path.join('{libdir}', 'pkgconfig') - relocatable = state.get_option('relocatable', module='pkgconfig') + relocatable = state.get_option('pkgconfig.relocatable') self._generate_pkgconfig_file(state, deps, subdirs, name, description, url, version, pcfile, conflicts, variables, unescaped_variables, False, dataonly, diff --git a/mesonbuild/modules/python.py b/mesonbuild/modules/python.py index dec77e249..1b7a05640 100644 --- a/mesonbuild/modules/python.py +++ b/mesonbuild/modules/python.py @@ -83,13 +83,13 @@ class PythonExternalProgram(BasicPythonExternalProgram): if not state: # This happens only from run_project_tests.py return rel_path - value = T.cast('str', state.get_option(f'{key}dir', module='python')) + value = T.cast('str', state.get_option(f'python.{key}dir')) if value: - if state.is_user_defined_option('install_env', module='python'): + if state.is_user_defined_option('python.install_env'): raise mesonlib.MesonException(f'python.{key}dir and python.install_env are mutually exclusive') return value - install_env = state.get_option('install_env', module='python') + install_env = state.get_option('python.install_env') if install_env == 'auto': install_env = 'venv' if self.info['is_venv'] else 'system' @@ -169,7 +169,7 @@ class PythonInstallation(_ExternalProgramHolder['PythonExternalProgram']): self.current_node) limited_api_version = kwargs.pop('limited_api') - allow_limited_api = self.interpreter.environment.coredata.get_option(OptionKey('allow_limited_api', module='python')) + allow_limited_api = self.interpreter.environment.coredata.get_option(OptionKey('python.allow_limited_api')) if limited_api_version != '' and allow_limited_api: target_suffix = self.limited_api_suffix @@ -374,7 +374,7 @@ class PythonModule(ExtensionModule): def _get_install_scripts(self) -> T.List[mesonlib.ExecutableSerialisation]: backend = self.interpreter.backend ret = [] - optlevel = self.interpreter.environment.coredata.get_option(OptionKey('bytecompile', module='python')) + optlevel = self.interpreter.environment.coredata.get_option(OptionKey('python.bytecompile')) if optlevel == -1: return ret if not any(PythonExternalProgram.run_bytecompile.values()): diff --git a/mesonbuild/options.py b/mesonbuild/options.py index e50aa431f..912cfa23b 100644 --- a/mesonbuild/options.py +++ b/mesonbuild/options.py @@ -90,17 +90,15 @@ class OptionKey: internally easier to reason about and produce. """ - __slots__ = ['name', 'subproject', 'machine', '_hash', 'module'] + __slots__ = ['name', 'subproject', 'machine', '_hash'] name: str subproject: str machine: MachineChoice _hash: int - module: T.Optional[str] def __init__(self, name: str, subproject: str = '', - machine: MachineChoice = MachineChoice.HOST, - module: T.Optional[str] = None): + machine: MachineChoice = MachineChoice.HOST): # the _type option to the constructor is kinda private. We want to be # able tos ave the state and avoid the lookup function when # pickling/unpickling, but we need to be able to calculate it when @@ -108,8 +106,7 @@ class OptionKey: object.__setattr__(self, 'name', name) object.__setattr__(self, 'subproject', subproject) object.__setattr__(self, 'machine', machine) - object.__setattr__(self, 'module', module) - object.__setattr__(self, '_hash', hash((name, subproject, machine, module))) + object.__setattr__(self, '_hash', hash((name, subproject, machine))) def __setattr__(self, key: str, value: T.Any) -> None: raise AttributeError('OptionKey instances do not support mutation.') @@ -119,7 +116,6 @@ class OptionKey: 'name': self.name, 'subproject': self.subproject, 'machine': self.machine, - 'module': self.module, } def __setstate__(self, state: T.Dict[str, T.Any]) -> None: @@ -137,7 +133,7 @@ class OptionKey: return self._hash def _to_tuple(self) -> T.Tuple[str, str, str, MachineChoice, str]: - return (self.subproject, self.module or '', self.machine, self.name) + return (self.subproject, self.machine, self.name) def __eq__(self, other: object) -> bool: if isinstance(other, OptionKey): @@ -153,14 +149,12 @@ class OptionKey: out = self.name if self.machine is MachineChoice.BUILD: out = f'build.{out}' - if self.module: - out = f'{self.module}.{out}' if self.subproject: out = f'{self.subproject}:{out}' return out def __repr__(self) -> str: - return f'OptionKey({self.name!r}, {self.subproject!r}, {self.machine!r}, {self.module!r})' + return f'OptionKey({self.name!r}, {self.subproject!r}, {self.machine!r})' @classmethod def from_string(cls, raw: str) -> 'OptionKey': @@ -174,26 +168,24 @@ class OptionKey: except ValueError: subproject, raw2 = '', raw - module = None for_machine = MachineChoice.HOST try: prefix, raw3 = raw2.split('.') if prefix == 'build': for_machine = MachineChoice.BUILD else: - module = prefix + raw3 = raw2 except ValueError: raw3 = raw2 opt = raw3 assert ':' not in opt - assert '.' not in opt + assert opt.count('.') < 2 - return cls(opt, subproject, for_machine, module) + return cls(opt, subproject, for_machine) def evolve(self, name: T.Optional[str] = None, subproject: T.Optional[str] = None, - machine: T.Optional[MachineChoice] = None, - module: T.Optional[str] = '') -> 'OptionKey': + machine: T.Optional[MachineChoice] = None) -> 'OptionKey': """Create a new copy of this key, but with altered members. For example: @@ -208,7 +200,6 @@ class OptionKey: name if name is not None else self.name, subproject if subproject is not None else self.subproject, machine if machine is not None else self.machine, - module if module != '' else self.module ) def as_root(self) -> 'OptionKey': @@ -228,6 +219,20 @@ class OptionKey: import sys sys.exit('FATAL internal error. This should not make it into an actual release. File a bug.') + def has_module_prefix(self) -> bool: + return '.' in self.name + + def get_module_prefix(self) -> T.Optional[str]: + if self.has_module_prefix(): + return self.name.split('.', 1)[0] + return None + + def without_module_prefix(self) -> 'OptionKey': + if self.has_module_prefix(): + newname = self.name.split('.', 1)[1] + return self.evolve(newname) + return self + class UserOption(T.Generic[_T], HoldableObject): def __init__(self, name: str, description: str, choices: T.Optional[T.Union[str, T.List[_T]]], @@ -633,19 +638,19 @@ BUILTIN_CORE_OPTIONS: T.Dict['OptionKey', 'BuiltinOption'] = OrderedDict([ (OptionKey('vsenv'), BuiltinOption(UserBooleanOption, 'Activate Visual Studio environment', False, readonly=True)), # Pkgconfig module - (OptionKey('relocatable', module='pkgconfig'), + (OptionKey('pkgconfig.relocatable'), BuiltinOption(UserBooleanOption, 'Generate pkgconfig files as relocatable', False)), # Python module - (OptionKey('bytecompile', module='python'), + (OptionKey('python.bytecompile'), BuiltinOption(UserIntegerOption, 'Whether to compile bytecode', (-1, 2, 0))), - (OptionKey('install_env', module='python'), + (OptionKey('python.install_env'), BuiltinOption(UserComboOption, 'Which python environment to install to', 'prefix', choices=['auto', 'prefix', 'system', 'venv'])), - (OptionKey('platlibdir', module='python'), + (OptionKey('python.platlibdir'), BuiltinOption(UserStringOption, 'Directory for site-specific, platform-specific files.', '')), - (OptionKey('purelibdir', module='python'), + (OptionKey('python.purelibdir'), BuiltinOption(UserStringOption, 'Directory for site-specific, non-platform-specific files.', '')), - (OptionKey('allow_limited_api', module='python'), + (OptionKey('python.allow_limited_api'), BuiltinOption(UserBooleanOption, 'Whether to allow use of the Python Limited API', True)), ]) @@ -662,8 +667,8 @@ BUILTIN_DIR_NOPREFIX_OPTIONS: T.Dict[OptionKey, T.Dict[str, str]] = { OptionKey('sysconfdir'): {'/usr': '/etc'}, OptionKey('localstatedir'): {'/usr': '/var', '/usr/local': '/var/local'}, OptionKey('sharedstatedir'): {'/usr': '/var/lib', '/usr/local': '/var/local/lib'}, - OptionKey('platlibdir', module='python'): {}, - OptionKey('purelibdir', module='python'): {}, + OptionKey('python.platlibdir'): {}, + OptionKey('python.purelibdir'): {}, } class OptionStore: @@ -671,6 +676,7 @@ class OptionStore: self.d: T.Dict['OptionKey', 'UserOption[T.Any]'] = {} self.project_options = set() self.all_languages = set() + self.module_options = set() from .compilers import all_languages for lang in all_languages: self.all_languages.add(lang) @@ -691,6 +697,12 @@ class OptionStore: def add_system_option(self, key: T.Union[OptionKey, str], valobj: 'UserOption[T.Any]'): key = self.ensure_key(key) + if '.' in key.name: + raise MesonException(f'Internal error: non-module option has a period in its name {key.name}.') + self.add_system_option_internal(key, valobj) + + def add_system_option_internal(self, key: T.Union[OptionKey, str], valobj: 'UserOption[T.Any]'): + key = self.ensure_key(key) assert isinstance(valobj, UserOption) self.d[key] = valobj @@ -705,6 +717,15 @@ class OptionStore: self.d[key] = valobj self.project_options.add(key) + def add_module_option(self, modulename: str, key: T.Union[OptionKey, str], valobj: 'UserOption[T.Any]'): + key = self.ensure_key(key) + if key.name.startswith('build.'): + raise MesonException('FATAL internal error: somebody goofed option handling.') + if not key.name.startswith(modulename + '.'): + raise MesonException('Internal error: module option name {key.name} does not start with module prefix {modulename}.') + self.add_system_option_internal(key, valobj) + self.module_options.add(key) + def set_value(self, key: T.Union[OptionKey, str], new_value: 'T.Any') -> bool: key = self.ensure_key(key) return self.d[key].set_value(new_value) @@ -764,7 +785,7 @@ class OptionStore: def is_builtin_option(self, key: OptionKey) -> bool: """Convenience method to check if this is a builtin option.""" - return key.name in _BUILTIN_NAMES or key.module + return key.name in _BUILTIN_NAMES or self.is_module_option(key) def is_base_option(self, key: OptionKey) -> bool: """Convenience method to check if this is a base option.""" @@ -784,3 +805,6 @@ class OptionStore: if prefix in self.all_languages: return True return False + + def is_module_option(self, key: OptionKey) -> bool: + return key in self.module_options diff --git a/unittests/datatests.py b/unittests/datatests.py index 73b937d43..cb6542db8 100644 --- a/unittests/datatests.py +++ b/unittests/datatests.py @@ -139,8 +139,8 @@ class DataTests(unittest.TestCase): found_entries |= options self.assertEqual(found_entries, { - *(str(k.evolve(module=None)) for k in mesonbuild.options.BUILTIN_OPTIONS), - *(str(k.evolve(module=None)) for k in mesonbuild.options.BUILTIN_OPTIONS_PER_MACHINE), + *(str(k.without_module_prefix()) for k in mesonbuild.options.BUILTIN_OPTIONS), + *(str(k.without_module_prefix()) for k in mesonbuild.options.BUILTIN_OPTIONS_PER_MACHINE), }) # Check that `buildtype` table inside `Core options` matches how |
