Initial step towards the ability to reduce c-ares exported symbols
authorYang Tse <yangsita@gmail.com>
Wed, 28 Oct 2009 19:45:26 +0000 (19:45 +0000)
committerYang Tse <yangsita@gmail.com>
Wed, 28 Oct 2009 19:45:26 +0000 (19:45 +0000)
based on the 'visibility' attribute for GNUC and __global for Sun
compilers, taking also in account __declspec function decoration
for Win32 and Symbian DLL's.

Introducing configure options --enable-hidden-symbols and
--disable-hidden-symbols following libcurl's naming.

Makefile.am
ares.h
configure.ac
m4/cares-compilers.m4
m4/cares-confopts.m4

index 302ac9d..b1f364a 100644 (file)
@@ -91,9 +91,7 @@ if NO_UNDEFINED
 UNDEF = -no-undefined
 endif
 
-# EXPORT_SYMBOLS = -export-symbols-regex '^ares_[[:alnum:]].*'
-
-libcares_la_LDFLAGS = $(UNDEF) $(VER) $(EXPORT_SYMBOLS)
+libcares_la_LDFLAGS = $(UNDEF) $(VER)
 
 # Makefile.inc provides the CSOURCES and HHEADERS defines
 include Makefile.inc
diff --git a/ares.h b/ares.h
index d7c0ad2..c5ff242 100644 (file)
--- a/ares.h
+++ b/ares.h
@@ -45,9 +45,9 @@
 #endif
 
 #if defined(WATT32)
-  #include <netinet/in.h>
-  #include <sys/socket.h>
-  #include <tcp.h>
+#  include <netinet/in.h>
+#  include <sys/socket.h>
+#  include <tcp.h>
 #elif defined(WIN32)
 #  ifndef WIN32_LEAN_AND_MEAN
 #    define WIN32_LEAN_AND_MEAN
 #  include <winsock2.h>
 #  include <ws2tcpip.h>
 #else
