Add 'disabler' argument to functions returning not-found objects

When dependency(), find_library(), find_program(), or
python.find_installation() return a not-found object and disabler is
true, they return a Disabler object instead.
This commit is contained in:
Xavier Claessens 2018-04-10 15:01:05 -04:00 committed by Jussi Pakkanen
parent 87355c8132
commit 61348da069
7 changed files with 48 additions and 2 deletions

View File

@ -48,6 +48,9 @@ Keyword arguments are the following:
whether it was found or not. Since *0.48.0* the value of a whether it was found or not. Since *0.48.0* the value of a
[`feature`](Build-options.md#features) option can also be passed to the [`feature`](Build-options.md#features) option can also be passed to the
`required` keyword argument. `required` keyword argument.
- `disabler`: if `true` and no python installation can be found, return a
[disabler object](#disabler-object) instead of a not-found object.
*Since 0.49.0*
**Returns**: a [python installation][`python_installation` object] **Returns**: a [python installation][`python_installation` object]

View File

@ -408,6 +408,9 @@ otherwise. This function supports the following keyword arguments:
[library-specific](Dependencies.md#dependencies-with-custom-lookup-functionality) [library-specific](Dependencies.md#dependencies-with-custom-lookup-functionality)
keywords may also be accepted (e.g. `modules` specifies submodules to use for keywords may also be accepted (e.g. `modules` specifies submodules to use for
dependencies such as Qt5 or Boost. ) dependencies such as Qt5 or Boost. )
- `disabler` if `true` and the dependency couldn't be found, return a
[disabler object](#disabler-object) instead of a not-found dependency.
*Since 0.49.0*
If dependency_name is `''`, the dependency is always not found. So with If dependency_name is `''`, the dependency is always not found. So with
`required: false`, this always returns a dependency object for which the `required: false`, this always returns a dependency object for which the
@ -600,6 +603,10 @@ Keyword arguments are the following:
defined there, then from the system. If set to `true`, the cross defined there, then from the system. If set to `true`, the cross
file is ignored and the program is only searched from the system. file is ignored and the program is only searched from the system.
- `disabler` if `true` and the program couldn't be found, return a
[disabler object](#disabler-object) instead of a not-found object.
*Since 0.49.0*
Meson will also autodetect scripts with a shebang line and run them Meson will also autodetect scripts with a shebang line and run them
with the executable/interpreter specified in it both on Windows with the executable/interpreter specified in it both on Windows
(because the command invocator will reject the command otherwise) and (because the command invocator will reject the command otherwise) and
@ -1666,6 +1673,9 @@ the following methods:
argument, which can be either a string or a list of strings. Since argument, which can be either a string or a list of strings. Since
*0.47.0* the value of a [`feature`](Build-options.md#features) *0.47.0* the value of a [`feature`](Build-options.md#features)
option can also be passed to the `required` keyword argument. option can also be passed to the `required` keyword argument.
*Since 0.49.0* if the keyword argument `disabler` is `true` and the
dependency couldn't be found, return a [disabler object](#disabler-object)
instead of a not-found dependency.
- `first_supported_argument(list_of_strings)`, given a list of - `first_supported_argument(list_of_strings)`, given a list of
strings, returns the first argument that passes the `has_argument` strings, returns the first argument that passes the `has_argument`

View File

@ -0,0 +1,6 @@
## Return `Disabler()` instead of not-found object
Functions such as `dependency()`, `find_library()`, `find_program()`, and
`python.find_installation()` have a new keyword argument: `disabler`. When set
to `true` those functions return `Disabler()` objects instead of not-found
objects.

View File

@ -27,7 +27,7 @@ from .dependencies import InternalDependency, Dependency, NotFoundDependency, De
from .interpreterbase import InterpreterBase from .interpreterbase import InterpreterBase
from .interpreterbase import check_stringlist, flatten, noPosargs, noKwargs, stringArgs, permittedKwargs, noArgsFlattening from .interpreterbase import check_stringlist, flatten, noPosargs, noKwargs, stringArgs, permittedKwargs, noArgsFlattening
from .interpreterbase import InterpreterException, InvalidArguments, InvalidCode, SubdirDoneRequest from .interpreterbase import InterpreterException, InvalidArguments, InvalidCode, SubdirDoneRequest
from .interpreterbase import InterpreterObject, MutableInterpreterObject, Disabler from .interpreterbase import InterpreterObject, MutableInterpreterObject, Disabler, disablerIfNotFound
from .interpreterbase import FeatureNew, FeatureDeprecated, FeatureNewKwargs from .interpreterbase import FeatureNew, FeatureDeprecated, FeatureNewKwargs
from .interpreterbase import ObjectHolder from .interpreterbase import ObjectHolder
from .modules import ModuleReturnValue from .modules import ModuleReturnValue
@ -1381,6 +1381,8 @@ class CompilerHolder(InterpreterObject):
mlog.log('Header <{0}> has symbol "{1}":'.format(hname, symbol), h) mlog.log('Header <{0}> has symbol "{1}":'.format(hname, symbol), h)
return haz return haz
@FeatureNewKwargs('compiler.find_library', '0.49.0', ['disabler'])
@disablerIfNotFound
@permittedKwargs({ @permittedKwargs({
'required', 'required',
'dirs', 'dirs',
@ -2776,6 +2778,8 @@ external dependencies (including libraries) must go to "dependencies".''')
self.store_name_lookups(args) self.store_name_lookups(args)
return progobj return progobj
@FeatureNewKwargs('find_program', '0.49.0', ['disabler'])
@disablerIfNotFound
@permittedKwargs(permitted_kwargs['find_program']) @permittedKwargs(permitted_kwargs['find_program'])
def func_find_program(self, node, args, kwargs): def func_find_program(self, node, args, kwargs):
if not args: if not args:
@ -2902,8 +2906,10 @@ external dependencies (including libraries) must go to "dependencies".''')
elif name == 'openmp': elif name == 'openmp':
FeatureNew('OpenMP Dependency', '0.46.0').use(self.subproject) FeatureNew('OpenMP Dependency', '0.46.0').use(self.subproject)
@FeatureNewKwargs('dependency', '0.49.0', ['disabler'])
@FeatureNewKwargs('dependency', '0.40.0', ['method']) @FeatureNewKwargs('dependency', '0.40.0', ['method'])
@FeatureNewKwargs('dependency', '0.38.0', ['default_options']) @FeatureNewKwargs('dependency', '0.38.0', ['default_options'])
@disablerIfNotFound
@permittedKwargs(permitted_kwargs['dependency']) @permittedKwargs(permitted_kwargs['dependency'])
def func_dependency(self, node, args, kwargs): def func_dependency(self, node, args, kwargs):
self.validate_arguments(args, 1, [str]) self.validate_arguments(args, 1, [str])

View File

@ -145,6 +145,17 @@ def noArgsFlattening(f):
setattr(f, 'no-args-flattening', True) setattr(f, 'no-args-flattening', True)
return f return f
def disablerIfNotFound(f):
@wraps(f)
def wrapped(*wrapped_args, **wrapped_kwargs):
kwargs = _get_callee_args(wrapped_args)[3]
disabler = kwargs.pop('disabler', False)
ret = f(*wrapped_args, **wrapped_kwargs)
if disabler and not ret.held_object.found():
return Disabler()
return ret
return wrapped
class permittedKwargs: class permittedKwargs:
def __init__(self, permitted): def __init__(self, permitted):

View File

@ -23,7 +23,7 @@ from mesonbuild.modules import ModuleReturnValue
from ..interpreterbase import ( from ..interpreterbase import (
noPosargs, noKwargs, permittedKwargs, noPosargs, noKwargs, permittedKwargs,
InterpreterObject, InvalidArguments, InterpreterObject, InvalidArguments,
FeatureNew FeatureNew, FeatureNewKwargs, disablerIfNotFound
) )
from ..interpreter import ExternalProgramHolder, extract_required_kwarg from ..interpreter import ExternalProgramHolder, extract_required_kwarg
from ..interpreterbase import flatten from ..interpreterbase import flatten
@ -467,6 +467,8 @@ class PythonModule(ExtensionModule):
return mesonlib.version_compare(version, '>= 3.0') return mesonlib.version_compare(version, '>= 3.0')
return True return True
@FeatureNewKwargs('python.find_installation', '0.49.0', ['disabler'])
@disablerIfNotFound
@permittedKwargs(['required']) @permittedKwargs(['required'])
def find_installation(self, interpreter, state, args, kwargs): def find_installation(self, interpreter, state, args, kwargs):
feature_check = FeatureNew('Passing "feature" option to find_installation', '0.48.0') feature_check = FeatureNew('Passing "feature" option to find_installation', '0.48.0')

View File

@ -31,4 +31,12 @@ endif
assert(number == 2, 'If found handled incorrectly, value should be 2 but is @0@'.format(number)) assert(number == 2, 'If found handled incorrectly, value should be 2 but is @0@'.format(number))
dep = dependency('notfounddep', required : false, disabler : true)
app = executable('myapp', 'notfound.c', dependencies : [dep])
cc = meson.get_compiler('c')
dep = cc.find_library('notfounddep', required : false, disabler : true)
app = executable('myapp', 'notfound.c', dependencies : [dep])
dep = find_program('donotfindme', required : false, disabler : true)
app = executable('myapp', 'notfound.c', dependencies : [dep])