Merge pull request #1278 from mesonbuild/newmodules

Bring some order to modules
pull/1295/merge
Jussi Pakkanen 8 years ago committed by GitHub
commit 9cf0991a1d
  1. 76
      mesonbuild/interpreter.py
  2. 5
      mesonbuild/modules/__init__.py
  3. 40
      mesonbuild/modules/gnome.py
  4. 7
      mesonbuild/modules/i18n.py
  5. 4
      mesonbuild/modules/modtest.py
  6. 5
      mesonbuild/modules/pkgconfig.py
  7. 3
      mesonbuild/modules/qt4.py
  8. 3
      mesonbuild/modules/qt5.py
  9. 2
      mesonbuild/modules/rpm.py
  10. 4
      mesonbuild/modules/windows.py
  11. 11
      test cases/frameworks/7 gnome/gdbus/meson.build

@ -28,6 +28,7 @@ from .interpreterbase import InterpreterBase
from .interpreterbase import check_stringlist, noPosargs, noKwargs, stringArgs from .interpreterbase import check_stringlist, noPosargs, noKwargs, stringArgs
from .interpreterbase import InterpreterException, InvalidArguments, InvalidCode from .interpreterbase import InterpreterException, InvalidArguments, InvalidCode
from .interpreterbase import InterpreterObject, MutableInterpreterObject from .interpreterbase import InterpreterObject, MutableInterpreterObject
from .modules import ModuleReturnValue
import os, sys, shutil, uuid import os, sys, shutil, uuid
import re import re
@ -430,11 +431,9 @@ class Headers(InterpreterObject):
return self.custom_install_dir return self.custom_install_dir
class DataHolder(InterpreterObject): class DataHolder(InterpreterObject):
def __init__(self, sources, install_dir): def __init__(self, data):
super().__init__() super().__init__()
if not isinstance(install_dir, str): self.held_object = data
raise InterpreterException('Custom_install_dir must be a string.')
self.held_object = build.Data(sources, install_dir)
def get_source_subdir(self): def get_source_subdir(self):
return self.held_object.source_subdir return self.held_object.source_subdir
@ -984,6 +983,9 @@ class ModuleHolder(InterpreterObject):
raise InvalidArguments('Module %s does not have method %s.' % (self.modname, method_name)) raise InvalidArguments('Module %s does not have method %s.' % (self.modname, method_name))
if method_name.startswith('_'): if method_name.startswith('_'):
raise InvalidArguments('Function {!r} in module {!r} is private.'.format(method_name, self.modname)) raise InvalidArguments('Function {!r} in module {!r} is private.'.format(method_name, self.modname))
# This is not 100% reliable but we can't use hash()
# because the Build object contains dicts and lists.
num_targets = len(self.interpreter.build.targets)
state = ModuleState() state = ModuleState()
state.build_to_src = os.path.relpath(self.interpreter.environment.get_source_dir(), state.build_to_src = os.path.relpath(self.interpreter.environment.get_source_dir(),
self.interpreter.environment.get_build_dir()) self.interpreter.environment.get_build_dir())
@ -999,6 +1001,8 @@ class ModuleHolder(InterpreterObject):
state.global_args = self.interpreter.build.global_args state.global_args = self.interpreter.build.global_args
state.project_args = self.interpreter.build.projects_args.get(self.interpreter.subproject, {}) state.project_args = self.interpreter.build.projects_args.get(self.interpreter.subproject, {})
value = fn(state, args, kwargs) value = fn(state, args, kwargs)
if num_targets != len(self.interpreter.build.targets):
raise InterpreterException('Extension module altered internal state illegally.')
return self.interpreter.module_method_callback(value) return self.interpreter.module_method_callback(value)
class MesonMain(InterpreterObject): class MesonMain(InterpreterObject):
@ -1238,29 +1242,39 @@ class Interpreter(InterpreterBase):
'join_paths': self.func_join_paths, 'join_paths': self.func_join_paths,
}) })
def module_method_callback(self, invalues): def holderify(self, item):
unwrap_single = False if isinstance(item, list):
if invalues is None: return [self.holderify(x) for x in item]
return if isinstance(item, build.CustomTarget):
return CustomTargetHolder(item, self)
elif isinstance(item, (int, str)) or item is None:
return item
elif isinstance(item, build.Executable):
return ExecutableHolder(item, self)
elif isinstance(item, build.GeneratedList):
return GeneratedListHolder(item)
elif isinstance(item, build.RunTarget):
raise RuntimeError('This is not a pipe.')
elif isinstance(item, build.RunScript):
raise RuntimeError('Do not do this.')
elif isinstance(item, build.Data):
return DataHolder(item)
elif isinstance(item, dependencies.InternalDependency):
return InternalDependencyHolder(item)
else:
print(item)
raise InterpreterException('Module returned a value of unknown type.')
def process_new_values(self, invalues):
if not isinstance(invalues, list): if not isinstance(invalues, list):
unwrap_single = True
invalues = [invalues] invalues = [invalues]
outvalues = []
for v in invalues: for v in invalues:
if isinstance(v, build.CustomTarget): if isinstance(v, (build.BuildTarget, build.CustomTarget, build.RunTarget)):
self.add_target(v.name, v) self.add_target(v.name, v)
outvalues.append(CustomTargetHolder(v, self))
elif isinstance(v, (int, str)):
outvalues.append(v)
elif isinstance(v, build.Executable):
self.add_target(v.name, v)
outvalues.append(ExecutableHolder(v, self))
elif isinstance(v, list): elif isinstance(v, list):
outvalues.append(self.module_method_callback(v)) self.module_method_callback(v)
elif isinstance(v, build.GeneratedList): elif isinstance(v, build.GeneratedList):
outvalues.append(GeneratedListHolder(v)) pass
elif isinstance(v, build.RunTarget):
self.add_target(v.name, v)
elif isinstance(v, build.RunScript): elif isinstance(v, build.RunScript):
self.build.install_scripts.append(v) self.build.install_scripts.append(v)
elif isinstance(v, build.Data): elif isinstance(v, build.Data):
@ -1268,14 +1282,18 @@ class Interpreter(InterpreterBase):
elif isinstance(v, dependencies.InternalDependency): elif isinstance(v, dependencies.InternalDependency):
# FIXME: This is special cased and not ideal: # FIXME: This is special cased and not ideal:
# The first source is our new VapiTarget, the rest are deps # The first source is our new VapiTarget, the rest are deps
self.module_method_callback(v.sources[0]) self.process_new_values(v.sources[0])
outvalues.append(InternalDependencyHolder(v))
else: else:
print(v)
raise InterpreterException('Module returned a value of unknown type.') raise InterpreterException('Module returned a value of unknown type.')
if len(outvalues) == 1 and unwrap_single:
return outvalues[0] def module_method_callback(self, return_object):
return outvalues if not isinstance(return_object, ModuleReturnValue):
print(return_object)
assert(False)
raise InterpreterException('Bug in module, it returned an invalid object')
invalues = return_object.new_objects
self.process_new_values(invalues)
return self.holderify(return_object.return_value)
def get_build_def_files(self): def get_build_def_files(self):
return self.build_def_files return self.build_def_files
@ -2113,7 +2131,7 @@ requirements use the version keyword argument instead.''')
source_strings.append(s) source_strings.append(s)
sources += self.source_strings_to_files(source_strings) sources += self.source_strings_to_files(source_strings)
install_dir = kwargs.get('install_dir', None) install_dir = kwargs.get('install_dir', None)
data = DataHolder(sources, install_dir) data = DataHolder(build.Data(sources, install_dir))
self.build.data.append(data.held_object) self.build.data.append(data.held_object)
return data return data
@ -2173,7 +2191,7 @@ requirements use the version keyword argument instead.''')
idir = kwargs.get('install_dir', None) idir = kwargs.get('install_dir', None)
if isinstance(idir, str): if isinstance(idir, str):
cfile = mesonlib.File.from_built_file(ofile_path, ofile_fname) cfile = mesonlib.File.from_built_file(ofile_path, ofile_fname)
self.build.data.append(DataHolder([cfile], idir).held_object) self.build.data.append(build.Data([cfile], idir))
return mesonlib.File.from_built_file(self.subdir, output) return mesonlib.File.from_built_file(self.subdir, output)
@stringArgs @stringArgs

