Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix spurious error message so its clear using get_option() as a parameter to project() is prohibited #14016

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 52 additions & 23 deletions mesonbuild/interpreter/interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -1078,8 +1078,6 @@ def get_option_internal(self, optname: str) -> options.UserOption:
except KeyError:
pass

raise InterpreterException(f'Tried to access unknown option {optname!r}.')

@typed_pos_args('get_option', str)
@noKwargs
def func_get_option(self, nodes: mparser.BaseNode, args: T.Tuple[str],
Expand All @@ -1096,12 +1094,34 @@ def func_get_option(self, nodes: mparser.BaseNode, args: T.Tuple[str],
opt = self.get_option_internal(optname)
if isinstance(opt, options.UserFeatureOption):
opt.name = optname
return opt
_option_value = opt
elif isinstance(opt, options.UserOption):
if isinstance(opt.value, str):
return P_OBJ.OptionString(opt.value, f'{{{optname}}}')
return opt.value
return opt
_option_value = P_OBJ.OptionString(opt.value, f'{{{optname}}}')
else:
_option_value = opt.value
else:
_option_value = opt

self.load_options(nodes, args)
opt = self.get_option_internal(optname)
if isinstance(opt, options.UserFeatureOption):
opt.name = optname
option_value = opt
elif isinstance(opt, options.UserOption):
if isinstance(opt.value, str):
option_value = P_OBJ.OptionString(opt.value, f'{{{optname}}}')
else:
option_value = opt.value
else:
option_value = opt

if option_value is None and _option_value is None:
raise InterpreterException(f'Tried to access unknown option {optname!r}.')
elif not option_value == _option_value:
if not hasattr(self, 'prohibited_load_options_used'):
self.prohibited_load_options_used = {'option': optname, 'value': option_value}
return option_value

@typed_pos_args('configuration_data', optargs=[dict])
@noKwargs
Expand Down Expand Up @@ -1148,6 +1168,23 @@ 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]]) -> None:
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 not os.path.exists(option_file):
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',
Expand All @@ -1169,19 +1206,19 @@ 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 ':'")

# Read in the options file.
self.load_options(node, args)

# This needs to be evaluated as early as possible, as meson uses this
# for things like deprecation testing.
if kwargs['meson_version']:
self.handle_meson_version(kwargs['meson_version'], node)
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
# Warn about use of meson.options / meson_options.txt.
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):
Expand All @@ -1190,19 +1227,11 @@ def func_project(self, node: mparser.FunctionNode, args: T.Tuple[str, T.List[str
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

# Using get_option() in project() isn't allowed.
# For the reason see https://github.com/mesonbuild/meson/pull/14016
if hasattr(self, 'prohibited_load_options_used'):
FeatureBroken.single_use('Reading meson.options or a meson -Dopt=value parameter by using get_option() as a parameter to project() isn\'t allowed', '1.7', self.subproject, 'Instead use something similar to run_command(\'./get_value.py\', check: true).stdout().strip()')

if self.subproject:
self.project_default_options = {k.evolve(subproject=self.subproject): v
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Project
project('test', 'c', version: '1.0' + get_option('append_to_version'))
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
option('append_to_version', type : 'string', value : '.0001', description : 'append to version')
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"stdout": [
{
"line": "DEPRECATION: Project uses feature that was always broken, and is now deprecated since '1.7': Reading meson.options or a meson -Dopt=value parameter by using get_option() as a parameter to project() isn't allowed. Instead use something similar to run_command('./get_value.py', check: true).stdout().strip()"
}
]
}
Loading