Merge pull request #1194 from centricular/critical-bugfixes-vala

A bunch of bugfixes for Vala
pull/1191/merge
Jussi Pakkanen 8 years ago committed by GitHub
commit 21e475b64b
  1. 42
      mesonbuild/backend/backends.py
  2. 8
      mesonbuild/backend/ninjabackend.py
  3. 3
      mesonbuild/backend/vs2010backend.py
  4. 4
      mesonbuild/build.py
  5. 7
      mesonbuild/dependencies.py
  6. 34
      mesonbuild/modules/__init__.py
  7. 36
      mesonbuild/modules/gnome.py
  8. 2
      mesonbuild/modules/qt4.py
  9. 6
      mesonbuild/modules/rpm.py
  10. 3
      test cases/vala/14 target glib version and gresources/gres/meson.build
  11. 6
      test cases/vala/14 target glib version and gresources/gres/test-resources.xml
  12. 19
      test cases/vala/14 target glib version and gresources/gres/test.ui
  13. 12
      test cases/vala/14 target glib version and gresources/meson.build
  14. 37
      test cases/vala/14 target glib version and gresources/test.vala
  15. 13
      test cases/vala/15 static vapi in source tree/meson.build
  16. 6
      test cases/vala/15 static vapi in source tree/test.vala
  17. 4
      test cases/vala/15 static vapi in source tree/vapi/config.vapi
  18. 43
      test cases/vala/8 generated sources/dependency-generated/enum-types.c.template
  19. 26
      test cases/vala/8 generated sources/dependency-generated/enum-types.h.template
  20. 15
      test cases/vala/8 generated sources/dependency-generated/enums.h
  21. 3
      test cases/vala/8 generated sources/dependency-generated/lib.vala
  22. 3
      test cases/vala/8 generated sources/dependency-generated/main.vala
  23. 44
      test cases/vala/8 generated sources/dependency-generated/meson.build
  24. 1
      test cases/vala/8 generated sources/dependency-generated/null.c
  25. 1
      test cases/vala/8 generated sources/meson.build

