use the OptionKey type for command line and machine files

pull/8080/head
Dylan Baker 4 years ago
parent 983380d5ce
commit b25a423a64
  1. 6
      mesonbuild/ast/introspection.py
  2. 125
      mesonbuild/coredata.py
  3. 93
      mesonbuild/environment.py
  4. 7
      mesonbuild/interpreter.py
  5. 2
      mesonbuild/mconf.py
  6. 2
      run_unittests.py

@ -65,7 +65,7 @@ class IntrospectionInterpreter(AstInterpreter):
self.coredata = self.environment.get_coredata() self.coredata = self.environment.get_coredata()
self.option_file = os.path.join(self.source_root, self.subdir, 'meson_options.txt') self.option_file = os.path.join(self.source_root, self.subdir, 'meson_options.txt')
self.backend = backend self.backend = backend
self.default_options = {'backend': self.backend} self.default_options = {cdata.OptionKey('backend'): self.backend}
self.project_data = {} # type: T.Dict[str, T.Any] self.project_data = {} # type: T.Dict[str, T.Any]
self.targets = [] # type: T.List[T.Dict[str, T.Any]] self.targets = [] # type: T.List[T.Dict[str, T.Any]]
self.dependencies = [] # type: T.List[T.Dict[str, T.Any]] self.dependencies = [] # type: T.List[T.Dict[str, T.Any]]
@ -107,7 +107,7 @@ class IntrospectionInterpreter(AstInterpreter):
def_opts = self.flatten_args(kwargs.get('default_options', [])) def_opts = self.flatten_args(kwargs.get('default_options', []))
_project_default_options = mesonlib.stringlistify(def_opts) _project_default_options = mesonlib.stringlistify(def_opts)
self.project_default_options = cdata.create_options_dict(_project_default_options) self.project_default_options = cdata.create_options_dict(_project_default_options, self.subproject)
self.default_options.update(self.project_default_options) self.default_options.update(self.project_default_options)
self.coredata.set_default_options(self.default_options, self.subproject, self.environment) self.coredata.set_default_options(self.default_options, self.subproject, self.environment)
@ -125,7 +125,7 @@ class IntrospectionInterpreter(AstInterpreter):
self.do_subproject(i) self.do_subproject(i)
self.coredata.init_backend_options(self.backend) self.coredata.init_backend_options(self.backend)
options = {k: v for k, v in self.environment.raw_options.items() if k.startswith('backend_')} options = {k: v for k, v in self.environment.options.items() if k.name.startswith('backend_')}
self.coredata.set_options(options) self.coredata.set_options(options)
self._add_languages(proj_langs, MachineChoice.HOST) self._add_languages(proj_langs, MachineChoice.HOST)

