Re: [pcre-dev] [Bug 664] ABI breakage in PCRE 7.6

Etusivu
Poista viesti
Lähettäjä: Craig Silverstein
Päiväys:  
Vastaanottaja: 664, 686, ph10
Kopio: pcre-dev
Aihe: Re: [pcre-dev] [Bug 664] ABI breakage in PCRE 7.6
Here's a new version of the patch I had submitted earlier, which
replaces that earlier patch. This supports -i as well as -alias, so
it should work on all versions of os x.

I also added in a check for systems where really no c++ compiler is
installed, to make us just not compile in the c++ stuff then. I can't
test it very well, but it looks like it should work. :-) I've
verified it doesn't break systems that *do* have a c++ compiler.

craig

--cut here--

Index: configure.ac
===================================================================
--- configure.ac    (revision 328)
+++ configure.ac    (working copy)
@@ -60,6 +60,11 @@
   fi
 fi


+# AC_PROG_CXX will return "g++" even if no c++ compiler is installed.
+# Check for that case, and just disable c++ code if g++ doesn't run.
+AC_LANG_PUSH(C++)
+AC_COMPILE_IFELSE(AC_LANG_PROGRAM([],[]),, CXX=""; CXXCP=""; CXXFLAGS="")
+AC_LANG_POP

AC_PROG_INSTALL
AC_LIBTOOL_WIN32_DLL
@@ -277,6 +282,30 @@
then
AC_LANG_PUSH(C++)

+# Older versions of pcre defined pcrecpp::no_arg, but in new versions
+# it's called pcrecpp::RE::no_arg.  For backwards ABI compatibility,
+# we want to make one an alias for the other.  Different systems do
+# this in different ways.  Some systems, for instance, can do it via
+# a linker flag: -alias (for os x 10.5) or -i (for os x <=10.4).
+OLD_LDFLAGS="$LDFLAGS"
+for flag in "-alias,__ZN7pcrecpp2RE6no_argE,__ZN7pcrecpp6no_argE" \
+            "-i__ZN7pcrecpp6no_argE:__ZN7pcrecpp2RE6no_argE"; do
+  AC_MSG_CHECKING([for alias support in the linker])
+  LDFLAGS="$OLD_LDFLAGS -Wl,$flag"
+  # We try to run the linker with this new ld flag.  If the link fails,
+  # we give up and remove the new flag from LDFLAGS.
+  AC_LINK_IFELSE(AC_LANG_PROGRAM([namespace pcrecpp {
+                                    class RE { static int no_arg; };
+                                    int RE::no_arg;
+                                  }],
+                                 []),
+                 [AC_MSG_RESULT([yes]);
+                  EXTRA_LIBPCRECPP_LDFLAGS="$EXTRA_LIBPCRECPP_LDFLAGS -Wl,$flag";
+                  break;],
+                 AC_MSG_RESULT([no]))
+done
+LDFLAGS="$OLD_LDFLAGS"
+
 # We could be more clever here, given we're doing AC_SUBST with this
 # (eg set a var to be the name of the include file we want). But we're not
 # so it's easy to change back to 'regular' autoconf vars if we needed to.
@@ -286,6 +315,7 @@
                                      [pcre_have_bits_type_traits="0"])
 AC_CHECK_HEADERS(type_traits.h, [pcre_have_type_traits="1"],
                                 [pcre_have_type_traits="0"])
+
 AC_LANG_POP
 fi
 # Using AC_SUBST eliminates the need to include config.h in a public .h file
@@ -490,11 +520,15 @@
 # The extra LDFLAGS for each particular library
 # (Note: The libpcre*_version bits are m4 variables, assigned above)


-EXTRA_LIBPCRE_LDFLAGS="$NO_UNDEFINED -version-info libpcre_version"
+EXTRA_LIBPCRE_LDFLAGS="$EXTRA_LIBPCRE_LDFLAGS \
+                       $NO_UNDEFINED -version-info libpcre_version"


-EXTRA_LIBPCREPOSIX_LDFLAGS="$NO_UNDEFINED -version-info libpcreposix_version"
+EXTRA_LIBPCREPOSIX_LDFLAGS="$EXTRA_LIBPCREPOSIX_LDFLAGS \
+                            $NO_UNDEFINED -version-info libpcreposix_version"


-EXTRA_LIBPCRECPP_LDFLAGS="$NO_UNDEFINED $EXPORT_ALL_SYMBOLS -version-info libpcrecpp_version"
+EXTRA_LIBPCRECPP_LDFLAGS="$EXTRA_LIBPCRECPP_LDFLAGS \
+                          $NO_UNDEFINED -version-info libpcrecpp_version \
+                          $EXPORT_ALL_SYMBOLS"


 AC_SUBST(EXTRA_LIBPCRE_LDFLAGS)
 AC_SUBST(EXTRA_LIBPCREPOSIX_LDFLAGS)
Index: pcrecpp.cc
===================================================================
--- pcrecpp.cc    (revision 328)
+++ pcrecpp.cc    (working copy)
@@ -59,23 +59,19 @@


 // This is for ABI compatibility with old versions of pcre (pre-7.6),
 // which defined a global no_arg variable instead of putting it in the
-// RE class.  This works on GCC >= 3, at least.  We could probably
-// have a more inclusive test if we ever needed it.  (Note that not
-// only the __attribute__ syntax, but also __USER_LABEL_PREFIX__, are
+// RE class.  This works on GCC >= 3, at least.  It definitely works
+// for ELF, but may not for other object formats (Mach-O, for
+// instance, does not support aliases.)  We could probably have a more
+// inclusive test if we ever needed it.  (Note that not only the
+// __attribute__ syntax, but also __USER_LABEL_PREFIX__, are
 // gnu-specific.)
-#if defined(__GNUC__) && __GNUC__ >= 3
-#if defined(__ELF__)
+#if defined(__GNUC__) && __GNUC__ >= 3 && defined(__ELF__)
+# define ULP_AS_STRING(x)            ULP_AS_STRING_INTERNAL(x)
+# define ULP_AS_STRING_INTERNAL(x)   #x
+# define USER_LABEL_PREFIX_STR       ULP_AS_STRING(__USER_LABEL_PREFIX__)
 extern Arg no_arg
-  __attribute__((alias(__USER_LABEL_PREFIX__ "_ZN7pcrecpp2RE6no_argE")));
-#else
-// While we know elf supports strong aliases, not all formats do (Mach
-// doesn't, for instance).  So make aliases weak by default.  This is
-// a smidge less safe in theory (conceivably, someone could override
-// this symbol in their own binary), but perfectly ok in practice.
-extern Arg no_arg
-  __attribute__((weak, alias(__USER_LABEL_PREFIX__ "_ZN7pcrecpp2RE6no_argE")));
+  __attribute__((alias(USER_LABEL_PREFIX_STR "_ZN7pcrecpp2RE6no_argE")));
 #endif
-#endif


// If a regular expression has no error, its error_ field points here
static const string empty_string;