aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSalamandar <felix@piedallu.me>2018-06-04 14:32:02 +0200
committerNirbheek Chauhan <nirbheek.chauhan@gmail.com>2018-07-02 07:05:08 +0000
commitdf1970d3add1f673f06f6269b45e8833a0bfd5c1 (patch)
treee041aa74fdfc5ae3b831694ef055ef30a33ec83a
parent5113eb14b9ca4711c5fc197b150dc125eeaf77f6 (diff)
downloadmeson-df1970d3add1f673f06f6269b45e8833a0bfd5c1.zip
meson-df1970d3add1f673f06f6269b45e8833a0bfd5c1.tar.gz
meson-df1970d3add1f673f06f6269b45e8833a0bfd5c1.tar.bz2
Various bug fixes for FeatureNew
* Use _get_callee_args to unwrap function call arguments, needed for module functions. * Move some FeatureNewKwargs from build.py to interpreter.py * Print a summary for featurenew only if conflicts were found. The summary now only prints conflicting features. * Report and store featurenew/featuredeprecated only once * Fix version comparison: use le/ge and resize arrays to not fail on '0.47.0>=0.47' Closes https://github.com/mesonbuild/meson/issues/3660
-rw-r--r--mesonbuild/build.py6
-rw-r--r--mesonbuild/interpreter.py9
-rw-r--r--mesonbuild/interpreterbase.py62
-rw-r--r--mesonbuild/mesonlib.py27
4 files changed, 70 insertions, 34 deletions
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 6ee13d2..2b22521 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -25,7 +25,7 @@ from .mesonlib import typeslistify, stringlistify, classify_unity_sources
from .mesonlib import get_filenames_templates_dict, substitute_values
from .mesonlib import for_windows, for_darwin, for_cygwin, for_android, has_path_sep
from .compilers import is_object, clink_langs, sort_clink, lang_suffixes
-from .interpreterbase import FeatureNew, FeatureNewKwargs
+from .interpreterbase import FeatureNew
pch_kwargs = set(['c_pch', 'cpp_pch'])
@@ -332,9 +332,6 @@ a hard error in the future.''' % name)
myid = subdir_part + '@@' + myid
return myid
- @FeatureNewKwargs('build target', '0.42.0', ['rust_crate_type', 'build_rpath', 'implicit_include_directories'])
- @FeatureNewKwargs('build target', '0.41.0', ['rust_args'])
- @FeatureNewKwargs('build target', '0.40.0', ['build_by_default'])
def process_kwargs(self, kwargs):
if 'build_by_default' in kwargs:
self.build_by_default = kwargs['build_by_default']
@@ -1095,7 +1092,6 @@ recommended as it is not supported on some platforms''')
return
class Generator:
- @FeatureNewKwargs('generator', '0.43.0', ['capture'])
def __init__(self, args, kwargs):
if len(args) != 1:
raise InvalidArguments('Generator requires exactly one positional argument: the executable')
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index 2cf1752..fa9ae84 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -504,6 +504,7 @@ class ExternalLibraryHolder(InterpreterObject, ObjectHolder):
return DependencyHolder(self.held_object.get_partial_dependency(**kwargs))
class GeneratorHolder(InterpreterObject, ObjectHolder):
+ @FeatureNewKwargs('generator', '0.43.0', ['capture'])
def __init__(self, interpreter, args, kwargs):
InterpreterObject.__init__(self)
self.interpreter = interpreter
@@ -3792,6 +3793,14 @@ Try setting b_lundef to false instead.''')
raise InterpreterException('Unknown default_library value: %s.', default_library)
def build_target(self, node, args, kwargs, targetholder):
+ @FeatureNewKwargs('build target', '0.42.0', ['rust_crate_type', 'build_rpath', 'implicit_include_directories'])
+ @FeatureNewKwargs('build target', '0.41.0', ['rust_args'])
+ @FeatureNewKwargs('build target', '0.40.0', ['build_by_default'])
+ def build_target_decorator_caller(self, node, args, kwargs):
+ return True
+
+ build_target_decorator_caller(self, node, args, kwargs)
+
if not args:
raise InterpreterException('Target does not have a name.')
name = args[0]
diff --git a/mesonbuild/interpreterbase.py b/mesonbuild/interpreterbase.py
index 1c61345..d5761cd 100644
--- a/mesonbuild/interpreterbase.py
+++ b/mesonbuild/interpreterbase.py
@@ -127,6 +127,7 @@ class FeatureNew:
"""Checks for new features"""
# Shared across all instances
feature_versions = dict()
+ feature_warnings = False
def __init__(self, feature_name, version):
self.feature_name = feature_name
@@ -135,24 +136,33 @@ class FeatureNew:
def add_called_feature(self):
if self.feature_version not in self.feature_versions:
self.feature_versions[self.feature_version] = set()
- self.feature_versions[self.feature_version].add(self.feature_name)
+
+ if self.feature_name in self.feature_versions[self.feature_version]:
+ return False
+ else:
+ self.feature_versions[self.feature_version].add(self.feature_name)
+ return True
def called_features_report():
- fv = FeatureNew.feature_versions
- if fv:
- print('Minimum version of features used:')
+ if FeatureNew.feature_warnings:
+ warning_str = 'Invalid minimum meson_version \'{}\' conflicts with:'\
+ .format(mesonlib.target_version)
+ fv = FeatureNew.feature_versions
for version in sorted(fv.keys()):
- print('{}: {}'.format(version, fv[version]))
+ warning_str += '\n * {}: {}'.format(version, fv[version])
+ mlog.warning(warning_str)
def use(self):
- self.add_called_feature()
tv = mesonlib.target_version
if tv == '':
return
if not mesonlib.version_compare_condition_with_min(tv, self.feature_version):
- mlog.warning(
- '''Project targetting \'{}\' but tried to use feature introduced in \'{}\': {}'''
- .format(tv, self.feature_version, self.feature_name))
+ FeatureNew.feature_warnings = True
+ if self.add_called_feature():
+ mlog.warning(
+ '''Project targetting \'{}\' but tried to use feature introduced in \'{}\': {}'''
+ .format(tv, self.feature_version, self.feature_name)
+ )
def __call__(self, f):
@wraps(f)
@@ -165,6 +175,7 @@ class FeatureDeprecated:
"""Checks for deprecated features"""
# Shared across all instances
feature_versions = dict()
+ feature_warnings = False
def __init__(self, feature_name, version):
self.feature_name = feature_name
@@ -173,24 +184,33 @@ class FeatureDeprecated:
def add_called_feature(self):
if self.feature_version not in self.feature_versions:
self.feature_versions[self.feature_version] = set()
- self.feature_versions[self.feature_version].add(self.feature_name)
+
+ if self.feature_name in self.feature_versions[self.feature_version]:
+ return False
+ else:
+ self.feature_versions[self.feature_version].add(self.feature_name)
+ return True
def called_features_report():
- fv = FeatureDeprecated.feature_versions
- if fv:
- print('Deprecated features used:')
+ if FeatureDeprecated.feature_warnings:
+ warning_str = 'Deprecated features used:'\
+ .format(mesonlib.target_version)
+ fv = FeatureDeprecated.feature_versions
for version in sorted(fv.keys()):
- print('{}: {}'.format(version, fv[version]))
+ warning_str += '\n * {}: {}'.format(version, fv[version])
+ mlog.warning(warning_str)
def use(self):
- self.add_called_feature()
tv = mesonlib.target_version
if tv == '':
return
if not mesonlib.version_compare_condition_with_max(tv, self.feature_version):
- mlog.warning(
- '''Project targetting \'{}\' but tried to use feature deprecated since \'{}\': {}'''
- .format(tv, self.feature_version, self.feature_name))
+ FeatureDeprecated.feature_warnings = True
+ if self.add_called_feature():
+ mlog.warning(
+ '''Project targetting \'{}\' but tried to use feature deprecated since \'{}\': {}'''
+ .format(tv, self.feature_version, self.feature_name)
+ )
def __call__(self, f):
@wraps(f)
@@ -208,8 +228,9 @@ class FeatureNewKwargs:
def __call__(self, f):
@wraps(f)
def wrapped(*wrapped_args, **wrapped_kwargs):
+ s, node_or_state, args, call_kwargs = _get_callee_args(wrapped_args)
for arg in self.kwargs:
- if arg in wrapped_kwargs:
+ if arg in call_kwargs:
FeatureNew(arg + ' arg in ' + self.feature_name, self.feature_version).use()
return f(*wrapped_args, **wrapped_kwargs)
return wrapped
@@ -223,8 +244,9 @@ class FeatureDeprecatedKwargs:
def __call__(self, f):
@wraps(f)
def wrapped(*wrapped_args, **wrapped_kwargs):
+ s, node_or_state, args, call_kwargs = _get_callee_args(wrapped_args)
for arg in self.kwargs:
- if arg in wrapped_kwargs:
+ if arg in call_kwargs:
FeatureDeprecated(arg + ' arg in ' + self.feature_name, self.feature_version).use()
return f(*wrapped_args, **wrapped_kwargs)
return wrapped
diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py
index 21a6e29..c122589 100644
--- a/mesonbuild/mesonlib.py
+++ b/mesonbuild/mesonlib.py
@@ -396,6 +396,12 @@ def grab_leading_numbers(vstr, strict=False):
break
return result
+def make_same_len(listA, listB):
+ maxlen = max(len(listA), len(listB))
+ for i in listA, listB:
+ for n in range(len(i), maxlen):
+ i.append(0)
+
numpart = re.compile('[0-9.]+')
def version_compare(vstr1, vstr2, strict=False):
@@ -429,6 +435,7 @@ def version_compare(vstr1, vstr2, strict=False):
cmpop = operator.eq
varr1 = grab_leading_numbers(vstr1, strict)
varr2 = grab_leading_numbers(vstr2, strict)
+ make_same_len(varr1, varr2)
return cmpop(varr1, varr2)
def version_compare_many(vstr1, conditions):
@@ -451,7 +458,7 @@ def version_compare_condition_with_min(condition, minimum):
raise MesonException(msg.format(minimum))
minimum = match.group(0)
if condition.startswith('>='):
- cmpop = operator.lt
+ cmpop = operator.le
condition = condition[2:]
elif condition.startswith('<='):
return True
@@ -460,10 +467,10 @@ def version_compare_condition_with_min(condition, minimum):
return True
condition = condition[2:]
elif condition.startswith('=='):
- cmpop = operator.lt
+ cmpop = operator.le
condition = condition[2:]
elif condition.startswith('='):
- cmpop = operator.lt
+ cmpop = operator.le
condition = condition[1:]
elif condition.startswith('>'):
cmpop = operator.lt
@@ -472,9 +479,10 @@ def version_compare_condition_with_min(condition, minimum):
return True
condition = condition[2:]
else:
- cmpop = operator.eq
+ cmpop = operator.le
varr1 = grab_leading_numbers(minimum, True)
varr2 = grab_leading_numbers(condition, True)
+ make_same_len(varr1, varr2)
return cmpop(varr1, varr2)
def version_compare_condition_with_max(condition, maximum):
@@ -487,27 +495,28 @@ def version_compare_condition_with_max(condition, maximum):
return False
condition = condition[2:]
elif condition.startswith('<='):
- cmpop = operator.lt
+ cmpop = operator.ge
condition = condition[2:]
elif condition.startswith('!='):
return False
condition = condition[2:]
elif condition.startswith('=='):
- cmpop = operator.lt
+ cmpop = operator.ge
condition = condition[2:]
elif condition.startswith('='):
- cmpop = operator.lt
+ cmpop = operator.ge
condition = condition[1:]
elif condition.startswith('>'):
return False
condition = condition[1:]
elif condition.startswith('<'):
- cmpop = operator.lt
+ cmpop = operator.gt
condition = condition[2:]
else:
- cmpop = operator.eq
+ cmpop = operator.ge
varr1 = grab_leading_numbers(maximum, True)
varr2 = grab_leading_numbers(condition, True)
+ make_same_len(varr1, varr2)
return cmpop(varr1, varr2)