@ -504,19 +504,13 @@ class Backend():
libs.append(os.path.join(self.get_target_dir(t), f)) libs.append(os.path.join(self.get_target_dir(t), f))
return libs return libs
def eval_custom_target_command(self, target, absolute_paths=False): def get_custom_target_sources(self, target):
if not absolute_paths: '''
ofilenames = [os.path.join(self.get_target_dir(target), i) for i in target.output] Custom target sources can be of various object types; strings, File,
else: BuildTarget, even other CustomTargets.
ofilenames = [os.path.join(self.environment.get_build_dir(), self.get_target_dir(target), i) \ Returns the path to them relative to the build root directory.
for i in target.output] '''
srcs = [] srcs = []
outdir = self.get_target_dir(target)
# Many external programs fail on empty arguments.
if outdir == '':
outdir = '.'
if absolute_paths:
outdir = os.path.join(self.environment.get_build_dir(), outdir)
for i in target.get_sources(): for i in target.get_sources():
if hasattr(i, 'held_object'): if hasattr(i, 'held_object'):
i = i.held_object i = i.held_object
@ -530,9 +524,25 @@ class Backend():
fname = [os.path.join(self.get_target_private_dir(target), p) for p in i.get_outputs()] fname = [os.path.join(self.get_target_private_dir(target), p) for p in i.get_outputs()]
else: else:
fname = [i.rel_to_builddir(self.build_to_src)] fname = [i.rel_to_builddir(self.build_to_src)]
if absolute_paths: if target.absolute_paths:
fname = [os.path.join(self.environment.get_build_dir(), f) for f in fname] fname = [os.path.join(self.environment.get_build_dir(), f) for f in fname]
srcs += fname srcs += fname
return srcs
def eval_custom_target_command(self, target, absolute_outputs=False):
# We only want the outputs to be absolute when using the VS backend
if not absolute_outputs:
ofilenames = [os.path.join(self.get_target_dir(target), i) for i in target.output]
else:
ofilenames = [os.path.join(self.environment.get_build_dir(), self.get_target_dir(target), i) \
for i in target.output]
srcs = self.get_custom_target_sources(target)
outdir = self.get_target_dir(target)
# Many external programs fail on empty arguments.
if outdir == '':
outdir = '.'
if target.absolute_paths:
outdir = os.path.join(self.environment.get_build_dir(), outdir)
cmd = [] cmd = []
for i in target.command: for i in target.command:
if isinstance(i, build.Executable): if isinstance(i, build.Executable):
@ -545,9 +555,9 @@ class Backend():
i = os.path.join(self.get_target_dir(i), tmp) i = os.path.join(self.get_target_dir(i), tmp)
elif isinstance(i, mesonlib.File): elif isinstance(i, mesonlib.File):
i = i.rel_to_builddir(self.build_to_src) i = i.rel_to_builddir(self.build_to_src)
if absolute_paths: if target.absolute_paths:
i = os.path.join(self.environment.get_build_dir(), i) i = os.path.join(self.environment.get_build_dir(), i)
# FIXME: str types are blindly added and ignore the 'absolute_paths' argument # FIXME: str types are blindly added ignoring 'target.absolute_paths'
elif not isinstance(i, str): elif not isinstance(i, str):
err_msg = 'Argument {0} is of unknown type {1}' err_msg = 'Argument {0} is of unknown type {1}'
raise RuntimeError(err_msg.format(str(i), str(type(i)))) raise RuntimeError(err_msg.format(str(i), str(type(i))))
@ -593,7 +603,7 @@ class Backend():
''.format(target.name, i) ''.format(target.name, i)
raise MesonException(msg) raise MesonException(msg)
source = match.group(0) source = match.group(0)
if match.group(1) is None and not absolute_paths: if match.group(1) is None and not target.absolute_paths:
lead_dir = '' lead_dir = ''
else: else:
lead_dir = self.environment.get_build_dir() lead_dir = self.environment.get_build_dir()

@ -13,6 +13,7 @@
# limitations under the License. # limitations under the License.
from . import backends from . import backends
from .. import modules
from .. import environment, mesonlib from .. import environment, mesonlib
from .. import build from .. import build
from .. import mlog from .. import mlog
@ -951,7 +952,7 @@ int dummy;
else: else:
srctype = othersgen srctype = othersgen
# Duplicate outputs are disastrous # Duplicate outputs are disastrous
if f in srctype: if f in srctype and srctype[f] is not gensrc:
msg = 'Duplicate output {0!r} from {1!r} {2!r}; ' \ msg = 'Duplicate output {0!r} from {1!r} {2!r}; ' \
'conflicts with {0!r} from {4!r} {3!r}' \ 'conflicts with {0!r} from {4!r} {3!r}' \
''.format(f, type(gensrc).__name__, gensrc.name, ''.format(f, type(gensrc).__name__, gensrc.name,
@ -1032,6 +1033,11 @@ int dummy;
args += ['--pkg', d.name] args += ['--pkg', d.name]
elif isinstance(d, dependencies.ExternalLibrary): elif isinstance(d, dependencies.ExternalLibrary):
args += d.get_lang_args('vala') args += d.get_lang_args('vala')
# Detect gresources and add --gresources arguments for each
for (gres, gensrc) in other_src[1].items():
if isinstance(gensrc, modules.GResourceTarget):
gres_xml, = self.get_custom_target_sources(gensrc)
args += ['--gresources=' + gres_xml]
extra_args = [] extra_args = []
for a in target.extra_args.get('vala', []): for a in target.extra_args.get('vala', []):

@ -392,6 +392,9 @@ class Vs2010Backend(backends.Backend):
root = self.create_basic_crap(target) root = self.create_basic_crap(target)
action = ET.SubElement(root, 'ItemDefinitionGroup') action = ET.SubElement(root, 'ItemDefinitionGroup')
customstep = ET.SubElement(action, 'CustomBuildStep') customstep = ET.SubElement(action, 'CustomBuildStep')
# We need to always use absolute paths because our invocation is always
# from the target dir, not the build root.
target.absolute_paths = True
(srcs, ofilenames, cmd) = self.eval_custom_target_command(target, True) (srcs, ofilenames, cmd) = self.eval_custom_target_command(target, True)
cmd_templ = '''"%s" '''*len(cmd) cmd_templ = '''"%s" '''*len(cmd)
ET.SubElement(customstep, 'Command').text = cmd_templ % tuple(cmd) ET.SubElement(customstep, 'Command').text = cmd_templ % tuple(cmd)

@ -1218,7 +1218,7 @@ class CustomTarget:
'depfile' : True, 'depfile' : True,
} }
def __init__(self, name, subdir, kwargs): def __init__(self, name, subdir, kwargs, absolute_paths=False):
self.name = name self.name = name
self.subdir = subdir self.subdir = subdir
self.dependencies = [] self.dependencies = []
@ -1227,6 +1227,8 @@ class CustomTarget:
self.depfile = None self.depfile = None
self.process_kwargs(kwargs) self.process_kwargs(kwargs)
self.extra_files = [] self.extra_files = []
# Whether to use absolute paths for all files on the commandline
self.absolute_paths = absolute_paths
unknowns = [] unknowns = []
for k in kwargs: for k in kwargs:
if k not in CustomTarget.known_kwargs: if k not in CustomTarget.known_kwargs:

