aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXavier Claessens <xavier.claessens@collabora.com>2021-08-04 11:30:27 -0400
committerXavier Claessens <xclaesse@gmail.com>2021-08-23 10:52:18 -0400
commite646130ef1a703a3624cff4ca11f926703a6fcf4 (patch)
treeafc6527bdd1e01de853fa4ecdab66ee2a8baf75b
parent0063eb251e836e777b427cbe59b43ab937ac1924 (diff)
downloadmeson-e646130ef1a703a3624cff4ca11f926703a6fcf4.zip
meson-e646130ef1a703a3624cff4ca11f926703a6fcf4.tar.gz
meson-e646130ef1a703a3624cff4ca11f926703a6fcf4.tar.bz2
interpreter: Fix dependency(..., static: true) fallback
It should build the fallback subprject with default_library=static and override the dependency for both static=True and static kwarg not given. Fixes: #8050.
-rw-r--r--docs/markdown/Reference-manual.md5
-rw-r--r--docs/markdown/snippets/static_fallback_override.md46
-rw-r--r--mesonbuild/interpreter/dependencyfallbacks.py11
-rw-r--r--mesonbuild/interpreter/mesonmain.py58
-rw-r--r--test cases/common/98 subproject subdir/meson.build27
-rw-r--r--test cases/common/98 subproject subdir/subprojects/sub_static/meson.build8
-rw-r--r--unittests/allplatformstests.py5
7 files changed, 150 insertions, 10 deletions
diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md
index fd156f9..8ef36de 100644
--- a/docs/markdown/Reference-manual.md
+++ b/docs/markdown/Reference-manual.md
@@ -568,6 +568,8 @@ This function supports the following keyword arguments:
- `static`: tells the dependency provider to try to get static
libraries instead of dynamic ones (note that this is not supported
by all dependency backends)
+ *Since 0.60.0* it also sets `default_library` option accordingly on the fallback
+ subproject if it was not set explicitly in `default_options` keyword argument.
- `version` *(since 0.37.0)*: specifies the required version, a string containing a
comparison operator followed by the version string, examples include
`>1.0.0`, `<=2.3.5` or `3.1.4` for exact matching.
@@ -2151,6 +2153,9 @@ the following methods.
`native` keyword arguments. Doing this in a subproject allows the parent
project to retrieve the dependency without having to know the dependency
variable name: `dependency(name, fallback : subproject_name)`.
+ *Since 0.60.0* `static` boolean keyword argument can be specified to override
+ static and/or shared dependencies separately. If not specified it is assumed
+ `dep_object` follows `default_library` option value.
- `project_version()`: returns the version string specified in
`project` function call.
diff --git a/docs/markdown/snippets/static_fallback_override.md b/docs/markdown/snippets/static_fallback_override.md
new file mode 100644
index 0000000..1a6faaf
--- /dev/null
+++ b/docs/markdown/snippets/static_fallback_override.md
@@ -0,0 +1,46 @@
+## `static` keyword argument to `meson.override_dependency()`
+
+It is now possible to override shared and/or static dependencies separately.
+When the `static` keyword argument is not specified in `dependency()`, the first
+override will be used (`static_dep` in the example below).
+```meson
+static_lib = static_library()
+static_dep = declare_dependency(link_with: static_lib)
+meson.override_dependency('foo', static_dep, static: true)
+
+shared_lib = shared_library()
+shared_dep = declare_dependency(link_with: shared_lib)
+meson.override_dependency('foo', shared_dep, static: false)
+
+# Returns static_dep
+dependency('foo')
+
+# Returns static_dep
+dependency('foo', static: true)
+
+# Returns shared_dep
+dependency('foo', static: false)
+```
+
+When the `static` keyword argument is not specified in `meson.override_dependency()`,
+the dependency is assumed to follow the value of `default_library` option.
+```meson
+dep = declare_dependency(...)
+meson.override_dependency('foo', dep)
+
+# Always works
+dependency('foo')
+
+# Works only if default_library is 'static' or 'both'
+dependency('foo', static: true)
+
+# Works only if default_library is 'shared' or 'both'
+dependency('foo', static: false)
+```
+
+## `dependency()` sets `default_library` on fallback subproject
+
+When the `static` keyword argument is set but `default_library` is missing in
+`default_options`, `dependency()` will set it when configuring fallback
+subproject. `dependency('foo', static: true)` is now equivalent to
+`dependency('foo', static: true, default_options: ['default_library=static'])`.
diff --git a/mesonbuild/interpreter/dependencyfallbacks.py b/mesonbuild/interpreter/dependencyfallbacks.py
index 5934cbd..4baa5cf 100644
--- a/mesonbuild/interpreter/dependencyfallbacks.py
+++ b/mesonbuild/interpreter/dependencyfallbacks.py
@@ -116,6 +116,17 @@ class DependencyFallbacksHolder(MesonInterpreterObject):
mlog.log('Looking for a fallback subproject for the dependency',
mlog.bold(self.display_name))
+ # dependency('foo', static: true) should implicitly add
+ # default_options: ['default_library=static']
+ static = kwargs.get('static')
+ default_options = stringlistify(func_kwargs.get('default_options', []))
+ if static is not None and not any('default_library' in i for i in default_options):
+ default_library = 'static' if static else 'shared'
+ opt = f'default_library={default_library}'
+ mlog.log(f'Building fallback subproject with {opt}')
+ default_options.append(opt)
+ func_kwargs['default_options'] = default_options
+
# Configure the subproject
subp_name = self.subproject_name
varname = self.subproject_varname
diff --git a/mesonbuild/interpreter/mesonmain.py b/mesonbuild/interpreter/mesonmain.py
index ea16b46..1c850b2 100644
--- a/mesonbuild/interpreter/mesonmain.py
+++ b/mesonbuild/interpreter/mesonmain.py
@@ -14,11 +14,16 @@ from ..interpreterbase import (MesonInterpreterObject, FeatureNew, FeatureDeprec
from .interpreterobjects import (ExecutableHolder, ExternalProgramHolder,
CustomTargetHolder, CustomTargetIndexHolder,
EnvironmentVariablesObject)
+from .type_checking import NATIVE_KW
import typing as T
if T.TYPE_CHECKING:
from .interpreter import Interpreter
+ from typing_extensions import TypedDict
+ class FuncOverrideDependency(TypedDict):
+ native: mesonlib.MachineChoice
+ static: T.Optional[bool]
class MesonMain(MesonInterpreterObject):
def __init__(self, build: 'build.Build', interpreter: 'Interpreter'):
@@ -294,21 +299,54 @@ class MesonMain(MesonInterpreterObject):
raise InterpreterException('Second argument must be an external program or executable.')
self.interpreter.add_find_program_override(name, exe)
+ @typed_kwargs('meson.override_dependency', NATIVE_KW,
+ KwargInfo('static', bool, since='0.60.0'))
+ @typed_pos_args('meson.override_dependency', str, dependencies.Dependency)
@FeatureNew('meson.override_dependency', '0.54.0')
- @permittedKwargs({'native'})
- def override_dependency_method(self, args, kwargs):
- if len(args) != 2:
- raise InterpreterException('Override needs two arguments')
- name = args[0]
- dep = args[1]
- if not isinstance(name, str) or not name:
+ def override_dependency_method(self, args: T.Tuple[str, dependencies.Dependency], kwargs: 'FuncOverrideDependency') -> None:
+ name, dep = args
+ if not name:
raise InterpreterException('First argument must be a string and cannot be empty')
- if not isinstance(dep, dependencies.Dependency):
- raise InterpreterException('Second argument must be a dependency object')
+
+ optkey = OptionKey('default_library', subproject=self.interpreter.subproject)
+ default_library = self.interpreter.coredata.get_option(optkey)
+ assert isinstance(default_library, str), 'for mypy'
+ static = kwargs['static']
+ if static is None:
+ # We don't know if dep represents a static or shared library, could
+ # be a mix of both. We assume it is following default_library
+ # value.
+ self._override_dependency_impl(name, dep, kwargs, static=None)
+ if default_library == 'static':
+ self._override_dependency_impl(name, dep, kwargs, static=True)
+ elif default_library == 'shared':
+ self._override_dependency_impl(name, dep, kwargs, static=False)
+ else:
+ self._override_dependency_impl(name, dep, kwargs, static=True)
+ self._override_dependency_impl(name, dep, kwargs, static=False)
+ else:
+ # dependency('foo') without specifying static kwarg should find this
+ # override regardless of the static value here. But do not raise error
+ # if it has already been overridden, which would happend when overriding
+ # static and shared separately:
+ # meson.override_dependency('foo', shared_dep, static: false)
+ # meson.override_dependency('foo', static_dep, static: true)
+ # In that case dependency('foo') would return the first override.
+ self._override_dependency_impl(name, dep, kwargs, static=None, permissive=True)
+ self._override_dependency_impl(name, dep, kwargs, static=static)
+
+ def _override_dependency_impl(self, name: str, dep: dependencies.Dependency, kwargs: 'FuncOverrideDependency', static: T.Optional[bool], permissive: bool = False) -> None:
+ kwargs = kwargs.copy()
+ if static is None:
+ del kwargs['static']
+ else:
+ kwargs['static'] = static
identifier = dependencies.get_dep_identifier(name, kwargs)
- for_machine = self.interpreter.machine_from_native_kwarg(kwargs)
+ for_machine = kwargs['native']
override = self.build.dependency_overrides[for_machine].get(identifier)
if override:
+ if permissive:
+ return
m = 'Tried to override dependency {!r} which has already been resolved or overridden at {}'
location = mlog.get_error_location_string(override.node.filename, override.node.lineno)
raise InterpreterException(m.format(name, location))
diff --git a/test cases/common/98 subproject subdir/meson.build b/test cases/common/98 subproject subdir/meson.build
index 36e48a7..95bf34e 100644
--- a/test cases/common/98 subproject subdir/meson.build
+++ b/test cases/common/98 subproject subdir/meson.build
@@ -65,3 +65,30 @@ assert(d.found(), 'Should be able to fallback to sub-subproject')
# file exists.
d = dependency('subsubsub')
assert(d.found(), 'Should be able to fallback to sub-sub-subproject')
+
+# Verify that `static: true` implies 'default_library=static'.
+d = dependency('sub_static', static: true)
+assert(d.found())
+# Verify that when not specifying static kwarg we can still get fallback dep.
+d = dependency('sub_static')
+assert(d.found())
+# But when asking for shared library explicitly, it is not found.
+d = dependency('sub_static', static: false, required: false)
+assert(not d.found())
+# The subproject also overrides sub_static2 with `static: true`
+d = dependency('sub_static2')
+assert(d.found())
+d = dependency('sub_static2', static: true)
+assert(d.found())
+d = dependency('sub_static2', static: false, required: false)
+assert(not d.found())
+# sub_static3 is overridden twice with `static: true` and `static: false`
+d = dependency('sub_static3')
+assert(d.found())
+assert(d.get_variable('static') == 'true')
+d = dependency('sub_static3', static: true)
+assert(d.found())
+assert(d.get_variable('static') == 'true')
+d = dependency('sub_static3', static: false)
+assert(d.found())
+assert(d.get_variable('static') == 'false')
diff --git a/test cases/common/98 subproject subdir/subprojects/sub_static/meson.build b/test cases/common/98 subproject subdir/subprojects/sub_static/meson.build
new file mode 100644
index 0000000..6c00623
--- /dev/null
+++ b/test cases/common/98 subproject subdir/subprojects/sub_static/meson.build
@@ -0,0 +1,8 @@
+project('sub_static')
+
+assert(get_option('default_library') == 'static')
+meson.override_dependency('sub_static', declare_dependency())
+meson.override_dependency('sub_static2', declare_dependency(), static: true)
+meson.override_dependency('sub_static3', declare_dependency(variables: {'static': 'true'}), static: true)
+meson.override_dependency('sub_static3', declare_dependency(variables: {'static': 'false'}), static: false)
+
diff --git a/unittests/allplatformstests.py b/unittests/allplatformstests.py
index 32e084d..911613e 100644
--- a/unittests/allplatformstests.py
+++ b/unittests/allplatformstests.py
@@ -2488,6 +2488,11 @@ class AllPlatformTests(BasePlatformTests):
'version': '1.0',
},
{
+ 'descriptive_name': 'sub_static',
+ 'name': 'sub_static',
+ 'version': 'undefined'
+ },
+ {
'descriptive_name': 'subsub',
'name': 'subsub',
'version': 'undefined'