X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fglib-compile-resources.c;h=6bad64fc49d2a7eb23461a6d5e06f4a5663cbfa1;hb=c8d10470939847069b1a346d4c44f2adde3469f6;hp=d5d8f75cc06bc82f34c960b50f930d07a23ae084;hpb=d825828b7b00f67a06ef1b6ba7ddb9c5dd6b0d87;p=platform%2Fupstream%2Fglib.git diff --git a/gio/glib-compile-resources.c b/gio/glib-compile-resources.c index d5d8f75..6bad64f 100644 --- a/gio/glib-compile-resources.c +++ b/gio/glib-compile-resources.c @@ -12,15 +12,14 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library; if not, see . * * Author: Alexander Larsson */ #include "config.h" +#include #include #include #include @@ -28,20 +27,30 @@ #include #include #include +#include +#ifdef G_OS_UNIX +#include +#endif +#ifdef G_OS_WIN32 +#include +#endif #include #include #include -#ifdef HAVE_UNISTD_H -#include -#endif - #include #include "gvdb/gvdb-builder.h" +#include "gconstructor_as_data.h" + +#ifdef G_OS_WIN32 +#include "glib/glib-private.h" +#endif + typedef struct { + char *filename; char *content; gsize content_size; gsize size; @@ -52,21 +61,27 @@ typedef struct { GHashTable *table; /* resource path -> FileData */ + gboolean collect_data; + /* per gresource */ char *prefix; /* per file */ char *alias; gboolean compressed; + char *preproc_options; GString *string; /* non-NULL when accepting text */ } ParseState; -gchar *sourcedir = NULL; +static gchar **sourcedirs = NULL; +static gchar *xmllint = NULL; +static gchar *gdk_pixbuf_pixdata = NULL; static void file_data_free (FileData *data) { + g_free (data->filename); g_free (data->content); g_free (data); } @@ -115,7 +130,8 @@ start_element (GMarkupParseContext *context, if (strcmp (element_name, "file") == 0) { COLLECT (OPTIONAL | STRDUP, "alias", &state->alias, - OPTIONAL | BOOL, "compressed", &state->compressed); + OPTIONAL | BOOL, "compressed", &state->compressed, + OPTIONAL | STRDUP, "preprocess", &state->preproc_options); state->string = g_string_new (""); return; } @@ -159,6 +175,28 @@ get_parent (GHashTable *table, return parent; } +static gchar * +find_file (const gchar *filename) +{ + guint i; + gchar *real_file; + gboolean exists; + + if (g_path_is_absolute (filename)) + return g_strdup (filename); + + /* search all the sourcedirs for the correct files in order */ + for (i = 0; sourcedirs[i] != NULL; i++) + { + real_file = g_build_path ("/", sourcedirs[i], filename, NULL); + exists = g_file_test (real_file, G_FILE_TEST_EXISTS); + if (exists) + return real_file; + g_free (real_file); + } + return NULL; +} + static void end_element (GMarkupParseContext *context, const gchar *element_name, @@ -179,6 +217,8 @@ end_element (GMarkupParseContext *context, gchar *file, *real_file; gchar *key; FileData *data; + char *tmp_file = NULL; + char *tmp_file2 = NULL; file = state->string->str; key = file; @@ -200,10 +240,139 @@ end_element (GMarkupParseContext *context, data = g_new0 (FileData, 1); - if (sourcedir != NULL) - real_file = g_build_filename (sourcedir, file, NULL); + if (sourcedirs != NULL) + { + real_file = find_file (file); + if (real_file == NULL) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + _("Failed to locate '%s' in any source directory"), file); + return; + } + } else - real_file = g_strdup (file); + { + gboolean exists; + exists = g_file_test (file, G_FILE_TEST_EXISTS); + if (!exists) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + _("Failed to locate '%s' in current directory"), file); + return; + } + real_file = g_strdup (file); + } + + data->filename = g_strdup (real_file); + if (!state->collect_data) + goto done; + + if (state->preproc_options) + { + gchar **options; + guint i; + gboolean xml_stripblanks = FALSE; + gboolean to_pixdata = FALSE; + + options = g_strsplit (state->preproc_options, ",", -1); + + for (i = 0; options[i]; i++) + { + if (!strcmp (options[i], "xml-stripblanks")) + xml_stripblanks = TRUE; + else if (!strcmp (options[i], "to-pixdata")) + to_pixdata = TRUE; + else + { + g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, + _("Unknown processing option \"%s\""), options[i]); + g_strfreev (options); + goto cleanup; + } + } + g_strfreev (options); + + if (xml_stripblanks && xmllint != NULL) + { + int fd; + GSubprocess *proc; + + tmp_file = g_strdup ("resource-XXXXXXXX"); + if ((fd = g_mkstemp (tmp_file)) == -1) + { + int errsv = errno; + + g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv), + _("Failed to create temp file: %s"), + g_strerror (errsv)); + g_free (tmp_file); + tmp_file = NULL; + goto cleanup; + } + close (fd); + + proc = g_subprocess_new (G_SUBPROCESS_FLAGS_STDOUT_SILENCE, error, + xmllint, "--nonet", "--noblanks", "--output", tmp_file, real_file, NULL); + g_free (real_file); + real_file = NULL; + + if (!proc) + goto cleanup; + + if (!g_subprocess_wait_check (proc, NULL, error)) + { + g_object_unref (proc); + goto cleanup; + } + + g_object_unref (proc); + + real_file = g_strdup (tmp_file); + } + + if (to_pixdata) + { + int fd; + GSubprocess *proc; + + if (gdk_pixbuf_pixdata == NULL) + { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "to-pixbuf preprocessing requested but GDK_PIXBUF_PIXDATA " + "not set and gdk-pixbuf-pixdata not found in path"); + goto cleanup; + } + + tmp_file2 = g_strdup ("resource-XXXXXXXX"); + if ((fd = g_mkstemp (tmp_file2)) == -1) + { + int errsv = errno; + + g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv), + _("Failed to create temp file: %s"), + g_strerror (errsv)); + g_free (tmp_file2); + tmp_file2 = NULL; + goto cleanup; + } + close (fd); + + proc = g_subprocess_new (G_SUBPROCESS_FLAGS_STDOUT_SILENCE, error, + gdk_pixbuf_pixdata, real_file, tmp_file2, NULL); + g_free (real_file); + real_file = NULL; + + if (!g_subprocess_wait_check (proc, NULL, error)) + { + g_object_unref (proc); + goto cleanup; + } + + g_object_unref (proc); + + real_file = g_strdup (tmp_file2); + } + } if (!g_file_get_contents (real_file, &data->content, &data->size, &my_error)) { @@ -211,7 +380,7 @@ end_element (GMarkupParseContext *context, _("Error reading file %s: %s"), real_file, my_error->message); g_clear_error (&my_error); - return; + goto cleanup; } /* Include zero termination in content_size for uncompressed files (but not in size) */ data->content_size = data->size + 1; @@ -230,7 +399,7 @@ end_element (GMarkupParseContext *context, g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, _("Error compressing file %s"), real_file); - return; + goto cleanup; } g_free (data->content); @@ -244,16 +413,33 @@ end_element (GMarkupParseContext *context, data->flags |= G_RESOURCE_FLAGS_COMPRESSED; } - g_free (real_file); + done: g_hash_table_insert (state->table, key, data); + cleanup: /* Cleanup */ g_free (state->alias); state->alias = NULL; g_string_free (state->string, TRUE); state->string = NULL; + g_free (state->preproc_options); + state->preproc_options = NULL; + + g_free (real_file); + + if (tmp_file) + { + unlink (tmp_file); + g_free (tmp_file); + } + + if (tmp_file2) + { + unlink (tmp_file2); + g_free (tmp_file2); + } } } @@ -283,7 +469,8 @@ text (GMarkupParseContext *context, } static GHashTable * -parse_resource_file (const gchar *filename) +parse_resource_file (const gchar *filename, + gboolean collect_data) { GMarkupParser parser = { start_element, end_element, text }; ParseState state = { 0, }; @@ -301,6 +488,7 @@ parse_resource_file (const gchar *filename) } state.table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)file_data_free); + state.collect_data = collect_data; context = g_markup_parse_context_new (&parser, G_MARKUP_TREAT_CDATA_AS_TEXT | @@ -313,7 +501,7 @@ parse_resource_file (const gchar *filename) g_printerr ("%s: %s.\n", filename, error->message); g_clear_error (&error); } - else + else if (collect_data) { GHashTableIter iter; const char *key; @@ -353,8 +541,12 @@ parse_resource_file (const gchar *filename) g_variant_builder_end (&builder)); } } + else + { + table = g_hash_table_ref (state.table); + } - g_hash_table_destroy (state.table); + g_hash_table_unref (state.table); g_markup_parse_context_free (context); g_free (contents); @@ -382,25 +574,31 @@ main (int argc, char **argv) GHashTable *table; gchar *srcfile; gchar *target = NULL; - gchar *binary_target; + gchar *binary_target = NULL; + gboolean generate_automatic = FALSE; gboolean generate_source = FALSE; gboolean generate_header = FALSE; gboolean manual_register = FALSE; + gboolean internal = FALSE; + gboolean generate_dependencies = FALSE; char *c_name = NULL; char *c_name_no_underscores; + const char *linkage = "extern"; GOptionContext *context; GOptionEntry entries[] = { { "target", 0, 0, G_OPTION_ARG_FILENAME, &target, N_("name of the output file"), N_("FILE") }, - { "sourcedir", 0, 0, G_OPTION_ARG_FILENAME, &sourcedir, N_("The directory where files are to be read from (default to current directory)"), N_("DIRECTORY") }, + { "sourcedir", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &sourcedirs, N_("The directories where files are to be read from (default to current directory)"), N_("DIRECTORY") }, + { "generate", 0, 0, G_OPTION_ARG_NONE, &generate_automatic, N_("Generate output in the format selected for by the target filename extension"), 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-dependencies", 0, 0, G_OPTION_ARG_NONE, &generate_dependencies, N_("Generate dependency list"), 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 }, { "c-name", 0, 0, G_OPTION_ARG_STRING, &c_name, N_("C identifier name used for the generated source code"), NULL }, { NULL } }; #ifdef G_OS_WIN32 - extern gchar *_glib_get_locale_dir (void); gchar *tmp; #endif @@ -419,8 +617,6 @@ main (int argc, char **argv) bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); #endif - g_type_init (); - context = g_option_context_new (N_("FILE")); g_option_context_set_translation_domain (context, GETTEXT_PACKAGE); g_option_context_set_summary (context, @@ -444,10 +640,20 @@ main (int argc, char **argv) return 1; } + if (internal) + linkage = "G_GNUC_INTERNAL"; + srcfile = argv[1]; - if (sourcedir == NULL) - sourcedir = ""; + xmllint = g_strdup (g_getenv ("XMLLINT")); + if (xmllint == NULL) + xmllint = g_find_program_in_path ("xmllint"); + if (xmllint == NULL) + g_printerr ("XMLLINT not set and xmllint not found in path; skipping xml preprocessing.\n"); + + gdk_pixbuf_pixdata = g_strdup (g_getenv ("GDK_PIXBUF_PIXDATA")); + if (gdk_pixbuf_pixdata == NULL) + gdk_pixbuf_pixdata = g_find_program_in_path ("gdk-pixbuf-pixdata"); if (target == NULL) { @@ -476,14 +682,36 @@ main (int argc, char **argv) g_free (dirname); g_free (base); } + else if (generate_automatic) + { + if (g_str_has_suffix (target, ".c")) + generate_source = TRUE; + else if (g_str_has_suffix (target, ".h")) + generate_header = TRUE; + else if (g_str_has_suffix (target, ".gresource")) + ; + } - if ((table = parse_resource_file (srcfile)) == NULL) + if ((table = parse_resource_file (srcfile, !generate_dependencies)) == NULL) { g_free (target); return 1; } - if (generate_source || generate_header) + if (generate_dependencies) + { + GHashTableIter iter; + gpointer key, data; + FileData *file_data; + + g_hash_table_iter_init (&iter, table); + while (g_hash_table_iter_next (&iter, &key, &data)) + { + file_data = data; + g_print ("%s\n",file_data->filename); + } + } + else if (generate_source || generate_header) { if (generate_source) { @@ -495,8 +723,6 @@ main (int argc, char **argv) } close (fd); } - else - binary_target = NULL; if (c_name == NULL) { @@ -558,16 +784,16 @@ main (int argc, char **argv) "\n" "#include \n" "\n" - "extern GResource *%s_resource;\n", - c_name, c_name, c_name); + "%s GResource *%s_get_resource (void);\n", + c_name, c_name, linkage, c_name); if (manual_register) fprintf (file, "\n" - "extern void %s_register_resource (void);\n" - "extern void %s_unregister_resource (void);\n" + "%s void %s_register_resource (void);\n" + "%s void %s_unregister_resource (void);\n" "\n", - c_name, c_name); + linkage, c_name, linkage, c_name); fprintf (file, "#endif\n"); @@ -580,7 +806,6 @@ main (int argc, char **argv) guint8 *data; gsize data_size; gsize i; - char *static_str; if (!g_file_get_contents (binary_target, (char **)&data, &data_size, NULL)) @@ -621,13 +846,37 @@ main (int argc, char **argv) fprintf (file, "} };\n"); + fprintf (file, + "\n" + "static GStaticResource static_resource = { %s_resource_data.data, sizeof (%s_resource_data.data), NULL, NULL, NULL };\n" + "%s GResource *%s_get_resource (void);\n" + "GResource *%s_get_resource (void)\n" + "{\n" + " return g_static_resource_get_resource (&static_resource);\n" + "}\n", + c_name, c_name, linkage, c_name, c_name); + + if (manual_register) { - static_str = ""; + fprintf (file, + "\n" + "%s void %s_unregister_resource (void);\n" + "void %s_unregister_resource (void)\n" + "{\n" + " g_static_resource_fini (&static_resource);\n" + "}\n" + "\n" + "%s void %s_register_resource (void);\n" + "void %s_register_resource (void)\n" + "{\n" + " g_static_resource_init (&static_resource);\n" + "}\n", + linkage, c_name, c_name, linkage, c_name, c_name); } else { - static_str = "static "; + fprintf (file, "%s", gconstructor_code); fprintf (file, "\n" "#ifdef G_HAS_CONSTRUCTORS\n" @@ -644,55 +893,27 @@ main (int argc, char **argv) "#else\n" "#warning \"Constructor not supported on this compiler, linking in resources will not work\"\n" "#endif\n" - "\n"); + "\n" + "static void resource_constructor (void)\n" + "{\n" + " g_static_resource_init (&static_resource);\n" + "}\n" + "\n" + "static void resource_destructor (void)\n" + "{\n" + " g_static_resource_fini (&static_resource);\n" + "}\n"); } - fprintf (file, - "\n" - "GResource *%s_resource = NULL;\n" - "\n" - "%svoid %s_unregister_resource (void)\n" - "{\n" - " if (%s_resource)\n" - " {\n" - " g_resources_unregister (%s_resource);\n" - " g_resource_unref (%s_resource);\n" - " %s_resource = NULL;\n" - " }\n" - "}\n" - "\n" - "%svoid %s_register_resource (void)\n" - "{\n" - " if (%s_resource == NULL)\n" - " {\n" - " GBytes *bytes = g_bytes_new_static (%s_resource_data.data, sizeof (%s_resource_data.data));\n" - " %s_resource = g_resource_new_from_data (bytes, NULL);\n" - " if (%s_resource)\n" - " g_resources_register (%s_resource);\n" - " g_bytes_unref (bytes);\n" - " }\n" - "}\n", c_name, static_str, c_name, c_name, c_name, c_name, c_name, static_str, c_name, c_name, c_name, c_name, c_name, c_name, c_name); - - if (!manual_register) - fprintf (file, - "\n" - "static void resource_constructor (void)\n" - "{\n" - " %s_register_resource ();\n" - "}\n" - "\n" - "static void resource_destructor (void)\n" - "{\n" - " %s_unregister_resource ();\n" - "}\n", c_name, c_name); - fclose (file); + + g_free (data); } g_free (binary_target); - - g_free (target); + g_hash_table_destroy (table); + g_free (xmllint); return 0; }