gnome.generate_gir: support generating gir for multiple libraries

Fixes #3688
pull/4000/head
Mathieu Duponchelle 6 years ago
parent 8377ea45aa
commit 6ea939dd5f
  1. 13
      docs/markdown/Gnome-module.md
  2. 7
      docs/markdown/snippets/generate_gir_multiple_libraries.md
  3. 119
      mesonbuild/modules/gnome.py
  4. 45
      test cases/frameworks/7 gnome/gir/meson-sample2.c
  5. 21
      test cases/frameworks/7 gnome/gir/meson-sample2.h
  6. 12
      test cases/frameworks/7 gnome/gir/meson.build
  7. 3
      test cases/frameworks/7 gnome/gir/prog.py

@ -67,10 +67,15 @@ executable(
### gnome.generate_gir() ### gnome.generate_gir()
Generates GObject introspection data. Takes one positional argument, Generates GObject introspection data.
the build target you want to build gir data for. There are several
keyword arguments. Many of these map directly to the `g-ir-scanner` Takes one or more positional arguments:
tool so see its documentation for more information.
Either one or more library objects you want to build gir data for, or a single
executable object.
There are several keyword arguments. Many of these map directly to the
`g-ir-scanner` tool so see its documentation for more information.
* `dependencies`: deps to use during introspection scanning * `dependencies`: deps to use during introspection scanning
* `extra_args`: command line arguments to pass to gir compiler * `extra_args`: command line arguments to pass to gir compiler

@ -0,0 +1,7 @@
## gnome.generate_gir() now optionally accepts multiple libraries
The GNOME module can now generate a single gir for multiple libraries, which
is something `g-ir-scanner` supported, but had not been exposed yet.
gnome.generate_gir() will now accept multiple positional arguments, if none
of these arguments are an `Executable` instance.

@ -499,54 +499,69 @@ class GnomeModule(ExtensionModule):
'Gir include dirs should be include_directories().') 'Gir include dirs should be include_directories().')
return ret return ret
def _scan_lang(self, state, lang): def _scan_langs(self, state, langs):
ret = [] ret = []
for link_arg in state.environment.coredata.get_external_link_args(lang): for lang in langs:
if link_arg.startswith('-L'): for link_arg in state.environment.coredata.get_external_link_args(lang):
ret.append(link_arg) if link_arg.startswith('-L'):
ret.append(link_arg)
return ret return ret
def _scan_gir_target(self, state, girtarget): def _scan_gir_targets(self, state, girtargets):
ret = [] ret = []
if isinstance(girtarget, build.Executable): for girtarget in girtargets:
ret += ['--program', girtarget] if isinstance(girtarget, build.Executable):
elif isinstance(girtarget, build.SharedLibrary): ret += ['--program', girtarget]
libname = girtarget.get_basename() elif isinstance(girtarget, build.SharedLibrary):
# Needed for the following binutils bug: libname = girtarget.get_basename()
# https://github.com/mesonbuild/meson/issues/1911 # Needed for the following binutils bug:
# However, g-ir-scanner does not understand -Wl,-rpath # https://github.com/mesonbuild/meson/issues/1911
# so we need to use -L instead # However, g-ir-scanner does not understand -Wl,-rpath
for d in state.backend.determine_rpath_dirs(girtarget): # so we need to use -L instead
d = os.path.join(state.environment.get_build_dir(), d) for d in state.backend.determine_rpath_dirs(girtarget):
ret.append('-L' + d) d = os.path.join(state.environment.get_build_dir(), d)
ret += ['--library', libname] ret.append('-L' + d)
# need to put our output directory first as we need to use the ret += ['--library', libname]
# generated libraries instead of any possibly installed system/prefix # need to put our output directory first as we need to use the
# ones. # generated libraries instead of any possibly installed system/prefix
ret += ["-L@PRIVATE_OUTDIR_ABS_%s@" % girtarget.get_id()] # ones.
ret += ["-L@PRIVATE_OUTDIR_ABS_%s@" % girtarget.get_id()]
return ret return ret
def _get_girtarget_lang_compiler(self, girtarget): def _get_girtargets_langs_compilers(self, girtargets):
for lang, compiler in girtarget.compilers.items(): ret = []
# XXX: Can you use g-i with any other language? for girtarget in girtargets:
if lang in ('c', 'cpp', 'objc', 'objcpp', 'd'): for lang, compiler in girtarget.compilers.items():
break # XXX: Can you use g-i with any other language?
else: if lang in ('c', 'cpp', 'objc', 'objcpp', 'd'):
lang = None ret.append((lang, compiler))
compiler = None break
return ret
return lang, compiler def _get_gir_targets_deps(self, girtargets):
ret = []
for girtarget in girtargets:
ret += girtarget.get_all_link_deps()
ret += girtarget.get_external_deps()
return ret
def _get_gir_targets_inc_dirs(self, girtargets):
ret = []
for girtarget in girtargets:
ret += girtarget.get_include_dirs()
return ret
def _get_lang_compiler_flags(self, state, lang, compiler): def _get_langs_compilers_flags(self, state, langs_compilers):
cflags = [] cflags = []
internal_ldflags = [] internal_ldflags = []
external_ldflags = [] external_ldflags = []
if lang and compiler: for lang, compiler in langs_compilers:
if state.global_args.get(lang): if state.global_args.get(lang):
cflags += state.global_args[lang] cflags += state.global_args[lang]
if state.project_args.get(lang): if state.project_args.get(lang):
@ -562,8 +577,8 @@ class GnomeModule(ExtensionModule):
return cflags, internal_ldflags, external_ldflags return cflags, internal_ldflags, external_ldflags
def _make_gir_filelist(self, state, srcdir, ns, nsversion, girtarget, libsources): def _make_gir_filelist(self, state, srcdir, ns, nsversion, girtargets, libsources):
gir_filelist_dir = state.backend.get_target_private_dir_abs(girtarget) gir_filelist_dir = state.backend.get_target_private_dir_abs(girtargets[0])
if not os.path.isdir(gir_filelist_dir): if not os.path.isdir(gir_filelist_dir):
os.mkdir(gir_filelist_dir) os.mkdir(gir_filelist_dir)
gir_filelist_filename = os.path.join(gir_filelist_dir, '%s_%s_gir_filelist' % (ns, nsversion)) gir_filelist_filename = os.path.join(gir_filelist_dir, '%s_%s_gir_filelist' % (ns, nsversion))
@ -658,21 +673,30 @@ class GnomeModule(ExtensionModule):
return typelib_includes return typelib_includes
def _get_external_args_for_langs(self, state, langs):
ret = []
for lang in langs:
ret += state.environment.coredata.get_external_args(lang)
return ret
@FeatureNewKwargs('build target', '0.40.0', ['build_by_default']) @FeatureNewKwargs('build target', '0.40.0', ['build_by_default'])
@permittedKwargs({'sources', 'nsversion', 'namespace', 'symbol_prefix', 'identifier_prefix', @permittedKwargs({'sources', 'nsversion', 'namespace', 'symbol_prefix', 'identifier_prefix',
'export_packages', 'includes', 'dependencies', 'link_with', 'include_directories', 'export_packages', 'includes', 'dependencies', 'link_with', 'include_directories',
'install', 'install_dir_gir', 'install_dir_typelib', 'extra_args', 'install', 'install_dir_gir', 'install_dir_typelib', 'extra_args',
'packages', 'header', 'build_by_default'}) 'packages', 'header', 'build_by_default'})
def generate_gir(self, state, args, kwargs): def generate_gir(self, state, args, kwargs):
if len(args) != 1: if not args:
raise MesonException('Gir takes one argument') raise MesonException('generate_gir takes at least one argument')
if kwargs.get('install_dir'): if kwargs.get('install_dir'):
raise MesonException('install_dir is not supported with generate_gir(), see "install_dir_gir" and "install_dir_typelib"') raise MesonException('install_dir is not supported with generate_gir(), see "install_dir_gir" and "install_dir_typelib"')
giscanner = self.interpreter.find_program_impl('g-ir-scanner') giscanner = self.interpreter.find_program_impl('g-ir-scanner')
gicompiler = self.interpreter.find_program_impl('g-ir-compiler') gicompiler = self.interpreter.find_program_impl('g-ir-compiler')
girtarget = self._unwrap_gir_target(args[0]) girtargets = [self._unwrap_gir_target(arg) for arg in args]
if len(girtargets) > 1 and any([isinstance(el, build.Executable) for el in girtargets]):
raise MesonException('generate_gir only accepts a single argument when one of the arguments is an executable')
self.gir_dep, pkgargs = self._get_gir_dep(state) self.gir_dep, pkgargs = self._get_gir_dep(state)
@ -682,12 +706,12 @@ class GnomeModule(ExtensionModule):
girfile = '%s-%s.gir' % (ns, nsversion) girfile = '%s-%s.gir' % (ns, nsversion)
srcdir = os.path.join(state.environment.get_source_dir(), state.subdir) srcdir = os.path.join(state.environment.get_source_dir(), state.subdir)
builddir = os.path.join(state.environment.get_build_dir(), state.subdir) builddir = os.path.join(state.environment.get_build_dir(), state.subdir)
depends = [girtarget] depends = [] + girtargets
gir_inc_dirs = [] gir_inc_dirs = []
lang, compiler = self._get_girtarget_lang_compiler(girtarget) langs_compilers = self._get_girtargets_langs_compilers(girtargets)
cflags, internal_ldflags, external_ldflags = self._get_lang_compiler_flags(state, lang, compiler) cflags, internal_ldflags, external_ldflags = self._get_langs_compilers_flags(state, langs_compilers)
deps = (girtarget.get_all_link_deps() + girtarget.get_external_deps() + deps = self._get_gir_targets_deps(girtargets)
extract_as_list(kwargs, 'dependencies', pop=True, unholder=True)) deps += extract_as_list(kwargs, 'dependencies', pop=True, unholder=True)
typelib_includes = self._gather_typelib_includes_and_update_depends(state, deps, depends) typelib_includes = self._gather_typelib_includes_and_update_depends(state, deps, depends)
# ldflags will be misinterpreted by gir scanner (showing # ldflags will be misinterpreted by gir scanner (showing
# spurious dependencies) but building GStreamer fails if they # spurious dependencies) but building GStreamer fails if they
@ -697,6 +721,7 @@ class GnomeModule(ExtensionModule):
cflags += list(dep_cflags) cflags += list(dep_cflags)
internal_ldflags += list(dep_internal_ldflags) internal_ldflags += list(dep_internal_ldflags)
external_ldflags += list(dep_external_ldflags) external_ldflags += list(dep_external_ldflags)
girtargets_inc_dirs = self._get_gir_targets_inc_dirs(girtargets)
inc_dirs = self._scan_inc_dirs(kwargs) inc_dirs = self._scan_inc_dirs(kwargs)
scan_command = [giscanner] scan_command = [giscanner]
@ -708,8 +733,8 @@ class GnomeModule(ExtensionModule):
scan_command += self._scan_header(kwargs) scan_command += self._scan_header(kwargs)
scan_command += self._scan_extra_args(kwargs) scan_command += self._scan_extra_args(kwargs)
scan_command += ['-I' + srcdir, '-I' + builddir] scan_command += ['-I' + srcdir, '-I' + builddir]
scan_command += get_include_args(girtarget.get_include_dirs()) scan_command += get_include_args(girtargets_inc_dirs)
scan_command += ['--filelist=' + self._make_gir_filelist(state, srcdir, ns, nsversion, girtarget, libsources)] scan_command += ['--filelist=' + self._make_gir_filelist(state, srcdir, ns, nsversion, girtargets, libsources)]
scan_command += self._scan_link_withs(state, depends, kwargs) scan_command += self._scan_link_withs(state, depends, kwargs)
scan_command += self._scan_include(state, depends, gir_inc_dirs, kwargs) scan_command += self._scan_include(state, depends, gir_inc_dirs, kwargs)
scan_command += self._scan_symbol_prefix(kwargs) scan_command += self._scan_symbol_prefix(kwargs)
@ -717,12 +742,12 @@ class GnomeModule(ExtensionModule):
scan_command += self._scan_export_packages(kwargs) scan_command += self._scan_export_packages(kwargs)
scan_command += ['--cflags-begin'] scan_command += ['--cflags-begin']
scan_command += cflags scan_command += cflags
scan_command += state.environment.coredata.get_external_args(lang) scan_command += self._get_external_args_for_langs(state, [lc[0] for lc in langs_compilers])
scan_command += ['--cflags-end'] scan_command += ['--cflags-end']
scan_command += get_include_args(inc_dirs) scan_command += get_include_args(inc_dirs)
scan_command += get_include_args(list(gi_includes) + gir_inc_dirs + inc_dirs, prefix='--add-include-path=') scan_command += get_include_args(list(gi_includes) + gir_inc_dirs + inc_dirs, prefix='--add-include-path=')
scan_command += self._scan_gir_target(state, girtarget) scan_command += self._scan_gir_targets(state, girtargets)
scan_command += self._scan_lang(state, lang) scan_command += self._scan_langs(state, [lc[0] for lc in langs_compilers])
scan_command += list(internal_ldflags) scan_command += list(internal_ldflags)
scan_command += list(external_ldflags) scan_command += list(external_ldflags)

