From 2c2fa66655538628374cdbff407308dafaa36fb3 Mon Sep 17 00:00:00 2001 From: Sam Thursfield Date: Sun, 21 May 2017 23:36:11 +0100 Subject: Add support for merging multiple .gir files into a single .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. --- girepository/girmodule.c | 34 +++++++++++++++++++ girepository/girmodule.h | 2 ++ tools/compiler.c | 86 ++++++++++++++++++++++++++++++++++++++---------- 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"); -- cgit v1.2.1