@ -45,6 +45,11 @@ def get_include_args(environment, include_dirs, prefix='-I'):
return dirs_str return dirs_str
class ModuleReturnValue:
def __init__(self, return_value, new_objects):
self.return_value = return_value
assert(isinstance(new_objects, list))
self.new_objects = new_objects
class GResourceTarget(build.CustomTarget): class GResourceTarget(build.CustomTarget):
def __init__(self, name, subdir, kwargs): def __init__(self, name, subdir, kwargs):

@ -20,6 +20,7 @@ import os
import sys import sys
import copy import copy
import subprocess import subprocess
from . import ModuleReturnValue
from ..mesonlib import MesonException, Popen_safe from ..mesonlib import MesonException, Popen_safe
from ..dependencies import Dependency, PkgConfigDependency, InternalDependency from ..dependencies import Dependency, PkgConfigDependency, InternalDependency
from .. import mlog from .. import mlog
@ -163,7 +164,7 @@ can not be used with the current version of glib-compiled-resources, due to
target_c = GResourceTarget(name, state.subdir, kwargs) target_c = GResourceTarget(name, state.subdir, kwargs)
if gresource: # Only one target for .gresource files if gresource: # Only one target for .gresource files
return [target_c] return ModuleReturnValue(target_c, [target_c])
h_kwargs = { h_kwargs = {
'command': cmd, 'command': cmd,
@ -177,7 +178,8 @@ can not be used with the current version of glib-compiled-resources, due to
h_kwargs['install_dir'] = kwargs.get('install_dir', h_kwargs['install_dir'] = kwargs.get('install_dir',
state.environment.coredata.get_builtin_option('includedir')) state.environment.coredata.get_builtin_option('includedir'))
target_h = GResourceHeaderTarget(args[0] + '_h', state.subdir, h_kwargs) target_h = GResourceHeaderTarget(args[0] + '_h', state.subdir, h_kwargs)
return [target_c, target_h] rv = [target_c, target_h]
return ModuleReturnValue(rv, rv)
def _get_gresource_dependencies(self, state, input_file, source_dirs, dependencies): def _get_gresource_dependencies(self, state, input_file, source_dirs, dependencies):
for dep in dependencies: for dep in dependencies:
@ -352,7 +354,7 @@ can not be used with the current version of glib-compiled-resources, due to
if not girwarning_printed: if not girwarning_printed:
mlog.warning('gobject-introspection dependency was not found, disabling gir generation.') mlog.warning('gobject-introspection dependency was not found, disabling gir generation.')
girwarning_printed = True girwarning_printed = True
return [] return ModuleReturnValue(None, [])
ns = kwargs.pop('namespace') ns = kwargs.pop('namespace')
nsversion = kwargs.pop('nsversion') nsversion = kwargs.pop('nsversion')
libsources = kwargs.pop('sources') libsources = kwargs.pop('sources')
@ -529,7 +531,8 @@ can not be used with the current version of glib-compiled-resources, due to
typelib_kwargs['install_dir'] = kwargs.get('install_dir_typelib', typelib_kwargs['install_dir'] = kwargs.get('install_dir_typelib',
os.path.join(state.environment.get_libdir(), 'girepository-1.0')) os.path.join(state.environment.get_libdir(), 'girepository-1.0'))
typelib_target = TypelibTarget(typelib_output, state.subdir, typelib_kwargs) typelib_target = TypelibTarget(typelib_output, state.subdir, typelib_kwargs)
return [scan_target, typelib_target] rv = [scan_target, typelib_target]
return ModuleReturnValue(rv, rv)
def compile_schemas(self, state, args, kwargs): def compile_schemas(self, state, args, kwargs):
if len(args) != 0: if len(args) != 0:
@ -547,7 +550,7 @@ can not be used with the current version of glib-compiled-resources, due to
else: else:
targetname = 'gsettings-compile-' + state.subdir targetname = 'gsettings-compile-' + state.subdir
target_g = build.CustomTarget(targetname, state.subdir, kwargs) target_g = build.CustomTarget(targetname, state.subdir, kwargs)
return target_g return ModuleReturnValue(target_g, [target_g])
def yelp(self, state, args, kwargs): def yelp(self, state, args, kwargs):
if len(args) < 1: if len(args) < 1:
@ -603,7 +606,8 @@ can not be used with the current version of glib-compiled-resources, due to
potarget = build.RunTarget('help-' + project_id + '-update-po', sys.executable, potarget = build.RunTarget('help-' + project_id + '-update-po', sys.executable,
poargs, [], state.subdir) poargs, [], state.subdir)
return [inscript, pottarget, potarget] rv = [inscript, pottarget, potarget]
return ModuleReturnValue(None, rv)
def gtkdoc(self, state, args, kwargs): def gtkdoc(self, state, args, kwargs):
if len(args) != 1: if len(args) != 1:
@ -671,7 +675,7 @@ can not be used with the current version of glib-compiled-resources, due to
res = [build.RunTarget(targetname, command[0], command[1:] + args, [], state.subdir)] res = [build.RunTarget(targetname, command[0], command[1:] + args, [], state.subdir)]
if kwargs.get('install', True): if kwargs.get('install', True):
res.append(build.RunScript(command, args)) res.append(build.RunScript(command, args))
return res return ModuleReturnValue(None, res)
def _get_build_args(self, kwargs, state): def _get_build_args(self, kwargs, state):
args = [] args = []
@ -701,7 +705,7 @@ can not be used with the current version of glib-compiled-resources, due to
modulename = args[0] modulename = args[0]
if not isinstance(modulename, str): if not isinstance(modulename, str):
raise MesonException('Argument must be a string') raise MesonException('Argument must be a string')
return os.path.join('share/gtkdoc/html', modulename) return ModuleReturnValue(os.path.join('share/gtkdoc/html', modulename), [])
@staticmethod @staticmethod
def _unpack_args(arg, kwarg_name, kwargs, expend_file_state=None): def _unpack_args(arg, kwarg_name, kwargs, expend_file_state=None):
@ -741,7 +745,8 @@ can not be used with the current version of glib-compiled-resources, due to
'output': outputs, 'output': outputs,
'command': cmd 'command': cmd
} }
return build.CustomTarget(target_name, state.subdir, custom_kwargs) ct = build.CustomTarget(target_name, state.subdir, custom_kwargs)
return ModuleReturnValue(ct, [ct])
def mkenums(self, state, args, kwargs): def mkenums(self, state, args, kwargs):
if len(args) != 1: if len(args) != 1:
@ -836,11 +841,11 @@ can not be used with the current version of glib-compiled-resources, due to
state.environment.coredata.get_builtin_option('includedir') state.environment.coredata.get_builtin_option('includedir')
target = self._make_mkenum_custom_target(state, sources, basename, target = self._make_mkenum_custom_target(state, sources, basename,
generic_cmd, custom_kwargs) generic_cmd, custom_kwargs)
return target return ModuleReturnValue(target, [target])
elif len(targets) == 1: elif len(targets) == 1:
return targets[0] return ModuleReturnValue(targets[0], [targets[0]])
else: else:
return targets return ModuleReturnValue(targets, targets)
@staticmethod @staticmethod
def _make_mkenum_custom_target(state, sources, output, cmd, kwargs): def _make_mkenum_custom_target(state, sources, output, cmd, kwargs):
@ -907,7 +912,8 @@ can not be used with the current version of glib-compiled-resources, due to
custom_kwargs['output'] = output + '.h' custom_kwargs['output'] = output + '.h'
header = build.CustomTarget(output + '_h', state.subdir, custom_kwargs) header = build.CustomTarget(output + '_h', state.subdir, custom_kwargs)
return [body, header] rv = [body, header]
return ModuleReturnValue(rv, rv)
@staticmethod @staticmethod
def _vapi_args_to_command(prefix, variable, kwargs, accept_vapi=False): def _vapi_args_to_command(prefix, variable, kwargs, accept_vapi=False):
@ -991,6 +997,7 @@ can not be used with the current version of glib-compiled-resources, due to
if not isinstance(args[0], str): if not isinstance(args[0], str):
raise MesonException('The first argument must be the name of the library') raise MesonException('The first argument must be the name of the library')
created_values = []
library = args[0] library = args[0]
build_dir = os.path.join(state.environment.get_build_dir(), state.subdir) build_dir = os.path.join(state.environment.get_build_dir(), state.subdir)
@ -1040,8 +1047,7 @@ can not be used with the current version of glib-compiled-resources, due to
# We shouldn't need this locally but we install it # We shouldn't need this locally but we install it
deps_target = self._generate_deps(state, library, vapi_packages, install_dir) deps_target = self._generate_deps(state, library, vapi_packages, install_dir)
# XXX WRONG, state objects must not be modified! Fix this! created_values.append(deps_target)
state.data.append(deps_target)
vapi_target = VapiTarget(vapi_output, state.subdir, custom_kwargs) vapi_target = VapiTarget(vapi_output, state.subdir, custom_kwargs)
# So to try our best to get this to just work we need: # So to try our best to get this to just work we need:
@ -1050,7 +1056,9 @@ can not be used with the current version of glib-compiled-resources, due to
# - add relevant directories to include dirs # - add relevant directories to include dirs
incs = [build.IncludeDirs(state.subdir, ['.'] + vapi_includes, False)] incs = [build.IncludeDirs(state.subdir, ['.'] + vapi_includes, False)]
sources = [vapi_target] + vapi_depends sources = [vapi_target] + vapi_depends
return InternalDependency(None, incs, [], [], link_with, sources, []) rv = InternalDependency(None, incs, [], [], link_with, sources, [])
created_values.append(rv)
return ModuleReturnValue(rv, created_values)
def initialize(): def initialize():
return GnomeModule() return GnomeModule()