@ -551,7 +551,7 @@ class CoreData:
self.target_guids = {} self.target_guids = {}
self.version = version self.version = version
self.builtins = {} # type: OptionDictType self.builtins = {} # type: OptionDictType
self.builtins_per_machine = PerMachine({}, {}) self.builtins_per_machine: PerMachine['OptionDictType'] = PerMachine({}, {})
self.backend_options = {} # type: OptionDictType self.backend_options = {} # type: OptionDictType
self.user_options = {} # type: OptionDictType self.user_options = {} # type: OptionDictType
self.compiler_options = PerMachine( self.compiler_options = PerMachine(
@ -835,14 +835,10 @@ class CoreData:
return k[:idx + 1] + 'build.' + k[idx + 1:] return k[:idx + 1] + 'build.' + k[idx + 1:]
@classmethod @classmethod
def is_per_machine_option(cls, optname): def is_per_machine_option(cls, optname: OptionKey) -> bool:
if optname in BUILTIN_OPTIONS_PER_MACHINE: if optname.name in BUILTIN_OPTIONS_PER_MACHINE:
return True return True
from .compilers import compilers return optname.lang is not None
for lang_prefix in [lang + '_' for lang in compilers.all_languages]:
if optname.startswith(lang_prefix):
return True
return False
def _get_all_nonbuiltin_options(self) -> T.Iterable[T.Dict[str, UserOption]]: def _get_all_nonbuiltin_options(self) -> T.Iterable[T.Dict[str, UserOption]]:
yield self.backend_options yield self.backend_options
@ -899,16 +895,6 @@ class CoreData:
return False return False
return len(self.cross_files) > 0 return len(self.cross_files) > 0
def strip_build_option_names(self, options):
res = OrderedDict()
for k, v in options.items():
if k.startswith('build.'):
k = k.split('.', 1)[1]
res.setdefault(k, v)
else:
res[k] = v
return res
def copy_build_options_from_regular_ones(self): def copy_build_options_from_regular_ones(self):
assert(not self.is_cross_build()) assert(not self.is_cross_build())
for k, o in self.builtins_per_machine.host.items(): for k, o in self.builtins_per_machine.host.items():
@ -919,25 +905,26 @@ class CoreData:
if k in build_opts: if k in build_opts:
build_opts[k].set_value(o.value) build_opts[k].set_value(o.value)
def set_options(self, options: T.Dict[str, T.Any], subproject: str = '', warn_unknown: bool = True) -> None: def set_options(self, options: T.Dict[OptionKey, T.Any], subproject: str = '', warn_unknown: bool = True) -> None:
if not self.is_cross_build(): if not self.is_cross_build():
options = self.strip_build_option_names(options) options = {k: v for k, v in options.items() if k.machine is not MachineChoice.BUILD}
# Set prefix first because it's needed to sanitize other options # Set prefix first because it's needed to sanitize other options
if 'prefix' in options: pfk = OptionKey('prefix')
prefix = self.sanitize_prefix(options['prefix']) if pfk in options:
prefix = self.sanitize_prefix(options[pfk])
self.builtins['prefix'].set_value(prefix) self.builtins['prefix'].set_value(prefix)
for key in builtin_dir_noprefix_options: for key in builtin_dir_noprefix_options:
if key not in options: if key not in options:
self.builtins[key].set_value(BUILTIN_OPTIONS[key].prefixed_default(key, prefix)) self.builtins[key].set_value(BUILTIN_OPTIONS[key].prefixed_default(key, prefix))
unknown_options = [] unknown_options: T.List[OptionKey] = []
for k, v in options.items(): for k, v in options.items():
if k == 'prefix': if k == pfk:
continue continue
if self._try_set_builtin_option(k, v): if self._try_set_builtin_option(str(k), v):
continue continue
for opts in self._get_all_nonbuiltin_options(): for opts in self._get_all_nonbuiltin_options():
tgt = opts.get(k) tgt = opts.get(str(k))
if tgt is None: if tgt is None:
continue continue
tgt.set_value(v) tgt.set_value(v)
@ -945,59 +932,50 @@ class CoreData:
else: else:
unknown_options.append(k) unknown_options.append(k)
if unknown_options and warn_unknown: if unknown_options and warn_unknown:
unknown_options = ', '.join(sorted(unknown_options)) unknown_options_str = ', '.join(sorted(str(s) for s in unknown_options))
sub = 'In subproject {}: '.format(subproject) if subproject else '' sub = 'In subproject {}: '.format(subproject) if subproject else ''
mlog.warning('{}Unknown options: "{}"'.format(sub, unknown_options)) mlog.warning('{}Unknown options: "{}"'.format(sub, unknown_options_str))
mlog.log('The value of new options can be set with:') mlog.log('The value of new options can be set with:')
mlog.log(mlog.bold('meson setup <builddir> --reconfigure -Dnew_option=new_value ...')) mlog.log(mlog.bold('meson setup <builddir> --reconfigure -Dnew_option=new_value ...'))
if not self.is_cross_build(): if not self.is_cross_build():
self.copy_build_options_from_regular_ones() self.copy_build_options_from_regular_ones()
def set_default_options(self, default_options: 'T.OrderedDict[str, str]', subproject: str, env: 'Environment') -> None: def set_default_options(self, default_options: T.MutableMapping[OptionKey, str], subproject: str, env: 'Environment') -> None:
# Preserve order: if env.raw_options has 'buildtype' it must come after # Preserve order: if env.options has 'buildtype' it must come after
# 'optimization' if it is in default_options. # 'optimization' if it is in default_options.
raw_options = OrderedDict() if not subproject:
for k, v in default_options.items(): options: T.MutableMapping[OptionKey, T.Any] = OrderedDict()
if subproject: for k, v in default_options.items():
k = subproject + ':' + k options[k] = v
raw_options[k] = v options.update(env.options)
raw_options.update(env.raw_options) env.options = options
env.raw_options = raw_options
# Create a subset of options, keeping only project and builtin
# Create a subset of raw_options, keeping only project and builtin
# options for this subproject. # options for this subproject.
# Language and backend specific options will be set later when adding # Language and backend specific options will be set later when adding
# languages and setting the backend (builtin options must be set first # languages and setting the backend (builtin options must be set first
# to know which backend we'll use). # to know which backend we'll use).
options = OrderedDict() options: T.MutableMapping[OptionKey, T.Any] = OrderedDict()
from . import optinterpreter from . import optinterpreter
for k, v in env.raw_options.items(): for k, v in chain(default_options.items(), env.options.items()):
raw_optname = k # Subproject: skip options for other subprojects
if subproject: if k.subproject and k.subproject != subproject:
# Subproject: skip options for other subprojects
if not k.startswith(subproject + ':'):
continue
raw_optname = k.split(':')[1]
elif ':' in k:
# Main prject: skip options for subprojects
continue continue
# Skip base, compiler, and backend options, they are handled when # Skip base, compiler, and backend options, they are handled when
# adding languages and setting backend. # adding languages and setting backend.
if (k not in self.builtins and if (k.name not in self.builtins and k.name not in self.builtins_per_machine[k.machine] and
k not in self.get_prefixed_options_per_machine(self.builtins_per_machine) and optinterpreter.is_invalid_name(str(k), log=False)):
optinterpreter.is_invalid_name(raw_optname, log=False)):
continue continue
options[k] = v options[k] = v
self.set_options(options, subproject=subproject) self.set_options(options, subproject=subproject)
def add_compiler_options(self, options, lang, for_machine, env): def add_compiler_options(self, options: 'OptionDictType', lang: str, for_machine: MachineChoice,
# prefixed compiler options affect just this machine env: 'Environment') -> None:
opt_prefix = for_machine.get_prefix()
for k, o in options.items(): for k, o in options.items():
optname = opt_prefix + lang + '_' + k key = OptionKey(k, lang=lang, machine=for_machine)
value = env.raw_options.get(optname) value = env.options.get(key)
if value is not None: if value is not None:
o.set_value(value) o.set_value(value)
self.compiler_options[for_machine][lang].setdefault(k, o) self.compiler_options[for_machine][lang].setdefault(k, o)
@ -1006,8 +984,7 @@ class CoreData:
for_machine: MachineChoice, env: 'Environment') -> None: for_machine: MachineChoice, env: 'Environment') -> None:
"""Add global language arguments that are needed before compiler/linker detection.""" """Add global language arguments that are needed before compiler/linker detection."""
from .compilers import compilers from .compilers import compilers
options = compilers.get_global_options(lang, comp, for_machine, options = compilers.get_global_options(lang, comp, for_machine, env.is_cross_build())
env.is_cross_build())
self.add_compiler_options(options, lang, for_machine, env) self.add_compiler_options(options, lang, for_machine, env)
def process_new_compiler(self, lang: str, comp: 'Compiler', env: 'Environment') -> None: def process_new_compiler(self, lang: str, comp: 'Compiler', env: 'Environment') -> None:
@ -1021,8 +998,9 @@ class CoreData:
if optname in self.base_options: if optname in self.base_options:
continue continue
oobj = compilers.base_options[optname] oobj = compilers.base_options[optname]
if optname in env.raw_options: key = OptionKey(optname, machine=comp.for_machine)
oobj.set_value(env.raw_options[optname]) if key in env.options:
oobj.set_value(env.options[key])
enabled_opts.append(optname) enabled_opts.append(optname)
self.base_options[optname] = oobj self.base_options[optname] = oobj
self.emit_base_options_warnings(enabled_opts) self.emit_base_options_warnings(enabled_opts)
@ -1118,7 +1096,7 @@ def read_cmd_line_file(build_dir: str, options: argparse.Namespace) -> None:
# Do a copy because config is not really a dict. options.cmd_line_options # Do a copy because config is not really a dict. options.cmd_line_options
# overrides values from the file. # overrides values from the file.
d = dict(config['options']) d = {OptionKey.from_string(k): v for k, v in config['options'].items()}
d.update(options.cmd_line_options) d.update(options.cmd_line_options)
options.cmd_line_options = d options.cmd_line_options = d
@ -1130,9 +1108,6 @@ def read_cmd_line_file(build_dir: str, options: argparse.Namespace) -> None:
# literal_eval to get it into the list of strings. # literal_eval to get it into the list of strings.
options.native_file = ast.literal_eval(properties.get('native_file', '[]')) options.native_file = ast.literal_eval(properties.get('native_file', '[]'))
def cmd_line_options_to_string(options: argparse.Namespace) -> T.Dict[str, str]:
return {k: str(v) for k, v in options.cmd_line_options.items()}
def write_cmd_line_file(build_dir: str, options: argparse.Namespace) -> None: def write_cmd_line_file(build_dir: str, options: argparse.Namespace) -> None:
filename = get_cmd_line_file(build_dir) filename = get_cmd_line_file(build_dir)
config = CmdLineFileParser() config = CmdLineFileParser()
@ -1143,7 +1118,7 @@ def write_cmd_line_file(build_dir: str, options: argparse.Namespace) -> None:
if options.native_file: if options.native_file:
properties['native_file'] = [os.path.abspath(f) for f in options.native_file] properties['native_file'] = [os.path.abspath(f) for f in options.native_file]
config['options'] = cmd_line_options_to_string(options) config['options'] = {str(k): str(v) for k, v in options.cmd_line_options.items()}
config['properties'] = properties config['properties'] = properties
with open(filename, 'w') as f: with open(filename, 'w') as f:
config.write(f) config.write(f)
@ -1152,14 +1127,14 @@ def update_cmd_line_file(build_dir: str, options: argparse.Namespace):
filename = get_cmd_line_file(build_dir) filename = get_cmd_line_file(build_dir)
config = CmdLineFileParser() config = CmdLineFileParser()
config.read(filename) config.read(filename)
config['options'].update(cmd_line_options_to_string(options)) config['options'].update({str(k): str(v) for k, v in options.cmd_line_options.items()})
with open(filename, 'w') as f: with open(filename, 'w') as f:
config.write(f) config.write(f)
def get_cmd_line_options(build_dir: str, options: argparse.Namespace) -> str: def get_cmd_line_options(build_dir: str, options: argparse.Namespace) -> str:
copy = argparse.Namespace(**vars(options)) copy = argparse.Namespace(**vars(options))
read_cmd_line_file(build_dir, copy) read_cmd_line_file(build_dir, copy)
cmdline = ['-D{}={}'.format(k, v) for k, v in copy.cmd_line_options.items()] cmdline = ['-D{}={}'.format(str(k), v) for k, v in copy.cmd_line_options.items()]
if options.cross_file: if options.cross_file:
cmdline += ['--cross-file {}'.format(f) for f in options.cross_file] cmdline += ['--cross-file {}'.format(f) for f in options.cross_file]
if options.native_file: if options.native_file:
@ -1214,14 +1189,17 @@ def register_builtin_arguments(parser: argparse.ArgumentParser) -> None:
parser.add_argument('-D', action='append', dest='projectoptions', default=[], metavar="option", 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.') help='Set the value of an option, can be used several times to set multiple options.')
def create_options_dict(options: T.List[str]) -> T.Dict[str, str]: def create_options_dict(options: T.List[str], subproject: str = '') -> T.Dict[OptionKey, str]:
result = OrderedDict() result: T.OrderedDict[OptionKey, str] = OrderedDict()
for o in options: for o in options:
try: try:
(key, value) = o.split('=', 1) (key, value) = o.split('=', 1)
except ValueError: except ValueError:
raise MesonException('Option {!r} must have a value separated by equals sign.'.format(o)) raise MesonException('Option {!r} must have a value separated by equals sign.'.format(o))
result[key] = value k = OptionKey.from_string(key)
if subproject:
k = k.evolve(subproject=subproject)
result[k] = value
return result return result
def parse_cmd_line_options(args: argparse.Namespace) -> None: def parse_cmd_line_options(args: argparse.Namespace) -> None:
@ -1235,11 +1213,12 @@ def parse_cmd_line_options(args: argparse.Namespace) -> None:
): ):
value = getattr(args, name, None) value = getattr(args, name, None)
if value is not None: if value is not None:
if name in args.cmd_line_options: key = OptionKey.from_string(name)
if key in args.cmd_line_options:
cmdline_name = BuiltinOption.argparse_name_to_arg(name) cmdline_name = BuiltinOption.argparse_name_to_arg(name)
raise MesonException( raise MesonException(
'Got argument {0} as both -D{0} and {1}. Pick one.'.format(name, cmdline_name)) 'Got argument {0} as both -D{0} and {1}. Pick one.'.format(name, cmdline_name))
args.cmd_line_options[name] = value args.cmd_line_options[key] = value
delattr(args, name) delattr(args, name)

