aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild/interpreter.py
diff options
context:
space:
mode:
Diffstat (limited to 'mesonbuild/interpreter.py')
-rw-r--r--mesonbuild/interpreter.py142
1 files changed, 62 insertions, 80 deletions
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index ffe942f..86c55e4 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -1755,7 +1755,7 @@ permitted_kwargs = {'add_global_arguments': {'language'},
class Interpreter(InterpreterBase):
def __init__(self, build, backend=None, subproject='', subdir='', subproject_dir='subprojects',
- modules = None, default_project_options=[]):
+ modules = None, default_project_options=None):
super().__init__(build.environment.get_source_dir(), subdir)
self.an_unpicklable_object = mesonlib.an_unpicklable_object
self.build = build
@@ -1781,7 +1781,11 @@ class Interpreter(InterpreterBase):
self.global_args_frozen = False # implies self.project_args_frozen
self.subprojects = {}
self.subproject_stack = []
- self.default_project_options = default_project_options[:] # Passed from the outside, only used in subprojects.
+ # Passed from the outside, only used in subprojects.
+ if default_project_options:
+ self.default_project_options = default_project_options.copy()
+ else:
+ self.default_project_options = {}
self.build_func_dict()
# build_def_files needs to be defined before parse_project is called
self.build_def_files = [os.path.join(self.subdir, environment.build_filename)]
@@ -2106,6 +2110,8 @@ external dependencies (including libraries) must go to "dependencies".''')
return self.do_subproject(dirname, kwargs)
def do_subproject(self, dirname, kwargs):
+ default_options = mesonlib.stringlistify(kwargs.get('default_options', []))
+ default_options = coredata.create_options_dict(default_options)
if dirname == '':
raise InterpreterException('Subproject dir name must not be empty.')
if dirname[0] == '.':
@@ -2142,7 +2148,7 @@ external dependencies (including libraries) must go to "dependencies".''')
with mlog.nested():
mlog.log('\nExecuting subproject ', mlog.bold(dirname), '.\n', sep='')
subi = Interpreter(self.build, self.backend, dirname, subdir, self.subproject_dir,
- self.modules, mesonlib.stringlistify(kwargs.get('default_options', [])))
+ self.modules, default_options)
subi.subprojects = self.subprojects
subi.subproject_stack = self.subproject_stack + [dirname]
@@ -2206,53 +2212,34 @@ to directly access options of other subprojects.''')
raise InterpreterException('configuration_data takes no arguments')
return ConfigurationDataHolder()
- def parse_default_options(self, default_options):
- default_options = listify(default_options)
- for option in default_options:
- if not isinstance(option, str):
- mlog.debug(option)
- raise InterpreterException('Default options must be strings')
- if '=' not in option:
- raise InterpreterException('All default options must be of type key=value.')
- key, value = option.split('=', 1)
- if coredata.is_builtin_option(key):
- if self.subproject != '':
- continue # Only the master project is allowed to set global options.
- newoptions = [option] + self.environment.cmd_line_options.projectoptions
- self.environment.cmd_line_options.projectoptions = newoptions
- else:
- # Option values set with subproject() default_options override those
- # set in project() default_options.
- pref = key + '='
- for i in self.default_project_options:
- if i.startswith(pref):
- option = i
- break
- # If we are in a subproject, add the subproject prefix to option
- # name.
- if self.subproject != '':
- option = self.subproject + ':' + option
- newoptions = [option] + self.environment.cmd_line_options.projectoptions
- self.environment.cmd_line_options.projectoptions = newoptions
- # Add options that are only in default_options.
- for defopt in self.default_project_options:
- key, value = defopt.split('=')
- pref = key + '='
- for i in default_options:
- if i.startswith(pref):
- break
- else:
- defopt = self.subproject + ':' + defopt
- newoptions = [defopt] + self.environment.cmd_line_options.projectoptions
- self.environment.cmd_line_options.projectoptions = newoptions
-
- def set_builtin_options(self):
- # Create a dict containing only builtin options, then use
- # coredata.set_options() because it already has code to set the prefix
- # option first to sanitize all other options.
- options = coredata.create_options_dict(self.environment.cmd_line_options.projectoptions)
- options = {k: v for k, v in options.items() if coredata.is_builtin_option(k)}
- self.coredata.set_options(options)
+ def set_options(self, default_options):
+ # Set default options as if they were passed to the command line.
+ # Subprojects can only define default for user options.
+ for k, v in default_options.items():
+ if self.subproject:
+ if optinterpreter.is_invalid_name(k):
+ continue
+ k = self.subproject + ':' + k
+ self.environment.cmd_line_options.setdefault(k, v)
+
+ # Create a subset of cmd_line_options, keeping only options for this
+ # subproject. Also take builtin options if it's the main project.
+ # Language and backend specific options will be set later when adding
+ # languages and setting the backend (builtin options must be set first
+ # to know which backend we'll use).
+ options = {}
+ for k, v in self.environment.cmd_line_options.items():
+ if self.subproject:
+ if not k.startswith(self.subproject + ':'):
+ continue
+ elif k not in coredata.get_builtin_options():
+ if ':' in k:
+ continue
+ if optinterpreter.is_invalid_name(k):
+ continue
+ options[k] = v
+
+ self.coredata.set_options(options, self.subproject)
def set_backend(self):
# The backend is already set when parsing subprojects
@@ -2282,7 +2269,10 @@ to directly access options of other subprojects.''')
else:
raise InterpreterException('Unknown backend "%s".' % backend)
- self.coredata.init_backend_options(backend, self.environment.cmd_line_options.projectoptions)
+ self.coredata.init_backend_options(backend)
+
+ options = {k: v for k, v in self.environment.cmd_line_options.items() if k.startswith('backend_')}
+ self.coredata.set_options(options)
@stringArgs
@permittedKwargs(permitted_kwargs['project'])
@@ -2293,20 +2283,20 @@ to directly access options of other subprojects.''')
proj_langs = args[1:]
if ':' in proj_name:
raise InvalidArguments("Project name {!r} must not contain ':'".format(proj_name))
- default_options = kwargs.get('default_options', [])
- if self.environment.first_invocation and (len(default_options) > 0 or
- len(self.default_project_options) > 0):
- self.parse_default_options(default_options)
- if not self.is_subproject():
- self.build.project_name = proj_name
- self.set_builtin_options()
+
if os.path.exists(self.option_file):
- oi = optinterpreter.OptionInterpreter(self.subproject,
- self.build.environment.cmd_line_options.projectoptions,
- )
+ oi = optinterpreter.OptionInterpreter(self.subproject)
oi.process(self.option_file)
self.coredata.merge_user_options(oi.options)
+
+ default_options = mesonlib.stringlistify(kwargs.get('default_options', []))
+ default_options = coredata.create_options_dict(default_options)
+ default_options.update(self.default_project_options)
+ self.set_options(default_options)
self.set_backend()
+
+ if not self.is_subproject():
+ self.build.project_name = proj_name
self.active_projectname = proj_name
self.project_version = kwargs.get('version', 'undefined')
if self.build.project_version is None:
@@ -2450,17 +2440,14 @@ to directly access options of other subprojects.''')
cross_comp.sanity_check(self.environment.get_scratch_dir(), self.environment)
self.coredata.cross_compilers[lang] = cross_comp
new_options.update(cross_comp.get_options())
+
optprefix = lang + '_'
- for i in new_options:
- if not i.startswith(optprefix):
- raise InterpreterException('Internal error, %s has incorrect prefix.' % i)
- cmd_prefix = i + '='
- for cmd_arg in self.environment.cmd_line_options.projectoptions:
- if cmd_arg.startswith(cmd_prefix):
- value = cmd_arg.split('=', 1)[1]
- new_options[i].set_value(value)
- new_options.update(self.coredata.compiler_options)
- self.coredata.compiler_options = new_options
+ for k, o in new_options.items():
+ if not k.startswith(optprefix):
+ raise InterpreterException('Internal error, %s has incorrect prefix.' % k)
+ if k in self.environment.cmd_line_options:
+ o.set_value(self.environment.cmd_line_options[k])
+ self.coredata.compiler_options.setdefault(k, o)
# Unlike compiler and linker flags, preprocessor flags are not in
# compiler_options because they are not visible to user.
@@ -2510,19 +2497,14 @@ to directly access options of other subprojects.''')
def add_base_options(self, compiler):
enabled_opts = []
- proj_opt = self.environment.cmd_line_options.projectoptions
for optname in compiler.base_options:
if optname in self.coredata.base_options:
continue
oobj = compilers.base_options[optname]
- for po in proj_opt:
- if po.startswith(optname + '='):
- opt, value = po.split('=', 1)
- oobj.set_value(value)
- if oobj.value:
- enabled_opts.append(opt)
- break
- self.coredata.base_options[optname] = oobj
+ if optname in self.environment.cmd_line_options:
+ oobj.set_value(self.environment.cmd_line_options[optname])
+ enabled_opts.append(optname)
+ self.coredata. base_options[optname] = oobj
self.emit_base_options_warnings(enabled_opts)
def program_from_cross_file(self, prognames, silent=False):