@ -15,6 +15,8 @@
from os import path from os import path
from .. import coredata, mesonlib, build from .. import coredata, mesonlib, build
from ..mesonlib import MesonException from ..mesonlib import MesonException
from . import ModuleReturnValue
import sys import sys
import shutil import shutil
@ -59,7 +61,8 @@ class I18nModule:
kwargs['command'] = ['msgfmt', '--' + file_type, kwargs['command'] = ['msgfmt', '--' + file_type,
'--template', '@INPUT@', '-d', podir, '-o', '@OUTPUT@'] '--template', '@INPUT@', '-d', podir, '-o', '@OUTPUT@']
return build.CustomTarget(kwargs['output'] + '_merge', state.subdir, kwargs) ct = build.CustomTarget(kwargs['output'] + '_merge', state.subdir, kwargs)
return ModuleReturnValue(ct, [ct])
def gettext(self, state, args, kwargs): def gettext(self, state, args, kwargs):
if len(args) != 1: if len(args) != 1:
@ -114,7 +117,7 @@ class I18nModule:
args.append(lang_arg) args.append(lang_arg)
iscript = build.RunScript(script, args) iscript = build.RunScript(script, args)
return [pottarget, gmotarget, iscript, updatepotarget] return ModuleReturnValue(None, [pottarget, gmotarget, iscript, updatepotarget])
def initialize(): def initialize():
return I18nModule() return I18nModule()