-  #include <sys/socket.h>
-  #include <netinet/in.h>
+#  include <sys/socket.h>
+#  include <netinet/in.h>
 #endif
 
 #ifdef  __cplusplus
 extern "C" {
 #endif
 
+/*
+** c-ares external API function linkage decorations.
+*/
+
+#if !defined(CARES_STATICLIB) && \
+    (defined(WIN32) || defined(_WIN32) || defined(__SYMBIAN32__))
+   /* __declspec function decoration for Win32 and Symbian DLL's */
+#  if defined(CARES_BUILDING_LIB)
+#    define CARES_EXTERN  __declspec(dllexport)
+#  else
+#    define CARES_EXTERN  __declspec(dllimport)
+#  endif
+#else
+   /* visibility function decoration for other cases */
+#  ifdef CARES_HIDDEN_SYMBOLS
+#    define CARES_EXTERN CARES_EXTERN_SYMBOL
+#  else
+#    define CARES_EXTERN
+#  endif
+#endif
+
+
 #define ARES_SUCCESS            0
 
 /* Server error codes (ARES_ENODATA indicates no relevant answer) */
@@ -241,62 +263,143 @@ struct hostent;
 struct timeval;
 struct sockaddr;
 struct ares_channeldata;
+
 typedef struct ares_channeldata *ares_channel;
-typedef void (*ares_callback)(void *arg, int status, int timeouts,
-                              unsigned char *abuf, int alen);
-typedef void (*ares_host_callback)(void *arg, int status, int timeouts,
+
+typedef void (*ares_callback)(void *arg,
+                              int status,
+                              int timeouts,
+                              unsigned char *abuf,
+                              int alen);
+
+typedef void (*ares_host_callback)(void *arg,
+                                   int status,
+                                   int timeouts,
                                    struct hostent *hostent);
-typedef void (*ares_nameinfo_callback)(void *arg, int status, int timeouts,
-                                       char *node, char *service);
+
+typedef void (*ares_nameinfo_callback)(void *arg,
+                                       int status,
+                                       int timeouts,
+                                       char *node,
+                                       char *service);
+
 typedef int  (*ares_sock_create_callback)(ares_socket_t socket_fd,
-                                          int type, void *data);
-
-int ares_library_init(int flags);
-void ares_library_cleanup(void);
-const char *ares_version(int *version);
-
-int ares_init(ares_channel *channelptr);
-int ares_init_options(ares_channel *channelptr, struct ares_options *options,
-                      int optmask);
-int ares_save_options(ares_channel channel, struct ares_options *options,
-                      int *optmask);
-void ares_destroy_options(struct ares_options *options);
-int ares_dup(ares_channel *dest, ares_channel src);
-void ares_destroy(ares_channel channel);
-void ares_cancel(ares_channel channel);
+                                          int type,
+                                          void *data);
+
+CARES_EXTERN int ares_library_init(int flags);
+
+CARES_EXTERN void ares_library_cleanup(void);
+
+CARES_EXTERN const char *ares_version(int *version);
+
+CARES_EXTERN int ares_init(ares_channel *channelptr);
+
+CARES_EXTERN int ares_init_options(ares_channel *channelptr,
+                                   struct ares_options *options,
+                                   int optmask);
+
+CARES_EXTERN int ares_save_options(ares_channel channel,
+                                   struct ares_options *options,
+                                   int *optmask);
+
+CARES_EXTERN void ares_destroy_options(struct ares_options *options);
+
+CARES_EXTERN int ares_dup(ares_channel *dest,
+                          ares_channel src);
+
+CARES_EXTERN void ares_destroy(ares_channel channel);
+
+CARES_EXTERN void ares_cancel(ares_channel channel);
+
 void ares_set_socket_callback(ares_channel channel,
                               ares_sock_create_callback callback,
                               void *user_data);
-void ares_send(ares_channel channel, const unsigned char *qbuf, int qlen,
-               ares_callback callback, void *arg);
-void ares_query(ares_channel channel, const char *name, int dnsclass,
-                int type, ares_callback callback, void *arg);
-void ares_search(ares_channel channel, const char *name, int dnsclass,
-                 int type, ares_callback callback, void *arg);
-void ares_gethostbyname(ares_channel channel, const char *name, int family,
-                        ares_host_callback callback, void *arg);
-int ares_gethostbyname_file(ares_channel channel, const char *name,
-                            int family, struct hostent **host);
-void ares_gethostbyaddr(ares_channel channel, const void *addr, int addrlen,
-                        int family, ares_host_callback callback, void *arg);
-void ares_getnameinfo(ares_channel channel, const struct sockaddr *sa,
-                      ares_socklen_t salen, int flags,
-                      ares_nameinfo_callback callback,
-                      void *arg);
-int ares_fds(ares_channel channel, fd_set *read_fds, fd_set *write_fds);
-int ares_getsock(ares_channel channel, int *socks, int numsocks);
-struct timeval *ares_timeout(ares_channel channel, struct timeval *maxtv,
-                             struct timeval *tv);
-void ares_process(ares_channel channel, fd_set *read_fds, fd_set *write_fds);
-void ares_process_fd(ares_channel channel, ares_socket_t read_fd,
-                     ares_socket_t write_fd);
-
-int ares_mkquery(const char *name, int dnsclass, int type, unsigned short id,
-                 int rd, unsigned char **buf, int *buflen);
-int ares_expand_name(const unsigned char *encoded, const unsigned char *abuf,
-                     int alen, char **s, long *enclen);
-int ares_expand_string(const unsigned char *encoded, const unsigned char *abuf,
-                     int alen, unsigned char **s, long *enclen);
+
+CARES_EXTERN void ares_send(ares_channel channel,
+                            const unsigned char *qbuf,
+                            int qlen,
+                            ares_callback callback,
+                            void *arg);
+
+CARES_EXTERN void ares_query(ares_channel channel,
+                             const char *name,
+                             int dnsclass,
+                             int type,
+                             ares_callback callback,
+                             void *arg);
+
+CARES_EXTERN void ares_search(ares_channel channel,
+                              const char *name,
+                              int dnsclass,
+                              int type,
+                              ares_callback callback,
+                              void *arg);
+
+CARES_EXTERN void ares_gethostbyname(ares_channel channel,
+                                     const char *name,
+                                     int family,
+                                     ares_host_callback callback,
+                                     void *arg);
+
+CARES_EXTERN int ares_gethostbyname_file(ares_channel channel,
+                                         const char *name,
+                                         int family,
+                                         struct hostent **host);
+
+CARES_EXTERN void ares_gethostbyaddr(ares_channel channel,
+                                     const void *addr,
+                                     int addrlen,
+                                     int family,
+                                     ares_host_callback callback,
+                                     void *arg);
+
+CARES_EXTERN void ares_getnameinfo(ares_channel channel,
+                                   const struct sockaddr *sa,
+                                   ares_socklen_t salen,
+                                   int flags,
+                                   ares_nameinfo_callback callback,
+                                   void *arg);
+
+CARES_EXTERN int ares_fds(ares_channel channel,
+                          fd_set *read_fds,
+                          fd_set *write_fds);
+
+CARES_EXTERN int ares_getsock(ares_channel channel,
+                              int *socks,
+                              int numsocks);
+
+CARES_EXTERN struct timeval *ares_timeout(ares_channel channel,
+                                          struct timeval *maxtv,
+                                          struct timeval *tv);
+
+CARES_EXTERN void ares_process(ares_channel channel,
+                               fd_set *read_fds,
+                               fd_set *write_fds);
+
+CARES_EXTERN void ares_process_fd(ares_channel channel,
+                                  ares_socket_t read_fd,
+                                  ares_socket_t write_fd);
+
+CARES_EXTERN int ares_mkquery(const char *name,
+                              int dnsclass,
+                              int type,
+                              unsigned short id,
+                              int rd,
+                              unsigned char **buf,
+                              int *buflen);
+
+CARES_EXTERN int ares_expand_name(const unsigned char *encoded,
+                                  const unsigned char *abuf,
+                                  int alen,
+                                  char **s,
+                                  long *enclen);
+
+CARES_EXTERN int ares_expand_string(const unsigned char *encoded,
+                                    const unsigned char *abuf,
+                                    int alen,
+                                    unsigned char **s,
+                                    long *enclen);
 
 /*
  * NOTE: before c-ares 1.6.1 we would most often use the system in6_addr
@@ -338,21 +441,40 @@ struct srv_reply {
 ** their TTLs in that array, and set *naddrttls to the number of addresses
 ** so written.
 */
-int ares_parse_a_reply(const unsigned char *abuf, int alen,
-                       struct hostent **host,
-                       struct addrttl *addrttls, int *naddrttls);
-int ares_parse_aaaa_reply(const unsigned char *abuf, int alen,
-                          struct hostent **host,
-                          struct addr6ttl *addrttls, int *naddrttls);
-int ares_parse_ptr_reply(const unsigned char *abuf, int alen, const void *addr,
-                         int addrlen, int family, struct hostent **host);
-int ares_parse_ns_reply(const unsigned char *abuf, int alen,
-                        struct hostent **host);
-int ares_parse_srv_reply(const unsigned char* abuf, int alen,
-                         struct srv_reply** srv_out, int *nsrvreply);
-void ares_free_string(void *str);
-void ares_free_hostent(struct hostent *host);
-const char *ares_strerror(int code);
+
+CARES_EXTERN int ares_parse_a_reply(const unsigned char *abuf,
+                                    int alen,
+                                    struct hostent **host,
+                                    struct addrttl *addrttls,
+                                    int *naddrttls);
+
+CARES_EXTERN int ares_parse_aaaa_reply(const unsigned char *abuf,
+                                       int alen,
+                                       struct hostent **host,
+                                       struct addr6ttl *addrttls,
+                                       int *naddrttls);
+
+CARES_EXTERN int ares_parse_ptr_reply(const unsigned char *abuf,
+                                      int alen,
+                                      const void *addr,
+                                      int addrlen,
+                                      int family,
+                                      struct hostent **host);
+
+CARES_EXTERN int ares_parse_ns_reply(const unsigned char *abuf,
+                                     int alen,
+                                     struct hostent **host);
+
+CARES_EXTERN int ares_parse_srv_reply(const unsigned char* abuf,
+                                      int alen,
+                                      struct srv_reply** srv_out,
+                                      int *nsrvreply);
+
+CARES_EXTERN void ares_free_string(void *str);
+
+CARES_EXTERN void ares_free_hostent(struct hostent *host);
+
+CARES_EXTERN const char *ares_strerror(int code);
 
 #ifdef  __cplusplus
 }
