Do not generate C resources for all possible toolchains

The resources data is generated for both GCC and MSVC toolchains, even
though we know beforehand which toolchain we're going to compile it for.
By dropping the data duplication we make the generated resources file
faster to compile, especially when dealing with large embedded data,
instead of relying on the C pre-processor to walk the whole file and
discard the branch we're not using.
This commit is contained in:
Emmanuele Bassi 2021-09-18 13:45:57 +01:00
parent 058251ad5b
commit 7bc6ef8734
2 changed files with 126 additions and 30 deletions

View File

@ -200,6 +200,16 @@ be used with <literal>make</literal>.
</para></listitem> </para></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>--compiler=<replaceable>NAME</replaceable></option></term>
<listitem><para>
Generate code that is going to target the given compiler <replaceable>NAME</replaceable>.
The current two compiler modes are "gcc", for all GCC-compatible toolchains; and "msvc",
for the Microsoft Visual C Compiler. If this option isn't set, then the default will be
taken from the <envar>CC</envar> environment variable.
</para></listitem>
</varlistentry>
</variablelist> </variablelist>
</refsect1> </refsect1>

View File

@ -710,6 +710,86 @@ escape_makefile_string (const char *string)
return g_string_free (str, FALSE); return g_string_free (str, FALSE);
} }
typedef enum {
COMPILER_GCC,
COMPILER_CLANG,
COMPILER_MSVC,
COMPILER_UNKNOWN
} CompilerType;
/* Get the compiler id from the platform, environment, or command line
*
* Keep compiler IDs consistent with https://mesonbuild.com/Reference-tables.html#compiler-ids
* for simplicity
*/
static CompilerType
get_compiler_id (const char *compiler)
{
char *base, *ext_p;
CompilerType compiler_type;
if (compiler == NULL)
{
#ifdef G_OS_UNIX
const char *compiler_env = g_getenv ("CC");
# ifdef __APPLE__
if (compiler_env == NULL || *compiler_env == '\0')
compiler = "clang";
else
compiler = compiler_env;
# elif __linux__
if (compiler_env == NULL || *compiler_env == '\0')
compiler = "gcc";
else
compiler = compiler_env;
# else
if (compiler_env == NULL || *compiler_env == '\0')
compiler = "unknown";
else
compiler = compiler_env;
# endif
#endif
#ifdef G_OS_WIN32
if (g_getenv ("MSYSTEM") != NULL)
{
const char *compiler_env = g_getenv ("CC");
if (compiler_env == NULL || *compiler_env == '\0')
compiler = "gcc";
else
compiler = compiler_env;
}
else
compiler = "msvc";
#endif
}
base = g_path_get_basename (compiler);
ext_p = strrchr (base, '.');
if (ext_p != NULL)
{
gsize offset = ext_p - base;
base[offset] = '\0';
}
compiler = base;
if (g_strcmp0 (compiler, "gcc") == 0)
compiler_type = COMPILER_GCC;
else if (g_strcmp0 (compiler, "clang") == 0)
compiler_type = COMPILER_CLANG;
else if (g_strcmp0 (compiler, "msvc") == 0)
compiler_type = COMPILER_MSVC;
else
compiler_type = COMPILER_UNKNOWN;
g_free (base);
return compiler_type;
}
int int
main (int argc, char **argv) main (int argc, char **argv)
{ {
@ -732,6 +812,8 @@ main (int argc, char **argv)
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";
const char *compiler = NULL;
CompilerType compiler_type = COMPILER_GCC;
GOptionContext *context; GOptionContext *context;
GOptionEntry entries[] = { GOptionEntry entries[] = {
{ "version", 0, 0, G_OPTION_ARG_NONE, &show_version_and_exit, N_("Show program version and exit"), NULL }, { "version", 0, 0, G_OPTION_ARG_NONE, &show_version_and_exit, N_("Show program version and exit"), NULL },
@ -747,6 +829,7 @@ main (int argc, char **argv)
{ "internal", 0, 0, G_OPTION_ARG_NONE, &internal, N_("Dont export functions; declare them G_GNUC_INTERNAL"), NULL }, { "internal", 0, 0, G_OPTION_ARG_NONE, &internal, N_("Dont export functions; declare them G_GNUC_INTERNAL"), NULL },
{ "external-data", 0, 0, G_OPTION_ARG_NONE, &external_data, N_("Dont embed resource data in the C file; assume it's linked externally instead"), NULL }, { "external-data", 0, 0, G_OPTION_ARG_NONE, &external_data, N_("Dont embed resource data in the C file; assume it's linked externally instead"), 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 },
{ "compiler", 'C', 0, G_OPTION_ARG_STRING, &compiler, N_("The target C compiler (default: the CC environment variable)"), NULL },
G_OPTION_ENTRY_NULL G_OPTION_ENTRY_NULL
}; };
@ -802,6 +885,8 @@ main (int argc, char **argv)
if (internal) if (internal)
linkage = "G_GNUC_INTERNAL"; linkage = "G_GNUC_INTERNAL";
compiler_type = get_compiler_id (compiler);
srcfile = argv[1]; srcfile = argv[1];
xmllint = g_strdup (g_getenv ("XMLLINT")); xmllint = g_strdup (g_getenv ("XMLLINT"));
@ -1105,40 +1190,41 @@ main (int argc, char **argv)
} }
else else
{ {
/* For Visual Studio builds: Avoid surpassing the 65535-character limit for a string, GitLab issue #1580 */ if (compiler_type == COMPILER_MSVC || compiler_type == COMPILER_UNKNOWN)
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) /* For Visual Studio builds: Avoid surpassing the 65535-character limit for a string, GitLab issue #1580 */
g_fprintf (file, " "); g_fprintf (file,
g_fprintf (file, "0%3.3o", (int)data[i]); "static const SECTION union { const guint8 data[%"G_GSIZE_FORMAT"]; const double alignment; void * const ptr;} %s_resource_data = { {\n",
if (i != data_size - 1) data_size + 1 /* nul terminator */, c_name);
g_fprintf (file, ", ");
if (i % 16 == 15 || i == data_size - 1) for (i = 0; i < data_size; i++)
g_fprintf (file, "\n"); {
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");
} }
else
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 \"",
data_size + 1 /* nul terminator */, c_name);
for (i = 0; i < data_size; i++)
{ {
g_fprintf (file, "\\%3.3o", (int)data[i]); g_fprintf (file,
if (i % 16 == 15) "static const SECTION union { const guint8 data[%"G_GSIZE_FORMAT"]; const double alignment; void * const ptr;} %s_resource_data = {\n \"",
g_fprintf (file, "\"\n \""); data_size + 1 /* nul terminator */, c_name);
}
g_fprintf (file, "\" };\n"); for (i = 0; i < data_size; i++)
g_fprintf (file, "#endif /* !_MSC_VER */\n"); {
g_fprintf (file, "\\%3.3o", (int)data[i]);
if (i % 16 == 15)
g_fprintf (file, "\"\n \"");
}
g_fprintf (file, "\" };\n");
}
} }
g_fprintf (file, g_fprintf (file,