Merge pull request #3486 from Salamandar/salamandar/meson_version_introspection
Add FeatureNew and FeatureDeprecated, to alert the user of bad meson_version
This commit is contained in:
commit
bf2e21ec0e
|
@ -25,6 +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, clike_langs, sort_clike, lang_suffixes
|
||||
from .interpreterbase import FeatureNew, FeatureNewKwargs
|
||||
|
||||
pch_kwargs = set(['c_pch', 'cpp_pch'])
|
||||
|
||||
|
@ -330,6 +331,9 @@ 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']
|
||||
|
@ -1082,6 +1086,7 @@ recommended as it can lead to undefined behaviour 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')
|
||||
|
@ -1763,6 +1768,9 @@ class CustomTarget(Target):
|
|||
if 'install_dir' not in kwargs:
|
||||
raise InvalidArguments('"install_dir" must be specified '
|
||||
'when installing a target')
|
||||
|
||||
if isinstance(kwargs['install_dir'], list):
|
||||
FeatureNew('multiple install_dir for custom_target', '0.40.0').use()
|
||||
# If an item in this list is False, the output corresponding to
|
||||
# the list index of that item will not be installed
|
||||
self.install_dir = typeslistify(kwargs['install_dir'], (str, bool))
|
||||
|
|
|
@ -31,8 +31,11 @@ from .base import (
|
|||
ConfigToolDependency,
|
||||
)
|
||||
|
||||
from ..interpreterbase import FeatureNew
|
||||
|
||||
class MPIDependency(ExternalDependency):
|
||||
|
||||
@FeatureNew('MPI Dependency', '0.42.0')
|
||||
def __init__(self, environment, kwargs):
|
||||
language = kwargs.get('language', 'c')
|
||||
super().__init__('mpi', environment, language, kwargs)
|
||||
|
@ -249,6 +252,7 @@ class OpenMPDependency(ExternalDependency):
|
|||
'199810': '1.0',
|
||||
}
|
||||
|
||||
@FeatureNew('OpenMP Dependency', '0.46.0')
|
||||
def __init__(self, environment, kwargs):
|
||||
language = kwargs.get('language')
|
||||
super().__init__('openmp', environment, language, kwargs)
|
||||
|
@ -428,6 +432,8 @@ class Python3Dependency(ExternalDependency):
|
|||
|
||||
|
||||
class PcapDependency(ExternalDependency):
|
||||
|
||||
@FeatureNew('Pcap Dependency', '0.42.0')
|
||||
def __init__(self, environment, kwargs):
|
||||
super().__init__('pcap', environment, None, kwargs)
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ from .base import ExternalDependency, ExternalProgram
|
|||
from .base import ExtraFrameworkDependency, PkgConfigDependency
|
||||
from .base import ConfigToolDependency
|
||||
|
||||
from ..interpreterbase import FeatureNew
|
||||
|
||||
class GLDependency(ExternalDependency):
|
||||
def __init__(self, environment, kwargs):
|
||||
|
@ -514,6 +515,8 @@ class WxDependency(ConfigToolDependency):
|
|||
|
||||
|
||||
class VulkanDependency(ExternalDependency):
|
||||
|
||||
@FeatureNew('Vulkan Dependency', '0.42.0')
|
||||
def __init__(self, environment, kwargs):
|
||||
super().__init__('vulkan', environment, None, kwargs)
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ from .interpreterbase import InterpreterBase
|
|||
from .interpreterbase import check_stringlist, flatten, noPosargs, noKwargs, stringArgs, permittedKwargs, noArgsFlattening
|
||||
from .interpreterbase import InterpreterException, InvalidArguments, InvalidCode, SubdirDoneRequest
|
||||
from .interpreterbase import InterpreterObject, MutableInterpreterObject, Disabler
|
||||
from .interpreterbase import FeatureNew, FeatureDeprecated, FeatureNewKwargs
|
||||
from .modules import ModuleReturnValue
|
||||
|
||||
import os, sys, shutil, uuid
|
||||
|
@ -259,6 +260,7 @@ This will become a hard error in the future''')
|
|||
def has_method(self, args, kwargs):
|
||||
return args[0] in self.held_object.values
|
||||
|
||||
@FeatureNew('configuration_data.get()', '0.38.0')
|
||||
@noArgsFlattening
|
||||
def get_method(self, args, kwargs):
|
||||
if len(args) < 1 or len(args) > 2:
|
||||
|
@ -270,6 +272,7 @@ This will become a hard error in the future''')
|
|||
return args[1]
|
||||
raise InterpreterException('Entry %s not in configuration data.' % name)
|
||||
|
||||
@FeatureNew('get_unquoted', '0.44.0')
|
||||
def get_unquoted_method(self, args, kwargs):
|
||||
if len(args) < 1 or len(args) > 2:
|
||||
raise InterpreterException('Get method takes one or two arguments.')
|
||||
|
@ -342,6 +345,7 @@ class DependencyHolder(InterpreterObject, ObjectHolder):
|
|||
raise InterpreterException('Variable name must be a string.')
|
||||
return self.held_object.get_pkgconfig_variable(varname, kwargs)
|
||||
|
||||
@FeatureNew('get_configtool_variable', '0.44.0')
|
||||
@permittedKwargs({})
|
||||
def configtool_method(self, args, kwargs):
|
||||
args = listify(args)
|
||||
|
@ -352,6 +356,7 @@ class DependencyHolder(InterpreterObject, ObjectHolder):
|
|||
raise InterpreterException('Variable name must be a string.')
|
||||
return self.held_object.get_configtool_variable(varname)
|
||||
|
||||
@FeatureNew('dep.partial_dependency', '0.46.0')
|
||||
@noPosargs
|
||||
@permittedKwargs(permitted_method_kwargs['partial_dependency'])
|
||||
def partial_dependency_method(self, args, kwargs):
|
||||
|
@ -376,6 +381,7 @@ class InternalDependencyHolder(InterpreterObject, ObjectHolder):
|
|||
def version_method(self, args, kwargs):
|
||||
return self.held_object.get_version()
|
||||
|
||||
@FeatureNew('dep.partial_dependency', '0.46.0')
|
||||
@noPosargs
|
||||
@permittedKwargs(permitted_method_kwargs['partial_dependency'])
|
||||
def partial_dependency_method(self, args, kwargs):
|
||||
|
@ -435,6 +441,7 @@ class ExternalLibraryHolder(InterpreterObject, ObjectHolder):
|
|||
def get_exe_args(self):
|
||||
return self.held_object.get_exe_args()
|
||||
|
||||
@FeatureNew('dep.partial_dependency', '0.46.0')
|
||||
@noPosargs
|
||||
@permittedKwargs(permitted_method_kwargs['partial_dependency'])
|
||||
def partial_dependency_method(self, args, kwargs):
|
||||
|
@ -447,6 +454,7 @@ class GeneratorHolder(InterpreterObject, ObjectHolder):
|
|||
ObjectHolder.__init__(self, build.Generator(args, kwargs))
|
||||
self.methods.update({'process': self.process_method})
|
||||
|
||||
@FeatureNewKwargs('generator.process', '0.45.0', ['preserve_path_from'])
|
||||
@permittedKwargs({'extra_args', 'preserve_path_from'})
|
||||
def process_method(self, args, kwargs):
|
||||
extras = mesonlib.stringlistify(kwargs.get('extra_args', []))
|
||||
|
@ -685,6 +693,7 @@ class BuildTargetHolder(TargetHolder):
|
|||
gobjs = self.held_object.extract_objects(args)
|
||||
return GeneratedObjectsHolder(gobjs)
|
||||
|
||||
@FeatureNewKwargs('extract_all_objects', '0.46.0', ['recursive'])
|
||||
@noPosargs
|
||||
@permittedKwargs({'recursive'})
|
||||
def extract_all_objects_method(self, args, kwargs):
|
||||
|
@ -1095,6 +1104,7 @@ class CompilerHolder(InterpreterObject):
|
|||
mlog.log('Checking for type "', mlog.bold(typename), '": ', hadtxt, sep='')
|
||||
return had
|
||||
|
||||
@FeatureNew('compiler.compute_int', '0.40.0')
|
||||
@permittedKwargs({
|
||||
'prefix',
|
||||
'low',
|
||||
|
@ -1149,6 +1159,7 @@ class CompilerHolder(InterpreterObject):
|
|||
mlog.log('Checking for size of "%s": %d' % (element, esize))
|
||||
return esize
|
||||
|
||||
@FeatureNew('compiler.get_define', '0.40.0')
|
||||
@permittedKwargs({
|
||||
'prefix',
|
||||
'no_builtin_args',
|
||||
|
@ -1230,6 +1241,7 @@ class CompilerHolder(InterpreterObject):
|
|||
mlog.log('Checking if "', mlog.bold(testname), '" links: ', h, sep='')
|
||||
return result
|
||||
|
||||
@FeatureNew('check_header', '0.47.0')
|
||||
@permittedKwargs({
|
||||
'prefix',
|
||||
'no_builtin_args',
|
||||
|
@ -1352,6 +1364,7 @@ class CompilerHolder(InterpreterObject):
|
|||
h)
|
||||
return result
|
||||
|
||||
@FeatureNew('compiler.get_supported_arguments', '0.43.0')
|
||||
@permittedKwargs({})
|
||||
def get_supported_arguments_method(self, args, kwargs):
|
||||
args = mesonlib.stringlistify(args)
|
||||
|
@ -1370,6 +1383,7 @@ class CompilerHolder(InterpreterObject):
|
|||
mlog.log('First supported argument:', mlog.red('None'))
|
||||
return []
|
||||
|
||||
@FeatureNew('has_link_argument', '0.46.0')
|
||||
@permittedKwargs({})
|
||||
def has_link_argument_method(self, args, kwargs):
|
||||
args = mesonlib.stringlistify(args)
|
||||
|
@ -1377,6 +1391,7 @@ class CompilerHolder(InterpreterObject):
|
|||
raise InterpreterException('has_link_argument takes exactly one argument.')
|
||||
return self.has_multi_link_arguments_method(args, kwargs)
|
||||
|
||||
@FeatureNew('has_multi_link_argument', '0.46.0')
|
||||
@permittedKwargs({})
|
||||
def has_multi_link_arguments_method(self, args, kwargs):
|
||||
args = mesonlib.stringlistify(args)
|
||||
|
@ -1391,6 +1406,7 @@ class CompilerHolder(InterpreterObject):
|
|||
h)
|
||||
return result
|
||||
|
||||
@FeatureNew('get_supported_link_arguments_method', '0.46.0')
|
||||
@permittedKwargs({})
|
||||
def get_supported_link_arguments_method(self, args, kwargs):
|
||||
args = mesonlib.stringlistify(args)
|
||||
|
@ -1400,6 +1416,7 @@ class CompilerHolder(InterpreterObject):
|
|||
supported_args.append(arg)
|
||||
return supported_args
|
||||
|
||||
@FeatureNew('first_supported_link_argument_method', '0.46.0')
|
||||
@permittedKwargs({})
|
||||
def first_supported_link_argument_method(self, args, kwargs):
|
||||
for i in mesonlib.stringlistify(args):
|
||||
|
@ -1619,6 +1636,7 @@ class MesonMain(InterpreterObject):
|
|||
raise InterpreterException('Argument must be a string.')
|
||||
self.build.dep_manifest_name = args[0]
|
||||
|
||||
@FeatureNew('override_find_program', '0.46.0')
|
||||
@permittedKwargs({})
|
||||
def override_find_program_method(self, args, kwargs):
|
||||
if len(args) != 2:
|
||||
|
@ -1645,6 +1663,7 @@ class MesonMain(InterpreterObject):
|
|||
def project_version_method(self, args, kwargs):
|
||||
return self.build.dep_manifest[self.interpreter.active_projectname]['version']
|
||||
|
||||
@FeatureNew('meson.project_license()', '0.45.0')
|
||||
@noPosargs
|
||||
@permittedKwargs({})
|
||||
def project_license_method(self, args, kwargs):
|
||||
|
@ -1935,6 +1954,7 @@ class Interpreter(InterpreterBase):
|
|||
def func_files(self, node, args, kwargs):
|
||||
return [mesonlib.File.from_source_file(self.environment.source_dir, self.subdir, fname) for fname in args]
|
||||
|
||||
@FeatureNewKwargs('declare_dependency', '0.46.0', ['link_whole'])
|
||||
@permittedKwargs(permitted_kwargs['declare_dependency'])
|
||||
@noPosargs
|
||||
def func_declare_dependency(self, node, args, kwargs):
|
||||
|
@ -1990,6 +2010,7 @@ external dependencies (including libraries) must go to "dependencies".''')
|
|||
if not isinstance(actual, wanted):
|
||||
raise InvalidArguments('Incorrect argument type.')
|
||||
|
||||
@FeatureNewKwargs('run_command', '0.47.0', ['check'])
|
||||
@permittedKwargs(permitted_kwargs['run_command'])
|
||||
def func_run_command(self, node, args, kwargs):
|
||||
return self.run_command_impl(node, args, kwargs)
|
||||
|
@ -2067,6 +2088,7 @@ external dependencies (including libraries) must go to "dependencies".''')
|
|||
def func_option(self, nodes, args, kwargs):
|
||||
raise InterpreterException('Tried to call option() in build description file. All options must be in the option file.')
|
||||
|
||||
@FeatureNewKwargs('subproject', '0.38.0', ['default_options'])
|
||||
@permittedKwargs(permitted_kwargs['subproject'])
|
||||
@stringArgs
|
||||
def func_subproject(self, nodes, args, kwargs):
|
||||
|
@ -2285,6 +2307,7 @@ to directly access options of other subprojects.''')
|
|||
if 'meson_version' in kwargs:
|
||||
cv = coredata.version
|
||||
pv = kwargs['meson_version']
|
||||
mesonlib.target_version = pv
|
||||
if not mesonlib.version_compare(cv, pv):
|
||||
raise InterpreterException('Meson version is %s but project requires %s.' % (cv, pv))
|
||||
self.build.projects[self.subproject] = proj_name
|
||||
|
@ -2328,6 +2351,7 @@ to directly access options of other subprojects.''')
|
|||
argstr = self.get_message_string_arg(node)
|
||||
mlog.log(mlog.bold('Message:'), argstr)
|
||||
|
||||
@FeatureNew('warning()', '0.44.0')
|
||||
@noKwargs
|
||||
def func_warning(self, node, args, kwargs):
|
||||
argstr = self.get_message_string_arg(node)
|
||||
|
@ -2651,6 +2675,8 @@ to directly access options of other subprojects.''')
|
|||
'dep {}'.format(found, dirname, wanted, name))
|
||||
return None
|
||||
|
||||
@FeatureNewKwargs('dependency', '0.40.0', ['method'])
|
||||
@FeatureNewKwargs('dependency', '0.38.0', ['default_options'])
|
||||
@permittedKwargs(permitted_kwargs['dependency'])
|
||||
def func_dependency(self, node, args, kwargs):
|
||||
self.validate_arguments(args, 1, [str])
|
||||
|
@ -2715,6 +2741,7 @@ to directly access options of other subprojects.''')
|
|||
self.coredata.deps[identifier] = dep
|
||||
return DependencyHolder(dep)
|
||||
|
||||
@FeatureNew('disabler', '0.44.0')
|
||||
@noKwargs
|
||||
@noPosargs
|
||||
def func_disabler(self, node, args, kwargs):
|
||||
|
@ -2797,6 +2824,7 @@ root and issuing %s.
|
|||
mlog.bold(subproj_path), 'found:', mlog.green('YES'))
|
||||
return dep
|
||||
|
||||
@FeatureNewKwargs('executable', '0.42.0', 'implib')
|
||||
@permittedKwargs(permitted_kwargs['executable'])
|
||||
def func_executable(self, node, args, kwargs):
|
||||
return self.build_target(node, args, kwargs, ExecutableHolder)
|
||||
|
@ -2815,6 +2843,7 @@ root and issuing %s.
|
|||
def func_both_lib(self, node, args, kwargs):
|
||||
return self.build_both_libraries(node, args, kwargs)
|
||||
|
||||
@FeatureNew('Shared Modules', '0.37.0')
|
||||
@permittedKwargs(permitted_kwargs['shared_module'])
|
||||
def func_shared_module(self, node, args, kwargs):
|
||||
return self.build_target(node, args, kwargs, SharedModuleHolder)
|
||||
|
@ -2827,6 +2856,7 @@ root and issuing %s.
|
|||
def func_jar(self, node, args, kwargs):
|
||||
return self.build_target(node, args, kwargs, JarHolder)
|
||||
|
||||
@FeatureNewKwargs('build_target', '0.40.0', ['link_whole', 'override_options'])
|
||||
@permittedKwargs(permitted_kwargs['build_target'])
|
||||
def func_build_target(self, node, args, kwargs):
|
||||
if 'target_type' not in kwargs:
|
||||
|
@ -2851,6 +2881,8 @@ root and issuing %s.
|
|||
def func_vcs_tag(self, node, args, kwargs):
|
||||
if 'input' not in kwargs or 'output' not in kwargs:
|
||||
raise InterpreterException('Keyword arguments input and output must exist')
|
||||
if 'fallback' not in kwargs:
|
||||
FeatureNew('Optional fallback in vcs_tag', '0.41.0').use()
|
||||
fallback = kwargs.pop('fallback', self.project_version)
|
||||
if not isinstance(fallback, str):
|
||||
raise InterpreterException('Keyword argument fallback must be a string.')
|
||||
|
@ -2884,6 +2916,7 @@ root and issuing %s.
|
|||
kwargs.setdefault('build_always', True)
|
||||
return self.func_custom_target(node, [kwargs['output']], kwargs)
|
||||
|
||||
@FeatureNew('subdir_done', '0.46.0')
|
||||
@stringArgs
|
||||
def func_subdir_done(self, node, args, kwargs):
|
||||
if len(kwargs) > 0:
|
||||
|
@ -2893,6 +2926,7 @@ root and issuing %s.
|
|||
raise SubdirDoneRequest()
|
||||
|
||||
@stringArgs
|
||||
@FeatureNewKwargs('build target', '0.40.0', ['build_by_default'])
|
||||
@permittedKwargs(permitted_kwargs['custom_target'])
|
||||
def func_custom_target(self, node, args, kwargs):
|
||||
if len(args) != 1:
|
||||
|
@ -2944,6 +2978,7 @@ root and issuing %s.
|
|||
def func_benchmark(self, node, args, kwargs):
|
||||
self.add_test(node, args, kwargs, False)
|
||||
|
||||
@FeatureNewKwargs('test', '0.46.0', ['depends'])
|
||||
@permittedKwargs(permitted_kwargs['test'])
|
||||
def func_test(self, node, args, kwargs):
|
||||
self.add_test(node, args, kwargs, True)
|
||||
|
@ -3034,6 +3069,7 @@ root and issuing %s.
|
|||
self.build.man.append(m)
|
||||
return m
|
||||
|
||||
@FeatureNewKwargs('subdir', '0.44.0', ['if_found'])
|
||||
@permittedKwargs(permitted_kwargs['subdir'])
|
||||
def func_subdir(self, node, args, kwargs):
|
||||
self.validate_arguments(args, 1, [str])
|
||||
|
@ -3097,6 +3133,8 @@ root and issuing %s.
|
|||
'permissions arg to be a string or false')
|
||||
return FileMode(*install_mode)
|
||||
|
||||
@FeatureNewKwargs('install_data', '0.46.0', ['rename'])
|
||||
@FeatureNewKwargs('install_data', '0.38.0', ['install_mode'])
|
||||
@permittedKwargs(permitted_kwargs['install_data'])
|
||||
def func_install_data(self, node, args, kwargs):
|
||||
kwsource = mesonlib.stringlistify(kwargs.get('sources', []))
|
||||
|
@ -3118,6 +3156,8 @@ root and issuing %s.
|
|||
self.build.data.append(data.held_object)
|
||||
return data
|
||||
|
||||
@FeatureNewKwargs('install_subdir', '0.42.0', ['exclude_files', 'exclude_directories'])
|
||||
@FeatureNewKwargs('install_subdir', '0.38.0', ['install_mode'])
|
||||
@permittedKwargs(permitted_kwargs['install_subdir'])
|
||||
@stringArgs
|
||||
def func_install_subdir(self, node, args, kwargs):
|
||||
|
@ -3161,6 +3201,9 @@ root and issuing %s.
|
|||
self.build.install_dirs.append(idir)
|
||||
return idir
|
||||
|
||||
@FeatureNewKwargs('configure_file', '0.47.0', ['copy'])
|
||||
@FeatureNewKwargs('configure_file', '0.46.0', ['format'])
|
||||
@FeatureNewKwargs('configure_file', '0.41.0', ['capture'])
|
||||
@permittedKwargs(permitted_kwargs['configure_file'])
|
||||
def func_configure_file(self, node, args, kwargs):
|
||||
if len(args) > 0:
|
||||
|
@ -3458,6 +3501,8 @@ different subdirectory.
|
|||
def run(self):
|
||||
super().run()
|
||||
mlog.log('Build targets in project:', mlog.bold(str(len(self.build.targets))))
|
||||
FeatureNew.called_features_report()
|
||||
FeatureDeprecated.called_features_report()
|
||||
|
||||
def evaluate_subproject_info(self, path_from_source_root, subproject_dirname):
|
||||
depth = 0
|
||||
|
@ -3544,6 +3589,7 @@ different subdirectory.
|
|||
if idname not in self.coredata.target_guids:
|
||||
self.coredata.target_guids[idname] = str(uuid.uuid4()).upper()
|
||||
|
||||
@FeatureNew('both_libraries', '0.46.0')
|
||||
def build_both_libraries(self, node, args, kwargs):
|
||||
shared_holder = self.build_target(node, args, kwargs, SharedLibraryHolder)
|
||||
|
||||
|
|
|
@ -123,6 +123,113 @@ class permittedKwargs:
|
|||
return f(*wrapped_args, **wrapped_kwargs)
|
||||
return wrapped
|
||||
|
||||
class FeatureNew:
|
||||
"""Checks for new features"""
|
||||
# Shared across all instances
|
||||
feature_versions = dict()
|
||||
|
||||
def __init__(self, feature_name, version):
|
||||
self.feature_name = feature_name
|
||||
self.feature_version = version
|
||||
|
||||
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)
|
||||
|
||||
def called_features_report():
|
||||
fv = FeatureNew.feature_versions
|
||||
if fv:
|
||||
print('Minimum version of features used:')
|
||||
for version in sorted(fv.keys()):
|
||||
print('{}: {}'.format(version, fv[version]))
|
||||
|
||||
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.error(
|
||||
'''Project targetting \'{}\' but tried to use feature introduced in \'{}\': {}'''
|
||||
.format(tv, self.feature_version, self.feature_name))
|
||||
|
||||
def __call__(self, f):
|
||||
@wraps(f)
|
||||
def wrapped(*wrapped_args, **wrapped_kwargs):
|
||||
self.use()
|
||||
return f(*wrapped_args, **wrapped_kwargs)
|
||||
return wrapped
|
||||
|
||||
class FeatureDeprecated:
|
||||
"""Checks for deprecated features"""
|
||||
# Shared across all instances
|
||||
feature_versions = dict()
|
||||
|
||||
def __init__(self, feature_name, version):
|
||||
self.feature_name = feature_name
|
||||
self.feature_version = version
|
||||
|
||||
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)
|
||||
|
||||
def called_features_report():
|
||||
fv = FeatureDeprecated.feature_versions
|
||||
if fv:
|
||||
print('Deprecated features used:')
|
||||
for version in sorted(fv.keys()):
|
||||
print('{}: {}'.format(version, fv[version]))
|
||||
|
||||
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.error(
|
||||
'''Project targetting \'{}\' but tried to use feature deprecated since \'{}\': {}'''
|
||||
.format(tv, self.feature_version, self.feature_name))
|
||||
|
||||
def __call__(self, f):
|
||||
@wraps(f)
|
||||
def wrapped(*wrapped_args, **wrapped_kwargs):
|
||||
self.use()
|
||||
return f(*wrapped_args, **wrapped_kwargs)
|
||||
return wrapped
|
||||
|
||||
class FeatureNewKwargs:
|
||||
def __init__(self, feature_name, feature_version, kwargs):
|
||||
self.feature_name = feature_name
|
||||
self.feature_version = feature_version
|
||||
self.kwargs = kwargs
|
||||
|
||||
def __call__(self, f):
|
||||
@wraps(f)
|
||||
def wrapped(*wrapped_args, **wrapped_kwargs):
|
||||
for arg in self.kwargs:
|
||||
if arg in wrapped_kwargs:
|
||||
FeatureNew(arg + ' arg in ' + self.feature_name, self.feature_version).use()
|
||||
return f(*wrapped_args, **wrapped_kwargs)
|
||||
return wrapped
|
||||
|
||||
class FeatureDeprecatedKwargs:
|
||||
def __init__(self, feature_name, feature_version, kwargs):
|
||||
self.feature_name = feature_name
|
||||
self.feature_version = feature_version
|
||||
self.kwargs = kwargs
|
||||
|
||||
def __call__(self, f):
|
||||
@wraps(f)
|
||||
def wrapped(*wrapped_args, **wrapped_kwargs):
|
||||
for arg in self.kwargs:
|
||||
if arg in wrapped_kwargs:
|
||||
FeatureDeprecated(arg + ' arg in ' + self.feature_name, self.feature_version).use()
|
||||
return f(*wrapped_args, **wrapped_kwargs)
|
||||
return wrapped
|
||||
|
||||
|
||||
class InterpreterException(mesonlib.MesonException):
|
||||
pass
|
||||
|
||||
|
@ -298,6 +405,7 @@ class InterpreterBase:
|
|||
raise InvalidCode('Keyword arguments are invalid in array construction.')
|
||||
return arguments
|
||||
|
||||
@FeatureNew('dict', '0.47.0')
|
||||
def evaluate_dictstatement(self, cur):
|
||||
(arguments, kwargs) = self.reduce_arguments(cur.args)
|
||||
assert (not arguments)
|
||||
|
|
|
@ -23,6 +23,8 @@ from mesonbuild import mlog
|
|||
|
||||
have_fcntl = False
|
||||
have_msvcrt = False
|
||||
# Used to report conflicts between meson_version and new features used
|
||||
target_version = ''
|
||||
|
||||
try:
|
||||
import fcntl
|
||||
|
@ -441,6 +443,74 @@ def version_compare_many(vstr1, conditions):
|
|||
found.append(req)
|
||||
return not_found == [], not_found, found
|
||||
|
||||
|
||||
def version_compare_condition_with_min(condition, minimum):
|
||||
match = numpart.match(minimum.strip())
|
||||
if match is None:
|
||||
msg = 'Uncomparable version string {!r}.'
|
||||
raise MesonException(msg.format(minimum))
|
||||
minimum = match.group(0)
|
||||
if condition.startswith('>='):
|
||||
cmpop = operator.lt
|
||||
condition = condition[2:]
|
||||
elif condition.startswith('<='):
|
||||
return True
|
||||
condition = condition[2:]
|
||||
elif condition.startswith('!='):
|
||||
return True
|
||||
condition = condition[2:]
|
||||
elif condition.startswith('=='):
|
||||
cmpop = operator.lt
|
||||
condition = condition[2:]
|
||||
elif condition.startswith('='):
|
||||
cmpop = operator.lt
|
||||
condition = condition[1:]
|
||||
elif condition.startswith('>'):
|
||||
cmpop = operator.lt
|
||||
condition = condition[1:]
|
||||
elif condition.startswith('<'):
|
||||
return True
|
||||
condition = condition[2:]
|
||||
else:
|
||||
cmpop = operator.eq
|
||||
varr1 = grab_leading_numbers(minimum, True)
|
||||
varr2 = grab_leading_numbers(condition, True)
|
||||
return cmpop(varr1, varr2)
|
||||
|
||||
def version_compare_condition_with_max(condition, maximum):
|
||||
match = numpart.match(maximum.strip())
|
||||
if match is None:
|
||||
msg = 'Uncomparable version string {!r}.'
|
||||
raise MesonException(msg.format(maximum))
|
||||
maximum = match.group(0)
|
||||
if condition.startswith('>='):
|
||||
return False
|
||||
condition = condition[2:]
|
||||
elif condition.startswith('<='):
|
||||
cmpop = operator.lt
|
||||
condition = condition[2:]
|
||||
elif condition.startswith('!='):
|
||||
return False
|
||||
condition = condition[2:]
|
||||
elif condition.startswith('=='):
|
||||
cmpop = operator.lt
|
||||
condition = condition[2:]
|
||||
elif condition.startswith('='):
|
||||
cmpop = operator.lt
|
||||
condition = condition[1:]
|
||||
elif condition.startswith('>'):
|
||||
return False
|
||||
condition = condition[1:]
|
||||
elif condition.startswith('<'):
|
||||
cmpop = operator.lt
|
||||
condition = condition[2:]
|
||||
else:
|
||||
cmpop = operator.eq
|
||||
varr1 = grab_leading_numbers(maximum, True)
|
||||
varr2 = grab_leading_numbers(condition, True)
|
||||
return cmpop(varr1, varr2)
|
||||
|
||||
|
||||
def default_libdir():
|
||||
if is_debianlike():
|
||||
try:
|
||||
|
|
|
@ -30,7 +30,7 @@ from . import ExtensionModule
|
|||
from . import ModuleReturnValue
|
||||
from ..mesonlib import MesonException, OrderedSet, Popen_safe, extract_as_list
|
||||
from ..dependencies import Dependency, PkgConfigDependency, InternalDependency
|
||||
from ..interpreterbase import noKwargs, permittedKwargs
|
||||
from ..interpreterbase import noKwargs, permittedKwargs, FeatureNew, FeatureNewKwargs
|
||||
|
||||
# gresource compilation is broken due to the way
|
||||
# the resource compiler and Ninja clash about it
|
||||
|
@ -95,6 +95,7 @@ class GnomeModule(ExtensionModule):
|
|||
mlog.bold('https://github.com/mesonbuild/meson/issues/1387'))
|
||||
gdbuswarning_printed = True
|
||||
|
||||
@FeatureNewKwargs('gnome.compile_resources', '0.37.0', ['gresource_bundle', 'export', 'install_header'])
|
||||
@permittedKwargs({'source_dir', 'c_name', 'dependencies', 'export', 'gresource_bundle', 'install_header',
|
||||
'install', 'install_dir', 'extra_args', 'build_by_default'})
|
||||
def compile_resources(self, state, args, kwargs):
|
||||
|
@ -384,6 +385,7 @@ class GnomeModule(ExtensionModule):
|
|||
ldflags = fixed_ldflags
|
||||
return cflags, ldflags, gi_includes
|
||||
|
||||
@FeatureNewKwargs('build target', '0.40.0', ['build_by_default'])
|
||||
@permittedKwargs({'sources', 'nsversion', 'namespace', 'symbol_prefix', 'identifier_prefix',
|
||||
'export_packages', 'includes', 'dependencies', 'link_with', 'include_directories',
|
||||
'install', 'install_dir_gir', 'install_dir_typelib', 'extra_args',
|
||||
|
@ -635,6 +637,7 @@ class GnomeModule(ExtensionModule):
|
|||
rv = [scan_target, typelib_target]
|
||||
return ModuleReturnValue(rv, rv)
|
||||
|
||||
@FeatureNewKwargs('build target', '0.40.0', ['build_by_default'])
|
||||
@permittedKwargs({'build_by_default', 'depend_files'})
|
||||
def compile_schemas(self, state, args, kwargs):
|
||||
if args:
|
||||
|
@ -721,6 +724,7 @@ This will become a hard error in the future.''')
|
|||
rv = [inscript, pottarget, potarget]
|
||||
return ModuleReturnValue(None, rv)
|
||||
|
||||
@FeatureNewKwargs('gnome.gtkdoc', '0.37.0', ['namespace', 'mode'])
|
||||
@permittedKwargs({'main_xml', 'main_sgml', 'src_dir', 'dependencies', 'install',
|
||||
'install_dir', 'scan_args', 'scanobjs_args', 'gobject_typesfile',
|
||||
'fixxref_args', 'html_args', 'html_assets', 'content_files',
|
||||
|
@ -875,6 +879,8 @@ This will become a hard error in the future.''')
|
|||
|
||||
return []
|
||||
|
||||
@FeatureNewKwargs('build target', '0.46.0', ['install_header', 'install_dir', 'sources'])
|
||||
@FeatureNewKwargs('build target', '0.40.0', ['build_by_default'])
|
||||
@permittedKwargs({'interface_prefix', 'namespace', 'object_manager', 'build_by_default',
|
||||
'annotations', 'docbook', 'install_header', 'install_dir', 'sources'})
|
||||
def gdbus_codegen(self, state, args, kwargs):
|
||||
|
@ -1090,6 +1096,7 @@ This will become a hard error in the future.''')
|
|||
else:
|
||||
return ModuleReturnValue(targets, targets)
|
||||
|
||||
@FeatureNew('gnome.mkenums_simple', '0.42.0')
|
||||
def mkenums_simple(self, state, args, kwargs):
|
||||
hdr_filename = args[0] + '.h'
|
||||
body_filename = args[0] + '.c'
|
||||
|
|
|
@ -19,7 +19,7 @@ from .. import coredata, mesonlib, build
|
|||
from ..mesonlib import MesonException
|
||||
from . import ModuleReturnValue
|
||||
from . import ExtensionModule
|
||||
from ..interpreterbase import permittedKwargs
|
||||
from ..interpreterbase import permittedKwargs, FeatureNew, FeatureNewKwargs
|
||||
|
||||
PRESET_ARGS = {
|
||||
'glib': [
|
||||
|
@ -55,6 +55,7 @@ class I18nModule(ExtensionModule):
|
|||
src_dir = path.join(state.environment.get_source_dir(), state.subdir)
|
||||
return [path.join(src_dir, d) for d in dirs]
|
||||
|
||||
@FeatureNew('i18n.merge_file', '0.37.0')
|
||||
@permittedKwargs({'languages', 'data_dirs', 'preset', 'args', 'po_dir', 'type',
|
||||
'input', 'output', 'install', 'install_dir'})
|
||||
def merge_file(self, state, args, kwargs):
|
||||
|
@ -82,6 +83,7 @@ class I18nModule(ExtensionModule):
|
|||
ct = build.CustomTarget(kwargs['output'] + '_merge', state.subdir, state.subproject, kwargs)
|
||||
return ModuleReturnValue(ct, [ct])
|
||||
|
||||
@FeatureNewKwargs('i18n.gettext', '0.37.0', ['preset'])
|
||||
@permittedKwargs({'po_dir', 'data_dirs', 'type', 'languages', 'args', 'preset', 'install'})
|
||||
def gettext(self, state, args, kwargs):
|
||||
if len(args) != 1:
|
||||
|
|
|
@ -21,7 +21,7 @@ from .. import mesonlib
|
|||
from .. import mlog
|
||||
from . import ModuleReturnValue
|
||||
from . import ExtensionModule
|
||||
from ..interpreterbase import permittedKwargs
|
||||
from ..interpreterbase import permittedKwargs, FeatureNew, FeatureNewKwargs
|
||||
|
||||
class DependenciesHelper:
|
||||
def __init__(self, name):
|
||||
|
@ -304,16 +304,21 @@ class PkgConfigModule(ExtensionModule):
|
|||
ofile.write(self._escape(f))
|
||||
ofile.write('\n')
|
||||
|
||||
@FeatureNewKwargs('pkgconfig.generate', '0.42.0', ['extra_cflags'])
|
||||
@FeatureNewKwargs('pkgconfig.generate', '0.41.0', ['variables'])
|
||||
@permittedKwargs({'libraries', 'version', 'name', 'description', 'filebase',
|
||||
'subdirs', 'requires', 'requires_private', 'libraries_private',
|
||||
'install_dir', 'extra_cflags', 'variables', 'url', 'd_module_versions'})
|
||||
def generate(self, state, args, kwargs):
|
||||
if 'variables' in kwargs:
|
||||
FeatureNew('custom pkgconfig variables', '0.41.0').use()
|
||||
default_version = state.project_version['version']
|
||||
default_install_dir = None
|
||||
default_description = None
|
||||
default_name = None
|
||||
mainlib = None
|
||||
if len(args) == 1:
|
||||
FeatureNew('pkgconfig.generate optional positional argument', '0.46.0').use()
|
||||
mainlib = getattr(args[0], 'held_object', args[0])
|
||||
if not isinstance(mainlib, (build.StaticLibrary, build.SharedLibrary)):
|
||||
raise mesonlib.MesonException('Pkgconfig_gen first positional argument must be a library object')
|
||||
|
|
|
@ -22,7 +22,8 @@ from mesonbuild.modules import ModuleReturnValue
|
|||
from . import permittedSnippetKwargs
|
||||
from ..interpreterbase import (
|
||||
noPosargs, noKwargs, permittedKwargs,
|
||||
InterpreterObject, InvalidArguments
|
||||
InterpreterObject, InvalidArguments,
|
||||
FeatureNew
|
||||
)
|
||||
from ..interpreter import ExternalProgramHolder
|
||||
from ..interpreterbase import flatten
|
||||
|
@ -49,6 +50,8 @@ def run_command(python, command):
|
|||
|
||||
|
||||
class PythonDependency(ExternalDependency):
|
||||
|
||||
@FeatureNew('Python Module', '0.46.0')
|
||||
def __init__(self, python_holder, environment, kwargs):
|
||||
super().__init__('python', environment, None, kwargs)
|
||||
self.name = 'python'
|
||||
|
|
|
@ -19,7 +19,7 @@ from ..mesonlib import MesonException, Popen_safe, extract_as_list, File
|
|||
from ..dependencies import Qt4Dependency, Qt5Dependency
|
||||
import xml.etree.ElementTree as ET
|
||||
from . import ModuleReturnValue, get_include_args
|
||||
from ..interpreterbase import permittedKwargs
|
||||
from ..interpreterbase import permittedKwargs, FeatureNewKwargs
|
||||
|
||||
_QT_DEPS_LUT = {
|
||||
4: Qt4Dependency,
|
||||
|
@ -116,6 +116,7 @@ class QtBaseModule:
|
|||
except Exception:
|
||||
return []
|
||||
|
||||
@FeatureNewKwargs('qt.preprocess', '0.44.0', ['moc_extra_arguments'])
|
||||
@permittedKwargs({'moc_headers', 'moc_sources', 'moc_extra_arguments', 'include_directories', 'ui_files', 'qresources', 'method'})
|
||||
def preprocess(self, state, args, kwargs):
|
||||
rcc_files, ui_files, moc_headers, moc_sources, moc_extra_arguments, sources, include_directories \
|
||||
|
@ -181,6 +182,7 @@ class QtBaseModule:
|
|||
sources.append(moc_output)
|
||||
return ModuleReturnValue(sources, sources)
|
||||
|
||||
@FeatureNewKwargs('build target', '0.40.0', ['build_by_default'])
|
||||
@permittedKwargs({'ts_files', 'install', 'install_dir', 'build_by_default', 'method'})
|
||||
def compile_translations(self, state, args, kwargs):
|
||||
ts_files, install_dir = extract_as_list(kwargs, 'ts_files', 'install_dir', pop=True)
|
||||
|
|
|
@ -14,11 +14,13 @@
|
|||
|
||||
from .. import mesonlib
|
||||
from ..interpreterbase import flatten
|
||||
from ..interpreterbase import FeatureNew
|
||||
|
||||
from . import ExtensionModule
|
||||
|
||||
class IceStormModule(ExtensionModule):
|
||||
|
||||
@FeatureNew('FPGA/Icestorm Module', '0.45.0')
|
||||
def __init__(self, interpreter):
|
||||
super().__init__(interpreter)
|
||||
self.snippets.add('project')
|
||||
|
|
|
@ -16,8 +16,11 @@ from .. import mesonlib, compilers, mlog
|
|||
|
||||
from . import ExtensionModule
|
||||
|
||||
from ..interpreterbase import FeatureNew
|
||||
|
||||
class SimdModule(ExtensionModule):
|
||||
|
||||
@FeatureNew('SIMD module', '0.42.0')
|
||||
def __init__(self, interpreter):
|
||||
super().__init__(interpreter)
|
||||
self.snippets.add('check')
|
||||
|
|
|
@ -19,7 +19,7 @@ from . import mlog
|
|||
from . import mparser
|
||||
from . import coredata
|
||||
from . import mesonlib
|
||||
|
||||
from .interpreterbase import FeatureNew
|
||||
|
||||
forbidden_option_names = coredata.get_builtin_options()
|
||||
forbidden_prefixes = {'c_',
|
||||
|
@ -106,6 +106,7 @@ def IntegerParser(name, description, kwargs):
|
|||
kwargs['value'],
|
||||
kwargs.get('yield', coredata.default_yielding))
|
||||
|
||||
@FeatureNew('array type option()', '0.44.0')
|
||||
@permitted_kwargs({'value', 'yield', 'choices'})
|
||||
def string_array_parser(name, description, kwargs):
|
||||
if 'choices' in kwargs:
|
||||
|
@ -230,6 +231,10 @@ class OptionInterpreter:
|
|||
if func_name != 'option':
|
||||
raise OptionException('Only calls to option() are allowed in option files.')
|
||||
(posargs, kwargs) = self.reduce_arguments(node.args)
|
||||
|
||||
if 'yield' in kwargs:
|
||||
FeatureNew('option yield', '0.45.0').use()
|
||||
|
||||
if 'type' not in kwargs:
|
||||
raise OptionException('Option call missing mandatory "type" keyword argument')
|
||||
opt_type = kwargs.pop('type')
|
||||
|
|
Loading…
Reference in New Issue