index 42ccd49..92db52e 100644 (file)
@@ -14,6 +14,7 @@ CARES_CHECK_OPTION_DEBUG
 CARES_CHECK_OPTION_OPTIMIZE
 CARES_CHECK_OPTION_WARNINGS
 CARES_CHECK_OPTION_CURLDEBUG
+CARES_CHECK_OPTION_HIDDEN_SYMBOLS
 
 CARES_CHECK_PATH_SEPARATOR_REQUIRED
 
@@ -110,6 +111,25 @@ esac
 dnl libtool setup
 AC_PROG_LIBTOOL
 
+AC_MSG_CHECKING([if we need CARES_BUILDING_LIB])
+case $host in
+  *-*-mingw*)
+    AC_DEFINE(CARES_BUILDING_LIB, 1, [when building c-ares library])
+    AC_MSG_RESULT(yes)
+    AC_MSG_CHECKING([if we need CARES_STATICLIB])
+    if test "X$enable_shared" = "Xno"
+    then
+      AC_DEFINE(CARES_STATICLIB, 1, [when not building a shared library])
+      AC_MSG_RESULT(yes)
+    else
+      AC_MSG_RESULT(no)
+    fi
+    ;;
+  *)
+    AC_MSG_RESULT(no)
+    ;;
+esac
+
 dnl **********************************************************************
 dnl platform/compiler/architecture specific checks/flags
 dnl **********************************************************************