@ -130,6 +130,8 @@ from .compilers import (
) )
if T.TYPE_CHECKING: if T.TYPE_CHECKING:
from configparser import ConfigParser
from .dependencies import ExternalProgram from .dependencies import ExternalProgram
build_filename = 'meson.build' build_filename = 'meson.build'
@ -599,12 +601,11 @@ class Environment:
binaries.build = BinaryTable() binaries.build = BinaryTable()
properties.build = Properties() properties.build = Properties()
# Unparsed options as given by the user in machine files, command line, # Options with the key parsed into an OptionKey type.
# and project()'s default_options. Keys are in the command line format: #
# "[<subproject>:][build.]option_name".
# Note that order matters because of 'buildtype', if it is after # Note that order matters because of 'buildtype', if it is after
# 'optimization' and 'debug' keys, it override them. # 'optimization' and 'debug' keys, it override them.
self.raw_options = collections.OrderedDict() # type: collections.OrderedDict[str, str] self.options: T.MutableMapping[coredata.OptionKey, str] = collections.OrderedDict()
## Read in native file(s) to override build machine configuration ## Read in native file(s) to override build machine configuration
@ -613,7 +614,7 @@ class Environment:
binaries.build = BinaryTable(config.get('binaries', {})) binaries.build = BinaryTable(config.get('binaries', {}))
properties.build = Properties(config.get('properties', {})) properties.build = Properties(config.get('properties', {}))
cmakevars.build = CMakeVariables(config.get('cmake', {})) cmakevars.build = CMakeVariables(config.get('cmake', {}))
self.load_machine_file_options(config, properties.build) self.load_machine_file_options(config, properties.build, MachineChoice.BUILD)
## Read in cross file(s) to override host machine configuration ## Read in cross file(s) to override host machine configuration
@ -626,10 +627,16 @@ class Environment:
machines.host = MachineInfo.from_literal(config['host_machine']) machines.host = MachineInfo.from_literal(config['host_machine'])
if 'target_machine' in config: if 'target_machine' in config:
machines.target = MachineInfo.from_literal(config['target_machine']) machines.target = MachineInfo.from_literal(config['target_machine'])
# Keep only per machine options from the native file and prefix them # Keep only per machine options from the native file. The cross
# with "build.". The cross file takes precedence over all other options. # file takes precedence over all other options.
self.keep_per_machine_options() self.keep_per_machine_options()
self.load_machine_file_options(config, properties.host) self.load_machine_file_options(config, properties.host, MachineChoice.HOST)
else:
# IF we aren't cross compiling, but we hav ea native file, the
# native file is for the host. This is due to an mismatch between
# meson internals which talk about build an host, and external
# interfaces which talk about native and cross.
self.options = {k.as_host(): v for k, v in self.options.items()}
## "freeze" now initialized configuration, and "save" to the class. ## "freeze" now initialized configuration, and "save" to the class.
@ -639,15 +646,17 @@ class Environment:
self.cmakevars = cmakevars.default_missing() self.cmakevars = cmakevars.default_missing()
# Command line options override those from cross/native files # Command line options override those from cross/native files
self.raw_options.update(options.cmd_line_options) self.options.update(options.cmd_line_options)
# Take default value from env if not set in cross/native files or command line. # Take default value from env if not set in cross/native files or command line.
self.set_default_options_from_env() self.set_default_options_from_env()
# Warn if the user is using two different ways of setting build-type # Warn if the user is using two different ways of setting build-type
# options that override each other # options that override each other
if 'buildtype' in self.raw_options and \ bt = coredata.OptionKey('buildtype')
('optimization' in self.raw_options or 'debug' in self.raw_options): db = coredata.OptionKey('debug')
op = coredata.OptionKey('optimization')
if bt in self.options and (db in self.options or op in self.options):
mlog.warning('Recommend using either -Dbuildtype or -Doptimization + -Ddebug. ' mlog.warning('Recommend using either -Dbuildtype or -Doptimization + -Ddebug. '
'Using both is redundant since they override each other. ' 'Using both is redundant since they override each other. '
'See: https://mesonbuild.com/Builtin-options.html#build-type-options') 'See: https://mesonbuild.com/Builtin-options.html#build-type-options')
@ -706,11 +715,13 @@ class Environment:
self.default_pkgconfig = ['pkg-config'] self.default_pkgconfig = ['pkg-config']
self.wrap_resolver = None self.wrap_resolver = None
def load_machine_file_options(self, config, properties): def load_machine_file_options(self, config: 'ConfigParser', properties: Properties, machine: MachineChoice) -> None:
"""Read the contents of a Machine file and put it in the options store."""
paths = config.get('paths') paths = config.get('paths')
if paths: if paths:
mlog.deprecation('The [paths] section is deprecated, use the [built-in options] section instead.') mlog.deprecation('The [paths] section is deprecated, use the [built-in options] section instead.')
self.raw_options.update(paths) for k, v in paths.items():
self.options[coredata.OptionKey.from_string(k).evolve(machine=machine)] = v
deprecated_properties = set() deprecated_properties = set()
for lang in compilers.all_languages: for lang in compilers.all_languages:
deprecated_properties.add(lang + '_args') deprecated_properties.add(lang + '_args')
@ -718,44 +729,40 @@ class Environment:
for k, v in properties.properties.copy().items(): for k, v in properties.properties.copy().items():
if k in deprecated_properties: if k in deprecated_properties:
mlog.deprecation('{} in the [properties] section of the machine file is deprecated, use the [built-in options] section.'.format(k)) mlog.deprecation('{} in the [properties] section of the machine file is deprecated, use the [built-in options] section.'.format(k))
self.raw_options[k] = v self.options[coredata.OptionKey.from_string(k).evolve(machine=machine)] = v
del properties.properties[k] del properties.properties[k]
for section, values in config.items(): for section, values in config.items():
prefix = ''
if ':' in section: if ':' in section:
subproject, section = section.split(':') subproject, section = section.split(':')
prefix = subproject + ':' else:
subproject = ''
if section in ['project options', 'built-in options']: if section in ['project options', 'built-in options']:
self.raw_options.update({prefix + k: v for k, v in values.items()}) for k, v in values.items():
key = coredata.OptionKey.from_string(k).evolve(subproject=subproject, machine=machine)
self.options[key] = v
def keep_per_machine_options(self): def keep_per_machine_options(self) -> None:
per_machine_options = {} for key, value in self.options.items():
for optname, value in self.raw_options.items(): if self.coredata.is_per_machine_option(key):
if self.coredata.is_per_machine_option(optname): self.options[key.as_build()] = value
build_optname = self.coredata.insert_build_prefix(optname)
per_machine_options[build_optname] = value
self.raw_options = per_machine_options
def set_default_options_from_env(self): def set_default_options_from_env(self) -> None:
for for_machine in MachineChoice: for for_machine in MachineChoice:
p_env_pair = get_env_var_pair(for_machine, self.is_cross_build(), 'PKG_CONFIG_PATH') for evar, keyname in [('PKG_CONFIG_PATH', 'pkg_config_path')]:
if p_env_pair is not None: p_env_pair = get_env_var_pair(for_machine, self.is_cross_build(), evar)
p_env_var, p_env = p_env_pair if p_env_pair is not None:
_, p_env = p_env_pair
# PKG_CONFIG_PATH may contain duplicates, which must be
# removed, else a duplicates-in-array-option warning arises. # PKG_CONFIG_PATH may contain duplicates, which must be
p_list = list(mesonlib.OrderedSet(p_env.split(':'))) # removed, else a duplicates-in-array-option warning arises.
p_list = list(mesonlib.OrderedSet(p_env.split(':')))
key = 'pkg_config_path' # Take env vars only on first invocation, if the env changes when
if for_machine == MachineChoice.BUILD: # reconfiguring it gets ignored.
key = 'build.' + key # FIXME: We should remember if we took the value from env to warn
# if it changes on future invocations.
# Take env vars only on first invocation, if the env changes when if self.first_invocation:
# reconfiguring it gets ignored. key = coredata.OptionKey(keyname, machine=for_machine)
# FIXME: We should remember if we took the value from env to warn self.options.setdefault(key, p_list)
# if it changes on future invocations.
if self.first_invocation:
self.raw_options.setdefault(key, p_list)
def create_new_coredata(self, options: 'argparse.Namespace') -> None: def create_new_coredata(self, options: 'argparse.Namespace') -> None:
# WARNING: Don't use any values from coredata in __init__. It gets # WARNING: Don't use any values from coredata in __init__. It gets

