aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild
diff options
context:
space:
mode:
Diffstat (limited to 'mesonbuild')
-rw-r--r--mesonbuild/dependencies/base.py6
-rw-r--r--mesonbuild/interpreter.py73
2 files changed, 45 insertions, 34 deletions
diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py
index 14db6a5..95202fe 100644
--- a/mesonbuild/dependencies/base.py
+++ b/mesonbuild/dependencies/base.py
@@ -2320,9 +2320,11 @@ def get_dep_identifier(name, kwargs) -> T.Tuple:
# 'version' is irrelevant for caching; the caller must check version matches
# 'native' is handled above with `for_machine`
# 'required' is irrelevant for caching; the caller handles it separately
- # 'fallback' subprojects cannot be cached -- they must be initialized
+ # 'fallback' and 'allow_fallback' is not part of the cache because,
+ # once a dependency has been found through a fallback, it should
+ # be used for the rest of the Meson run.
# 'default_options' is only used in fallback case
- if key in ('version', 'native', 'required', 'fallback', 'default_options', 'force_fallback'):
+ if key in ('version', 'native', 'required', 'fallback', 'allow_fallback', 'default_options'):
continue
# All keyword arguments are strings, ints, or lists (or lists of lists)
if isinstance(value, list):
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index 9f54b0a..ca1411e 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -2642,10 +2642,9 @@ class Interpreter(InterpreterBase):
FeatureNew.single_use('stdlib without variable name', '0.56.0', self.subproject)
kwargs = {'fallback': di,
'native': for_machine is MachineChoice.BUILD,
- 'force_fallback': True,
}
name = display_name = l + '_stdlib'
- dep = self.dependency_impl(name, display_name, kwargs)
+ dep = self.dependency_impl(name, display_name, kwargs, force_fallback=True)
self.build.stdlibs[for_machine][l] = dep
def import_module(self, modname):
@@ -3701,31 +3700,41 @@ external dependencies (including libraries) must go to "dependencies".''')
build.DependencyOverride(d.held_object, node, explicit=False)
return d
- def dependency_impl(self, name, display_name, kwargs):
+ def dependency_impl(self, name, display_name, kwargs, force_fallback=False):
disabled, required, feature = extract_required_kwarg(kwargs, self.subproject)
if disabled:
mlog.log('Dependency', mlog.bold(display_name), 'skipped: feature', mlog.bold(feature), 'disabled')
return self.notfound_dependency()
- has_fallback = 'fallback' in kwargs
- if not has_fallback and name:
+ fallback = kwargs.get('fallback', None)
+ allow_fallback = kwargs.get('allow_fallback', None)
+ if allow_fallback is not None:
+ FeatureNew.single_use('"allow_fallback" keyword argument for dependency', '0.56.0', self.subproject)
+ if fallback is not None:
+ raise InvalidArguments('"fallback" and "allow_fallback" arguments are mutually exclusive')
+ if not isinstance(allow_fallback, bool):
+ raise InvalidArguments('"allow_fallback" argument must be boolean')
+
+ # If "fallback" is absent, look for an implicit fallback.
+ if name and fallback is None and allow_fallback is not False:
# Add an implicit fallback if we have a wrap file or a directory with the same name,
# but only if this dependency is required. It is common to first check for a pkg-config,
# then fallback to use find_library() and only afterward check again the dependency
# with a fallback. If the fallback has already been configured then we have to use it
# even if the dependency is not required.
provider = self.environment.wrap_resolver.find_dep_provider(name)
+ if not provider and allow_fallback is True:
+ raise InvalidArguments('Fallback wrap or subproject not found for dependency \'%s\'' % name)
dirname = mesonlib.listify(provider)[0]
- if provider and (required or self.get_subproject(dirname)):
- kwargs['fallback'] = provider
- has_fallback = True
+ if provider and (allow_fallback is True or required or self.get_subproject(dirname)):
+ fallback = provider
- if 'default_options' in kwargs and not has_fallback:
- mlog.warning('The "default_options" keyworg argument does nothing without a "fallback" keyword argument.',
+ if 'default_options' in kwargs and not fallback:
+ mlog.warning('The "default_options" keyword argument does nothing without a fallback subproject.',
location=self.current_node)
# writing just "dependency('')" is an error, because it can only fail
- if name == '' and required and not has_fallback:
+ if name == '' and required and not fallback:
raise InvalidArguments('Dependency is both required and not-found')
if '<' in name or '>' in name or '=' in name:
@@ -3734,31 +3743,31 @@ external dependencies (including libraries) must go to "dependencies".''')
identifier, cached_dep = self._find_cached_dep(name, display_name, kwargs)
if cached_dep:
- if has_fallback:
- dirname, varname = self.get_subproject_infos(kwargs)
+ if fallback:
+ dirname, varname = self.get_subproject_infos(fallback)
self.verify_fallback_consistency(dirname, varname, cached_dep)
if required and not cached_dep.found():
m = 'Dependency {!r} was already checked and was not found'
raise DependencyException(m.format(display_name))
return DependencyHolder(cached_dep, self.subproject)
- # If the dependency has already been configured, possibly by
- # a higher level project, try to use it first.
- if has_fallback:
- dirname, varname = self.get_subproject_infos(kwargs)
+ if fallback:
+ # If the dependency has already been configured, possibly by
+ # a higher level project, try to use it first.
+ dirname, varname = self.get_subproject_infos(fallback)
if self.get_subproject(dirname):
return self.get_subproject_dep(name, display_name, dirname, varname, kwargs)
- wrap_mode = self.coredata.get_builtin_option('wrap_mode')
- force_fallback_for = self.coredata.get_builtin_option('force_fallback_for')
- force_fallback = kwargs.get('force_fallback', False)
- forcefallback = has_fallback and (wrap_mode == WrapMode.forcefallback or \
- name in force_fallback_for or \
- dirname in force_fallback_for or \
- force_fallback)
- if name != '' and not forcefallback:
+ wrap_mode = self.coredata.get_builtin_option('wrap_mode')
+ force_fallback_for = self.coredata.get_builtin_option('force_fallback_for')
+ force_fallback = (force_fallback or
+ wrap_mode == WrapMode.forcefallback or
+ name in force_fallback_for or
+ dirname in force_fallback_for)
+
+ if name != '' and (not fallback or not force_fallback):
self._handle_featurenew_dependencies(name)
- kwargs['required'] = required and not has_fallback
+ kwargs['required'] = required and not fallback
dep = dependencies.find_external_dependency(name, self.environment, kwargs)
kwargs['required'] = required
# Only store found-deps in the cache
@@ -3770,8 +3779,8 @@ external dependencies (including libraries) must go to "dependencies".''')
self.coredata.deps[for_machine].put(identifier, dep)
return DependencyHolder(dep, self.subproject)
- if has_fallback:
- return self.dependency_fallback(name, display_name, kwargs)
+ if fallback:
+ return self.dependency_fallback(name, display_name, fallback, kwargs)
return self.notfound_dependency()
@@ -3798,8 +3807,8 @@ external dependencies (including libraries) must go to "dependencies".''')
message.append(mlog.bold(command_templ.format(l[len(self.source_root) + 1:])))
mlog.warning(*message, location=self.current_node)
- def get_subproject_infos(self, kwargs):
- fbinfo = mesonlib.stringlistify(kwargs['fallback'])
+ def get_subproject_infos(self, fbinfo):
+ fbinfo = mesonlib.stringlistify(fbinfo)
if len(fbinfo) == 1:
FeatureNew.single_use('Fallback without variable name', '0.53.0', self.subproject)
return fbinfo[0], None
@@ -3807,8 +3816,8 @@ external dependencies (including libraries) must go to "dependencies".''')
raise InterpreterException('Fallback info must have one or two items.')
return fbinfo
- def dependency_fallback(self, name, display_name, kwargs):
- dirname, varname = self.get_subproject_infos(kwargs)
+ def dependency_fallback(self, name, display_name, fallback, kwargs):
+ dirname, varname = self.get_subproject_infos(fallback)
required = kwargs.get('required', True)
# Explicitly listed fallback preferences for specific subprojects