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