@ -11,6 +11,7 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
import pdb
from . import mparser from . import mparser
from . import environment from . import environment
from . import coredata from . import coredata
@ -2905,7 +2906,7 @@ external dependencies (including libraries) must go to "dependencies".''')
return self.disabled_subproject(subp_name, disabled_feature=feature) return self.disabled_subproject(subp_name, disabled_feature=feature)
default_options = mesonlib.stringlistify(kwargs.get('default_options', [])) default_options = mesonlib.stringlistify(kwargs.get('default_options', []))
default_options = coredata.create_options_dict(default_options) default_options = coredata.create_options_dict(default_options, subp_name)
if subp_name == '': if subp_name == '':
raise InterpreterException('Subproject name must not be empty.') raise InterpreterException('Subproject name must not be empty.')
@ -3140,7 +3141,7 @@ external dependencies (including libraries) must go to "dependencies".''')
if self.environment.first_invocation: if self.environment.first_invocation:
self.coredata.init_backend_options(backend) self.coredata.init_backend_options(backend)
options = {k: v for k, v in self.environment.raw_options.items() if k.startswith('backend_')} options = {k: v for k, v in self.environment.options.items() if k.name.startswith('backend_')}
self.coredata.set_options(options) self.coredata.set_options(options)
@stringArgs @stringArgs
@ -3172,7 +3173,7 @@ external dependencies (including libraries) must go to "dependencies".''')
# default_options in a project will trigger a reconfigure but won't # default_options in a project will trigger a reconfigure but won't
# have any effect. # have any effect.
self.project_default_options = mesonlib.stringlistify(kwargs.get('default_options', [])) self.project_default_options = mesonlib.stringlistify(kwargs.get('default_options', []))
self.project_default_options = coredata.create_options_dict(self.project_default_options) self.project_default_options = coredata.create_options_dict(self.project_default_options, self.subproject)
if self.environment.first_invocation: if self.environment.first_invocation:
default_options = self.project_default_options.copy() default_options = self.project_default_options.copy()
default_options.update(self.default_project_options) default_options.update(self.default_project_options)

@ -251,7 +251,7 @@ def run(options):
return 0 return 0
save = False save = False
if len(options.cmd_line_options) > 0: if options.cmd_line_options:
c.set_options(options.cmd_line_options) c.set_options(options.cmd_line_options)
coredata.update_cmd_line_file(builddir, options) coredata.update_cmd_line_file(builddir, options)
save = True save = True

@ -6904,7 +6904,7 @@ class LinuxlikeTests(BasePlatformTests):
self.assertTrue(os.path.exists(os.path.join(pkg_dir, 'librelativepath.pc'))) self.assertTrue(os.path.exists(os.path.join(pkg_dir, 'librelativepath.pc')))
env = get_fake_env(testdir, self.builddir, self.prefix) env = get_fake_env(testdir, self.builddir, self.prefix)
env.coredata.set_options({'pkg_config_path': pkg_dir}, subproject='') env.coredata.set_options({mesonbuild.coredata.OptionKey('pkg_config_path'): pkg_dir}, subproject='')
kwargs = {'required': True, 'silent': True} kwargs = {'required': True, 'silent': True}
relative_path_dep = PkgConfigDependency('librelativepath', env, kwargs) relative_path_dep = PkgConfigDependency('librelativepath', env, kwargs)
self.assertTrue(relative_path_dep.found()) self.assertTrue(relative_path_dep.found())

Loading…
Cancel
Save