summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorSam Thursfield <sam@afuera.me.uk>2017-06-23 16:25:05 +0100
committerCarlos Garnacho <carlosg@gnome.org>2017-06-28 11:53:54 +0200
commit796e025156d5176afd3a76907d0f881a6069fd25 (patch)
tree3249002514251c1605e5cb6fd90fa44d8b1dcfbc /utils
parent1ef2fb92c66078b9604ca7a1026f8e324f4495c3 (diff)
downloadtracker-796e025156d5176afd3a76907d0f881a6069fd25.tar.gz
Fix missing introspection data for libtracker-sparql (when using Meson)
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
Diffstat (limited to 'utils')
-rw-r--r--utils/Makefile.am2
-rwxr-xr-xutils/g-ir-merge/g-ir-merge172
2 files changed, 173 insertions, 1 deletions
diff --git a/utils/Makefile.am b/utils/Makefile.am
index caf0f72f4..88dcffd10 100644
--- a/utils/Makefile.am
+++ b/utils/Makefile.am
@@ -9,4 +9,4 @@ if HAVE_TRACKER_RESDUMP
SUBDIRS += tracker-resdump
endif
-EXTRA_DIST = meson.build
+EXTRA_DIST = meson.build g-ir-merge/g-ir-merge
diff --git a/utils/g-ir-merge/g-ir-merge b/utils/g-ir-merge/g-ir-merge
new file mode 100755
index 000000000..45ed5f535
--- /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
+
+CORE_NAMESPACE = 'http://www.gtk.org/introspection/core/1.0'
+C_NAMESPACE = 'http://www.gtk.org/introspection/c/1.0'
+GLIB_NAMESPACE = 'http://www.gtk.org/introspection/glib/1.0'
+
+def argument_parser():
+ parser = argparse.ArgumentParser(
+ description="Merge .gir repositories 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 contradictory info.
+
+ '''
+ ns = {
+ 'core': CORE_NAMESPACE,
+ 'c': C_NAMESPACE
+ }
+
+ 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('', CORE_NAMESPACE)
+ ElementTree.register_namespace('c', C_NAMESPACE)
+ ElementTree.register_namespace('glib', GLIB_NAMESPACE)
+ 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)