@ -12,10 +12,14 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
from . import ModuleReturnValue
class TestModule: class TestModule:
def print_hello(self, state, args, kwargs): def print_hello(self, state, args, kwargs):
print('Hello from a Meson module') print('Hello from a Meson module')
rv = ModuleReturnValue(None, [])
return rv
def initialize(): def initialize():
return TestModule() return TestModule()

@ -15,6 +15,8 @@
from .. import build from .. import build
from .. import mesonlib from .. import mesonlib
from .. import mlog from .. import mlog
from . import ModuleReturnValue
import os import os
class PkgConfigModule: class PkgConfigModule:
@ -138,7 +140,8 @@ class PkgConfigModule:
self.generate_pkgconfig_file(state, libs, subdirs, name, description, url, self.generate_pkgconfig_file(state, libs, subdirs, name, description, url,
version, pcfile, pub_reqs, priv_reqs, version, pcfile, pub_reqs, priv_reqs,
conflicts, priv_libs) conflicts, priv_libs)
return build.Data(mesonlib.File(True, state.environment.get_scratch_dir(), pcfile), pkgroot) res = build.Data(mesonlib.File(True, state.environment.get_scratch_dir(), pcfile), pkgroot)
return ModuleReturnValue(res, [res])
def initialize(): def initialize():
return PkgConfigModule() return PkgConfigModule()