@@ -144,6 +164,7 @@ esac
 
 CARES_CHECK_COMPILER_HALT_ON_ERROR
 CARES_CHECK_COMPILER_ARRAY_SIZE_NEGATIVE
+CARES_CHECK_COMPILER_HIDDEN_SYMBOLS
 
 CARES_CHECK_NO_UNDEFINED
 AM_CONDITIONAL(NO_UNDEFINED, test x$need_no_undefined = xyes)
@@ -876,6 +897,8 @@ fi
 CARES_CHECK_OPTION_NONBLOCKING
 CARES_CHECK_NONBLOCKING_SOCKET
 
+CARES_CONFIGURE_HIDDEN_SYMBOLS
+
 CARES_PRIVATE_LIBS="$LIBS"
 AC_SUBST(CARES_PRIVATE_LIBS)
 
index e4fd1ec..77e4651 100644 (file)
@@ -16,7 +16,7 @@
 #***************************************************************************
 
 # File version for 'aclocal' use. Keep it a single number.
-# serial 56
+# serial 59
 
 
 dnl CARES_CHECK_COMPILER
@@ -1249,6 +1249,100 @@ AC_DEFUN([CARES_CHECK_COMPILER_ARRAY_SIZE_NEGATIVE], [
 ])
 
 
+dnl CARES_CHECK_COMPILER_HIDDEN_SYMBOLS
+dnl -------------------------------------------------
+dnl Verify if compiler supports hiding library internal symbols, setting
+dnl shell variable hidden_symbols_supported value as appropriate, as well
+dnl as variable hidden_symbols_CFLAGS when supported.
+
+AC_DEFUN([CARES_CHECK_COMPILER_HIDDEN_SYMBOLS], [
+  AC_REQUIRE([CARES_CHECK_COMPILER])dnl
+  AC_BEFORE([$0],[CARES_CONFIGURE_HIDDEN_SYMBOLS])dnl
+  AC_MSG_CHECKING([if compiler supports hiding library internal symbols])
+  hidden_symbols_supported="no"
+  hidden_symbols_CFLAGS=""
+  tmp_CFLAGS=""
+  tmp_extern=""
+  case "$compiler_id" in
+    GNU_C)
+      dnl Only gcc 3.4 or later
+      if test "$compiler_num" -ge "304"; then
+        if $CC --help --verbose 2>&1 | grep fvisibility= > /dev/null ; then
+          tmp_extern="__attribute__ ((visibility (\"default\")))"
+          tmp_CFLAGS="-fvisibility=hidden"
+          hidden_symbols_supported="yes"
+          echo " " >&6
+          echo "debug: should work with this compiler and version" >&6
+          echo " " >&6
+        fi
+      fi
+      ;;
+    INTEL_UNIX_C)
+      dnl Only icc 9.0 or later
+      if test "$compiler_num" -ge "900"; then
+        if $CC --help --verbose 2>&1 | grep fvisibility= > /dev/null ; then
+          tmp_extern="__attribute__ ((visibility (\"default\")))"
+          tmp_CFLAGS="-fvisibility=hidden"
+          hidden_symbols_supported="yes"
+          echo " " >&6
+          echo "debug: should work with this compiler and version" >&6
+          echo " " >&6
+        fi
+      fi
+      ;;
+    SUNPRO_C)
+      if $CC 2>&1 | grep flags >/dev/null && $CC -flags | grep xldscope= >/dev/null ; then
+        tmp_extern="__global"
+        tmp_CFLAGS="-xldscope=hidden"
+        hidden_symbols_supported="yes"
+        echo " " >&6
+        echo "debug: should work with this compiler and version" >&6
+        echo " " >&6
+      fi
+      ;;
+  esac
+  if test "$hidden_symbols_supported" = "yes"; then
+    tmp_save_CFLAGS="$CFLAGS"
+    CFLAGS="$tmp_save_CFLAGS $tmp_CFLAGS"
+    squeeze CFLAGS
+    AC_COMPILE_IFELSE([
+      AC_LANG_PROGRAM([[
+        $tmp_extern char *dummy(char *buff);
+        char *dummy(char *buff)
+        {
+         if(buff)
+           return ++buff;
+         else
+           return buff;
+        }
+      ]],[[
+        char b[16];
+        char *r = dummy(&b);
+        if(r)
+          return (int)*r;
+      ]])
+    ],[
+      hidden_symbols_supported="yes"
+    ],[
+      hidden_symbols_supported="no"
+      sed 's/^/cc-src: /' conftest.$ac_ext >&6
+      sed 's/^/cc-err: /' conftest.err >&6
+    ])
+    CFLAGS="$tmp_save_CFLAGS"
+  fi
+  if test "$hidden_symbols_supported" = "yes"; then
+    AC_MSG_RESULT([yes])
+    AC_DEFINE_UNQUOTED(CARES_HIDDEN_SYMBOLS, 1,
+      [Define to 1 to enable hiding of library internal symbols.])
+    AC_DEFINE_UNQUOTED(CARES_EXTERN_SYMBOL, $tmp_extern,
+      [Definition to make a library symbol externally visible.])
+    hidden_symbols_CFLAGS="$tmp_CFLAGS"
+  else
+    AC_MSG_RESULT([no])
+  fi
+])
+
+
 dnl CARES_CHECK_COMPILER_STRUCT_MEMBER_SIZE
 dnl -------------------------------------------------
 dnl Verifies if the compiler is capable of handling the
