From 4501807d7319726a620841cafbab705a21c378dc Mon Sep 17 00:00:00 2001 From: Chun-wei Fan Date: Thu, 29 Nov 2018 16:12:26 +0800 Subject: [PATCH 1/2] glib-compile-resources: Fix code generation for MSVC builds glib-compile-resources was updated to generate octal byte representation in a string, but unfortunately this breaks the build on Visual Studio when the generated string sequence exceeds 65535 characters, which is the imposed limit on Visual Studio compilers. To make things work on Visual Studio builds and to not slow down things on other compilers, generate a code path for Visual Studio an array of octal byte representations, as well as a code path for other compilers that use the new string representation of octal values, and let the compiler take the appropriate code path when compiling the generated code. Fixes issue #1580. --- gio/glib-compile-resources.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/gio/glib-compile-resources.c b/gio/glib-compile-resources.c index 7e318b254..2c421b6a4 100644 --- a/gio/glib-compile-resources.c +++ b/gio/glib-compile-resources.c @@ -1086,9 +1086,33 @@ main (int argc, char **argv) "#else\n" "# define SECTION\n" "#endif\n" - "\n" + "\n", + c_name_no_underscores); + + /* For Visual Studio builds: Avoid surpassing the 65535-character limit for a string, GitLab issue #1580 */ + g_fprintf (file, "#ifdef _MSC_VER\n"); + g_fprintf (file, + "static const SECTION union { const guint8 data[%"G_GSIZE_FORMAT"]; const double alignment; void * const ptr;} %s_resource_data = { {\n", + data_size + 1 /* nul terminator */, c_name); + + for (i = 0; i < data_size; i++) + { + if (i % 16 == 0) + g_fprintf (file, " "); + g_fprintf (file, "0%3.3o", (int)data[i]); + if (i != data_size - 1) + g_fprintf (file, ", "); + if (i % 16 == 15 || i == data_size - 1) + g_fprintf (file, "\n"); + } + + g_fprintf (file, "} };\n"); + + /* For other compilers, use the long string approach */ + g_fprintf (file, "#else /* _MSC_VER */\n"); + g_fprintf (file, "static const SECTION union { const guint8 data[%"G_GSIZE_FORMAT"]; const double alignment; void * const ptr;} %s_resource_data = {\n \"", - c_name_no_underscores, data_size + 1 /* nul terminator */, c_name); + data_size + 1 /* nul terminator */, c_name); for (i = 0; i < data_size; i++) { g_fprintf (file, "\\%3.3o", (int)data[i]); @@ -1097,6 +1121,7 @@ main (int argc, char **argv) } g_fprintf (file, "\" };\n"); + g_fprintf (file, "#endif /* !_MSC_VER */\n"); g_fprintf (file, "\n" From cd30faae1f2b14f4356eeb0c4ac00cba032d7ee0 Mon Sep 17 00:00:00 2001 From: Chun-wei Fan Date: Fri, 30 Nov 2018 17:49:44 +0800 Subject: [PATCH 2/2] gresources: Add a test with resources > 64kb This is to ensure that the generated code is still compilable by the running compiler, and see whether we can read the things in there properly. See issue #1580. --- gio/tests/.gitignore | 1 + gio/tests/Makefile.am | 9 ++++-- gio/tests/gen-big-test-resource.py | 27 ++++++++++++++++++ gio/tests/meson.build | 9 ++++++ gio/tests/resources.c | 45 ++++++++++++++++++++++++++++++ gio/tests/test2.gresource.xml | 5 ++++ 6 files changed, 93 insertions(+), 3 deletions(-) create mode 100644 gio/tests/gen-big-test-resource.py diff --git a/gio/tests/.gitignore b/gio/tests/.gitignore index 0b772ad93..cf724c3de 100644 --- a/gio/tests/.gitignore +++ b/gio/tests/.gitignore @@ -146,3 +146,4 @@ xdgdatadir xdgdatahome xgen-gio xgen-giosrc.c +gresource-big-test.txt diff --git a/gio/tests/Makefile.am b/gio/tests/Makefile.am index 8efb1eaa0..a6023e94d 100644 --- a/gio/tests/Makefile.am +++ b/gio/tests/Makefile.am @@ -589,9 +589,12 @@ test-generated.txt: test1.txt $(AM_V_GEN) echo "Generated" > $@ && \ cat $< >> $@ +gresource-big-test.txt: gen-big-test-resource.py + $(AM_V_GEN) $(PYTHON) $< $@ + resources.o: test_resources2.h test_resources.c: test2.gresource.xml Makefile $(shell $(glib_compile_resources) --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/test2.gresource.xml) - $(AM_V_GEN) $(glib_compile_resources) --target=$@ --sourcedir=$(srcdir) --generate-source --c-name _g_test1 $< + $(AM_V_GEN) $(glib_compile_resources) --target=$@ --sourcedir=. --sourcedir=$(srcdir) --generate-source --c-name _g_test1 $< test_resources2.h test_resources2.c: test3.gresource.xml Makefile $(shell $(glib_compile_resources) --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/test3.gresource.xml) $(AM_V_GEN) $(glib_compile_resources) --target=$@ --sourcedir=$(srcdir) --generate --c-name _g_test2 --manual-register $< @@ -602,8 +605,8 @@ plugin_resources.c: test4.gresource.xml Makefile $(shell $(glib_compile_resource test.gresource: test.gresource.xml Makefile $(shell $(glib_compile_resources) --sourcedir=. --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/test.gresource.xml) $(AM_V_GEN) $(glib_compile_resources) --target=$@ --sourcedir=. --sourcedir=$(srcdir) $< -EXTRA_DIST += test.gresource.xml test1.txt test2.gresource.xml test2.txt test3.gresource.xml test3.txt test4.gresource.xml -CLEANFILES += test-generated.txt test_resources.c test_resources2.[ch] plugin_resources.c test.gresource +EXTRA_DIST += test.gresource.xml test1.txt test2.gresource.xml test2.txt test3.gresource.xml test3.txt test4.gresource.xml gen-big-test-resource.py +CLEANFILES += test-generated.txt test_resources.c test_resources2.[ch] plugin_resources.c test.gresource gresource-big-test.txt endif # !CROSS_COMPILING BUILT_SOURCES += giotypefuncs.inc diff --git a/gio/tests/gen-big-test-resource.py b/gio/tests/gen-big-test-resource.py new file mode 100644 index 000000000..e031a0a08 --- /dev/null +++ b/gio/tests/gen-big-test-resource.py @@ -0,0 +1,27 @@ +# Generate a large text file to test compile +# the resulting code that contains a large (>65536 bytes) +# resource entry. Just have 12 iterations of the following: +# +# -100 of each of the lowercase letters +# -100 of each of the uppercase letters +# -100 of the numbers 0 to 9 +# +# See issue #1580 + +import io +import string +import sys + +if len(sys.argv) != 2: + raise SystemExit('Usage: %s ' % sys.argv[0]) + +with open(sys.argv[1], 'w', newline='\n') as f: + for count in range(12): + for c in string.ascii_lowercase: + f.write("%s\n" % (c * 100)) + + for c in string.ascii_uppercase: + f.write("%s\n" % (c * 100)) + + for i in range(10): + f.write("%s\n" % (str(i) * 100)) diff --git a/gio/tests/meson.build b/gio/tests/meson.build index a81715c11..44bc2a818 100644 --- a/gio/tests/meson.build +++ b/gio/tests/meson.build @@ -411,6 +411,13 @@ if not meson.is_cross_build() or meson.has_exe_wrapper() install : installed_tests_enabled ) + # referenced by test2.gresource.xml + big_test_resource = custom_target( + 'gresource-big-test.txt', + input : ['gen-big-test-resource.py'], + output : ['gresource-big-test.txt'], + command : [python, '@INPUT0@', '@OUTPUT@']) + test_gresource = custom_target('test.gresource', input : 'test.gresource.xml', output : 'test.gresource', @@ -446,10 +453,12 @@ if not meson.is_cross_build() or meson.has_exe_wrapper() test_resources_c = custom_target('test_resources.c', input : 'test2.gresource.xml', + depends : big_test_resource, output : 'test_resources.c', command : [glib_compile_resources, '--target=@OUTPUT@', '--sourcedir=' + meson.current_source_dir(), + '--sourcedir=' + meson.current_build_dir(), '--generate-source', '--c-name', '_g_test1', '@INPUT@']) diff --git a/gio/tests/resources.c b/gio/tests/resources.c index 70d8c03a6..11f1f3f2c 100644 --- a/gio/tests/resources.c +++ b/gio/tests/resources.c @@ -812,6 +812,50 @@ test_uri_file (void) g_resource_unref (resource); } +static void +test_resource_64k (void) +{ + GError *error = NULL; + gboolean found; + gsize size; + guint32 flags; + GBytes *data; + gchar **tokens; + + found = g_resources_get_info ("/big_prefix/gresource-big-test.txt", + G_RESOURCE_LOOKUP_FLAGS_NONE, + &size, &flags, &error); + g_assert_true (found); + g_assert_no_error (error); + + /* Check size: 100 of all lower case letters + newline char + + * 100 all upper case letters + newline char + + * 100 of all numbers between 0 to 9 + newline char + * (for 12 iterations) + */ + + g_assert_cmpint (size, ==, (26 + 26 + 10) * (100 + 1) * 12); + g_assert_cmpuint (flags, ==, 0); + data = g_resources_lookup_data ("/big_prefix/gresource-big-test.txt", + G_RESOURCE_LOOKUP_FLAGS_NONE, + &error); + g_assert_nonnull (data); + g_assert_no_error (error); + size = g_bytes_get_size (data); + + g_assert_cmpint (size, ==, (26 + 26 + 10) * (100 + 1) * 12); + tokens = g_strsplit ((const gchar *) g_bytes_get_data (data, NULL), "\n", -1); + + /* check tokens[x] == entry at gresource-big-test.txt's line, where x = line - 1 */ + g_assert_cmpstr (tokens[0], ==, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); + g_assert_cmpstr (tokens[27], ==, "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"); + g_assert_cmpstr (tokens[183], ==, "7777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777"); + g_assert_cmpstr (tokens[600], ==, "QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ"); + g_assert_cmpstr (tokens[742], ==, "8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888"); + g_strfreev (tokens); + g_bytes_unref (data); +} + int main (int argc, char *argv[]) @@ -836,6 +880,7 @@ main (int argc, #endif g_test_add_func ("/resource/uri/query-info", test_uri_query_info); g_test_add_func ("/resource/uri/file", test_uri_file); + g_test_add_func ("/resource/64k", test_resource_64k); return g_test_run(); } diff --git a/gio/tests/test2.gresource.xml b/gio/tests/test2.gresource.xml index 68762804a..0323b47ec 100644 --- a/gio/tests/test2.gresource.xml +++ b/gio/tests/test2.gresource.xml @@ -3,4 +3,9 @@ test1.txt + + + gresource-big-test.txt +