diff options
author | Sam Thursfield <sam@afuera.me.uk> | 2017-06-23 16:25:05 +0100 |
---|---|---|
committer | Sam Thursfield <sam@afuera.me.uk> | 2017-06-23 19:59:09 +0100 |
commit | d0d3ab9296f248dd21f9036f3cb6d60a413e530f (patch) | |
tree | 19dbb5706e22a5c790c10caf1e120b2ca4b5a89b | |
parent | d5ae8e05f8e04b66a1e44fdfd85170b1d80d14d3 (diff) | |
download | tracker-sam/introspection-fix.tar.gz |
Fix missing introspection data for libtracker-sparql (when using Meson)sam/introspection-fix
Up til now only the Tracker.SparqlConnection and Tracker.SparqlBuilder
resources were introspectable. This is because we only used the
introspection output from `valac`, but other bits of libtracker-sparql
have since been added that are written in C.
There seems to be no way to generate a single .gir for a combined C and
Vala codebase, so instead I have written a simple `g-ir-merge` script
which can combine two different namespaces into a single .gir.
This is currently tested and working with the Meson build instructions.
It would be possible to implement this for the Autotools build
instructions as well.
https://bugzilla.gnome.org/show_bug.cgi?id=782091
-rw-r--r-- | meson.build | 10 | ||||
-rw-r--r-- | src/libtracker-sparql-backend/meson.build | 38 | ||||
-rw-r--r-- | src/libtracker-sparql/meson.build | 71 | ||||
-rw-r--r-- | utils/Makefile.am | 1 | ||||
-rw-r--r-- | utils/g-ir-merge/Makefile.am | 1 | ||||
-rw-r--r-- | utils/g-ir-merge/g-ir-merge | 172 |
6 files changed, 258 insertions, 35 deletions
diff --git a/meson.build b/meson.build index da221d880..94020d517 100644 --- a/meson.build +++ b/meson.build @@ -32,6 +32,7 @@ gio_unix = dependency('gio-unix-2.0', version: '>' + glib_required) glib = dependency('glib-2.0', version: '>' + glib_required) gmodule = dependency('gmodule-2.0', version: '>' + glib_required) gobject = dependency('gobject-2.0', version: '>' + glib_required) +gobject_introspection = dependency('gobject-introspection-1.0') gstreamer = dependency('gstreamer-1.0', required: false) gstreamer_pbutils = dependency('gstreamer-pbutils-1.0', required: false) gstreamer_tag = dependency('gstreamer-tag-1.0', required: false) @@ -489,6 +490,15 @@ tracker_writeback_modules_dir = join_paths(get_option('prefix'), get_option('lib vapi_dir = join_paths(get_option('prefix'), get_option('datadir'), 'vala', 'vapi') +g_ir_compiler = find_program('g-ir-compiler', gobject_introspection.get_pkgconfig_variable('g_ir_compiler')) +g_ir_merge = find_program('g-ir-merge', join_paths(meson.source_root(), 'utils', 'g-ir-merge', 'g-ir-merge')) + +# You can use the gobject_introspection.get_pkgconfig_variable() to find these, +# but then get_option('prefix') won't be honoured if it differs from the prefix +# gobject-introspection is installed to. +gir_dir = join_paths(get_option('prefix'), get_option('datadir'), 'gir-1.0') +typelib_dir = join_paths(get_option('libdir'), 'girepository-1.0') + subdir('src') if get_option('docs') diff --git a/src/libtracker-sparql-backend/meson.build b/src/libtracker-sparql-backend/meson.build index cbbc890b2..bf2f5ba75 100644 --- a/src/libtracker-sparql-backend/meson.build +++ b/src/libtracker-sparql-backend/meson.build @@ -2,6 +2,7 @@ libtracker_sparql = library('tracker-sparql-' + tracker_api_version, 'tracker-backend.vala', install: true, install_rpath: tracker_internal_libs_dir, + link_whole: libtracker_sparql_intermediate_c, dependencies: [tracker_sparql_intermediate_dep, tracker_sparql_remote_dep, tracker_sparql_bus_dep, tracker_sparql_direct_dep], ) @@ -10,3 +11,40 @@ tracker_sparql_dep = declare_dependency( include_directories: srcinc, dependencies: [tracker_sparql_intermediate_dep], ) + +# The introspection generation for libtracker-sparql is awkward because we have +# both C and Vala code, and we have to generate an introspection repo for each +# one separately and then combine them together manually. +# +# See: <https://bugzilla.gnome.org/show_bug.cgi?id=782091> + +tracker_sparql_c_gir = gnome.generate_gir(libtracker_sparql, + sources: libtracker_sparql_c_sources + libtracker_sparql_c_public_headers, + nsversion: tracker_api_version, + namespace: 'Tracker_C', + identifier_prefix: 'Tracker', + symbol_prefix: 'tracker', + includes : ['GLib-2.0', 'GObject-2.0', 'Gio-2.0' ], + link_with: libtracker_sparql, + extra_args: [ + '--c-include', 'libtracker-sparql/tracker-sparql.h', + '-D', 'TRACKER_COMPILATION', + ]) + +tracker_sparql_c_gir = tracker_sparql_c_gir[0] # Ignore this .typelib +tracker_sparql_vala_gir = join_paths(meson.current_build_dir(), '..', 'libtracker-sparql', 'Tracker_Vala-' + tracker_api_version + '.gir') + +tracker_sparql_gir = custom_target('tracker-sparql-gir', + command: [g_ir_merge, '--namespace', 'Tracker', '--nsversion', tracker_api_version, '@INPUT@', tracker_sparql_vala_gir], + input: [tracker_sparql_c_gir], + capture: true, + output: 'Tracker-1.0.gir', + install: true, + install_dir: gir_dir) + +tracker_sparql_typelib = custom_target('tracker-sparql-typelib', + command: [g_ir_compiler, '--output', '@OUTPUT@', '@INPUT@'], + input: tracker_sparql_gir, + output: 'Tracker-1.0.typelib', + install: true, + install_dir: typelib_dir) diff --git a/src/libtracker-sparql/meson.build b/src/libtracker-sparql/meson.build index 9c6c4a718..495c5ad5a 100644 --- a/src/libtracker-sparql/meson.build +++ b/src/libtracker-sparql/meson.build @@ -9,26 +9,18 @@ enums_h = gnome.mkenums('tracker-sparql-enum-types', tracker_sparql_intermediate_dependencies = [uuid] -libtracker_sparql_intermediate = static_library('tracker-sparql', +# First build the Vala parts ... + +libtracker_sparql_intermediate_vala = static_library('tracker-sparql-intermediate-vala', enums_c, enums_h, 'tracker-namespace.vala', 'tracker-builder.vala', 'tracker-connection.vala', 'tracker-cursor.vala', 'tracker-utils.vala', - 'tracker-namespace-manager.c', - 'tracker-notifier.c', - 'tracker-resource.c', - 'tracker-uri.c', - 'tracker-version.c', vala_header: 'tracker-generated-no-checks.h', c_args: [ '-DTRACKER_COMPILATION', ], - # FIXME: getting Vala to output the GIR means that the symbols from the - # C files aren't included. This problem seems to affect the Autotools - # build system as well. - # FIXME: we also can't depend on this in the TrackerMiner GIR, which - # probably breaks stuff - vala_gir: 'Tracker-' + tracker_api_version + '.gir', + vala_gir: 'Tracker_Vala-' + tracker_api_version + '.gir', vala_args: [ '--debug', '--includedir', 'libtracker-sparql', @@ -56,10 +48,36 @@ tracker_sparql_generated_header = custom_target('tracker-sparql-generated-header # output: 'tracker-generated.h', command: [join_paths(meson.current_source_dir(), 'tracker-sparql-add-include-guards.sh'), join_paths(meson.current_build_dir(), 'tracker-generated-no-checks.h'), '@OUTPUT@'], - depends: libtracker_sparql_intermediate) + depends: libtracker_sparql_intermediate_vala) + +# Now build the C parts ... + +libtracker_sparql_c_sources = files( + 'tracker-namespace-manager.c', + 'tracker-notifier.c', + 'tracker-resource.c', + 'tracker-uri.c', + 'tracker-version.c', +) + +libtracker_sparql_c_public_headers = files( + 'tracker-namespace-manager.h', + 'tracker-notifier.h', + 'tracker-resource.h', + 'tracker-version.h', +) + +libtracker_sparql_intermediate_c = static_library('tracker-sparql-intermediate-c', + enums_c, enums_h, + libtracker_sparql_c_sources, + dependencies: [tracker_common_dep], + c_args: [ + '-DTRACKER_COMPILATION', + ], +) tracker_sparql_intermediate_dep = declare_dependency( - link_with: [libtracker_sparql_intermediate], + link_with: [libtracker_sparql_intermediate_c, libtracker_sparql_intermediate_vala], sources: tracker_sparql_generated_header, include_directories: [srcinc, include_directories('.')], dependencies: tracker_sparql_intermediate_dependencies @@ -73,12 +91,9 @@ configure_file( install_dir: join_paths(get_option('prefix'), get_option('libdir'), 'pkgconfig')) install_headers( - 'tracker-notifier.h', - 'tracker-resource.h', + libtracker_sparql_c_public_headers, 'tracker-ontologies.h', 'tracker-sparql.h', - 'tracker-namespace-manager.h', - 'tracker-version.h', subdir: 'tracker-1.0/libtracker-sparql') # FIXME: we need a custom script to install generated Vala headers; see @@ -87,26 +102,12 @@ meson.add_install_script('../install-generated-header.sh', join_paths(meson.current_build_dir(), 'tracker-generated.h'), join_paths(get_option('prefix'), get_option('includedir'), 'tracker-1.0', 'libtracker-sparql')) -custom_target('tracker-sparql-typelib', - command: ['g-ir-compiler', '--output', '@OUTPUT@', join_paths(meson.current_build_dir(), 'Tracker-1.0.gir')], - #input: join_paths(meson.current_build_dir(), 'Tracker-1.0.gir'), - output: 'Tracker-1.0.typelib', - depends: libtracker_sparql_intermediate, - install: true, - install_dir: join_paths(get_option('libdir'), 'girepository-1.0')) - -# FIXME: reusing the same script to install the .gir; see -# <https://github.com/mesonbuild/meson/issues/891>. -meson.add_install_script('../install-generated-header.sh', - join_paths(meson.current_build_dir(), 'Tracker-1.0.gir'), - join_paths(get_option('prefix'), get_option('datadir'), 'gir-1.0')) - # FIXME: we can't depend properly on the generated .vapi to do this. custom_target('tracker-sparql-' + tracker_api_version + '.vapi', - #input: 'tracker-sparql-vala.vapi', + #input: 'tracker-sparql-intermediate-vala.vapi', output: 'tracker-sparql-' + tracker_api_version + '.vapi', - command: ['sed', '-e', 's/tracker-generated-no-checks.h/tracker-sparql.h/', join_paths(meson.current_build_dir(), 'tracker-sparql.vapi')], - depends: libtracker_sparql_intermediate, + command: ['sed', '-e', 's/tracker-generated-no-checks.h/tracker-sparql.h/', join_paths(meson.current_build_dir(), 'tracker-sparql-intermediate-vala.vapi')], + depends: libtracker_sparql_intermediate_vala, capture: true, install: true, install_dir: vapi_dir) diff --git a/utils/Makefile.am b/utils/Makefile.am index caf0f72f4..caaa83837 100644 --- a/utils/Makefile.am +++ b/utils/Makefile.am @@ -1,4 +1,5 @@ SUBDIRS = \ + g-ir-merge \ gtk-sparql \ ontology \ data-generators \ diff --git a/utils/g-ir-merge/Makefile.am b/utils/g-ir-merge/Makefile.am new file mode 100644 index 000000000..34afbf192 --- /dev/null +++ b/utils/g-ir-merge/Makefile.am @@ -0,0 +1 @@ +EXTRA_DIST = g-ir-merge diff --git a/utils/g-ir-merge/g-ir-merge b/utils/g-ir-merge/g-ir-merge new file mode 100644 index 000000000..66dfb7cb3 --- /dev/null +++ b/utils/g-ir-merge/g-ir-merge @@ -0,0 +1,172 @@ +#!/usr/bin/python3 +# +# Copyright 2017, Sam Thursfield <sam@afuera.me.uk> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA. + + +'''g-ir-merge: combine multiple GObject Introspection namespaces together. + +This tool exists to solve a problem in Tracker: we have code for +libtracker-sparql written in both C and Vala. It's not possible to generate +a single .gir for all of this code as `g-ir-scanner` can't deal with Vala's +generated .c code, and `valac` only handles .vala code. + +The only workable solution seems to be to generate two different .gir files +and manually combine them. Thankfully it's not too difficult to do this. + +For more discussion, see: https://bugzilla.gnome.org/show_bug.cgi?id=782091 + +''' + + +import argparse +import sys +from xml.etree import ElementTree + + +def argument_parser(): + parser = argparse.ArgumentParser( + description="Merge .gir repostories together.") + + parser.add_argument('--namespace', '-n', metavar='NAMESPACE_NAME', type=str, required=True, + help="name for combined .gir namespace") + parser.add_argument('--nsversion', metavar='NAMESPACE_VERSION', type=str, required=True, + help="version for combined .gir namespace") + + parser.add_argument('--c-include', metavar='C_INCLUDES', type=list, + help="override list of C includes") + + parser.add_argument('files', metavar="GIR_FILE", type=str, nargs='+', + help="input .gir file") + return parser + + +def parse_inputs(files): + '''Read the important contents from one or more .gir files and return all. + + This does no post-processing of the data, it simply returns everything + including any duplicate or contractory info. + + ''' + ns = { + 'core': 'http://www.gtk.org/introspection/core/1.0', + 'c': 'http://www.gtk.org/introspection/c/1.0' + } + + includes = [] + namespaces = [] + c_includes = [] + + for file in files: + gi_repository = ElementTree.parse(file).getroot() + + for gi_include in gi_repository.findall('core:include', ns): + includes.append(gi_include) + + for gi_namespace in gi_repository.findall('core:namespace', ns): + namespaces.append(gi_namespace) + + for gi_c_include in gi_repository.findall('c:include', ns): + c_includes.append(gi_c_include) + + return includes, namespaces, c_includes + + +def merge_includes(all_includes): + merged = {} + for element in all_includes: + name = element.get('name') + version = element.get('version') + if name not in merged: + merged[name] = element + return merged.values() + + +def merge_namespaces(all_namespaces): + identifier_prefixes = set() + symbol_prefixes = set() + shared_libraries = set() + + contents = [] + + for element in all_namespaces: + if element.get('c:identifier_prefixes', None): + identifier_prefixes.update(element.get('c:identifier_prefixes').split(',')) + if element.get('c:symbol_prefixes', None): + symbol_prefixes.update(element.get('c:symbol_prefixes').split(',')) + identifier_prefixes.update(element.get('c:prefix', [])) + symbol_prefixes.update(element.get('c:prefix', [])) + + if element.get('shared-library', None): + shared_libraries.update(element.get('shared-library', '').split(',')) + + contents.extend(element) + + return (contents, + ','.join(sorted(identifier_prefixes)), + ','.join(sorted(symbol_prefixes)), + ','.join(sorted(shared_libraries))) + + +def create_repository(namespace_name, namespace_version, shared_libraries, + c_identifier_prefixes, c_symbol_prefixes, includes, namespace_contents): + '''Create a new GI repository with a single namespace.''' + ElementTree.register_namespace( + '', 'http://www.gtk.org/introspection/core/1.0') + ElementTree.register_namespace( + 'c', 'http://www.gtk.org/introspection/c/1.0') + ElementTree.register_namespace( + 'glib', 'http://www.gtk.org/introspection/glib/1.0') + gir_version = '1.2' + + repository = ElementTree.Element('repository', attrib={'version': gir_version}) + repository.extend(includes) + + namespace = ElementTree.SubElement(repository, 'namespace', attrib={ + 'name': namespace_name, + 'version': namespace_version, + 'shared-library': shared_libraries, + 'c:identifier-prefixes': c_identifier_prefixes, + 'c:symbol-prefixes': c_symbol_prefixes, + }) + namespace.extend(namespace_contents) + + return repository + + +def main(): + args = argument_parser().parse_args() + + all_includes, all_namespaces, all_c_includes = parse_inputs(args.files) + + includes = merge_includes(all_includes) + + namespace_contents, identifier_prefixes, symbol_prefixes, shared_libraries \ + = merge_namespaces(all_namespaces) + + repository = create_repository(args.namespace, args.nsversion, shared_libraries, + identifier_prefixes, symbol_prefixes, + includes, namespace_contents) + + print(ElementTree.tostring(repository, encoding="unicode")) + + +try: + main() +except RuntimeError as e: + sys.stderr.write("{}\n".format(e)) + sys.exit(1) |