From ff2aa5a9ef48bc083e01d7af578799fc4eada764 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Thu, 6 Dec 2018 13:11:59 -0500 Subject: [PATCH] Add 'required' kwarg in header check functions Closes: #3940 --- docs/markdown/Reference-manual.md | 11 +++++++--- mesonbuild/interpreter.py | 34 ++++++++++++++++++++++++++----- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/docs/markdown/Reference-manual.md b/docs/markdown/Reference-manual.md index 8d0d123e3..f2d21297a 100644 --- a/docs/markdown/Reference-manual.md +++ b/docs/markdown/Reference-manual.md @@ -1760,7 +1760,9 @@ the following methods: the `prefix` keyword. In order to look for headers in a specific directory you can use `args : '-I/extra/include/dir`, but this should only be used in exceptional cases for includes that can't be - detected via pkg-config and passed via `dependencies`. + detected via pkg-config and passed via `dependencies`. Since *0.50.0* the + `required` keyword argument can be used to abort if the header cannot be + found. - `has_header` returns true if the specified header *exists*, and is faster than `check_header()` since it only does a pre-processor check. @@ -1769,13 +1771,16 @@ the following methods: the `prefix` keyword. In order to look for headers in a specific directory you can use `args : '-I/extra/include/dir`, but this should only be used in exceptional cases for includes that can't be - detected via pkg-config and passed via `dependencies`. + detected via pkg-config and passed via `dependencies`. Since *0.50.0* the + `required` keyword argument can be used to abort if the header cannot be + found. - `has_header_symbol(headername, symbolname)` allows one to detect whether a particular symbol (function, variable, #define, type definition, etc) is declared in the specified header, you can specify external dependencies to use with `dependencies` keyword - argument. + argument. Since *0.50.0* the `required` keyword argument can be used to abort + if the symbol cannot be found. - `has_member(typename, membername)` takes two arguments, type name and member name and returns true if the type has the specified diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 6fef4a90a..6870fc1e6 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -86,8 +86,8 @@ class FeatureOptionHolder(InterpreterObject, ObjectHolder): def auto_method(self, args, kwargs): return self.held_object.is_auto() -def extract_required_kwarg(kwargs, subproject, feature_check=None): - val = kwargs.get('required', True) +def extract_required_kwarg(kwargs, subproject, feature_check=None, default=True): + val = kwargs.get('required', default) disabled = False required = False feature = None @@ -1344,7 +1344,9 @@ class CompilerHolder(InterpreterObject): return result @FeatureNew('compiler.check_header', '0.47.0') + @FeatureNewKwargs('compiler.check_header', '0.50.0', ['required']) @permittedKwargs({ + 'required', 'prefix', 'no_builtin_args', 'include_directories', @@ -1359,19 +1361,27 @@ class CompilerHolder(InterpreterObject): prefix = kwargs.get('prefix', '') if not isinstance(prefix, str): raise InterpreterException('Prefix argument of has_header must be a string.') + disabled, required, feature = extract_required_kwarg(kwargs, self.subproject, default=False) + if disabled: + mlog.log('Check usable header', mlog.bold(hname, True), 'skipped: feature', mlog.bold(feature), 'disabled') + return False extra_args = functools.partial(self.determine_args, kwargs) deps, msg = self.determine_dependencies(kwargs) haz = self.compiler.check_header(hname, prefix, self.environment, extra_args=extra_args, dependencies=deps) - if haz: + if required and not haz: + raise InterpreterException('{} header {!r} not usable'.format(self.compiler.get_display_language(), hname)) + elif haz: h = mlog.green('YES') else: h = mlog.red('NO') mlog.log('Check usable header', mlog.bold(hname, True), msg, h) return haz + @FeatureNewKwargs('compiler.has_header', '0.50.0', ['required']) @permittedKwargs({ + 'required', 'prefix', 'no_builtin_args', 'include_directories', @@ -1386,18 +1396,26 @@ class CompilerHolder(InterpreterObject): prefix = kwargs.get('prefix', '') if not isinstance(prefix, str): raise InterpreterException('Prefix argument of has_header must be a string.') + disabled, required, feature = extract_required_kwarg(kwargs, self.subproject, default=False) + if disabled: + mlog.log('Has header', mlog.bold(hname, True), 'skipped: feature', mlog.bold(feature), 'disabled') + return False extra_args = functools.partial(self.determine_args, kwargs) deps, msg = self.determine_dependencies(kwargs) haz = self.compiler.has_header(hname, prefix, self.environment, extra_args=extra_args, dependencies=deps) - if haz: + if required and not haz: + raise InterpreterException('{} header {!r} not found'.format(self.compiler.get_display_language(), hname)) + elif haz: h = mlog.green('YES') else: h = mlog.red('NO') mlog.log('Has header', mlog.bold(hname, True), msg, h) return haz + @FeatureNewKwargs('compiler.has_header_symbol', '0.50.0', ['required']) @permittedKwargs({ + 'required', 'prefix', 'no_builtin_args', 'include_directories', @@ -1413,12 +1431,18 @@ class CompilerHolder(InterpreterObject): prefix = kwargs.get('prefix', '') if not isinstance(prefix, str): raise InterpreterException('Prefix argument of has_header_symbol must be a string.') + disabled, required, feature = extract_required_kwarg(kwargs, self.subproject, default=False) + if disabled: + mlog.log('Header <{0}> has symbol'.format(hname), mlog.bold(symbol, True), 'skipped: feature', mlog.bold(feature), 'disabled') + return False extra_args = functools.partial(self.determine_args, kwargs) deps, msg = self.determine_dependencies(kwargs) haz = self.compiler.has_header_symbol(hname, symbol, prefix, self.environment, extra_args=extra_args, dependencies=deps) - if haz: + if required and not haz: + raise InterpreterException('{} symbol {} not found in header {}'.format(self.compiler.get_display_language(), symbol, hname)) + elif haz: h = mlog.green('YES') else: h = mlog.red('NO')