aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mesonbuild/build.py25
-rw-r--r--mesonbuild/dependencies/base.py6
-rw-r--r--mesonbuild/dependencies/dev.py4
-rw-r--r--mesonbuild/interpreter.py184
-rw-r--r--mesonbuild/mesonlib.py59
-rw-r--r--mesonbuild/modules/gnome.py16
-rwxr-xr-xrun_unittests.py45
-rw-r--r--test cases/frameworks/7 gnome/gir/meson.build2
8 files changed, 183 insertions, 158 deletions
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index 5f5dd6b..9837d5a 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -20,7 +20,7 @@ from . import environment
from . import dependencies
from . import mlog
from .mesonlib import File, MesonException, listify, extract_as_list
-from .mesonlib import flatten, typeslistify, stringlistify, classify_unity_sources
+from .mesonlib import typeslistify, stringlistify, classify_unity_sources
from .mesonlib import get_filenames_templates_dict, substitute_values
from .environment import for_windows, for_darwin, for_cygwin
from .compilers import is_object, clike_langs, sort_clike, lang_suffixes
@@ -682,7 +682,7 @@ class BuildTarget(Target):
if 'd' in self.compilers:
self.add_compiler_args('d', self.compilers['d'].get_feature_args(dfeatures))
- self.link_args = flatten(kwargs.get('link_args', []))
+ self.link_args = extract_as_list(kwargs, 'link_args')
for i in self.link_args:
if not isinstance(i, str):
raise InvalidArguments('Link_args arguments must be strings.')
@@ -856,9 +856,7 @@ You probably should put it in link_with instead.''')
return self.external_deps
def link(self, target):
- for t in flatten(target):
- if hasattr(t, 'held_object'):
- t = t.held_object
+ for t in listify(target, unholder=True):
if not t.is_linkable_target():
raise InvalidArguments('Link target {!r} is not linkable.'.format(t))
if isinstance(self, SharedLibrary) and isinstance(t, StaticLibrary) and not t.pic:
@@ -870,9 +868,7 @@ You probably should put it in link_with instead.''')
self.link_targets.append(t)
def link_whole(self, target):
- for t in flatten(target):
- if hasattr(t, 'held_object'):
- t = t.held_object
+ for t in listify(target, unholder=True):
if not isinstance(t, StaticLibrary):
raise InvalidArguments('{!r} is not a static library.'.format(t))
if isinstance(self, SharedLibrary) and not t.pic:
@@ -915,7 +911,7 @@ You probably should put it in link_with instead.''')
self.include_dirs += ids
def add_compiler_args(self, language, args):
- args = flatten(args)
+ args = listify(args)
for a in args:
if not isinstance(a, (str, File)):
raise InvalidArguments('A non-string passed to compiler args.')
@@ -1546,11 +1542,9 @@ class CustomTarget(Target):
return deps
def flatten_command(self, cmd):
- cmd = listify(cmd)
+ cmd = listify(cmd, unholder=True)
final_cmd = []
for c in cmd:
- if hasattr(c, 'held_object'):
- c = c.held_object
if isinstance(c, str):
final_cmd.append(c)
elif isinstance(c, File):
@@ -1573,12 +1567,7 @@ class CustomTarget(Target):
def process_kwargs(self, kwargs):
super().process_kwargs(kwargs)
- sources = flatten(kwargs.get('input', []))
- self.sources = []
- for s in sources:
- if hasattr(s, 'held_object'):
- s = s.held_object
- self.sources.append(s)
+ self.sources = extract_as_list(kwargs, 'input', unholder=True)
if 'output' not in kwargs:
raise InvalidArguments('Missing keyword argument "output".')
self.outputs = listify(kwargs['output'])
diff --git a/mesonbuild/dependencies/base.py b/mesonbuild/dependencies/base.py
index 7c7f986..0d9742d 100644
--- a/mesonbuild/dependencies/base.py
+++ b/mesonbuild/dependencies/base.py
@@ -23,7 +23,7 @@ from enum import Enum
from .. import mlog
from .. import mesonlib
-from ..mesonlib import MesonException, Popen_safe, flatten, version_compare_many, listify
+from ..mesonlib import MesonException, Popen_safe, version_compare_many, listify
# These must be defined in this file to avoid cyclical references.
@@ -586,7 +586,7 @@ class ExtraFrameworkDependency(ExternalDependency):
def get_dep_identifier(name, kwargs, want_cross):
# Need immutable objects since the identifier will be used as a dict key
- version_reqs = flatten(kwargs.get('version', []))
+ version_reqs = listify(kwargs.get('version', []))
if isinstance(version_reqs, list):
version_reqs = frozenset(version_reqs)
identifier = (name, version_reqs, want_cross)
@@ -599,7 +599,7 @@ def get_dep_identifier(name, kwargs, want_cross):
continue
# All keyword arguments are strings, ints, or lists (or lists of lists)
if isinstance(value, list):
- value = frozenset(flatten(value))
+ value = frozenset(listify(value))
identifier += (key, value)
return identifier
diff --git a/mesonbuild/dependencies/dev.py b/mesonbuild/dependencies/dev.py
index d2dd107..387300a 100644
--- a/mesonbuild/dependencies/dev.py
+++ b/mesonbuild/dependencies/dev.py
@@ -21,7 +21,7 @@ import shutil
from .. import mlog
from .. import mesonlib
-from ..mesonlib import version_compare, Popen_safe
+from ..mesonlib import version_compare, Popen_safe, stringlistify, extract_as_list
from .base import DependencyException, ExternalDependency, PkgConfigDependency
class GTestDependency(ExternalDependency):
@@ -185,7 +185,7 @@ class LLVMDependency(ExternalDependency):
raise DependencyException('Could not generate modules for LLVM.')
self.modules = shlex.split(out)
- modules = mesonlib.stringlistify(mesonlib.flatten(kwargs.get('modules', [])))
+ modules = stringlistify(extract_as_list(kwargs, 'modules'))
for mod in sorted(set(modules)):
if mod not in self.modules:
mlog.log('LLVM module', mod, 'found:', mlog.red('NO'))
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index 7641514..b938080 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -48,6 +48,14 @@ def stringifyUserArguments(args):
raise InvalidArguments('Function accepts only strings, integers, lists and lists thereof.')
+class ObjectHolder:
+ def __init__(self, obj):
+ self.held_object = obj
+
+ def __repr__(self):
+ return '<Holder: {!r}>'.format(self.held_object)
+
+
class TryRunResultHolder(InterpreterObject):
def __init__(self, res):
super().__init__()
@@ -117,17 +125,18 @@ class RunProcess(InterpreterObject):
def stderr_method(self, args, kwargs):
return self.stderr
-class ConfigureFileHolder(InterpreterObject):
+class ConfigureFileHolder(InterpreterObject, ObjectHolder):
def __init__(self, subdir, sourcename, targetname, configuration_data):
InterpreterObject.__init__(self)
- self.held_object = build.ConfigureFile(subdir, sourcename, targetname, configuration_data)
+ ObjectHolder.__init__(self, build.ConfigureFile(subdir, sourcename,
+ targetname, configuration_data))
-class EnvironmentVariablesHolder(MutableInterpreterObject):
+class EnvironmentVariablesHolder(MutableInterpreterObject, ObjectHolder):
def __init__(self):
- super().__init__()
- self.held_object = build.EnvironmentVariables()
+ MutableInterpreterObject.__init__(self)
+ ObjectHolder.__init__(self, build.EnvironmentVariables())
self.methods.update({'set': self.set_method,
'append': self.append_method,
'prepend': self.prepend_method,
@@ -158,11 +167,11 @@ class EnvironmentVariablesHolder(MutableInterpreterObject):
self.add_var(self.held_object.prepend, args, kwargs)
-class ConfigurationDataHolder(MutableInterpreterObject):
+class ConfigurationDataHolder(MutableInterpreterObject, ObjectHolder):
def __init__(self):
- super().__init__()
+ MutableInterpreterObject.__init__(self)
self.used = False # These objects become immutable after use in configure_file.
- self.held_object = build.ConfigurationData()
+ ObjectHolder.__init__(self, build.ConfigurationData())
self.methods.update({'set': self.set_method,
'set10': self.set10_method,
'set_quoted': self.set_quoted_method,
@@ -242,10 +251,10 @@ class ConfigurationDataHolder(MutableInterpreterObject):
# Interpreter objects can not be pickled so we must have
# these wrappers.
-class DependencyHolder(InterpreterObject):
+class DependencyHolder(InterpreterObject, ObjectHolder):
def __init__(self, dep):
InterpreterObject.__init__(self)
- self.held_object = dep
+ ObjectHolder.__init__(self, dep)
self.methods.update({'found': self.found_method,
'type_name': self.type_name_method,
'version': self.version_method,
@@ -272,10 +281,10 @@ class DependencyHolder(InterpreterObject):
raise InterpreterException('Variable name must be a string.')
return self.held_object.get_pkgconfig_variable(varname)
-class InternalDependencyHolder(InterpreterObject):
+class InternalDependencyHolder(InterpreterObject, ObjectHolder):
def __init__(self, dep):
InterpreterObject.__init__(self)
- self.held_object = dep
+ ObjectHolder.__init__(self, dep)
self.methods.update({'found': self.found_method,
'version': self.version_method,
})
@@ -286,10 +295,10 @@ class InternalDependencyHolder(InterpreterObject):
def version_method(self, args, kwargs):
return self.held_object.get_version()
-class ExternalProgramHolder(InterpreterObject):
+class ExternalProgramHolder(InterpreterObject, ObjectHolder):
def __init__(self, ep):
InterpreterObject.__init__(self)
- self.held_object = ep
+ ObjectHolder.__init__(self, ep)
self.methods.update({'found': self.found_method,
'path': self.path_method})
@@ -308,10 +317,10 @@ class ExternalProgramHolder(InterpreterObject):
def get_name(self):
return self.held_object.get_name()
-class ExternalLibraryHolder(InterpreterObject):
+class ExternalLibraryHolder(InterpreterObject, ObjectHolder):
def __init__(self, el):
InterpreterObject.__init__(self)
- self.held_object = el
+ ObjectHolder.__init__(self, el)
self.methods.update({'found': self.found_method})
def found(self):
@@ -332,11 +341,11 @@ class ExternalLibraryHolder(InterpreterObject):
def get_exe_args(self):
return self.held_object.get_exe_args()
-class GeneratorHolder(InterpreterObject):
+class GeneratorHolder(InterpreterObject, ObjectHolder):
def __init__(self, interpreter, args, kwargs):
- super().__init__()
+ InterpreterObject.__init__(self)
self.interpreter = interpreter
- self.held_object = build.Generator(args, kwargs)
+ ObjectHolder.__init__(self, build.Generator(args, kwargs))
self.methods.update({'process': self.process_method})
def process_method(self, args, kwargs):
@@ -345,13 +354,13 @@ class GeneratorHolder(InterpreterObject):
return GeneratedListHolder(gl)
-class GeneratedListHolder(InterpreterObject):
+class GeneratedListHolder(InterpreterObject, ObjectHolder):
def __init__(self, arg1, extra_args=[]):
- super().__init__()
+ InterpreterObject.__init__(self)
if isinstance(arg1, GeneratorHolder):
- self.held_object = build.GeneratedList(arg1.held_object, extra_args)
+ ObjectHolder.__init__(self, build.GeneratedList(arg1.held_object, extra_args))
else:
- self.held_object = arg1
+ ObjectHolder.__init__(self, arg1)
def __repr__(self):
r = '<{}: {!r}>'
@@ -360,14 +369,15 @@ class GeneratedListHolder(InterpreterObject):
def add_file(self, a):
self.held_object.add_file(a)
-class BuildMachine(InterpreterObject):
+class BuildMachine(InterpreterObject, ObjectHolder):
def __init__(self, compilers):
self.compilers = compilers
InterpreterObject.__init__(self)
- self.held_object = environment.MachineInfo(environment.detect_system(),
- environment.detect_cpu_family(self.compilers),
- environment.detect_cpu(self.compilers),
- sys.byteorder)
+ held_object = environment.MachineInfo(environment.detect_system(),
+ environment.detect_cpu_family(self.compilers),
+ environment.detect_cpu(self.compilers),
+ sys.byteorder)
+ ObjectHolder.__init__(self, held_object)
self.methods.update({'system': self.system_method,
'cpu_family': self.cpu_family_method,
'cpu': self.cpu_method,
@@ -388,7 +398,7 @@ class BuildMachine(InterpreterObject):
# This class will provide both host_machine and
# target_machine
-class CrossMachineInfo(InterpreterObject):
+class CrossMachineInfo(InterpreterObject, ObjectHolder):
def __init__(self, cross_info):
InterpreterObject.__init__(self)
minimum_cross_info = {'cpu', 'cpu_family', 'endian', 'system'}
@@ -397,10 +407,11 @@ class CrossMachineInfo(InterpreterObject):
'Machine info is currently {}\n'.format(cross_info) +
'but is missing {}.'.format(minimum_cross_info - set(cross_info)))
self.info = cross_info
- self.held_object = environment.MachineInfo(cross_info['system'],
- cross_info['cpu_family'],
- cross_info['cpu'],
- cross_info['endian'])
+ minfo = environment.MachineInfo(cross_info['system'],
+ cross_info['cpu_family'],
+ cross_info['cpu'],
+ cross_info['endian'])
+ ObjectHolder.__init__(self, minfo)
self.methods.update({'system': self.system_method,
'cpu': self.cpu_method,
'cpu_family': self.cpu_family_method,
@@ -419,10 +430,10 @@ class CrossMachineInfo(InterpreterObject):
def endian_method(self, args, kwargs):
return self.held_object.endian
-class IncludeDirsHolder(InterpreterObject):
+class IncludeDirsHolder(InterpreterObject, ObjectHolder):
def __init__(self, idobj):
- super().__init__()
- self.held_object = idobj
+ InterpreterObject.__init__(self)
+ ObjectHolder.__init__(self, idobj)
class Headers(InterpreterObject):
@@ -447,10 +458,10 @@ class Headers(InterpreterObject):
def get_custom_install_dir(self):
return self.custom_install_dir
-class DataHolder(InterpreterObject):
+class DataHolder(InterpreterObject, ObjectHolder):
def __init__(self, data):
- super().__init__()
- self.held_object = data
+ InterpreterObject.__init__(self)
+ ObjectHolder.__init__(self, data)
def get_source_subdir(self):
return self.held_object.source_subdir
@@ -495,20 +506,20 @@ class Man(InterpreterObject):
def get_sources(self):
return self.sources
-class GeneratedObjectsHolder(InterpreterObject):
+class GeneratedObjectsHolder(InterpreterObject, ObjectHolder):
def __init__(self, held_object):
- super().__init__()
- self.held_object = held_object
+ InterpreterObject.__init__(self)
+ ObjectHolder.__init__(self, held_object)
-class TargetHolder(InterpreterObject):
- def __init__(self):
- super().__init__()
+class TargetHolder(InterpreterObject, ObjectHolder):
+ def __init__(self, target, interp):
+ InterpreterObject.__init__(self)
+ ObjectHolder.__init__(self, target)
+ self.interpreter = interp
class BuildTargetHolder(TargetHolder):
def __init__(self, target, interp):
- super().__init__()
- self.held_object = target
- self.interpreter = interp
+ super().__init__(target, interp)
self.methods.update({'extract_objects': self.extract_objects_method,
'extract_all_objects': self.extract_all_objects_method,
'get_id': self.get_id_method,
@@ -566,16 +577,14 @@ class JarHolder(BuildTargetHolder):
def __init__(self, target, interp):
super().__init__(target, interp)
-class CustomTargetIndexHolder(InterpreterObject):
+class CustomTargetIndexHolder(InterpreterObject, ObjectHolder):
def __init__(self, object_to_hold):
- super().__init__()
- self.held_object = object_to_hold
+ InterpreterObject.__init__(self)
+ ObjectHolder.__init__(self, object_to_hold)
class CustomTargetHolder(TargetHolder):
- def __init__(self, object_to_hold, interp):
- super().__init__()
- self.held_object = object_to_hold
- self.interpreter = interp
+ def __init__(self, target, interp):
+ super().__init__(target, interp)
self.methods.update({'full_path': self.full_path_method,
})
@@ -596,10 +605,10 @@ class CustomTargetHolder(TargetHolder):
def __delitem__(self, index):
raise InterpreterException('Cannot delete a member of a CustomTarget')
-class RunTargetHolder(InterpreterObject):
+class RunTargetHolder(InterpreterObject, ObjectHolder):
def __init__(self, name, command, args, dependencies, subdir):
- super().__init__()
- self.held_object = build.RunTarget(name, command, args, dependencies, subdir)
+ InterpreterObject.__init__(self)
+ ObjectHolder.__init__(self, build.RunTarget(name, command, args, dependencies, subdir))
def __repr__(self):
r = '<{} {}: {}>'
@@ -625,11 +634,11 @@ class Test(InterpreterObject):
def get_name(self):
return self.name
-class SubprojectHolder(InterpreterObject):
+class SubprojectHolder(InterpreterObject, ObjectHolder):
def __init__(self, subinterpreter):
- super().__init__()
- self.held_object = subinterpreter
+ InterpreterObject.__init__(self)
+ ObjectHolder.__init__(self, subinterpreter)
self.methods.update({'get_variable': self.get_variable_method,
})
@@ -1056,11 +1065,11 @@ ModuleState = namedtuple('ModuleState', [
'man', 'global_args', 'project_args', 'build_machine', 'host_machine',
'target_machine'])
-class ModuleHolder(InterpreterObject):
+class ModuleHolder(InterpreterObject, ObjectHolder):
def __init__(self, modname, module, interpreter):
InterpreterObject.__init__(self)
+ ObjectHolder.__init__(self, module)
self.modname = modname
- self.held_object = module
self.interpreter = interpreter
def method_call(self, method_name, args, kwargs):
@@ -1551,12 +1560,11 @@ class Interpreter(InterpreterBase):
version = kwargs.get('version', self.project_version)
if not isinstance(version, str):
raise InterpreterException('Version must be a string.')
- incs = extract_as_list(kwargs, 'include_directories')
- libs = extract_as_list(kwargs, 'link_with')
+ incs = extract_as_list(kwargs, 'include_directories', unholder=True)
+ libs = extract_as_list(kwargs, 'link_with', unholder=True)
sources = extract_as_list(kwargs, 'sources')
- sources = self.source_strings_to_files(self.flatten(sources))
- deps = self.flatten(kwargs.get('dependencies', []))
- deps = listify(deps)
+ sources = listify(self.source_strings_to_files(sources), unholder=True)
+ deps = extract_as_list(kwargs, 'dependencies', unholder=True)
compile_args = mesonlib.stringlistify(kwargs.get('compile_args', []))
link_args = mesonlib.stringlistify(kwargs.get('link_args', []))
final_deps = []
@@ -1568,13 +1576,8 @@ class Interpreter(InterpreterBase):
if not isinstance(d, (dependencies.Dependency, dependencies.ExternalLibrary, dependencies.InternalDependency)):
raise InterpreterException('Dependencies must be external deps')
final_deps.append(d)
- dep = dependencies.InternalDependency(version,
- mesonlib.unholder_array(incs),
- compile_args,
- link_args,
- mesonlib.unholder_array(libs),
- mesonlib.unholder_array(sources),
- final_deps)
+ dep = dependencies.InternalDependency(version, incs, compile_args,
+ link_args, libs, sources, final_deps)
return DependencyHolder(dep)
@noKwargs
@@ -1629,7 +1632,7 @@ class Interpreter(InterpreterBase):
'or not executable'.format(cmd))
cmd = prog
expanded_args = []
- for a in mesonlib.flatten(cargs):
+ for a in listify(cargs):
if isinstance(a, str):
expanded_args.append(a)
elif isinstance(a, mesonlib.File):
@@ -2299,11 +2302,7 @@ to directly access options of other subprojects.''')
raise InterpreterException('Run_target needs at least one positional argument.')
cleaned_args = []
- for i in mesonlib.flatten(all_args):
- try:
- i = i.held_object
- except AttributeError:
- pass
+ for i in listify(all_args, unholder=True):
if not isinstance(i, (str, build.BuildTarget, build.CustomTarget, dependencies.ExternalProgram, mesonlib.File)):
mlog.debug('Wrong type:', str(i))
raise InterpreterException('Invalid argument to run_target.')
@@ -2374,11 +2373,10 @@ to directly access options of other subprojects.''')
par = kwargs.get('is_parallel', True)
if not isinstance(par, bool):
raise InterpreterException('Keyword argument is_parallel must be a boolean.')
- cmd_args = extract_as_list(kwargs, 'args')
+ cmd_args = extract_as_list(kwargs, 'args', unholder=True)
for i in cmd_args:
- if not isinstance(i, (str, mesonlib.File, TargetHolder)):
+ if not isinstance(i, (str, mesonlib.File, build.Target)):
raise InterpreterException('Command line arguments must be strings, files or targets.')
- cmd_args = mesonlib.unholder_array(cmd_args)
env = self.unpack_env_kwarg(kwargs)
should_fail = kwargs.get('should_fail', False)
if not isinstance(should_fail, bool):
@@ -2796,7 +2794,8 @@ different subdirectory.
elif isinstance(s, str):
s = mesonlib.File.from_source_file(self.environment.source_dir, self.subdir, s)
else:
- raise InterpreterException("Source item is not string or File-type object.")
+ raise InterpreterException('Source item is {!r} instead of '
+ 'string or File-type object'.format(s))
results.append(s)
return results
@@ -2822,7 +2821,7 @@ different subdirectory.
if not args:
raise InterpreterException('Target does not have a name.')
name = args[0]
- sources = args[1:]
+ sources = listify(args[1:])
if self.environment.is_cross_build():
if kwargs.get('native', False):
is_cross = False
@@ -2830,19 +2829,14 @@ different subdirectory.
is_cross = True
else:
is_cross = False
- try:
- kw_src = self.flatten(kwargs['sources'])
- kw_src = listify(kw_src)
- except KeyError:
- kw_src = []
- sources += kw_src
+ if 'sources' in kwargs:
+ sources += listify(kwargs['sources'])
sources = self.source_strings_to_files(sources)
- objs = self.flatten(kwargs.get('objects', []))
- kwargs['dependencies'] = self.flatten(kwargs.get('dependencies', []))
+ objs = extract_as_list(kwargs, 'objects')
+ kwargs['dependencies'] = extract_as_list(kwargs, 'dependencies')
if 'extra_files' in kwargs:
ef = extract_as_list(kwargs, 'extra_files')
kwargs['extra_files'] = self.source_strings_to_files(ef)
- objs = listify(objs)
self.check_sources_exist(os.path.join(self.source_root, self.subdir), sources)
if targetholder is ExecutableHolder:
targetclass = build.Executable
diff --git a/mesonbuild/mesonlib.py b/mesonbuild/mesonlib.py
index 71134a8..5c4c374 100644
--- a/mesonbuild/mesonlib.py
+++ b/mesonbuild/mesonlib.py
@@ -199,17 +199,6 @@ def classify_unity_sources(compilers, sources):
compsrclist[comp].append(src)
return compsrclist
-def flatten(item):
- if not isinstance(item, list):
- return [item]
- result = []
- for i in item:
- if isinstance(i, list):
- result += flatten(i)
- else:
- result.append(i)
- return result
-
def is_osx():
return platform.system().lower() == 'darwin'
@@ -474,24 +463,45 @@ def replace_if_different(dst, dst_tmp):
else:
os.unlink(dst_tmp)
-
-def listify(*args):
+def listify(item, flatten=True, unholder=False):
'''
- Returns a list with all args embedded in a list if they are not of type list.
+ Returns a list with all args embedded in a list if they are not a list.
This function preserves order.
+ @flatten: Convert lists of lists to a flat list
+ @unholder: Replace each item with the object it holds, if required
+
+ Note: unholding only works recursively when flattening
'''
- if len(args) == 1: # Special case with one single arg
- return args[0] if type(args[0]) is list else [args[0]]
- return [item if type(item) is list else [item] for item in args]
+ if not isinstance(item, list):
+ if unholder and hasattr(item, 'held_object'):
+ item = item.held_object
+ return [item]
+ result = []
+ for i in item:
+ if unholder and hasattr(i, 'held_object'):
+ i = i.held_object
+ if flatten and isinstance(i, list):
+ result += listify(i, flatten=True, unholder=unholder)
+ else:
+ result.append(i)
+ return result
-def extract_as_list(dict_object, *keys, pop = False):
+def extract_as_list(dict_object, *keys, pop=False, **kwargs):
'''
Extracts all values from given dict_object and listifies them.
'''
+ result = []
+ fetch = dict_object.get
if pop:
- return listify(*[dict_object.pop(key, []) for key in keys])
- return listify(*[dict_object.get(key, []) for key in keys])
+ fetch = dict_object.pop
+ # If there's only one key, we don't return a list with one element
+ if len(keys) == 1:
+ return listify(fetch(keys[0], []), **kwargs)
+ # Return a list of values corresponding to *keys
+ for key in keys:
+ result.append(listify(fetch(key, []), **kwargs))
+ return result
def typeslistify(item, types):
@@ -750,15 +760,6 @@ def windows_proof_rmtree(f):
# Try one last time and throw if it fails.
shutil.rmtree(f)
-def unholder_array(entries):
- result = []
- entries = flatten(entries)
- for e in entries:
- if hasattr(e, 'held_object'):
- e = e.held_object
- result.append(e)
- return result
-
class OrderedSet(collections.MutableSet):
"""A set that preserves the order in which items are added, by first
insertion.
diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py
index fa2bbb4..1f813da 100644
--- a/mesonbuild/modules/gnome.py
+++ b/mesonbuild/modules/gnome.py
@@ -20,7 +20,7 @@ import os
import copy
import subprocess
from . import ModuleReturnValue
-from ..mesonlib import MesonException, OrderedSet, Popen_safe
+from ..mesonlib import MesonException, OrderedSet, Popen_safe, extract_as_list
from ..dependencies import Dependency, PkgConfigDependency, InternalDependency
from .. import mlog
from .. import mesonlib
@@ -323,11 +323,9 @@ class GnomeModule(ExtensionModule):
cflags = OrderedSet()
ldflags = OrderedSet()
gi_includes = OrderedSet()
- deps = mesonlib.listify(deps)
+ deps = mesonlib.listify(deps, unholder=True)
for dep in deps:
- if hasattr(dep, 'held_object'):
- dep = dep.held_object
if isinstance(dep, InternalDependency):
cflags.update(get_include_args(dep.include_directories))
for lib in dep.libraries:
@@ -378,7 +376,7 @@ class GnomeModule(ExtensionModule):
elif isinstance(dep, (build.StaticLibrary, build.SharedLibrary)):
cflags.update(get_include_args(dep.get_include_dirs()))
else:
- mlog.log('dependency %s not handled to build gir files' % dep)
+ mlog.log('dependency {!r} not handled to build gir files'.format(dep))
continue
if gir_has_extra_lib_arg() and use_gir_args:
@@ -417,7 +415,7 @@ class GnomeModule(ExtensionModule):
raise MesonException('gobject-introspection dependency was not found, gir cannot be generated.')
ns = kwargs.pop('namespace')
nsversion = kwargs.pop('nsversion')
- libsources = mesonlib.flatten(kwargs.pop('sources'))
+ libsources = mesonlib.extract_as_list(kwargs, 'sources', pop=True)
girfile = '%s-%s.gir' % (ns, nsversion)
srcdir = os.path.join(state.environment.get_source_dir(), state.subdir)
builddir = os.path.join(state.environment.get_build_dir(), state.subdir)
@@ -531,9 +529,8 @@ class GnomeModule(ExtensionModule):
else:
raise MesonException('Gir export packages must be str or list')
- deps = mesonlib.extract_as_list(kwargs, 'dependencies', pop = True)
deps = (girtarget.get_all_link_deps() + girtarget.get_external_deps() +
- deps)
+ extract_as_list(kwargs, 'dependencies', pop=True, unholder=True))
# Need to recursively add deps on GirTarget sources from our
# dependencies and also find the include directories needed for the
# typelib generation custom target below.
@@ -800,7 +797,8 @@ This will become a hard error in the future.''')
def _get_build_args(self, kwargs, state):
args = []
- cflags, ldflags, gi_includes = self._get_dependencies_flags(kwargs.get('dependencies', []), state, include_rpath=True)
+ deps = extract_as_list(kwargs, 'dependencies', unholder=True)
+ cflags, ldflags, gi_includes = self._get_dependencies_flags(deps, state, include_rpath=True)
inc_dirs = mesonlib.extract_as_list(kwargs, 'include_directories')
for incd in inc_dirs:
if not isinstance(incd.held_object, (str, build.IncludeDirs)):
diff --git a/run_unittests.py b/run_unittests.py
index b217714..7ae9947 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -31,6 +31,7 @@ import mesonbuild.compilers
import mesonbuild.environment
import mesonbuild.mesonlib
import mesonbuild.coredata
+from mesonbuild.interpreter import ObjectHolder
from mesonbuild.mesonlib import is_linux, is_windows, is_osx, is_cygwin, windows_proof_rmtree
from mesonbuild.environment import Environment
from mesonbuild.dependencies import DependencyException
@@ -62,7 +63,6 @@ def get_soname(fname):
def get_rpath(fname):
return get_dynamic_section_entry(fname, r'(?:rpath|runpath)')
-
class InternalTests(unittest.TestCase):
def test_version_number(self):
@@ -398,6 +398,49 @@ class InternalTests(unittest.TestCase):
self.assertEqual(forced_value, desired_value)
+ def test_listify(self):
+ listify = mesonbuild.mesonlib.listify
+ # Test sanity
+ self.assertEqual([1], listify(1))
+ self.assertEqual([], listify([]))
+ self.assertEqual([1], listify([1]))
+ # Test flattening
+ self.assertEqual([1, 2, 3], listify([1, [2, 3]]))
+ self.assertEqual([1, 2, 3], listify([1, [2, [3]]]))
+ self.assertEqual([1, [2, [3]]], listify([1, [2, [3]]], flatten=False))
+ # Test flattening and unholdering
+ holder1 = ObjectHolder(1)
+ holder3 = ObjectHolder(3)
+ self.assertEqual([holder1], listify(holder1))
+ self.assertEqual([holder1], listify([holder1]))
+ self.assertEqual([holder1, 2], listify([holder1, 2]))
+ self.assertEqual([holder1, 2, 3], listify([holder1, 2, [3]]))
+ self.assertEqual([1], listify(holder1, unholder=True))
+ self.assertEqual([1], listify([holder1], unholder=True))
+ self.assertEqual([1, 2], listify([holder1, 2], unholder=True))
+ self.assertEqual([1, 2, 3], listify([holder1, 2, [holder3]], unholder=True))
+ # Unholding doesn't work recursively when not flattening
+ self.assertEqual([1, [2], [holder3]], listify([holder1, [2], [holder3]], unholder=True, flatten=False))
+
+ def test_extract_as_list(self):
+ extract = mesonbuild.mesonlib.extract_as_list
+ # Test sanity
+ kwargs = {'sources': [1, 2, 3]}
+ self.assertEqual([1, 2, 3], extract(kwargs, 'sources'))
+ self.assertEqual(kwargs, {'sources': [1, 2, 3]})
+ self.assertEqual([1, 2, 3], extract(kwargs, 'sources', pop=True))
+ self.assertEqual(kwargs, {})
+ # Test unholding
+ holder3 = ObjectHolder(3)
+ kwargs = {'sources': [1, 2, holder3]}
+ self.assertEqual([1, 2, 3], extract(kwargs, 'sources', unholder=True))
+ self.assertEqual(kwargs, {'sources': [1, 2, holder3]})
+ self.assertEqual([1, 2, 3], extract(kwargs, 'sources', unholder=True, pop=True))
+ self.assertEqual(kwargs, {})
+ # Test listification
+ kwargs = {'sources': [1, 2, 3], 'pch_sources': [4, 5, 6]}
+ self.assertEqual([[1, 2, 3], [4, 5, 6]], extract(kwargs, 'sources', 'pch_sources'))
+
class BasePlatformTests(unittest.TestCase):
def setUp(self):
diff --git a/test cases/frameworks/7 gnome/gir/meson.build b/test cases/frameworks/7 gnome/gir/meson.build
index 3598b66..a91cb97 100644
--- a/test cases/frameworks/7 gnome/gir/meson.build
+++ b/test cases/frameworks/7 gnome/gir/meson.build
@@ -27,7 +27,7 @@ gnome.generate_gir(
identifier_prefix : 'Meson',
includes : ['GObject-2.0', 'MesonDep1-1.0'],
# dep1_dep pulls in dep2_dep for us
- dependencies : [fake_dep, dep1_dep],
+ dependencies : [[fake_dep, dep1_dep]],
install : true,
build_by_default : true,
# Test that unknown kwargs do not crash the parser.