summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Thursfield <sam@afuera.me.uk>2017-06-23 16:25:05 +0100
committerSam Thursfield <sam@afuera.me.uk>2017-06-23 19:59:09 +0100
commitd0d3ab9296f248dd21f9036f3cb6d60a413e530f (patch)
tree19dbb5706e22a5c790c10caf1e120b2ca4b5a89b
parentd5ae8e05f8e04b66a1e44fdfd85170b1d80d14d3 (diff)
downloadtracker-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.build10
-rw-r--r--src/libtracker-sparql-backend/meson.build38
-rw-r--r--src/libtracker-sparql/meson.build71
-rw-r--r--utils/Makefile.am1
-rw-r--r--utils/g-ir-merge/Makefile.am1
-rw-r--r--utils/g-ir-merge/g-ir-merge172
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)