public inbox for
 help / color / mirror / Atom feed
From: Daniel Richard G. <>
To: <>
Subject: [PATCH] autostatic.c
Date: Fri, 27 Jul 2012 20:26:00 -0000	[thread overview]
Message-ID: <> (raw)

[-- Attachment #1: Type: text/plain, Size: 1624 bytes --]

My next patch is an overhaul of autostatic.c that adds support for older 
MSVC versions, fixes the no-init bug in small-static builds, and smooths 
out a number of rough edges.

++ autostatic.c

* Move the #includes up to the top, in case PTW32_STATIC_LIB is defined in
   a header file (and a later patch from me will need a symbol from
   implement.h early on)

* Added a big fat comment documenting the pre/post-main() black magic and
   the anchoring business

* The init/exit routines are supposed to return int, not void, and return
   a value of 0 to indicate "no error" (see the "Addendum: int Instead of
   void" section in the Codeguru article)

* I got rid of the attribute_section() macro (in favor of writing things
   out longhand) because it's not enough to abstract away all the
   differences between the various forms of declarations needed (for
   example, #pragma is needed in some cases, and that can't be stuffed into
   a macro (and __pragma() isn't supported by older MSVC versions))

* The way that MSVC pre/post-main() black magic is done changed in 8.0, so
   the code now implements the "old" and "new" ways. I've tested that this
   works for everything back to MSVC6.

* Added a bit at the end to avoid warnings when PTW32_STATIC_LIB is not
   defined in non-inlined builds

++ implement.h

* This bit sticks a reference to autostatic.obj into every object file, so
   that the linker won't optimize it away (for "small static" builds)


Daniel Richard G. || || Software Developer
Teragram Linguistic Technologies (a division of SAS)

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: Patch against git master --]
[-- Type: text/x-diff; name="ptw32-autostatic.patch", Size: 3795 bytes --]

diff --git a/autostatic.c b/autostatic.c
index 092aff2..21c1748 100755
--- a/autostatic.c
+++ b/autostatic.c
@@ -34,36 +34,73 @@
  *      59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+#include "pthread.h"
+#include "implement.h"
 #if defined(PTW32_STATIC_LIB)
 #if defined(__MINGW64__) || defined(__MINGW32__) || defined(_MSC_VER)
-#include "pthread.h"
-#include "implement.h"
+/* For an explanation of this code (at least the MSVC parts), refer to
+ *
+ *
+ * ("Running Code Before and After Main")
+ *
+ * Compatibility with MSVC8 was cribbed from Boost:
+ *
+ *
+ *
+ * In addition to that, because we are in a static library, and the linker
+ * can't tell that the constructor/destructor functions are actually
+ * needed, we need a way to prevent the linker from optimizing away this
+ * module. The pthread_win32_autostatic_anchor() hack below (and in
+ * implement.h) does the job in a portable manner.
+ */
-static void on_process_init(void)
+static int on_process_init(void)
     pthread_win32_process_attach_np ();
+    return 0;
-static void on_process_exit(void)
+static int on_process_exit(void)
     pthread_win32_thread_detach_np  ();
     pthread_win32_process_detach_np ();
+    return 0;
 #if defined(__MINGW64__) || defined(__MINGW32__)
-# define attribute_section(a) __attribute__((section(a)))
+__attribute__((section(".ctors"), used)) static int (*gcc_ctor)(void) = on_process_init;
+__attribute__((section(".dtors"), used)) static int (*gcc_dtor)(void) = on_process_exit;
 #elif defined(_MSC_VER)
-# define attribute_section(a) __pragma(section(a,long,read)); __declspec(allocate(a))
+#  if _MSC_VER >= 1400	/* MSVC8 */
+#    pragma section(".CRT$XCU", long, read)
+#    pragma section(".CRT$XPU", long, read)
+__declspec(allocate(".CRT$XCU")) static int (*msc_ctor)(void) = on_process_init;
+__declspec(allocate(".CRT$XPU")) static int (*msc_dtor)(void) = on_process_exit;
+#  else
+#    pragma data_seg(".CRT$XCU")
+static int (*msc_ctor)(void) = on_process_init;
+#    pragma data_seg(".CRT$XPU")
+static int (*msc_dtor)(void) = on_process_exit;
+#    pragma data_seg()	/* reset data segment */
+#  endif
-attribute_section(".ctors") void *gcc_ctor = on_process_init;
-attribute_section(".dtors") void *gcc_dtor = on_process_exit;
-attribute_section(".CRT$XCU") void *msc_ctor = on_process_init;
-attribute_section(".CRT$XPU") void *msc_dtor = on_process_exit;
 #endif /* defined(__MINGW64__) || defined(__MINGW32__) || defined(_MSC_VER) */
+/* This dummy function exists solely to be referenced by other modules
+ * (specifically, in implement.h), so that the linker can't optimize away
+ * this module. Don't call it.
+ */
+void pthread_win32_autostatic_anchor(void) { abort(); }
 #endif /* PTW32_STATIC_LIB */
+#if ! defined(PTW32_BUILD_INLINED)
+ * Avoid "translation unit is empty" warnings
+ */
+typedef int foo;
diff --git a/implement.h b/implement.h
index 92f5740..7529ad2 100644
--- a/implement.h
+++ b/implement.h
@@ -109,6 +109,16 @@ typedef VOID (APIENTRY *PAPCFUNC)(DWORD dwParam);
 #  if defined(_MSC_VER) && _MSC_VER < 1300
      typedef long intptr_t;
 #  endif
+ * Don't allow the linker to optimize away autostatic.obj in static builds.
+ */
+#if defined(PTW32_STATIC_LIB)
+void pthread_win32_autostatic_anchor(void);
+#  if defined(__MINGW64__) || defined(__MINGW32__)
+__attribute__((unused, used))
+#  endif
+static void (*local_autostatic_anchor)(void) = pthread_win32_autostatic_anchor;
 typedef enum

                 reply	other threads:[~2012-07-27 20:26 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \ \ \ \ \

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).