@ -145,6 +145,8 @@ class PkgConfigDependency(Dependency):
else: else:
if not isinstance(self.version_reqs, (str, list)): if not isinstance(self.version_reqs, (str, list)):
raise DependencyException('Version argument must be string or list.') raise DependencyException('Version argument must be string or list.')
if isinstance(self.version_reqs, str):
self.version_reqs = [self.version_reqs]
(self.is_found, not_found, found) = \ (self.is_found, not_found, found) = \
version_compare_many(self.modversion, self.version_reqs) version_compare_many(self.modversion, self.version_reqs)
if not self.is_found: if not self.is_found:
@ -169,6 +171,11 @@ class PkgConfigDependency(Dependency):
# Fetch the libraries and library paths needed for using this # Fetch the libraries and library paths needed for using this
self._set_libs() self._set_libs()
def __repr__(self):
s = '<{0} {1}: {2} {3}>'
return s.format(self.__class__.__name__, self.name, self.is_found,
self.version_reqs)
def _call_pkgbin(self, args): def _call_pkgbin(self, args):
p, out = Popen_safe([self.pkgbin] + args, env=os.environ)[0:2] p, out = Popen_safe([self.pkgbin] + args, env=os.environ)[0:2]
return (p.returncode, out.strip()) return (p.returncode, out.strip())

@ -0,0 +1,34 @@
from .. import build
from .. import dependencies
_found_programs = {}
def find_program(program_name, target_name):
if program_name in _found_programs:
return _found_programs[program_name]
program = dependencies.ExternalProgram(program_name)
if not program.found():
m = "Target {!r} can't be generated as {!r} could not be found"
raise MesonException(m.format(target_name, program_name))
_found_programs[program_name] = program
return program
class GResourceTarget(build.CustomTarget):
def __init__(self, name, subdir, kwargs):
super().__init__(name, subdir, kwargs)
class GResourceHeaderTarget(build.CustomTarget):
def __init__(self, name, subdir, kwargs):
super().__init__(name, subdir, kwargs)
class GirTarget(build.CustomTarget):
def __init__(self, name, subdir, kwargs):
super().__init__(name, subdir, kwargs)
class TypelibTarget(build.CustomTarget):
def __init__(self, name, subdir, kwargs):
super().__init__(name, subdir, kwargs)
class VapiTarget(build.CustomTarget):
def __init__(self, name, subdir, kwargs):
super().__init__(name, subdir, kwargs)