index cc03a09..5af3232 100644 (file)
@@ -16,7 +16,7 @@
 #***************************************************************************
 
 # File version for 'aclocal' use. Keep it a single number.
-# serial 5
+# serial 6
 
 
 dnl CARES_CHECK_OPTION_CURLDEBUG
@@ -92,6 +92,46 @@ AC_HELP_STRING([--disable-debug],[Disable debug build options]),
 ])
 
 
+dnl CARES_CHECK_OPTION_HIDDEN_SYMBOLS
+dnl -------------------------------------------------
+dnl Verify if configure has been invoked with option
+dnl --enable-hidden-symbols or --disable-hidden-symbols,
+dnl setting shell variable want_hidden_symbols value.
+
+AC_DEFUN([CARES_CHECK_OPTION_HIDDEN_SYMBOLS], [
+  AC_BEFORE([$0],[CARES_CHECK_COMPILER_HIDDEN_SYMBOLS])dnl
+  AC_MSG_CHECKING([whether to enable hiding symbols])
+  OPT_HIDDEN_SYMBOLS="default"
+  AC_ARG_ENABLE(hidden-symbols,
+AC_HELP_STRING([--enable-hidden-symbols],[Enable hiding of library internal symbols])
+AC_HELP_STRING([--disable-hidden-symbols],[Disable hiding of library internal symbols]),
+  OPT_HIDDEN_SYMBOLS=$enableval)
+  case "$OPT_HIDDEN_SYMBOLS" in
+    no)
+      dnl --disable-hidden-symbols option used.
+      dnl This is an indication to not attempt hiding of library internal
+      dnl symbols. Default symbol visibility will be used, which normally
+      dnl exposes all library internal symbols.
+      want_hidden_symbols="no"
+      AC_MSG_RESULT([no])
+      ;;
+    default)
+      dnl configure's hidden-symbols option not specified.
+      dnl Handle this as if --enable-hidden-symbols option was given.
+      want_hidden_symbols="yes"
+      AC_MSG_RESULT([not specified (assuming yes)])
+      ;;
+    *)
+      dnl --enable-hidden-symbols option used.
+      dnl This is an indication to attempt hiding of library internal
+      dnl symbols. This is only supported on some compilers/linkers.
+      want_hidden_symbols="yes"
+      AC_MSG_RESULT([yes])
+      ;;
+  esac
+])
+
+
 dnl CARES_CHECK_OPTION_NONBLOCKING
 dnl -------------------------------------------------
 dnl Verify if configure has been invoked with option
@@ -252,3 +292,24 @@ AC_DEFUN([CARES_CHECK_NONBLOCKING_SOCKET], [
   fi
 ])
 
+
+dnl CARES_CONFIGURE_HIDDEN_SYMBOLS
+dnl -------------------------------------------------
+dnl Depending on --enable-hidden-symbols or --disable-hidden-symbols
+dnl configure option, and compiler capability to actually honor such
+dnl option, compiler flags will be modified as appropriate.
+dnl This macro should not be used until all compilation tests have
+dnl been done to prevent interferences on other tests.
+
+AC_DEFUN([CARES_CONFIGURE_HIDDEN_SYMBOLS], [
+  AC_MSG_CHECKING([whether to actually hide library internal symbols])
+  if test "$want_hidden_symbols" = "yes" &&
+    test "$hidden_symbols_supported" = "yes"; then
+    tmp_save_CFLAGS="$CFLAGS"
+    CFLAGS="$tmp_save_CFLAGS $hidden_symbols_CFLAGS"
+    AC_MSG_RESULT([yes])
+  else
+    AC_MSG_RESULT([no])
+  fi
+])
+