@ -0,0 +1,45 @@
#include "meson-sample2.h"
struct _MesonSample2
{
GObject parent_instance;
};
G_DEFINE_TYPE (MesonSample2, meson_sample2, G_TYPE_OBJECT)
/**
* meson_sample2_new:
*
* Allocates a new #MesonSample2.
*
* Returns: (transfer full): a #MesonSample2.
*/
MesonSample2 *
meson_sample2_new (void)
{
return g_object_new (MESON_TYPE_SAMPLE2, NULL);
}
static void
meson_sample2_class_init (MesonSample2Class *klass)
{
}
static void
meson_sample2_init (MesonSample2 *self)
{
}
/**
* meson_sample2_print_message:
* @self: a #MesonSample2.
*
* Prints Hello.
*
* Returns: Nothing.
*/
void
meson_sample2_print_message (MesonSample2 *self)
{
g_print ("Message: Hello\n");
}

@ -0,0 +1,21 @@
#ifndef MESON_SAMPLE2_H
#define MESON_SAMPLE2_H
#if !defined (MESON_TEST)
#error "MESON_TEST not defined."
#endif
#include <glib-object.h>
G_BEGIN_DECLS
#define MESON_TYPE_SAMPLE2 (meson_sample2_get_type())
G_DECLARE_FINAL_TYPE (MesonSample2, meson_sample2, MESON, SAMPLE2, GObject)
MesonSample2 *meson_sample2_new (void);
void meson_sample2_print_message (MesonSample2 *self);
G_END_DECLS
#endif /* MESON_SAMPLE2_H */