@ -25,6 +25,7 @@ from .. import dependencies
from .. import mlog from .. import mlog
from .. import mesonlib from .. import mesonlib
from .. import interpreter from .. import interpreter
from . import find_program, GResourceTarget, GResourceHeaderTarget, GirTarget, TypelibTarget, VapiTarget
# gresource compilation is broken due to the way # gresource compilation is broken due to the way
# the resource compiler and Ninja clash about it # the resource compiler and Ninja clash about it
@ -45,19 +46,13 @@ def gir_has_extra_lib_arg():
_gir_has_extra_lib_arg = False _gir_has_extra_lib_arg = False
try: try:
scanner_options = subprocess.check_output(['g-ir-scanner', '--help']).decode() g_ir_scanner = find_program('g-ir-scanner', '').get_command()
_gir_has_extra_lib_arg = '--extra-library' in scanner_options opts = Popen_safe(g_ir_scanner + ['--help'], stderr=subprocess.STDOUT)[1]
except (FileNotFound, subprocess.CalledProcessError): _gir_has_extra_lib_arg = '--extra-library' in opts
except (MesonException, FileNotFoundError, subprocess.CalledProcessError):
pass pass
return _gir_has_extra_lib_arg return _gir_has_extra_lib_arg
def find_program(program_name, target_name):
program = dependencies.ExternalProgram(program_name)
if not program.found():
raise MesonException('%s can\'t be generated as %s could not be found' % (
target_name, program_name))
return program
class GnomeModule: class GnomeModule:
@staticmethod @staticmethod
@ -161,7 +156,7 @@ can not be used with the current version of glib-compiled-resources, due to
depfile = kwargs['output'] + '.d' depfile = kwargs['output'] + '.d'
kwargs['depfile'] = depfile kwargs['depfile'] = depfile
kwargs['command'] = copy.copy(cmd) + ['--dependency-file', '@DEPFILE@'] kwargs['command'] = copy.copy(cmd) + ['--dependency-file', '@DEPFILE@']
target_c = build.CustomTarget(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 [target_c]
@ -177,7 +172,7 @@ can not be used with the current version of glib-compiled-resources, due to
h_kwargs['install'] = install_header h_kwargs['install'] = install_header
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 = build.CustomTarget(args[0] + '_h', state.subdir, h_kwargs) target_h = GResourceHeaderTarget(args[0] + '_h', state.subdir, h_kwargs)
return [target_c, target_h] return [target_c, target_h]
def _get_gresource_dependencies(self, state, input_file, source_dirs, dependencies): def _get_gresource_dependencies(self, state, input_file, source_dirs, dependencies):
@ -798,7 +793,7 @@ can not be used with the current version of glib-compiled-resources, due to
install_header = False install_header = False
for arg, value in kwargs.items(): for arg, value in kwargs.items():
if arg == 'sources': if arg == 'sources':
sources = [value] + sources raise AssertionError("sources should've already been handled")
elif arg == 'c_template': elif arg == 'c_template':
c_template = value c_template = value
if 'template' in kwargs: if 'template' in kwargs:
@ -882,7 +877,8 @@ can not be used with the current version of glib-compiled-resources, due to
'command': cmd 'command': cmd
} }
custom_kwargs.update(kwargs) custom_kwargs.update(kwargs)
return build.CustomTarget(output, state.subdir, custom_kwargs) return build.CustomTarget(output, state.subdir, custom_kwargs,
absolute_paths=True)
def genmarshal(self, state, args, kwargs): def genmarshal(self, state, args, kwargs):
if len(args) != 1: if len(args) != 1:
@ -1087,15 +1083,3 @@ can not be used with the current version of glib-compiled-resources, due to
def initialize(): def initialize():
return GnomeModule() return GnomeModule()
class GirTarget(build.CustomTarget):
def __init__(self, name, subdir, kwargs):
super().__init__(name, subdir, kwargs)
class TypelibTarget(build.CustomTarget):
def __init__(self, name, subdir, kwargs):
super().__init__(name, subdir, kwargs)
class VapiTarget(build.CustomTarget):
def __init__(self, name, subdir, kwargs):
super().__init__(name, subdir, kwargs)

