summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Thursfield <sam@afuera.me.uk>2017-05-21 23:36:11 +0100
committerSam Thursfield <sam@afuera.me.uk>2017-05-21 23:36:11 +0100
commit2c2fa66655538628374cdbff407308dafaa36fb3 (patch)
treeb68c995ed6851026d2fa7ba377a9c160ea56f6b7
parent85b1d70b93211415d975deff6050f1401743e72d (diff)
downloadgobject-introspection-wip/sam/multiple-girs-one-typelib.tar.gz
Add support for merging multiple .gir files into a single .typelibwip/sam/multiple-girs-one-typelib
This is needed for libraries which are implemented in multiple languages, for example libtracker-sparql which partly C and partly Vala. The Vala compiler cannot generate a .gir for the C code, and g-ir-scanner cannot effectively scan the C code generated by `valac` (see https://bugzilla.gnome.org/show_bug.cgi?id=781354) Requires tests.
-rw-r--r--girepository/girmodule.c34
-rw-r--r--girepository/girmodule.h2
-rw-r--r--tools/compiler.c86
3 files changed, 104 insertions, 18 deletions
diff --git a/girepository/girmodule.c b/girepository/girmodule.c
index 66b33fa1..e166bedd 100644
--- a/girepository/girmodule.c
+++ b/girepository/girmodule.c
@@ -79,6 +79,40 @@ _g_ir_module_free (GIrModule *module)
g_slice_free (GIrModule, module);
}
+void
+_g_ir_module_merge (GIrModule *left,
+ GIrModule *right)
+{
+ GHashTableIter iter;
+ gpointer key, value;
+
+ g_assert (strcmp (left->name, right->name) == 0);
+ g_assert (strcmp (left->version, right->version) == 0);
+ g_assert (strcmp (left->shared_library, right->shared_library) == 0);
+ g_assert (strcmp (left->c_prefix, right->c_prefix) == 0);
+
+ /* FIXME: dedup */
+ left->dependencies = g_list_concat (left->dependencies, right->dependencies);
+
+ left->entries = g_list_concat (left->entries, right->entries);
+
+ left->include_modules = g_list_concat (left->include_modules, right->include_modules);
+
+ g_hash_table_iter_init (&iter, right->aliases);
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ {
+ /* FIXME: check for conflicts */
+ g_hash_table_insert (left->aliases, key, value);
+ }
+
+ g_hash_table_iter_init (&iter, right->disguised_structures);
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ {
+ /* FIXME: check for conflicts */
+ g_hash_table_insert (left->disguised_structures, key, value);
+ }
+}
+
/**
* _g_ir_module_fatal:
* @build: Current build
diff --git a/girepository/girmodule.h b/girepository/girmodule.h
index 7837f2cf..657a0c29 100644
--- a/girepository/girmodule.h
+++ b/girepository/girmodule.h
@@ -66,6 +66,8 @@ GIrModule *_g_ir_module_new (const gchar *name,
const gchar *c_prefix);
void _g_ir_module_free (GIrModule *module);
+void _g_ir_module_merge (GIrModule *left, GIrModule *right);
+
void _g_ir_module_add_include_module (GIrModule *module,
GIrModule *include_module);
diff --git a/tools/compiler.c b/tools/compiler.c
index 9485761c..787c5df1 100644
--- a/tools/compiler.c
+++ b/tools/compiler.c
@@ -45,6 +45,71 @@ gboolean include_cwd = FALSE;
gboolean debug = FALSE;
gboolean verbose = FALSE;
+static GIrModule *
+parse_modules () {
+ GIrParser *parser;
+ GIrModule *current_module, *first_module = NULL;
+ gchar **module_filename_ptr;
+ gint i;
+ GError *error = NULL;
+
+ if (includedirs != NULL)
+ for (i = 0; includedirs[i]; i++)
+ g_irepository_prepend_search_path (includedirs[i]);
+
+ parser = _g_ir_parser_new ();
+ _g_ir_parser_set_includes (parser, (const char*const*) includedirs);
+
+ for (module_filename_ptr = input; *module_filename_ptr != NULL; module_filename_ptr ++)
+ {
+ current_module = _g_ir_parser_parse_file (parser, *module_filename_ptr, &error);
+
+ if (current_module == NULL)
+ {
+ g_fprintf (stderr, "error parsing file %s: %s\n",
+ *module_filename_ptr, error->message);
+ return NULL;
+ }
+
+ if (first_module == NULL)
+ {
+ first_module = current_module;
+ }
+ else
+ {
+ if (strcmp (current_module->name, first_module->name) != 0)
+ {
+ g_fprintf (stderr, "All current_modules must have the same namespace name. "
+ "Got %s and %s.", first_module->name, current_module->name);
+ return NULL;
+ }
+ if (strcmp (current_module->version, first_module->version) != 0)
+ {
+ g_fprintf (stderr, "All current_modules must have the same namespace version. "
+ "Got %s and %s.", first_module->version, current_module->version);
+ return NULL;
+ }
+ if (strcmp (current_module->shared_library, first_module->shared_library) != 0)
+ {
+ g_fprintf (stderr, "All current_modules must be in the same shared library. "
+ "Got %s and %s.", first_module->shared_library, current_module->shared_library);
+ return NULL;
+ }
+ if (strcmp (current_module->c_prefix, first_module->c_prefix) != 0)
+ {
+ g_fprintf (stderr, "All current_modules must be in the same C prefix. "
+ "Got %s and %s.", first_module->c_prefix, current_module->c_prefix);
+ return NULL;
+ }
+
+ _g_ir_module_merge (first_module, current_module);
+ _g_ir_module_free (current_module);
+ }
+ }
+
+ return first_module;
+};
+
static gboolean
write_out_typelib (gchar *prefix,
GITypelib *typelib)
@@ -143,9 +208,7 @@ main (int argc, char ** argv)
{
GOptionContext *context;
GError *error = NULL;
- GIrParser *parser;
GIrModule *module;
- gint i;
g_typelib_check_sanity ();
context = g_option_context_new ("");
@@ -181,22 +244,9 @@ main (int argc, char ** argv)
g_debug ("[parsing] start, %d includes",
includedirs ? g_strv_length (includedirs) : 0);
- if (includedirs != NULL)
- for (i = 0; includedirs[i]; i++)
- g_irepository_prepend_search_path (includedirs[i]);
-
- parser = _g_ir_parser_new ();
-
- _g_ir_parser_set_includes (parser, (const char*const*) includedirs);
-
- module = _g_ir_parser_parse_file (parser, input[0], &error);
- if (module == NULL)
- {
- g_fprintf (stderr, "error parsing file %s: %s\n",
- input[0], error->message);
-
- return 1;
- }
+ module = parse_modules ();
+ if (!module)
+ return 1;
g_debug ("[parsing] done");