@ -1,6 +1,7 @@
subdir('dep1') subdir('dep1')
libsources = ['meson-sample.c', 'meson-sample.h'] libsources = ['meson-sample.c', 'meson-sample.h']
lib2sources = ['meson-sample2.c', 'meson-sample2.h']
girlib = shared_library( girlib = shared_library(
'gir_lib', 'gir_lib',
@ -9,6 +10,13 @@ girlib = shared_library(
install : true install : true
) )
girlib2 = shared_library(
'gir_lib2',
sources : lib2sources,
dependencies : [gobj],
install : true
)
girexe = executable( girexe = executable(
'girprog', 'girprog',
sources : 'prog.c', sources : 'prog.c',
@ -19,8 +27,8 @@ girexe = executable(
fake_dep = dependency('no-way-this-exists', required: false) fake_dep = dependency('no-way-this-exists', required: false)
gnome.generate_gir( gnome.generate_gir(
girlib, girlib, girlib2,
sources : libsources, sources : libsources + lib2sources,
nsversion : '1.0', nsversion : '1.0',
namespace : 'Meson', namespace : 'Meson',
symbol_prefix : 'meson', symbol_prefix : 'meson',

@ -6,3 +6,6 @@ if __name__ == "__main__":
dep1 = MesonDep1.Dep1.new() dep1 = MesonDep1.Dep1.new()
dep2 = MesonDep2.Dep2.new("Hello, meson/py!") dep2 = MesonDep2.Dep2.new("Hello, meson/py!")
s.print_message(dep1, dep2) s.print_message(dep1, dep2)
s2 = Meson.Sample2.new()
s2.print_message()

Loading…
Cancel
Save