@ -12,7 +12,7 @@
# 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.
import os, subprocess import os
from .. import mlog from .. import mlog
from .. import build from .. import build
from ..mesonlib import MesonException, Popen_safe from ..mesonlib import MesonException, Popen_safe

@ -19,7 +19,7 @@ from .. import build
from .. import compilers from .. import compilers
import datetime import datetime
from .. import mlog from .. import mlog
from ..modules import gnome from . import GirTarget, TypelibTarget
import os import os
@ -65,9 +65,9 @@ class RPMModule:
to_delete.add('%%{buildroot}%%{_libdir}/%s' % target.get_filename()) to_delete.add('%%{buildroot}%%{_libdir}/%s' % target.get_filename())
mlog.warning('removing', mlog.bold(target.get_filename()), mlog.warning('removing', mlog.bold(target.get_filename()),
'from package because packaging static libs not recommended') 'from package because packaging static libs not recommended')
elif isinstance(target, gnome.GirTarget) and target.should_install(): elif isinstance(target, GirTarget) and target.should_install():
files_devel.add('%%{_datadir}/gir-1.0/%s' % target.get_filename()[0]) files_devel.add('%%{_datadir}/gir-1.0/%s' % target.get_filename()[0])
elif isinstance(target, gnome.TypelibTarget) and target.should_install(): elif isinstance(target, TypelibTarget) and target.should_install():
files.add('%%{_libdir}/girepository-1.0/%s' % target.get_filename()[0]) files.add('%%{_libdir}/girepository-1.0/%s' % target.get_filename()[0])
for header in state.headers: for header in state.headers:
if len(header.get_install_subdir()) > 0: if len(header.get_install_subdir()) > 0:

@ -0,0 +1,3 @@
res = gnome.compile_resources('testui',
'test-resources.xml',
source_dir : '.')

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/Meson">
<file compressed="true" preprocess="xml-stripblanks">test.ui</file>
</gresource>
</gresources>

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<!-- interface-requires gtk+ 3.8 -->
<template class="TestWidget" parent="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">4</property>
<child>
<object class="GtkEntry" id="entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
</object>
<packing>
<property name="position">0</property>
</packing>
</child>
</template>
</interface>

@ -0,0 +1,12 @@
project('test glib target version and gresources', 'c', 'vala')
gnome = import('gnome')
glib = dependency('glib-2.0', version : '>=2.38')
gtk = dependency('gtk+-3.0')
subdir('gres')
e = executable('gtktemplate', 'test.vala', res, dependencies : [glib, gtk])
# No X on the CI, so disable this for now
#test('test-target-glib', e)

@ -0,0 +1,37 @@
using Gtk;
using GLib;
[GtkTemplate (ui = "/org/Meson/test.ui")]
public class TestWidget : Box {
public string text {
get { return entry.text; }
set { entry.text = value; }
}
[GtkChild]
private Entry entry;
public TestWidget (string text) {
this.text = text;
}
}
void main(string[] args) {
Gtk.init (ref args);
var win = new Window();
win.destroy.connect (Gtk.main_quit);
var widget = new TestWidget ("SOME TEXT HERE");
win.add (widget);
win.show_all ();
/* Exit immediately */
Timeout.add_full (Priority.DEFAULT_IDLE, 1, () =>
{
Gtk.main_quit();
return false;
});
Gtk.main ();
}

@ -0,0 +1,13 @@
project('static vapi', 'c', 'vala')
glib = dependency('glib-2.0')
conf = configuration_data()
conf.set_quoted('VERSION', '1.0.0')
config_h = configure_file(output : 'config.h',
configuration : conf)
e = executable('static-vapi', 'vapi/config.vapi', 'test.vala',
dependencies : glib)
test('test-config', e)

@ -0,0 +1,6 @@
using GLib;
using Config;
public int main (string[] args) {
return GLib.strcmp(VERSION, "1.0.0");
}

