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
This commit is contained in:
Chun-wei Fan 2015-11-10 17:20:18 +08:00
parent 228ad1ed9c
commit db4df9908e

View File

@ -30,17 +30,43 @@
#define G_HAS_CONSTRUCTORS 1 #define G_HAS_CONSTRUCTORS 1
#define G_DEFINE_CONSTRUCTOR(_func) \ /* We do some weird things to avoid the constructors being optimized
static void _func(void); \ * away on VS2015 if WholeProgramOptimization is enabled. First we
static int _func ## _wrapper(void) { _func(); return 0; } \ * make a reference to the array from the wrapper to make sure its
__pragma(section(".CRT$XCU",read)) \ * references. Then we use a pragma to make sure the wrapper function
__declspec(allocate(".CRT$XCU")) static int (* _array ## _func)(void) = _func ## _wrapper; * 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 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)) \ __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) #elif defined (_MSC_VER)