From 4fbdcf881de26bb30c63394de0fb4b261b5fcd8d Mon Sep 17 00:00:00 2001 From: Ben Corby Date: Mon, 16 Dec 2024 18:40:30 +1100 Subject: [PATCH] Enable the use of get_option() as a parameter for project() --- mesonbuild/interpreter/interpreter.py | 64 ++++++++++--------- .../meson.build | 4 ++ .../meson.options | 1 + 3 files changed, 40 insertions(+), 29 deletions(-) create mode 100644 test cases/common/281 get_option in project function/meson.build create mode 100644 test cases/common/281 get_option in project function/meson.options diff --git a/mesonbuild/interpreter/interpreter.py b/mesonbuild/interpreter/interpreter.py index d717485e8a1e..5518fa51d0bd 100644 --- a/mesonbuild/interpreter/interpreter.py +++ b/mesonbuild/interpreter/interpreter.py @@ -1,4 +1,3 @@ -# SPDX-License-Identifier: Apache-2.0 # Copyright 2012-2021 The Meson development team # Copyright © 2023-2024 Intel Corporation @@ -1085,6 +1084,9 @@ def get_option_internal(self, optname: str) -> options.UserOption: def func_get_option(self, nodes: mparser.BaseNode, args: T.Tuple[str], kwargs: 'TYPE_kwargs') -> T.Union[options.UserOption, 'TYPE_var']: optname = args[0] + + self.load_options(nodes, args, False) + if ':' in optname: raise InterpreterException('Having a colon in option name is forbidden, ' 'projects are not allowed to directly access ' @@ -1148,6 +1150,36 @@ def set_backend(self) -> None: options = {k: v for k, v in self.environment.options.items() if self.environment.coredata.optstore.is_backend_option(k)} self.coredata.set_options(options) + def load_options(self, node: mparser.FunctionNode, args: T.Tuple[str, T.List[str]], Bool warning) -> None: + # Load "meson.options" before "meson_options.txt", and produce a warning if + # it is being used with an old version. I have added check that if both + # exist the warning isn't raised + option_file = os.path.join(self.source_root, self.subdir, 'meson.options') + old_option_file = os.path.join(self.source_root, self.subdir, 'meson_options.txt') + + if os.path.exists(option_file): + if warning: + if os.path.exists(old_option_file): + if os.path.samefile(option_file, old_option_file): + mlog.debug("Not warning about meson.options with version minimum < 1.1 because meson_options.txt also exists") + else: + raise MesonException("meson.options and meson_options.txt both exist, but are not the same file.") + else: + FeatureNew.single_use('meson.options file', '1.1', self.subproject, 'Use meson_options.txt instead') + else: + option_file = old_option_file + if os.path.exists(option_file): + with open(option_file, 'rb') as f: + # We want fast not cryptographically secure, this is just to + # see if the option file has changed + self.coredata.options_files[self.subproject] = (option_file, hashlib.sha1(f.read()).hexdigest()) + oi = optinterpreter.OptionInterpreter(self.environment.coredata.optstore, self.subproject) + oi.process(option_file) + self.coredata.update_project_options(oi.options, self.subproject) + self.add_build_def_file(option_file) + else: + self.coredata.options_files[self.subproject] = None + @typed_pos_args('project', str, varargs=str) @typed_kwargs( 'project', @@ -1169,6 +1201,8 @@ def func_project(self, node: mparser.FunctionNode, args: T.Tuple[str, T.List[str if ':' in proj_name: raise InvalidArguments(f"Project name {proj_name!r} must not contain ':'") + self.load_options(nodes, args, True) + # This needs to be evaluated as early as possible, as meson uses this # for things like deprecation testing. if kwargs['meson_version']: @@ -1176,34 +1210,6 @@ def func_project(self, node: mparser.FunctionNode, args: T.Tuple[str, T.List[str else: mesonlib.project_meson_versions[self.subproject] = mesonlib.NoProjectVersion() - # Load "meson.options" before "meson_options.txt", and produce a warning if - # it is being used with an old version. I have added check that if both - # exist the warning isn't raised - option_file = os.path.join(self.source_root, self.subdir, 'meson.options') - old_option_file = os.path.join(self.source_root, self.subdir, 'meson_options.txt') - - if os.path.exists(option_file): - if os.path.exists(old_option_file): - if os.path.samefile(option_file, old_option_file): - mlog.debug("Not warning about meson.options with version minimum < 1.1 because meson_options.txt also exists") - else: - raise MesonException("meson.options and meson_options.txt both exist, but are not the same file.") - else: - FeatureNew.single_use('meson.options file', '1.1', self.subproject, 'Use meson_options.txt instead') - else: - option_file = old_option_file - if os.path.exists(option_file): - with open(option_file, 'rb') as f: - # We want fast not cryptographically secure, this is just to - # see if the option file has changed - self.coredata.options_files[self.subproject] = (option_file, hashlib.sha1(f.read()).hexdigest()) - oi = optinterpreter.OptionInterpreter(self.environment.coredata.optstore, self.subproject) - oi.process(option_file) - self.coredata.update_project_options(oi.options, self.subproject) - self.add_build_def_file(option_file) - else: - self.coredata.options_files[self.subproject] = None - if self.subproject: self.project_default_options = {k.evolve(subproject=self.subproject): v for k, v in kwargs['default_options'].items()} diff --git a/test cases/common/281 get_option in project function/meson.build b/test cases/common/281 get_option in project function/meson.build new file mode 100644 index 000000000000..bf028485236b --- /dev/null +++ b/test cases/common/281 get_option in project function/meson.build @@ -0,0 +1,4 @@ +# Project +project('test', + version: '1.0' + get_option('append_to_version') + ) diff --git a/test cases/common/281 get_option in project function/meson.options b/test cases/common/281 get_option in project function/meson.options new file mode 100644 index 000000000000..9fd0f5328d8f --- /dev/null +++ b/test cases/common/281 get_option in project function/meson.options @@ -0,0 +1 @@ +option('append_to_version', type : 'string', value : '.0001', description : 'append to version')