From db4df9908e0137c14f5aeeefba899240c4724970 Mon Sep 17 00:00:00 2001 From: Chun-wei Fan Date: Tue, 10 Nov 2015 17:20:18 +0800 Subject: [PATCH] gconstructor: Work around constructors being optimized away on MSVC Whole program optimization is enabled by default in visual studio release builds, and this causes constructors (for e.g. resources) to be optimized away as they are not referenced from elsewhere. This works around this by some pragma magic. https://bugzilla.gnome.org/show_bug.cgi?id=752837 --- glib/gconstructor.h | 42 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/glib/gconstructor.h b/glib/gconstructor.h index df98f8356..dccb0314c 100644 --- a/glib/gconstructor.h +++ b/glib/gconstructor.h @@ -30,17 +30,43 @@ #define G_HAS_CONSTRUCTORS 1 -#define G_DEFINE_CONSTRUCTOR(_func) \ - static void _func(void); \ - static int _func ## _wrapper(void) { _func(); return 0; } \ - __pragma(section(".CRT$XCU",read)) \ - __declspec(allocate(".CRT$XCU")) static int (* _array ## _func)(void) = _func ## _wrapper; +/* We do some weird things to avoid the constructors being optimized + * away on VS2015 if WholeProgramOptimization is enabled. First we + * make a reference to the array from the wrapper to make sure its + * references. Then we use a pragma to make sure the wrapper function + * symbol is always included at the link stage. Also, the symbols + * need to be extern (but not dllexport), even though they are not + * really used from another object file. + */ -#define G_DEFINE_DESTRUCTOR(_func) \ +/* We need to account for differences between the mangling of symbols + * for Win32 (x86) and x64 programs, as symbols on Win32 are prefixed + * with an underscore but symbols on x64 are not. + */ +#ifdef _WIN64 +#define G_MSVC_SYMBOL_PREFIX "" +#else +#define G_MSVC_SYMBOL_PREFIX "_" +#endif + +#define G_DEFINE_CONSTRUCTOR(_func) G_MSVC_CTOR (_func, G_MSVC_SYMBOL_PREFIX) +#define G_DEFINE_DESTRUCTOR(_func) G_MSVC_DTOR (_func, G_MSVC_SYMBOL_PREFIX) + +#define G_MSVC_CTOR(_func,_sym_prefix) \ static void _func(void); \ - static int _func ## _constructor(void) { atexit (_func); return 0; } \ + extern int (* _array ## _func)(void); \ + int _func ## _wrapper(void) { _func(); g_slist_find (NULL, _array ## _func); return 0; } \ + __pragma(comment(linker,"/include:" _sym_prefix # _func "_wrapper")) \ __pragma(section(".CRT$XCU",read)) \ - __declspec(allocate(".CRT$XCU")) static int (* _array ## _func)(void) = _func ## _constructor; + __declspec(allocate(".CRT$XCU")) int (* _array ## _func)(void) = _func ## _wrapper; + +#define G_MSVC_DTOR(_func,_sym_prefix) \ + static void _func(void); \ + extern int (* _array ## _func)(void); \ + int _func ## _constructor(void) { atexit (_func); g_slist_find (NULL, _array ## _func); return 0; } \ + __pragma(comment(linker,"/include:" _sym_prefix # _func "_constructor")) \ + __pragma(section(".CRT$XCU",read)) \ + __declspec(allocate(".CRT$XCU")) int (* _array ## _func)(void) = _func ## _constructor; #elif defined (_MSC_VER)