@ -0,0 +1,4 @@
[CCode (cprefix = "", lower_case_cprefix = "", cheader_filename = "config.h")]
namespace Config {
public const string VERSION;
}

@ -0,0 +1,43 @@
/*** BEGIN file-header ***/
#include "enum-types.h"
/*** END file-header ***/
/*** BEGIN file-production ***/
/* enumerations from "@filename@" */
#include "@filename@"
/*** END file-production ***/
/*** BEGIN value-header ***/
GType
@enum_name@_get_type (void)
{
static volatile gsize g_define_type_id__volatile = 0;
if (g_once_init_enter (&g_define_type_id__volatile)) {
static const G@Type@Value values[] = {
/*** END value-header ***/
/*** BEGIN value-production ***/
{ @VALUENAME@, "@VALUENAME@", "@valuenick@" },
/*** END value-production ***/
/*** BEGIN value-tail ***/
{ 0, NULL, NULL }
};
GType g_define_type_id =
g_@type@_register_static (g_intern_static_string ("@EnumName@"), values);
g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
}
return g_define_type_id__volatile;
}
/*** END value-tail ***/
/*** BEGIN file-tail ***/
/*** END file-tail ***/

@ -0,0 +1,26 @@
/*** BEGIN file-header ***/
#ifndef __EXAMPLE_ENUMS_TYPES_H__
#define __EXAMPLE_ENUMS_TYPES_H__
#include <glib-object.h>
#include "enums.h"
G_BEGIN_DECLS
/*** END file-header ***/
/*** BEGIN file-production ***/
/* enumerations from "@filename@" */
/*** END file-production ***/
/*** BEGIN value-header ***/
GType @enum_name@_get_type (void) G_GNUC_CONST;
#define EXAMPLE_TYPE_@ENUMSHORT@ (@enum_name@_get_type ())
/*** END value-header ***/
/*** BEGIN file-tail ***/
G_END_DECLS
#endif /* __EXAMPLE_ENUMS_TYPES_H__ */
/*** END file-tail ***/

@ -0,0 +1,15 @@
#ifndef __EXAMPLE_ENUMS_H__
#define __EXAMPLE_ENUMS_H__
G_BEGIN_DECLS
typedef enum {
EXAMPLE_VERBOSITY_ERRORS,
EXAMPLE_VERBOSITY_MINIMAL,
EXAMPLE_VERBOSITY_DETAILED,
EXAMPLE_VERBOSITY_DEBUG,
} ExampleVerbosity;
G_END_DECLS
#endif /* __EXAMPLE_ENUMS_H__ */

@ -0,0 +1,44 @@
# Test that dependencies with their own generated sources don't
# confuse the Vala build instruction generator.
# Test case for https://github.com/mesonbuild/meson/issues/1084
gnome = import('gnome')
gobject = dependency('gobject-2.0')
enums = gnome.mkenums('enum-types',
sources: 'enums.h',
c_template: 'enum-types.c.template',
h_template: 'enum-types.h.template',
)
libcommon = library('common',
enums[0], enums[1],
dependencies: gobject)
common_dep = declare_dependency(
# This is required so that whoever depends on this also depends
# on the generated header; that won't happen implicitly.
# See: https://github.com/mesonbuild/meson/issues/1084
sources: enums[1],
link_with: libcommon,
)
libplover_vala = library('plover',
'lib.vala',
dependencies: [common_dep, gobject]
)
plover_dep = declare_dependency(
link_with: libplover_vala,
dependencies: common_dep
)
vala_prog = executable('hello',
'main.vala',
link_with: libplover_vala,
# There's no need to specify common_dep here since plover_dep pulls it
# in, but it should be harmless to do so.
dependencies: [common_dep, plover_dep, gobject]
)

@ -6,3 +6,4 @@ cd.set('x', 'y')
subdir('src') subdir('src')
subdir('tools') subdir('tools')
subdir('onlygen') subdir('onlygen')
subdir('dependency-generated')

Loading…
Cancel
Save