[glib] gconstructor: Work around constructors being optimized away on MSVC



commit db4df9908e0137c14f5aeeefba899240c4724970
Author: Chun-wei Fan <fanchunwei src gnome org>
Date:   Tue Nov 10 17:20:18 2015 +0800

    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 |   38 ++++++++++++++++++++++++++++++++------
 1 files changed, 32 insertions(+), 6 deletions(-)
---
diff --git a/glib/gconstructor.h b/glib/gconstructor.h
index df98f83..dccb031 100644
--- a/glib/gconstructor.h
+++ b/glib/gconstructor.h
@@ -30,17 +30,43 @@
 
 #define G_HAS_CONSTRUCTORS 1
 
-#define G_DEFINE_CONSTRUCTOR(_func) \
+/* 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.
+ */
+
+/* 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 ## _wrapper(void) { _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 ## _wrapper;
+  __declspec(allocate(".CRT$XCU")) int (* _array ## _func)(void) = _func ## _wrapper;
 
-#define G_DEFINE_DESTRUCTOR(_func) \
+#define G_MSVC_DTOR(_func,_sym_prefix) \
   static void _func(void); \
-  static int _func ## _constructor(void) { atexit (_func); return 0; } \
+  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")) static int (* _array ## _func)(void) = _func ## _constructor;
+  __declspec(allocate(".CRT$XCU")) int (* _array ## _func)(void) = _func ## _constructor;
 
 #elif defined (_MSC_VER)
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]