@ -18,6 +18,7 @@ from .. import build
from ..mesonlib import MesonException, Popen_safe from ..mesonlib import MesonException, Popen_safe
from ..dependencies import Qt4Dependency from ..dependencies import Qt4Dependency
import xml.etree.ElementTree as ET import xml.etree.ElementTree as ET
from . import ModuleReturnValue
class Qt4Module(): class Qt4Module():
tools_detected = False tools_detected = False
@ -153,7 +154,7 @@ class Qt4Module():
moc_gen = build.Generator([self.moc], moc_kwargs) moc_gen = build.Generator([self.moc], moc_kwargs)
moc_output = moc_gen.process_files('Qt4 moc source', moc_sources, state) moc_output = moc_gen.process_files('Qt4 moc source', moc_sources, state)
sources.append(moc_output) sources.append(moc_output)
return sources return ModuleReturnValue(sources, sources)
def initialize(): def initialize():
mlog.warning('rcc dependencies will not work properly until this upstream issue is fixed:', mlog.warning('rcc dependencies will not work properly until this upstream issue is fixed:',

@ -18,6 +18,7 @@ from .. import build
from ..mesonlib import MesonException, Popen_safe from ..mesonlib import MesonException, Popen_safe
from ..dependencies import Qt5Dependency from ..dependencies import Qt5Dependency
import xml.etree.ElementTree as ET import xml.etree.ElementTree as ET
from . import ModuleReturnValue
class Qt5Module(): class Qt5Module():
tools_detected = False tools_detected = False
@ -159,7 +160,7 @@ class Qt5Module():
moc_gen = build.Generator([self.moc], moc_kwargs) moc_gen = build.Generator([self.moc], moc_kwargs)
moc_output = moc_gen.process_files('Qt5 moc source', moc_sources, state) moc_output = moc_gen.process_files('Qt5 moc source', moc_sources, state)
sources.append(moc_output) sources.append(moc_output)
return sources return ModuleReturnValue(sources, sources)
def initialize(): def initialize():
mlog.warning('rcc dependencies will not work reliably until this upstream issue is fixed:', mlog.warning('rcc dependencies will not work reliably until this upstream issue is fixed:',

@ -20,6 +20,7 @@ from .. import compilers
import datetime import datetime
from .. import mlog from .. import mlog
from . import GirTarget, TypelibTarget from . import GirTarget, TypelibTarget
from . import ModuleReturnValue
import os import os
@ -153,6 +154,7 @@ class RPMModule:
fn.write('- \n') fn.write('- \n')
fn.write('\n') fn.write('\n')
mlog.log('RPM spec template written to %s.spec.\n' % proj) mlog.log('RPM spec template written to %s.spec.\n' % proj)
return ModuleReturnValue(None, [])
def initialize(): def initialize():
return RPMModule() return RPMModule()

@ -15,6 +15,8 @@
from .. import mesonlib, dependencies, build from .. import mesonlib, dependencies, build
from ..mesonlib import MesonException from ..mesonlib import MesonException
from . import get_include_args from . import get_include_args
from . import ModuleReturnValue
import os import os
class WindowsModule: class WindowsModule:
@ -54,7 +56,7 @@ class WindowsModule:
'arguments': res_args} 'arguments': res_args}
res_gen = build.Generator([rescomp], res_kwargs) res_gen = build.Generator([rescomp], res_kwargs)
res_output = res_gen.process_files('Windows resource', args, state) res_output = res_gen.process_files('Windows resource', args, state)
return res_output return ModuleReturnValue(res_output, [res_output])
def initialize(): def initialize():
return WindowsModule() return WindowsModule()

@ -1,9 +1,10 @@
gdbus_src = gnome.gdbus_codegen('generated-gdbus', 'com.example.Sample.xml', gdbus_src = gnome.gdbus_codegen('generated-gdbus', 'com.example.Sample.xml',
interface_prefix : 'com.example.', interface_prefix : 'com.example.',
namespace : 'Sample') namespace : 'Sample')
gdbus_exe = executable('gdbus-test', 'gdbusprog.c', gdbus_exe = executable('gdbus-test', 'gdbusprog.c',
gdbus_src, gdbus_src,
include_directories : include_directories('..'), include_directories : include_directories('..'),
dependencies : giounix) dependencies : giounix)
test('gdbus', gdbus_exe) test('gdbus', gdbus_exe)

Loading…
Cancel
Save