Merge pull request #895 from mesonbuild/wip/tingping/gnome-vapi

gnome: Add generate_vapi function
pull/987/head
Jussi Pakkanen 8 years ago committed by GitHub
commit 36a0d162cb
  1. 6
      mesonbuild/interpreter.py
  2. 147
      mesonbuild/modules/gnome.py
  3. 7
      test cases/vala/12 generated vapi/installed_files.txt
  4. 12
      test cases/vala/12 generated vapi/libbar/bar.c
  5. 5
      test cases/vala/12 generated vapi/libbar/bar.h
  6. 33
      test cases/vala/12 generated vapi/libbar/meson.build
  7. 11
      test cases/vala/12 generated vapi/libfoo/foo.c
  8. 5
      test cases/vala/12 generated vapi/libfoo/foo.h
  9. 36
      test cases/vala/12 generated vapi/libfoo/meson.build
  10. 9
      test cases/vala/12 generated vapi/main.vala
  11. 13
      test cases/vala/12 generated vapi/meson.build

@ -990,6 +990,7 @@ class ModuleHolder(InterpreterObject):
state.project_version = self.interpreter.build.dep_manifest[self.interpreter.active_projectname]
state.compilers = self.interpreter.build.compilers
state.targets = self.interpreter.build.targets
state.data = self.interpreter.build.data
state.headers = self.interpreter.build.get_headers()
state.man = self.interpreter.build.get_man()
state.global_args = self.interpreter.build.global_args
@ -1269,6 +1270,11 @@ class Interpreter():
self.build.install_scripts.append(v)
elif isinstance(v, build.Data):
self.build.data.append(v)
elif isinstance(v, dependencies.InternalDependency):
# FIXME: This is special cased and not ideal:
# The first source is our new VapiTarget, the rest are deps
self.module_method_callback(v.sources[0])
outvalues.append(InternalDependencyHolder(v))
else:
print(v)
raise InterpreterException('Module returned a value of unknown type.')

@ -800,6 +800,149 @@ class GnomeModule:
return [body, header]
@staticmethod
def _vapi_args_to_command(prefix, variable, kwargs, accept_vapi=False):
arg_list = kwargs.get(variable)
if not arg_list:
return []
ret = []
if not isinstance(arg_list, list):
arg_list = [arg_list]
for arg in arg_list:
if not isinstance(arg, str):
types = 'strings' + ' or InternalDependencys' if accept_vapi else ''
raise MesonException('All {} must be {}'.format(variable, types))
ret.append(prefix + arg)
return ret
def _extract_vapi_packages(self, state, kwargs):
'''
Packages are special because we need to:
- Get a list of packages for the .deps file
- Get a list of depends for any VapiTargets
- Get package name from VapiTargets
- Add include dirs for any VapiTargets
'''
arg_list = kwargs.get('packages')
if not arg_list:
return [], [], [], []
if not isinstance(arg_list, list):
arg_list = [arg_list]
vapi_depends = []
vapi_packages = []
vapi_includes = []
ret = []
remaining_args = []
for arg in arg_list:
if hasattr(arg, 'held_object'):
arg = arg.held_object
if isinstance(arg, dependencies.InternalDependency):
targets = [t for t in arg.sources if isinstance(t, VapiTarget)]
for target in targets:
srcdir = os.path.join(state.environment.get_source_dir(),
target.get_subdir())
outdir = os.path.join(state.environment.get_build_dir(),
target.get_subdir())
outfile = target.output[0][:-5] # Strip .vapi
ret.append('--vapidir=' + outdir)
ret.append('--girdir=' + outdir)
ret.append('--pkg=' + outfile)
vapi_depends.append(target)
vapi_packages.append(outfile)
vapi_includes.append(srcdir)
else:
vapi_packages.append(arg)
remaining_args.append(arg)
kwargs['packages'] = remaining_args
vapi_args = ret + self._vapi_args_to_command('--pkg=', 'packages', kwargs, accept_vapi=True)
return vapi_args, vapi_depends, vapi_packages, vapi_includes
def _generate_deps(self, state, library, packages, indir):
outdir = state.environment.scratch_dir
fname = os.path.join(outdir, library + '.deps')
with open(fname, 'w') as ofile:
for package in packages:
ofile.write(package + '\n')
return build.Data(False, outdir, [fname], indir)
def _get_vapi_link_with(self, target):
link_with = []
for dep in target.get_target_dependencies():
if isinstance(dep, build.SharedLibrary):
link_with.append(dep)
elif isinstance(dep, GirTarget):
link_with += self._get_vapi_link_with(dep)
return link_with
def generate_vapi(self, state, args, kwargs):
if len(args) != 1:
raise MesonException('The library name is required')
if not isinstance(args[0], str):
raise MesonException('The first argument must be the name of the library')
library = args[0]
build_dir = os.path.join(state.environment.get_build_dir(), state.subdir)
source_dir = os.path.join(state.environment.get_source_dir(), state.subdir)
pkg_cmd, vapi_depends, vapi_packages, vapi_includes = self._extract_vapi_packages(state, kwargs)
cmd = ['vapigen', '--quiet', '--library=' + library, '--directory=' + build_dir]
cmd += self._vapi_args_to_command('--vapidir=', 'vapi_dirs', kwargs)
cmd += self._vapi_args_to_command('--metadatadir=', 'metadata_dirs', kwargs)
cmd += self._vapi_args_to_command('--girdir=', 'gir_dirs', kwargs)
cmd += pkg_cmd
cmd += ['--metadatadir=' + source_dir]
inputs = kwargs.get('sources')
if not inputs:
raise MesonException('sources are required to generate the vapi file')
if not isinstance(inputs, list):
inputs = [inputs]
link_with = []
for i in inputs:
if isinstance(i, str):
cmd.append(os.path.join(source_dir, i))
elif hasattr(i, 'held_object') \
and isinstance(i.held_object, GirTarget):
link_with += self._get_vapi_link_with(i.held_object)
subdir = os.path.join(state.environment.get_build_dir(),
i.held_object.get_subdir())
gir_file = os.path.join(subdir, i.held_object.output[0])
cmd.append(gir_file)
else:
raise MesonException('Input must be a str or GirTarget')
vapi_output = library + '.vapi'
custom_kwargs = {
'command': cmd,
'input': inputs,
'output': vapi_output,
'depends': vapi_depends,
}
install_dir = kwargs.get('install_dir',
os.path.join(state.environment.coredata.get_builtin_option('datadir'),
'vala', 'vapi'))
if kwargs.get('install'):
custom_kwargs['install'] = kwargs['install']
custom_kwargs['install_dir'] = install_dir
# We shouldn't need this locally but we install it
deps_target = self._generate_deps(state, library, vapi_packages, install_dir)
state.data.append(deps_target)
vapi_target = VapiTarget(vapi_output, state.subdir, custom_kwargs)
# So to try our best to get this to just work we need:
# - link with with the correct library
# - include the vapi and dependent vapi files in sources
# - add relevant directories to include dirs
includes = [build.IncludeDirs(state.subdir, ['.'] + vapi_includes, False)]
sources = [vapi_target] + vapi_depends
return dependencies.InternalDependency(
None, includes, [], [], link_with, sources, []
)
def initialize():
return GnomeModule()
@ -811,3 +954,7 @@ class GirTarget(build.CustomTarget):
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)

