Hi,

I've made a *draft* patch which introduces proper symbol visibility in the
libzmq.so DSO, at least on systems with GCC >= 4.0.

I've tried the least invasive approach code-wise, so what I've done is:

1) Added -fvisibility=hidden to LIBZMQ_EXTRA_CXXFLAGS if using GCC/G++.
This causes all symbols in objects compiled with those flags to have hidden
visibility by default.

2) In zmq.cpp (definitions), zmq.h and zmq_utils.h I have added the
appropriate prologue/epilogue to set the symbol visibility for all
functions declared or defined in those files back to "default" (i.e.
normal). This ensures that the API is exported correctly.

3) In order to hide OpenPGM's symbols I also added -fvisibility=hidden to
LIBZMQ_EXTRA_CFLAGS, again only when GCC/G++ is in use. I also defined
-DPGM_GNUC_INTERNAL to nothing; this ensures that the -fvisibility setting
is used for everything if present.

The above looks like it should all work, but has the following known
problems:

a) It'll fail on GCC < 4.0. For this I need to write an autoconf test that
will check if -fvisibility is actually supported by the compiler and if
not, just not use it. The parts in the actual source code can check against
__GNUC_MAJOR__.

Has anyone ever done anything like this with autoconf? How to check if the
compiler supports some flag is not obvious... Help with auto-kung-fu
appreciated :-)

b) It *should* work on Windows; there we already use __declspec() so for
the sake of sanity I guess we should not touch -fvisibility at all?

Comments please... I'd like to get this in master ASAP, that will mean we
can bump the ABI version in the soname to 1.0.0 and actually claim real ABI
stability for 2.1.x.

I guess another step would be explicit symbol versioning but I don't yet
fully understand the implications of that (a good guide is Drepper's paper:
http://www.akkadia.org/drepper/dsohowto.pdf) so it can wait.

Cheers,

-mato

DSO visibility *draft* patch

Signed-off-by: Martin Lucina <m...@kotelna.sk>

---

diff --git a/configure.in b/configure.in
index 27f8bab..da26d36 100644
--- a/configure.in
+++ b/configure.in
@@ -79,6 +79,13 @@ else
     gnu_compilers="no"
 fi
 
+# When using GNU compilers, set the default DSO symbol visibility to "hidden"
+# for all objects going into the libzmq shared library
+if test "x$gnu_compilers" = "xyes"; then
+    LIBZMQ_EXTRA_CFLAGS="-fvisibility=hidden $LIBZMQ_EXTRA_CFLAGS"
+    LIBZMQ_EXTRA_CXXFLAGS="-fvisibility=hidden $LIBZMQ_EXTRA_CXXFLAGS"
+fi
+
 # Set pedantic when using GNU compilers
 if test "x$gnu_compilers" = "xyes"; then
     pedantic="yes"
diff --git a/include/zmq.h b/include/zmq.h
index c2efa07..5ed7153 100644
--- a/include/zmq.h
+++ b/include/zmq.h
@@ -39,6 +39,9 @@ extern "C" {
 #   endif
 #else
 #   define ZMQ_EXPORT
+#   if defined __GNUC__
+#       pragma GCC visibility push(default)
+#   endif
 #endif
 
 /******************************************************************************/
@@ -242,6 +245,11 @@ ZMQ_EXPORT int zmq_poll (zmq_pollitem_t *items, int nitems, long timeout);
 
 ZMQ_EXPORT int zmq_device (int device, void * insocket, void* outsocket);
 
+#undef ZMQ_EXPORT
+#if !defined _WIN32 && defined __GNUC__
+#    pragma GCC visibility pop
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/zmq_utils.h b/include/zmq_utils.h
index 7d8d5fe..cbea513 100644
--- a/include/zmq_utils.h
+++ b/include/zmq_utils.h
@@ -33,6 +33,9 @@ extern "C" {
 #   endif
 #else
 #   define ZMQ_EXPORT
+#   if defined __GNUC__
+#       pragma GCC visibility push(default)
+#   endif
 #endif
 
 /*  Helper functions are used by perf tests so that they don't have to care   */
@@ -49,6 +52,9 @@ ZMQ_EXPORT unsigned long zmq_stopwatch_stop (void *watch_);
 ZMQ_EXPORT void zmq_sleep (int seconds_);
 
 #undef ZMQ_EXPORT
+#if !defined _WIN32 && defined __GNUC__
+#    pragma GCC visibility pop
+#endif
 
 #ifdef __cplusplus
 }
diff --git a/src/Makefile.am b/src/Makefile.am
index 761d8e8..a857ee7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -203,7 +203,6 @@ libpgm_diff_flags = \
     -DCONFIG_HAVE_ISO_VARARGS \
     -DCONFIG_HAVE_TSC \
     -DCONFIG_HAVE_WSACMSGHDR \
-    -DCONFIG_HAVE_DSO_VISIBILITY \
     -DCONFIG_BIND_INADDR_ANY
 
 else
@@ -225,7 +224,6 @@ libpgm_diff_flags = \
     -DCONFIG_HAVE_IP_MREQN \
     -DCONFIG_HAVE_SPRINTF_GROUPING \
     -DCONFIG_HAVE_VASPRINTF \
-    -DCONFIG_HAVE_DSO_VISIBILITY \
     -DCONFIG_BIND_INADDR_ANY \
     -DCONFIG_HAVE_GETOPT
 endif
@@ -237,6 +235,7 @@ libpgm_la_CFLAGS = -I$(top_srcdir)/foreign/openpgm/@pgm_basename@/openpgm/pgm/in
     -DCONFIG_16BIT_CHECKSUM \
     -DCONFIG_GALOIS_MUL_LUT \
     -DGETTEXT_PACKAGE='"pgm"' \
+    -DPGM_GNUC_INTERNAL= \
     ${libpgm_diff_flags}
 
 libzmq_la_CXXFLAGS = -I$(top_srcdir)/foreign/openpgm/@pgm_basename@/openpgm/pgm/include/ \
diff --git a/src/zmq.cpp b/src/zmq.cpp
index 62e50cd..3598542 100644
--- a/src/zmq.cpp
+++ b/src/zmq.cpp
@@ -60,6 +60,10 @@
 #include <pgm/pgm.h>
 #endif
 
+#if defined __GNUC__ && !defined ZMQ_HAVE_WINDOWS
+#pragma GCC visibility push(default)
+#endif
+
 void zmq_version (int *major_, int *minor_, int *patch_)
 {
     *major_ = ZMQ_VERSION_MAJOR;
@@ -725,3 +729,7 @@ unsigned long zmq_stopwatch_stop (void *watch_)
     return (unsigned long) (end - start);
 }
 
+#if defined __GNUC__ && !defined ZMQ_HAVE_WINDOWS
+#pragma GCC visibility pop
+#endif
+
_______________________________________________
zeromq-dev mailing list
zeromq-dev@lists.zeromq.org
http://lists.zeromq.org/mailman/listinfo/zeromq-dev

Reply via email to