glib-compile-resources: generate .d-file style dependency

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 in
https://bugzilla.gnome.org/show_bug.cgi?id=745754

The changes in this patch, compared to his are to always return
the hash table with file information from parse_resource_file, so
we can use it for dependency output, regardless if generate_dependencies
was TRUE or not.
This commit is contained in:
Matthias Clasen 2016-08-20 16:47:34 -04:00
parent 9afff5f05d
commit 87d76a5a9c
2 changed files with 81 additions and 15 deletions

View File

@ -124,6 +124,9 @@ test.gresource: test.gresource.xml $(shell $(GLIB_COMPILE_RESOURCES) --generate-
</programlisting> </programlisting>
Note that this may or may not be portable to non-GNU <command>make</command>. Note that this may or may not be portable to non-GNU <command>make</command>.
</para> </para>
<para>
Also see <option>--dependency-file</option>.
</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
@ -160,6 +163,17 @@ which is what <option>--internal</option> does.
</para></listitem> </para></listitem>
</varlistentry> </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> </variablelist>
</refsect1> </refsect1>

View File

@ -416,7 +416,6 @@ end_element (GMarkupParseContext *context,
} }
done: done:
g_hash_table_insert (state->table, key, data); g_hash_table_insert (state->table, key, data);
data = NULL; data = NULL;
@ -476,7 +475,8 @@ text (GMarkupParseContext *context,
static GHashTable * static GHashTable *
parse_resource_file (const gchar *filename, parse_resource_file (const gchar *filename,
gboolean collect_data) gboolean collect_data,
GHashTable *files)
{ {
GMarkupParser parser = { start_element, end_element, text }; GMarkupParser parser = { start_element, end_element, text };
ParseState state = { 0, }; ParseState state = { 0, };
@ -493,8 +493,8 @@ parse_resource_file (const gchar *filename,
return NULL; 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.collect_data = collect_data;
state.table = g_hash_table_ref (files);
context = g_markup_parse_context_new (&parser, context = g_markup_parse_context_new (&parser,
G_MARKUP_TREAT_CDATA_AS_TEXT | G_MARKUP_TREAT_CDATA_AS_TEXT |
@ -507,7 +507,7 @@ parse_resource_file (const gchar *filename,
g_printerr ("%s: %s.\n", filename, error->message); g_printerr ("%s: %s.\n", filename, error->message);
g_clear_error (&error); g_clear_error (&error);
} }
else if (collect_data) else
{ {
GHashTableIter iter; GHashTableIter iter;
const char *key; const char *key;
@ -547,10 +547,6 @@ parse_resource_file (const gchar *filename,
g_variant_builder_end (&builder)); g_variant_builder_end (&builder));
} }
} }
else
{
table = g_hash_table_ref (state.table);
}
g_hash_table_unref (state.table); g_hash_table_unref (state.table);
g_markup_parse_context_free (context); g_markup_parse_context_free (context);
@ -605,6 +601,7 @@ main (int argc, char **argv)
{ {
GError *error; GError *error;
GHashTable *table; GHashTable *table;
GHashTable *files;
gchar *srcfile; gchar *srcfile;
gchar *target = NULL; gchar *target = NULL;
gchar *binary_target = NULL; gchar *binary_target = NULL;
@ -614,6 +611,7 @@ main (int argc, char **argv)
gboolean manual_register = FALSE; gboolean manual_register = FALSE;
gboolean internal = FALSE; gboolean internal = FALSE;
gboolean generate_dependencies = FALSE; gboolean generate_dependencies = FALSE;
char *dependency_file = NULL;
char *c_name = NULL; char *c_name = NULL;
char *c_name_no_underscores; char *c_name_no_underscores;
const char *linkage = "extern"; const char *linkage = "extern";
@ -625,6 +623,7 @@ main (int argc, char **argv)
{ "generate-header", 0, 0, G_OPTION_ARG_NONE, &generate_header, N_("Generate source header"), NULL }, { "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-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 }, { "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 }, { "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 }, { "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 }, { "c-name", 0, 0, G_OPTION_ARG_STRING, &c_name, N_("C identifier name used for the generated source code"), NULL },
@ -732,26 +731,79 @@ 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, !generate_dependencies, files)) == NULL)
{ {
g_free (target); g_free (target);
g_free (c_name); g_free (c_name);
return 1; return 1;
} }
if (generate_dependencies) if (generate_dependencies || dependency_file != NULL)
{ {
GHashTableIter iter; GHashTableIter iter;
gpointer key, data; gpointer key, data;
FileData *file_data; FileData *file_data;
g_hash_table_iter_init (&iter, table); g_hash_table_iter_init (&iter, files);
if (dependency_file == NULL)
{
/* Generate list of files for direct use as dependencies in a Makefile */
while (g_hash_table_iter_next (&iter, &key, &data)) while (g_hash_table_iter_next (&iter, &key, &data))
{ {
file_data = data; file_data = data;
g_print ("%s\n", file_data->filename); 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) else if (generate_source || generate_header)
{ {
if (generate_source) if (generate_source)