@ -0,0 +1,7 @@
usr/bin/vapigen-test
usr/lib/libfoo.so
usr/lib/libbar.so
usr/share/vala/vapi/foo-1.0.vapi
usr/share/vala/vapi/foo-1.0.deps
usr/share/vala/vapi/bar-1.0.vapi
usr/share/vala/vapi/bar-1.0.deps

@ -0,0 +1,12 @@
#include "bar.h"
#include "foo.h"
/**
* bar_return_success:
*
* Returns 0
*/
int bar_return_success(void)
{
return foo_return_success();
}

@ -0,0 +1,5 @@
#include <glib-object.h>
#pragma once
int bar_return_success(void);

@ -0,0 +1,33 @@
libbar_sources = [
'bar.c',
'bar.h',
]
libbar_deps = [
dependency('gobject-2.0'),
libfoo_dep,
]
libbar = shared_library('bar', libbar_sources,
dependencies: libbar_deps,
install: true,
)
libbar_api_ver = '1.0'
libbar_gir = gnome.generate_gir(libbar,
sources: libbar_sources,
namespace: 'Bar',
nsversion: libbar_api_ver,
packages: 'gobject-2.0',
symbol_prefix: 'bar',
extra_args: [
'--c-include=bar.h',
],
)
libbar_vapi = gnome.generate_vapi('bar-' + libbar_api_ver,
sources: libbar_gir[0],
packages: libfoo_vapi,
install: true,
)

@ -0,0 +1,11 @@
#include "foo.h"
/**
* foo_return_success:
*
* Returns 0
*/
int foo_return_success(void)
{
return 0;
}

@ -0,0 +1,5 @@
#include <glib-object.h>
#pragma once
int foo_return_success(void);

@ -0,0 +1,36 @@
libfoo_sources = [
'foo.c',
'foo.h',
]
libfoo_deps = [
dependency('gobject-2.0')
]
libfoo = shared_library('foo', libfoo_sources,
dependencies: libfoo_deps,
install: true,
)
libfoo_api_ver = '1.0'
libfoo_gir = gnome.generate_gir(libfoo,
sources: libfoo_sources,
namespace: 'Foo',
nsversion: libfoo_api_ver,
packages: 'gobject-2.0',
symbol_prefix: 'foo',
extra_args: [
'--c-include=foo.h',
],
)
libfoo_vapi = gnome.generate_vapi('foo-' + libfoo_api_ver,
sources: libfoo_gir[0],
install: true,
)
libfoo_dep = declare_dependency(
link_with: libfoo,
include_directories: include_directories('.'),
)

@ -0,0 +1,9 @@
using Foo;
using Bar;
class Main : GLib.Object {
public static int main(string[] args) {
var ignore = Foo.return_success();
return Bar.return_success();
}
}

@ -0,0 +1,13 @@
project('vapi-test', ['c', 'vala'])
gnome = import('gnome')
subdir('libfoo')
subdir('libbar')
vapiexe = executable('vapigen-test',
'main.vala',
dependencies: [dependency('gobject-2.0'), libbar_vapi],
install: true,
)
test('vapigen-test', vapiexe)
Loading…
Cancel
Save