diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md index dad8c1223..293e41f98 100644 --- a/docs/markdown/Reference-manual.md +++ b/docs/markdown/Reference-manual.md @@ -456,7 +456,9 @@ arguments: *(since 0.54.0)* `'subproj_dep'` argument can be omitted in the case the subproject used `meson.override_dependency('dependency_name', subproj_dep)`. In that case, the `fallback` keyword argument can be a single string instead - of a list of 2 strings. + of a list of 2 strings. *Since 0.55.0* the `fallback` keyword argument can be + omitted when there is a wrap file or a directory with the same `dependency_name`, + and subproject used `meson.override_dependency('dependency_name', subproj_dep)`. - `language` *(since 0.42.0)*: defines what language-specific dependency to find if it's available for multiple languages. - `method`: defines the way the dependency is detected, the default is diff --git a/docs/markdown/snippets/implicit_fallback.md b/docs/markdown/snippets/implicit_fallback.md new file mode 100644 index 000000000..87003d069 --- /dev/null +++ b/docs/markdown/snippets/implicit_fallback.md @@ -0,0 +1,9 @@ +## Implicit dependency fallback + +`dependency('foo')` now automatically fallback if the dependency is not found on +the system but a subproject wrap file or directory exists with the same name. + +That means that simply adding `subprojects/foo.wrap` is enough to add fallback +to any `dependency('foo')` call. It is however requires that the subproject call +`meson.override_dependency('foo', foo_dep)` to specify which dependency object +should be used for `foo`. diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 487bdd69a..053db1258 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -3549,6 +3549,14 @@ external dependencies (including libraries) must go to "dependencies".''') return self.notfound_dependency() has_fallback = 'fallback' in kwargs + if not has_fallback and name: + # Add an implicit fallback if we have a wrap file or a directory with the same name. + subproject_dir_abs = os.path.join(self.environment.get_source_dir(), self.subproject_dir) + wrap_, directory = wrap.get_directory(subproject_dir_abs, name) + if wrap_ or os.path.exists(os.path.join(subproject_dir_abs, directory)): + kwargs['fallback'] = name + has_fallback = True + if 'default_options' in kwargs and not has_fallback: mlog.warning('The "default_options" keyworg argument does nothing without a "fallback" keyword argument.', location=self.current_node) diff --git a/run_unittests.py b/run_unittests.py index c4978c2d3..2f9fb7f4b 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -4080,6 +4080,11 @@ recommended as it is not supported on some platforms''') 'name': 'sub', 'version': '1.0' }, + { + 'descriptive_name': 'sub_implicit', + 'name': 'sub_implicit', + 'version': '1.0', + }, { 'descriptive_name': 'sub-novar', 'name': 'sub_novar', diff --git a/test cases/common/102 subproject subdir/meson.build b/test cases/common/102 subproject subdir/meson.build index 8299a371f..46a2bcea9 100644 --- a/test cases/common/102 subproject subdir/meson.build +++ b/test cases/common/102 subproject subdir/meson.build @@ -25,3 +25,7 @@ dependency('sub-novar', fallback : 'sub_novar') # Verify a subproject can force a dependency to be not-found d = dependency('sub-notfound', fallback : 'sub_novar', required : false) assert(not d.found(), 'Dependency should be not-found') + +# Verify that implicit fallback works because subprojects/sub_implicit directory exists +d = dependency('sub_implicit') +assert(d.found(), 'Should implicitly fallback') diff --git a/test cases/common/102 subproject subdir/subprojects/sub_implicit/meson.build b/test cases/common/102 subproject subdir/subprojects/sub_implicit/meson.build new file mode 100644 index 000000000..613bd0593 --- /dev/null +++ b/test cases/common/102 subproject subdir/subprojects/sub_implicit/meson.build @@ -0,0 +1,4 @@ +project('sub_implicit', 'c', version : '1.0') + +dep = declare_dependency() +meson.override_dependency('sub_implicit', dep) diff --git a/test cases/linuxlike/5 dependency versions/meson.build b/test cases/linuxlike/5 dependency versions/meson.build index 94f424deb..164e679c4 100644 --- a/test cases/linuxlike/5 dependency versions/meson.build +++ b/test cases/linuxlike/5 dependency versions/meson.build @@ -31,10 +31,10 @@ dependency('somebrokenlib', version : '>=1.0', required : false) # Search for an external dependency that won't be found, but must later be # found via fallbacks -somelibnotfound = dependency('somelib', required : false) +somelibnotfound = dependency('somelib1', required : false) assert(somelibnotfound.found() == false, 'somelibnotfound was found?') # Find internal dependency without version -somelibver = dependency('somelib', +somelibver = dependency('somelib1', fallback : ['somelibnover', 'some_dep']) assert(somelibver.type_name() == 'internal', 'somelibver should be of type "internal", not ' + somelibver.type_name()) # Find an internal dependency again with the same name and a specific version