[glib] glib-compile-resources: generate .d-file style dependency output for build tools



commit e8c8395f0e72f59e37189e94b08052bebb51ac77
Author: Tim-Philipp Müller <tim centricular com>
Date:   Tue Jan 26 19:21:57 2016 +0000

    glib-compile-resources: generate .d-file style dependency output for build tools
    
    Add --dependency-file=foo.d option to generate a gcc -M -MF style
    dependency file for other build tools. The current output of
    --generate-dependencies is only useful for use directly in Makefile
    rules, but can't be used in other build systems like that.
    
    The generated dependency file looks like this:
    $ glib-compile-resources --sourcedir= test.gresource.xml --dependency-file=-
    test.gresource.xml: test1.txt test2.txt test2.txt
    
    test1.txt:
    
    test2.txt:
    
    test2.txt:
    
    Unlike --generate-dependencies, the --dependency-file option can be
    used together with other --generate options to create dependencies
    as side-effect of generating sources.
    
    Based on a patch by Tim-Philipp Müller.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=745754

 docs/reference/gio/glib-compile-resources.xml |   14 ++++
 gio/glib-compile-resources.c                  |   89 +++++++++++++++++++------
 2 files changed, 81 insertions(+), 22 deletions(-)
---
diff --git a/docs/reference/gio/glib-compile-resources.xml b/docs/reference/gio/glib-compile-resources.xml
index fcce89a..c2c1989 100644
--- a/docs/reference/gio/glib-compile-resources.xml
+++ b/docs/reference/gio/glib-compile-resources.xml
@@ -124,6 +124,9 @@ test.gresource: test.gresource.xml $(shell $(GLIB_COMPILE_RESOURCES) --generate-
 </programlisting>
 Note that this may or may not be portable to non-GNU <command>make</command>.
 </para>
+<para>
+Also see <option>--dependency-file</option>.
+</para>
 </listitem>
 </varlistentry>
 
@@ -160,6 +163,17 @@ which is what <option>--internal</option> does.
 </para></listitem>
 </varlistentry>
 
+<varlistentry>
+<term><option>--dependency-file=<replaceable>FILE</replaceable></option></term>
+<listitem><para>
+Write dependencies in the same style as gcc -M -MF to the given file.
+If <option>FILE</option> is -, the dependencies are written to the standard
+output. Unlike <option>--generate-dependencies</option>, this option can be
+combined with other <option>--generate</option> options to generate dependencies
+as a side-effect of generating sources.
+</para></listitem>
+</varlistentry>
+
 </variablelist>
 </refsect1>
 
diff --git a/gio/glib-compile-resources.c b/gio/glib-compile-resources.c
index 71a0f48..7c35bf3 100644
--- a/gio/glib-compile-resources.c
+++ b/gio/glib-compile-resources.c
@@ -61,8 +61,6 @@ typedef struct
 {
   GHashTable *table; /* resource path -> FileData */
 
-  gboolean collect_data;
-
   /* per gresource */
   char *prefix;
 
@@ -242,7 +240,7 @@ end_element (GMarkupParseContext  *context,
       if (sourcedirs != NULL)
         {
          real_file = find_file (file);
-         if (real_file == NULL && state->collect_data)
+         if (real_file == NULL)
            {
                g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                             _("Failed to locate '%s' in any source directory"), file);
@@ -253,7 +251,7 @@ end_element (GMarkupParseContext  *context,
         {
          gboolean exists;
          exists = g_file_test (file, G_FILE_TEST_EXISTS);
-         if (!exists && state->collect_data)
+         if (!exists)
            {
              g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                           _("Failed to locate '%s' in current directory"), file);
@@ -266,8 +264,6 @@ end_element (GMarkupParseContext  *context,
 
       data = g_new0 (FileData, 1);
       data->filename = g_strdup (real_file);
-      if (!state->collect_data)
-        goto done;
 
       if (state->preproc_options)
         {
@@ -415,8 +411,6 @@ end_element (GMarkupParseContext  *context,
          data->flags |= G_RESOURCE_FLAGS_COMPRESSED;
        }
 
-    done:
-
       g_hash_table_insert (state->table, key, data);
       data = NULL;
 
@@ -476,7 +470,7 @@ text (GMarkupParseContext  *context,
 
 static GHashTable *
 parse_resource_file (const gchar *filename,
-                     gboolean collect_data)
+                     GHashTable  *files)
 {
   GMarkupParser parser = { start_element, end_element, text };
   ParseState state = { 0, };
@@ -493,8 +487,7 @@ parse_resource_file (const gchar *filename,
       return NULL;
     }
 
-  state.table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)file_data_free);
-  state.collect_data = collect_data;
+  state.table = g_hash_table_ref (files);
 
   context = g_markup_parse_context_new (&parser,
                                        G_MARKUP_TREAT_CDATA_AS_TEXT |
@@ -507,7 +500,7 @@ parse_resource_file (const gchar *filename,
       g_printerr ("%s: %s.\n", filename, error->message);
       g_clear_error (&error);
     }
-  else if (collect_data)
+  else
     {
       GHashTableIter iter;
       const char *key;
@@ -547,10 +540,6 @@ parse_resource_file (const gchar *filename,
                               g_variant_builder_end (&builder));
        }
     }
-  else
-    {
-      table = g_hash_table_ref (state.table);
-    }
 
   g_hash_table_unref (state.table);
   g_markup_parse_context_free (context);
@@ -605,6 +594,7 @@ main (int argc, char **argv)
 {
   GError *error;
   GHashTable *table;
+  GHashTable *files;
   gchar *srcfile;
   gchar *target = NULL;
   gchar *binary_target = NULL;
@@ -614,6 +604,7 @@ main (int argc, char **argv)
   gboolean manual_register = FALSE;
   gboolean internal = FALSE;
   gboolean generate_dependencies = FALSE;
+  char *dependency_file = NULL;
   char *c_name = NULL;
   char *c_name_no_underscores;
   const char *linkage = "extern";
@@ -625,6 +616,7 @@ main (int argc, char **argv)
     { "generate-header", 0, 0, G_OPTION_ARG_NONE, &generate_header, N_("Generate source header"), NULL },
     { "generate-source", 0, 0, G_OPTION_ARG_NONE, &generate_source, N_("Generate sourcecode used to link in 
the resource file into your code"), NULL },
     { "generate-dependencies", 0, 0, G_OPTION_ARG_NONE, &generate_dependencies, N_("Generate dependency 
list"), NULL },
+    { "dependency-file", 0, 0, G_OPTION_ARG_FILENAME, &dependency_file, N_("name of the dependency file to 
generate"), N_("FILE") },
     { "manual-register", 0, 0, G_OPTION_ARG_NONE, &manual_register, N_("Don't automatically create and 
register resource"), NULL },
     { "internal", 0, 0, G_OPTION_ARG_NONE, &internal, N_("Don't export functions; declare them 
G_GNUC_INTERNAL"), NULL },
     { "c-name", 0, 0, G_OPTION_ARG_STRING, &c_name, N_("C identifier name used for the generated source 
code"), NULL },
@@ -732,24 +724,77 @@ main (int argc, char **argv)
         ;
     }
 
-  if ((table = parse_resource_file (srcfile, !generate_dependencies)) == NULL)
+  files = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)file_data_free);
+
+  if ((table = parse_resource_file (srcfile, files)) == NULL)
     {
       g_free (target);
       g_free (c_name);
       return 1;
     }
 
-  if (generate_dependencies)
+  if (generate_dependencies || dependency_file != NULL)
     {
       GHashTableIter iter;
       gpointer key, data;
       FileData *file_data;
 
-      g_hash_table_iter_init (&iter, table);
-      while (g_hash_table_iter_next (&iter, &key, &data))
+      g_hash_table_iter_init (&iter, files);
+      if (dependency_file == NULL)
         {
-          file_data = data;
-          g_print ("%s\n",file_data->filename);
+          /* Generate list of files for direct use as dependencies in a Makefile */
+          while (g_hash_table_iter_next (&iter, &key, &data))
+            {
+              file_data = data;
+              g_print ("%s\n", file_data->filename);
+            }
+        }
+      else
+        {
+          /* Generate a .d file that describes the dependencies for
+           * build tools, gcc -M -MF style */
+          GString *dep_string;
+
+          dep_string = g_string_new (NULL);
+          g_string_printf (dep_string, "%s:", srcfile);
+
+          /* First rule: foo.xml: resource1 resource2.. */
+          while (g_hash_table_iter_next (&iter, &key, &data))
+            {
+              file_data = data;
+              if (!g_str_equal (file_data->filename, srcfile))
+                g_string_append_printf (dep_string, " %s", file_data->filename);
+            }
+
+          g_string_append (dep_string, "\n\n");
+
+          /* One rule for every resource: resourceN: */
+          g_hash_table_iter_init (&iter, files);
+          while (g_hash_table_iter_next (&iter, &key, &data))
+            {
+              file_data = data;
+              if (!g_str_equal (file_data->filename, srcfile))
+                g_string_append_printf (dep_string, "%s:\n\n", file_data->filename);
+            }
+
+          if (g_str_equal (dependency_file, "-"))
+            {
+              g_print ("%s\n", dep_string->str);
+            }
+          else
+            {
+              if (!g_file_set_contents (dependency_file, dep_string->str, dep_string->len, &error))
+                {
+                  g_printerr ("Error writing dependency file: %s\n", error->message);
+                  g_string_free (dep_string, TRUE);
+                  g_free (dependency_file);
+                  g_error_free (error);
+                  return 1;
+                }
+            }
+
+          g_string_free (dep_string, TRUE);
+          g_free (dependency_file);
         }
     }
   else if (generate_source || generate_header)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]