From 4545fa9b6866df47ce2f908631a84477a94d5f49 Mon Sep 17 00:00:00 2001
From: Trond Norbye <trond.norbye@gmail.com>
Date: Wed, 19 Feb 2014 06:31:27 +0100
Subject: [PATCH] Add option to build shared library

---
 CMakeLists.txt                   |  66 +++++++++++++++++---
 event-config.h.cmake             |   2 +
 include/event2/buffer.h          |  59 +++++++++++++++++-
 include/event2/buffer_compat.h   |   5 ++
 include/event2/bufferevent.h     |  62 +++++++++++++++++++
 include/event2/bufferevent_ssl.h |   9 ++-
 include/event2/dns.h             |  40 ++++++++++++
 include/event2/event.h           |  70 +++++++++++++++++++++
 include/event2/event_compat.h    |  10 +++
 include/event2/http.h            | 101 +++++++++++++++++++++++++++++++
 include/event2/listener.h        |  11 ++++
 include/event2/tag.h             |  22 +++++++
 include/event2/thread.h          |  10 +++
 include/event2/util.h            |  26 ++++++++
 include/event2/visibility.h      |  55 +++++++++++++++++
 include/include.am               |   3 +-
 util-internal.h                  |   3 +
 17 files changed, 542 insertions(+), 12 deletions(-)
 create mode 100644 include/event2/visibility.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 95973a63..5bb88d50 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -7,6 +7,7 @@
 # Additional changes:
 #   Brodie Thiesfield
 #   Joakim Soderberg 
+#   Trond Norbye
 #
 #   Build example:
 #
@@ -27,9 +28,16 @@ set(EVENT_VERSION_MAJOR 2)
 set(EVENT_VERSION_MINOR 1)
 set(EVENT_VERSION_PATCH 4)
 set(EVENT_NUMERIC_VERSION 0x02010401)
+
+set(EVENT_ABI_MAJOR 2)
+set(EVENT_ABI_MINOR 1)
+set(EVENT_ABI_PATCH 4)
+set(EVENT_ABI_LIBVERSION "${EVENT_ABI_MAJOR}.${EVENT_ABI_MINOR}.${EVENT_ABI_PATCH}")
+
 set(EVENT_VERSION "${EVENT_VERSION_MAJOR}.${EVENT_VERSION_MINOR}.${EVENT_VERSION_PATCH}-beta")
 set(EVENT_PACKAGE_VERSION "${EVENT_VERSION_MAJOR}.${EVENT_VERSION_MINOR}.${EVENT_VERSION_PATCH}")
 
+option(EVENT__BUILD_SHARED_LIBRARIES "Define if libevent should be built with shared libraries instead of archives" OFF)
 option(EVENT__DISABLE_DEBUG_MODE "Define if libevent should build without support for a debug mode" OFF)
 option(EVENT__ENABLE_VERBOSE_DEBUG "Enables verbose debugging" OFF)
 option(EVENT__DISABLE_MM_REPLACEMENT "Define if libevent should not allow replacing the mm functions" OFF)
@@ -653,8 +661,24 @@ source_group("Source Extra"     FILES ${SRC_EXTRA})
 # (Place them in the build dir so we don't polute the source tree with generated files).
 include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR}/include)
 
+if (EVENT__BUILD_SHARED_LIBRARIES)
+  set(EVENT__LIBRARY_TYPE SHARED)
+
+  if (CMAKE_COMPILER_IS_GNUC)
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden")
+  elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden")
+  elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "SunPro")
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -xldscope=hidden")
+  endif ()
+  set(EVENT__NEED_DLLIMPORT 1)
+
+else (EVENT__BUILD_SHARED_LIBRARIES)
+  set(EVENT__LIBRARY_TYPE STATIC)
+endif (EVENT__BUILD_SHARED_LIBRARIES)
+
 configure_file(
-    ${CMAKE_CURRENT_SOURCE_DIR}/event-config.h.cmake 
+    ${CMAKE_CURRENT_SOURCE_DIR}/event-config.h.cmake
     ${CMAKE_CURRENT_BINARY_DIR}/include/event2/event-config.h)
 
 configure_file(
@@ -666,13 +690,13 @@ configure_file(
 #
 
 # TODO: Add dynamic versions of the libraries as well.
-add_library(event_core STATIC
+add_library(event_core ${EVENT__LIBRARY_TYPE}
     ${HDR_PRIVATE}
     ${HDR_PUBLIC}
     ${SRC_CORE}
     )
-    
-add_library(event_extra STATIC
+
+add_library(event_extra ${EVENT__LIBRARY_TYPE}
     ${HDR_PRIVATE}
     ${HDR_PUBLIC}
     ${SRC_CORE}
@@ -682,13 +706,32 @@ add_library(event_extra STATIC
 # library exists for historical reasons; it contains the contents of
 # both libevent_core and libevent_extra. You shouldn’t use it; it may
 # go away in a future version of Libevent.
-add_library(event STATIC
+add_library(event ${EVENT__LIBRARY_TYPE}
     ${HDR_PRIVATE}
     ${HDR_PUBLIC}
     ${SRC_CORE}
     ${SRC_EXTRA}
     )
 
+if (EVENT__BUILD_SHARED_LIBRARIES)
+   target_link_libraries(event_core ${OPENSSL_LIBRARIES}
+                                    ${CMAKE_THREAD_LIBS_INIT}
+                                    ${LIB_PLATFORM})
+
+   target_link_libraries(event ${OPENSSL_LIBRARIES}
+                               ${CMAKE_THREAD_LIBS_INIT}
+                               ${LIB_PLATFORM})
+
+   target_link_libraries(event_extra ${OPENSSL_LIBRARIES}
+                                      ${CMAKE_THREAD_LIBS_INIT}
+                                      ${LIB_PLATFORM})
+
+  set_target_properties(event PROPERTIES SOVERSION ${EVENT_ABI_LIBVERSION})
+  set_target_properties(event_core PROPERTIES SOVERSION ${EVENT_ABI_LIBVERSION})
+  set_target_properties(event_extra PROPERTIES SOVERSION ${EVENT_ABI_LIBVERSION})
+
+endif (EVENT__BUILD_SHARED_LIBRARIES)
+
 #
 # Samples.
 #
@@ -777,6 +820,8 @@ if (NOT EVENT__DISABLE_TESTS)
                 test/regress_testutils.h
                 test/regress_util.c 
                 test/tinytest.c
+                ${SRC_CORE}
+                ${SRC_EXTRA}
                 )
 
             if (WIN32)
@@ -797,8 +842,14 @@ if (NOT EVENT__DISABLE_TESTS)
             endif()
 
             add_executable(regress ${SRC_REGRESS})
-            target_link_libraries(regress event_extra ${LIB_APPS} ${LIB_PLATFORM})
-            add_dependencies(regress event_extra)
+            # While building the test suite we don't want the visibility
+            # header trying to "dllimport" the symbols on windows (it
+            # generates a ton of warnings due to different link
+            # attributes for all of the symbols)
+            SET_TARGET_PROPERTIES(regress PROPERTIES COMPILE_DEFINITIONS
+                                  "EVENT_BUILDING_REGRESS_TEST=1")
+
+            target_link_libraries(regress ${LIB_APPS} ${LIB_PLATFORM})
         else()
             message(WARNING "Python not found, cannot generate regress tests!")
         endif()
@@ -1064,6 +1115,7 @@ set_target_properties(event event_core event_extra
 #
 install(TARGETS event event_core event_extra
         EXPORT LibeventTargets
+        RUNTIME DESTINATION "${EVENT_INSTALL_LIB_DIR}" COMPONENT bin
         LIBRARY DESTINATION "${EVENT_INSTALL_LIB_DIR}" COMPONENT lib
         ARCHIVE DESTINATION "${EVENT_INSTALL_LIB_DIR}" COMPONENT lib
         PUBLIC_HEADER DESTINATION "${EVENT_INSTALL_INCLUDE_DIR}/event2" COMPONENT dev)
diff --git a/event-config.h.cmake b/event-config.h.cmake
index 577b7448..36ae0585 100644
--- a/event-config.h.cmake
+++ b/event-config.h.cmake
@@ -497,4 +497,6 @@
 /* Define to `int' if <sys/types.h> does not define. */
 #cmakedefine EVENT__ssize_t ${EVENT__ssize_t}
 
+#cmakedefine EVENT__NEED_DLLIMPORT ${EVENT__NEED_DLLIMPORT}
+
 #endif
diff --git a/include/event2/buffer.h b/include/event2/buffer.h
index 712e4d79..839d6e7c 100644
--- a/include/event2/buffer.h
+++ b/include/event2/buffer.h
@@ -72,6 +72,8 @@
   evbuffer_peek() if you don't require that the memory to be contiguous.
  */
 
+#include <event2/visibility.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -151,12 +153,14 @@ struct evbuffer_iovec {
   @return a pointer to a newly allocated evbuffer struct, or NULL if an error
 	occurred
  */
+EVENT2_EXPORT_SYMBOL
 struct evbuffer *evbuffer_new(void);
 /**
   Deallocate storage for an evbuffer.
 
   @param buf pointer to the evbuffer to be freed
  */
+EVENT2_EXPORT_SYMBOL
 void evbuffer_free(struct evbuffer *buf);
 
 /**
@@ -171,18 +175,21 @@ void evbuffer_free(struct evbuffer *buf);
    @param lock A lock object, or NULL if we should allocate our own.
    @return 0 on success, -1 on failure.
  */
+EVENT2_EXPORT_SYMBOL
 int evbuffer_enable_locking(struct evbuffer *buf, void *lock);
 
 /**
    Acquire the lock on an evbuffer.  Has no effect if locking was not enabled
    with evbuffer_enable_locking.
 */
+EVENT2_EXPORT_SYMBOL
 void evbuffer_lock(struct evbuffer *buf);
 
 /**
    Release the lock on an evbuffer.  Has no effect if locking was not enabled
    with evbuffer_enable_locking.
 */
+EVENT2_EXPORT_SYMBOL
 void evbuffer_unlock(struct evbuffer *buf);
 
 
@@ -210,6 +217,7 @@ void evbuffer_unlock(struct evbuffer *buf);
  * @param flags One or more EVBUFFER_FLAG_* options
  * @return 0 on success, -1 on failure.
  */
+EVENT2_EXPORT_SYMBOL
 int evbuffer_set_flags(struct evbuffer *buf, ev_uint64_t flags);
 /** Change the flags that are set for an evbuffer by removing some.
  *
@@ -218,6 +226,7 @@ int evbuffer_set_flags(struct evbuffer *buf, ev_uint64_t flags);
  * @param flags One or more EVBUFFER_FLAG_* options
  * @return 0 on success, -1 on failure.
  */
+EVENT2_EXPORT_SYMBOL
 int evbuffer_clear_flags(struct evbuffer *buf, ev_uint64_t flags);
 
 /**
@@ -226,6 +235,7 @@ int evbuffer_clear_flags(struct evbuffer *buf, ev_uint64_t flags);
   @param buf pointer to the evbuffer
   @return the number of bytes stored in the evbuffer
 */
+EVENT2_EXPORT_SYMBOL
 size_t evbuffer_get_length(const struct evbuffer *buf);
 
 /**
@@ -240,6 +250,7 @@ size_t evbuffer_get_length(const struct evbuffer *buf);
    @return 0 if no data is available, otherwise the number of available bytes
      in the first buffer chain.
 */
+EVENT2_EXPORT_SYMBOL
 size_t evbuffer_get_contiguous_space(const struct evbuffer *buf);
 
 /**
@@ -252,6 +263,7 @@ size_t evbuffer_get_contiguous_space(const struct evbuffer *buf);
   @param datlen the new minimum length requirement
   @return 0 if successful, or -1 if an error occurred
 */
+EVENT2_EXPORT_SYMBOL
 int evbuffer_expand(struct evbuffer *buf, size_t datlen);
 
 /**
@@ -287,6 +299,7 @@ int evbuffer_expand(struct evbuffer *buf, size_t datlen);
    @return the number of provided extents, or -1 on error.
    @see evbuffer_commit_space()
 */
+EVENT2_EXPORT_SYMBOL
 int
 evbuffer_reserve_space(struct evbuffer *buf, ev_ssize_t size,
     struct evbuffer_iovec *vec, int n_vec);
@@ -312,6 +325,7 @@ evbuffer_reserve_space(struct evbuffer *buf, ev_ssize_t size,
    @return 0 on success, -1 on error
    @see evbuffer_reserve_space()
 */
+EVENT2_EXPORT_SYMBOL
 int evbuffer_commit_space(struct evbuffer *buf,
     struct evbuffer_iovec *vec, int n_vecs);
 
@@ -323,6 +337,7 @@ int evbuffer_commit_space(struct evbuffer *buf,
   @param datlen the number of bytes to be copied from the data buffer
   @return 0 on success, -1 on failure.
  */
+EVENT2_EXPORT_SYMBOL
 int evbuffer_add(struct evbuffer *buf, const void *data, size_t datlen);
 
 
@@ -337,6 +352,7 @@ int evbuffer_add(struct evbuffer *buf, const void *data, size_t datlen);
   @param datlen the maximum size of the destination buffer
   @return the number of bytes read, or -1 if we can't drain the buffer.
  */
+EVENT2_EXPORT_SYMBOL
 int evbuffer_remove(struct evbuffer *buf, void *data, size_t datlen);
 
 /**
@@ -350,6 +366,7 @@ int evbuffer_remove(struct evbuffer *buf, void *data, size_t datlen);
   @param datlen the maximum size of the destination buffer
   @return the number of bytes read, or -1 if we can't drain the buffer.
  */
+EVENT2_EXPORT_SYMBOL
 ev_ssize_t evbuffer_copyout(struct evbuffer *buf, void *data_out, size_t datlen);
 
 /**
@@ -364,6 +381,7 @@ ev_ssize_t evbuffer_copyout(struct evbuffer *buf, void *data_out, size_t datlen)
   @param datlen the maximum size of the destination buffer
   @return the number of bytes read, or -1 if we can't drain the buffer.
  */
+EVENT2_EXPORT_SYMBOL
 ev_ssize_t evbuffer_copyout_from(struct evbuffer *buf, const struct evbuffer_ptr *pos, void *data_out, size_t datlen);
 
 /**
@@ -379,6 +397,7 @@ ev_ssize_t evbuffer_copyout_from(struct evbuffer *buf, const struct evbuffer_ptr
   @param datlen the maximum numbers of bytes to transfer
   @return the number of bytes read
  */
+EVENT2_EXPORT_SYMBOL
 int evbuffer_remove_buffer(struct evbuffer *src, struct evbuffer *dst,
     size_t datlen);
 
@@ -420,6 +439,7 @@ enum evbuffer_eol_style {
  * @param eol_style the style of line-ending to use.
  * @return pointer to a single line, or NULL if an error occurred
  */
+EVENT2_EXPORT_SYMBOL
 char *evbuffer_readln(struct evbuffer *buffer, size_t *n_read_out,
     enum evbuffer_eol_style eol_style);
 
@@ -435,21 +455,23 @@ char *evbuffer_readln(struct evbuffer *buffer, size_t *n_read_out,
 
   @see evbuffer_remove_buffer()
  */
+EVENT2_EXPORT_SYMBOL
 int evbuffer_add_buffer(struct evbuffer *outbuf, struct evbuffer *inbuf);
 
 /**
   Copy data from one evbuffer into another evbuffer.
-  
+
   This is a non-destructive add.  The data from one buffer is copied
   into the other buffer.  However, no unnecessary memory copies occur.
-  
+
   Note that buffers already containing buffer references can't be added
   to other buffers.
-  
+
   @param outbuf the output buffer
   @param inbuf the input buffer
   @return 0 if successful, or -1 if an error occurred
  */
+EVENT2_EXPORT_SYMBOL
 int evbuffer_add_buffer_reference(struct evbuffer *outbuf,
     struct evbuffer *inbuf);
 
@@ -477,6 +499,7 @@ typedef void (*evbuffer_ref_cleanup_cb)(const void *data,
   @param cleanupfn_arg optional argument to the cleanup callback
   @return 0 if successful, or -1 if an error occurred
  */
+EVENT2_EXPORT_SYMBOL
 int evbuffer_add_reference(struct evbuffer *outbuf,
     const void *data, size_t datlen,
     evbuffer_ref_cleanup_cb cleanupfn, void *cleanupfn_arg);
@@ -505,6 +528,7 @@ int evbuffer_add_reference(struct evbuffer *outbuf,
   @return 0 if successful, or -1 if an error occurred
 */
 
+EVENT2_EXPORT_SYMBOL
 int evbuffer_add_file(struct evbuffer *outbuf, int fd, ev_off_t offset,
     ev_off_t length);
 
@@ -576,6 +600,7 @@ typedef void (*evbuffer_file_segment_cleanup_cb)(
    @param flags any number of the EVBUF_FS_* flags
    @return a new evbuffer_file_segment, or NULL on failure.
  **/
+EVENT2_EXPORT_SYMBOL
 struct evbuffer_file_segment *evbuffer_file_segment_new(
 	int fd, ev_off_t offset, ev_off_t length, unsigned flags);
 
@@ -586,6 +611,7 @@ struct evbuffer_file_segment *evbuffer_file_segment_new(
    one or more evbuffers.  The evbuffer_file_segment will not be freed
    until no more references to it exist.
  */
+EVENT2_EXPORT_SYMBOL
 void evbuffer_file_segment_free(struct evbuffer_file_segment *seg);
 
 /**
@@ -595,6 +621,7 @@ void evbuffer_file_segment_free(struct evbuffer_file_segment *seg);
    The cleanup callback will be invoked when no more references to the
    evbuffer_file_segment exist.
  **/
+EVENT2_EXPORT_SYMBOL
 void evbuffer_file_segment_add_cleanup_cb(struct evbuffer_file_segment *seg,
 	evbuffer_file_segment_cleanup_cb cb, void* arg);
 
@@ -620,6 +647,7 @@ void evbuffer_file_segment_add_cleanup_cb(struct evbuffer_file_segment *seg,
    @param length the amount of data to add, or -1 to add it all.
    @return 0 on success, -1 on failure.
  */
+EVENT2_EXPORT_SYMBOL
 int evbuffer_add_file_segment(struct evbuffer *buf,
     struct evbuffer_file_segment *seg, ev_off_t offset, ev_off_t length);
 
@@ -635,6 +663,7 @@ int evbuffer_add_file_segment(struct evbuffer *buf,
 
   @see evutil_printf(), evbuffer_add_vprintf()
  */
+EVENT2_EXPORT_SYMBOL
 int evbuffer_add_printf(struct evbuffer *buf, const char *fmt, ...)
 #ifdef __GNUC__
   __attribute__((format(printf, 2, 3)))
@@ -649,6 +678,7 @@ int evbuffer_add_printf(struct evbuffer *buf, const char *fmt, ...)
   @param ap a varargs va_list argument array that will be passed to vprintf(3)
   @return The number of bytes added if successful, or -1 if an error occurred.
  */
+EVENT2_EXPORT_SYMBOL
 int evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap)
 #ifdef __GNUC__
 	__attribute__((format(printf, 2, 0)))
@@ -663,6 +693,7 @@ int evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap)
   @param len the number of bytes to drain from the beginning of the buffer
   @return 0 on success, -1 on failure.
  */
+EVENT2_EXPORT_SYMBOL
 int evbuffer_drain(struct evbuffer *buf, size_t len);
 
 
@@ -676,6 +707,7 @@ int evbuffer_drain(struct evbuffer *buf, size_t len);
   @return the number of bytes written, or -1 if an error occurred
   @see evbuffer_read()
  */
+EVENT2_EXPORT_SYMBOL
 int evbuffer_write(struct evbuffer *buffer, evutil_socket_t fd);
 
 /**
@@ -690,6 +722,7 @@ int evbuffer_write(struct evbuffer *buffer, evutil_socket_t fd);
   @return the number of bytes written, or -1 if an error occurred
   @see evbuffer_read()
  */
+EVENT2_EXPORT_SYMBOL
 int evbuffer_write_atmost(struct evbuffer *buffer, evutil_socket_t fd,
 						  ev_ssize_t howmuch);
 
@@ -702,6 +735,7 @@ int evbuffer_write_atmost(struct evbuffer *buffer, evutil_socket_t fd,
   @return the number of bytes read, or -1 if an error occurred
   @see evbuffer_write()
  */
+EVENT2_EXPORT_SYMBOL
 int evbuffer_read(struct evbuffer *buffer, evutil_socket_t fd, int howmuch);
 
 /**
@@ -715,6 +749,7 @@ int evbuffer_read(struct evbuffer *buffer, evutil_socket_t fd, int howmuch);
      first occurrence of the string in the buffer after 'start'.  The 'pos'
      field of the result is -1 if the string was not found.
  */
+EVENT2_EXPORT_SYMBOL
 struct evbuffer_ptr evbuffer_search(struct evbuffer *buffer, const char *what, size_t len, const struct evbuffer_ptr *start);
 
 /**
@@ -731,6 +766,7 @@ struct evbuffer_ptr evbuffer_search(struct evbuffer *buffer, const char *what, s
      first occurrence of the string in the buffer after 'start'.  The 'pos'
      field of the result is -1 if the string was not found.
  */
+EVENT2_EXPORT_SYMBOL
 struct evbuffer_ptr evbuffer_search_range(struct evbuffer *buffer, const char *what, size_t len, const struct evbuffer_ptr *start, const struct evbuffer_ptr *end);
 
 /**
@@ -766,6 +802,7 @@ enum evbuffer_ptr_how {
    @param how determines how the pointer should be manipulated.
    @returns 0 on success or -1 otherwise
 */
+EVENT2_EXPORT_SYMBOL
 int
 evbuffer_ptr_set(struct evbuffer *buffer, struct evbuffer_ptr *ptr,
     size_t position, enum evbuffer_ptr_how how);
@@ -784,6 +821,7 @@ evbuffer_ptr_set(struct evbuffer *buffer, struct evbuffer_ptr *ptr,
      first occurrence EOL in the buffer after 'start'.  The 'pos'
      field of the result is -1 if the string was not found.
  */
+EVENT2_EXPORT_SYMBOL
 struct evbuffer_ptr evbuffer_search_eol(struct evbuffer *buffer,
     struct evbuffer_ptr *start, size_t *eol_len_out,
     enum evbuffer_eol_style eol_style);
@@ -816,6 +854,7 @@ struct evbuffer_ptr evbuffer_search_eol(struct evbuffer *buffer,
        than n_vec if we would need more to return all the data that was
        requested.
  */
+EVENT2_EXPORT_SYMBOL
 int evbuffer_peek(struct evbuffer *buffer, ev_ssize_t len,
     struct evbuffer_ptr *start_at,
     struct evbuffer_iovec *vec_out, int n_vec);
@@ -868,6 +907,7 @@ struct evbuffer_cb_entry;
   @param cbarg an argument to be provided to the callback function
   @return a handle to the callback on success, or NULL on failure.
  */
+EVENT2_EXPORT_SYMBOL
 struct evbuffer_cb_entry *evbuffer_add_cb(struct evbuffer *buffer, evbuffer_cb_func cb, void *cbarg);
 
 /** Remove a callback from an evbuffer, given a handle returned from
@@ -878,6 +918,7 @@ struct evbuffer_cb_entry *evbuffer_add_cb(struct evbuffer *buffer, evbuffer_cb_f
     @return 0 if a callback was removed, or -1 if no matching callback was
     found.
  */
+EVENT2_EXPORT_SYMBOL
 int evbuffer_remove_cb_entry(struct evbuffer *buffer,
 			     struct evbuffer_cb_entry *ent);
 
@@ -887,6 +928,7 @@ int evbuffer_remove_cb_entry(struct evbuffer *buffer,
     @return 0 if a callback was removed, or -1 if no matching callback was
     found.
  */
+EVENT2_EXPORT_SYMBOL
 int evbuffer_remove_cb(struct evbuffer *buffer, evbuffer_cb_func cb, void *cbarg);
 
 /** If this flag is not set, then a callback is temporarily disabled, and
@@ -903,6 +945,7 @@ int evbuffer_remove_cb(struct evbuffer *buffer, evbuffer_cb_func cb, void *cbarg
     @param flags EVBUFFER_CB_ENABLED to re-enable the callback.
     @return 0 on success, -1 on failure.
  */
+EVENT2_EXPORT_SYMBOL
 int evbuffer_cb_set_flags(struct evbuffer *buffer,
 			  struct evbuffer_cb_entry *cb, ev_uint32_t flags);
 
@@ -913,6 +956,7 @@ int evbuffer_cb_set_flags(struct evbuffer *buffer,
     @param flags EVBUFFER_CB_ENABLED to disable the callback.
     @return 0 on success, -1 on failure.
  */
+EVENT2_EXPORT_SYMBOL
 int evbuffer_cb_clear_flags(struct evbuffer *buffer,
 			  struct evbuffer_cb_entry *cb, ev_uint32_t flags);
 
@@ -926,6 +970,7 @@ int evbuffer_cb_clear_flags(struct evbuffer *buffer,
 	@param the buffer that the callback is watching.
 	@param cb the callback we want to suspend.
  */
+EVENT2_EXPORT_SYMBOL
 void evbuffer_cb_suspend(struct evbuffer *buffer, struct evbuffer_cb_entry *cb);
 /** Stop postponing a callback that we postponed with evbuffer_cb_suspend.
 
@@ -935,6 +980,7 @@ void evbuffer_cb_suspend(struct evbuffer *buffer, struct evbuffer_cb_entry *cb);
 	@param the buffer that the callback is watching.
 	@param cb the callback we want to stop suspending.
  */
+EVENT2_EXPORT_SYMBOL
 void evbuffer_cb_unsuspend(struct evbuffer *buffer, struct evbuffer_cb_entry *cb);
 #endif
 
@@ -948,6 +994,7 @@ void evbuffer_cb_unsuspend(struct evbuffer *buffer, struct evbuffer_cb_entry *cb
 	requested more data than is present in the buffer.
 */
 
+EVENT2_EXPORT_SYMBOL
 unsigned char *evbuffer_pullup(struct evbuffer *buf, ev_ssize_t size);
 
 /**
@@ -959,6 +1006,7 @@ unsigned char *evbuffer_pullup(struct evbuffer *buf, ev_ssize_t size);
   @return 0 if successful, or -1 otherwise
 */
 
+EVENT2_EXPORT_SYMBOL
 int evbuffer_prepend(struct evbuffer *buf, const void *data, size_t size);
 
 /**
@@ -969,6 +1017,7 @@ int evbuffer_prepend(struct evbuffer *buf, const void *data, size_t size);
   @param src the evbuffer to prepend; it will be emptied as a result
   @return 0 if successful, or -1 otherwise
 */
+EVENT2_EXPORT_SYMBOL
 int evbuffer_prepend_buffer(struct evbuffer *dst, struct evbuffer* src);
 
 /**
@@ -985,6 +1034,7 @@ int evbuffer_prepend_buffer(struct evbuffer *dst, struct evbuffer* src);
       we freeze the back.
    @return 0 on success, -1 on failure.
 */
+EVENT2_EXPORT_SYMBOL
 int evbuffer_freeze(struct evbuffer *buf, int at_front);
 /**
    Re-enable calls that modify an evbuffer.
@@ -994,6 +1044,7 @@ int evbuffer_freeze(struct evbuffer *buf, int at_front);
       we unfreeze the back.
    @return 0 on success, -1 on failure.
  */
+EVENT2_EXPORT_SYMBOL
 int evbuffer_unfreeze(struct evbuffer *buf, int at_front);
 
 struct event_base;
@@ -1004,6 +1055,7 @@ struct event_base;
    This can be used to serialize all the callbacks to a single thread
    of execution.
  */
+EVENT2_EXPORT_SYMBOL
 int evbuffer_defer_callbacks(struct evbuffer *buffer, struct event_base *base);
 
 /**
@@ -1019,6 +1071,7 @@ int evbuffer_defer_callbacks(struct evbuffer *buffer, struct event_base *base);
   @param n_vec the number of iovec structures.
   @return the number of bytes successfully written to the output buffer.
 */
+EVENT2_EXPORT_SYMBOL
 size_t evbuffer_add_iovec(struct evbuffer * buffer, struct evbuffer_iovec * vec, int n_vec);
 
 #ifdef __cplusplus
diff --git a/include/event2/buffer_compat.h b/include/event2/buffer_compat.h
index c155332e..c0bdd9d2 100644
--- a/include/event2/buffer_compat.h
+++ b/include/event2/buffer_compat.h
@@ -27,6 +27,8 @@
 #ifndef EVENT2_BUFFER_COMPAT_H_INCLUDED_
 #define EVENT2_BUFFER_COMPAT_H_INCLUDED_
 
+#include <event2/visibility.h>
+
 /** @file event2/buffer_compat.h
 
 	Obsolete and deprecated versions of the functions in buffer.h: provided
@@ -45,6 +47,7 @@
    @return pointer to a single line, or NULL if an error occurred
 
 */
+EVENT2_EXPORT_SYMBOL
 char *evbuffer_readline(struct evbuffer *buffer);
 
 /** Type definition for a callback that is invoked whenever data is added or
@@ -88,6 +91,7 @@ typedef void (*evbuffer_cb)(struct evbuffer *buffer, size_t old_len, size_t new_
 	 or NULL to remove all callbacks.
   @param cbarg an argument to be provided to the callback function
  */
+EVENT2_EXPORT_SYMBOL
 void evbuffer_setcb(struct evbuffer *buffer, evbuffer_cb cb, void *cbarg);
 
 
@@ -99,6 +103,7 @@ void evbuffer_setcb(struct evbuffer *buffer, evbuffer_cb cb, void *cbarg);
   @param len the length of the search string
   @return a pointer to the beginning of the search string, or NULL if the search failed.
  */
+EVENT2_EXPORT_SYMBOL
 unsigned char *evbuffer_find(struct evbuffer *buffer, const unsigned char *what, size_t len);
 
 /** deprecated in favor of calling the functions directly */
diff --git a/include/event2/bufferevent.h b/include/event2/bufferevent.h
index 07bfd19d..46203b04 100644
--- a/include/event2/bufferevent.h
+++ b/include/event2/bufferevent.h
@@ -74,6 +74,8 @@
   </dl>
  */
 
+#include <event2/visibility.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -184,6 +186,7 @@ enum bufferevent_options {
 	  error occurred
   @see bufferevent_free()
   */
+EVENT2_EXPORT_SYMBOL
 struct bufferevent *bufferevent_socket_new(struct event_base *base, evutil_socket_t fd, int options);
 
 /**
@@ -205,6 +208,7 @@ struct bufferevent *bufferevent_socket_new(struct event_base *base, evutil_socke
    @param socklen The length of the address
    @return 0 on success, -1 on failure.
  */
+EVENT2_EXPORT_SYMBOL
 int bufferevent_socket_connect(struct bufferevent *, struct sockaddr *, int);
 
 struct evdns_base;
@@ -234,6 +238,7 @@ struct evdns_base;
    may block while it waits for a DNS response.	 This is probably not
    what you want.
  */
+EVENT2_EXPORT_SYMBOL
 int bufferevent_socket_connect_hostname(struct bufferevent *,
     struct evdns_base *, int, const char *, int);
 
@@ -245,6 +250,7 @@ int bufferevent_socket_connect_hostname(struct bufferevent *,
    @return DNS error code.
    @see evutil_gai_strerror()
 */
+EVENT2_EXPORT_SYMBOL
 int bufferevent_socket_get_dns_error(struct bufferevent *bev);
 
 /**
@@ -258,11 +264,13 @@ int bufferevent_socket_get_dns_error(struct bufferevent *bev);
   @return 0 if successful, or -1 if an error occurred
   @see bufferevent_new()
  */
+EVENT2_EXPORT_SYMBOL
 int bufferevent_base_set(struct event_base *base, struct bufferevent *bufev);
 
 /**
    Return the event_base used by a bufferevent
 */
+EVENT2_EXPORT_SYMBOL
 struct event_base *bufferevent_get_base(struct bufferevent *bev);
 
 /**
@@ -274,6 +282,7 @@ struct event_base *bufferevent_get_base(struct bufferevent *bev);
   @param pri the priority to be assigned
   @return 0 if successful, or -1 if an error occurred
   */
+EVENT2_EXPORT_SYMBOL
 int bufferevent_priority_set(struct bufferevent *bufev, int pri);
 
 /**
@@ -281,6 +290,7 @@ int bufferevent_priority_set(struct bufferevent *bufev, int pri);
 
    Only supported for socket bufferevents
  */
+EVENT2_EXPORT_SYMBOL
 int bufferevent_get_priority(const struct bufferevent *bufev);
 
 /**
@@ -291,6 +301,7 @@ int bufferevent_get_priority(const struct bufferevent *bufev);
 
   @param bufev the bufferevent structure to be freed.
   */
+EVENT2_EXPORT_SYMBOL
 void bufferevent_free(struct bufferevent *bufev);
 
 
@@ -308,6 +319,7 @@ void bufferevent_free(struct bufferevent *bufev);
 	 (readcb, writecb, and errorcb)
   @see bufferevent_new()
   */
+EVENT2_EXPORT_SYMBOL
 void bufferevent_setcb(struct bufferevent *bufev,
     bufferevent_data_cb readcb, bufferevent_data_cb writecb,
     bufferevent_event_cb eventcb, void *cbarg);
@@ -326,6 +338,7 @@ void bufferevent_setcb(struct bufferevent *bufev,
     callback argument for the bufferevent.
  @see buffervent_setcb()
 */
+EVENT2_EXPORT_SYMBOL
 void bufferevent_getcb(struct bufferevent *bufev,
     bufferevent_data_cb *readcb_ptr,
     bufferevent_data_cb *writecb_ptr,
@@ -339,18 +352,21 @@ void bufferevent_getcb(struct bufferevent *bufev,
   @param bufev the bufferevent object for which to change the file descriptor
   @param fd the file descriptor to operate on
 */
+EVENT2_EXPORT_SYMBOL
 int bufferevent_setfd(struct bufferevent *bufev, evutil_socket_t fd);
 
 /**
    Returns the file descriptor associated with a bufferevent, or -1 if
    no file descriptor is associated with the bufferevent.
  */
+EVENT2_EXPORT_SYMBOL
 evutil_socket_t bufferevent_getfd(struct bufferevent *bufev);
 
 /**
    Returns the underlying bufferevent associated with a bufferevent (if
    the bufferevent is a wrapper), or NULL if there is no underlying bufferevent.
  */
+EVENT2_EXPORT_SYMBOL
 struct bufferevent *bufferevent_get_underlying(struct bufferevent *bufev);
 
 /**
@@ -366,6 +382,7 @@ struct bufferevent *bufferevent_get_underlying(struct bufferevent *bufev);
   @return 0 if successful, or -1 if an error occurred
   @see bufferevent_write_buffer()
   */
+EVENT2_EXPORT_SYMBOL
 int bufferevent_write(struct bufferevent *bufev,
     const void *data, size_t size);
 
@@ -379,6 +396,7 @@ int bufferevent_write(struct bufferevent *bufev,
   @return 0 if successful, or -1 if an error occurred
   @see bufferevent_write()
  */
+EVENT2_EXPORT_SYMBOL
 int bufferevent_write_buffer(struct bufferevent *bufev, struct evbuffer *buf);
 
 
@@ -392,6 +410,7 @@ int bufferevent_write_buffer(struct bufferevent *bufev, struct evbuffer *buf);
   @param size the size of the data buffer, in bytes
   @return the amount of data read, in bytes.
  */
+EVENT2_EXPORT_SYMBOL
 size_t bufferevent_read(struct bufferevent *bufev, void *data, size_t size);
 
 /**
@@ -402,6 +421,7 @@ size_t bufferevent_read(struct bufferevent *bufev, void *data, size_t size);
   @param buf the evbuffer to which to add data
   @return 0 if successful, or -1 if an error occurred.
  */
+EVENT2_EXPORT_SYMBOL
 int bufferevent_read_buffer(struct bufferevent *bufev, struct evbuffer *buf);
 
 /**
@@ -413,6 +433,7 @@ int bufferevent_read_buffer(struct bufferevent *bufev, struct evbuffer *buf);
    @return the evbuffer object for the input buffer
  */
 
+EVENT2_EXPORT_SYMBOL
 struct evbuffer *bufferevent_get_input(struct bufferevent *bufev);
 
 /**
@@ -427,6 +448,7 @@ struct evbuffer *bufferevent_get_input(struct bufferevent *bufev);
    @return the evbuffer object for the output buffer
  */
 
+EVENT2_EXPORT_SYMBOL
 struct evbuffer *bufferevent_get_output(struct bufferevent *bufev);
 
 /**
@@ -437,6 +459,7 @@ struct evbuffer *bufferevent_get_output(struct bufferevent *bufev);
   @return 0 if successful, or -1 if an error occurred
   @see bufferevent_disable()
  */
+EVENT2_EXPORT_SYMBOL
 int bufferevent_enable(struct bufferevent *bufev, short event);
 
 /**
@@ -447,6 +470,7 @@ int bufferevent_enable(struct bufferevent *bufev, short event);
   @return 0 if successful, or -1 if an error occurred
   @see bufferevent_enable()
  */
+EVENT2_EXPORT_SYMBOL
 int bufferevent_disable(struct bufferevent *bufev, short event);
 
 /**
@@ -455,6 +479,7 @@ int bufferevent_disable(struct bufferevent *bufev, short event);
    @param bufev the bufferevent to inspect
    @return A combination of EV_READ | EV_WRITE
  */
+EVENT2_EXPORT_SYMBOL
 short bufferevent_get_enabled(struct bufferevent *bufev);
 
 /**
@@ -483,6 +508,7 @@ short bufferevent_get_enabled(struct bufferevent *bufev);
   @param timeout_read the read timeout, or NULL
   @param timeout_write the write timeout, or NULL
  */
+EVENT2_EXPORT_SYMBOL
 int bufferevent_set_timeouts(struct bufferevent *bufev,
     const struct timeval *timeout_read, const struct timeval *timeout_write);
 
@@ -504,6 +530,7 @@ int bufferevent_set_timeouts(struct bufferevent *bufev,
   @param highmark the high watermark to set
 */
 
+EVENT2_EXPORT_SYMBOL
 void bufferevent_setwatermark(struct bufferevent *bufev, short events,
     size_t lowmark, size_t highmark);
 
@@ -516,6 +543,7 @@ void bufferevent_setwatermark(struct bufferevent *bufev, short events,
   @param lowmark receives the lower watermark if not NULL
   @param highmark receives the high watermark if not NULL
 */
+EVENT2_EXPORT_SYMBOL
 void bufferevent_getwatermark(struct bufferevent *bufev, short events,
     size_t *lowmark, size_t *highmark);
 
@@ -523,12 +551,14 @@ void bufferevent_getwatermark(struct bufferevent *bufev, short events,
    Acquire the lock on a bufferevent.  Has no effect if locking was not
    enabled with BEV_OPT_THREADSAFE.
  */
+EVENT2_EXPORT_SYMBOL
 void bufferevent_lock(struct bufferevent *bufev);
 
 /**
    Release the lock on a bufferevent.  Has no effect if locking was not
    enabled with BEV_OPT_THREADSAFE.
  */
+EVENT2_EXPORT_SYMBOL
 void bufferevent_unlock(struct bufferevent *bufev);
 
 /**
@@ -554,6 +584,7 @@ enum bufferevent_flush_mode {
    @param mode either BEV_NORMAL or BEV_FLUSH or BEV_FINISHED
    @return -1 on failure, 0 if no data was produces, 1 if data was produced
  */
+EVENT2_EXPORT_SYMBOL
 int bufferevent_flush(struct bufferevent *bufev,
     short iotype,
     enum bufferevent_flush_mode mode);
@@ -584,6 +615,7 @@ enum bufferevent_trigger_options {
    @param iotype either EV_READ or EV_WRITE or both.
    @param options
  */
+EVENT2_EXPORT_SYMBOL
 void bufferevent_trigger(struct bufferevent *bufev, short iotype,
     int options);
 
@@ -596,6 +628,7 @@ void bufferevent_trigger(struct bufferevent *bufev, short iotype,
    @param what the flags to pass onto the event callback
    @param options
  */
+EVENT2_EXPORT_SYMBOL
 void bufferevent_trigger_event(struct bufferevent *bufev, short what,
     int options);
 
@@ -654,6 +687,7 @@ typedef enum bufferevent_filter_result (*bufferevent_filter_cb)(
      this bufferevent is freed.
    @param ctx A context pointer to pass to the filter functions.
  */
+EVENT2_EXPORT_SYMBOL
 struct bufferevent *
 bufferevent_filter_new(struct bufferevent *underlying,
 		       bufferevent_filter_cb input_filter,
@@ -673,6 +707,7 @@ bufferevent_filter_new(struct bufferevent *underlying,
    @param pair A pointer to an array to hold the two new bufferevent objects.
    @return 0 on success, -1 on failure.
  */
+EVENT2_EXPORT_SYMBOL
 int bufferevent_pair_new(struct event_base *base, int options,
     struct bufferevent *pair[2]);
 
@@ -680,6 +715,7 @@ int bufferevent_pair_new(struct event_base *base, int options,
    Given one bufferevent returned by bufferevent_pair_new(), returns the
    other one if it still exists.  Otherwise returns NULL.
  */
+EVENT2_EXPORT_SYMBOL
 struct bufferevent *bufferevent_pair_get_partner(struct bufferevent *bev);
 
 /**
@@ -713,6 +749,7 @@ struct bufferevent_rate_limit_group;
    Note that all rate-limits hare are currently best-effort: future versions
    of Libevent may implement them more tightly.
  */
+EVENT2_EXPORT_SYMBOL
 struct ev_token_bucket_cfg *ev_token_bucket_cfg_new(
 	size_t read_rate, size_t read_burst,
 	size_t write_rate, size_t write_burst,
@@ -723,6 +760,7 @@ struct ev_token_bucket_cfg *ev_token_bucket_cfg_new(
     Note: 'cfg' is not currently reference-counted; it is not safe to free it
     until no bufferevent is using it.
  */
+EVENT2_EXPORT_SYMBOL
 void ev_token_bucket_cfg_free(struct ev_token_bucket_cfg *cfg);
 
 /**
@@ -736,6 +774,7 @@ void ev_token_bucket_cfg_free(struct ev_token_bucket_cfg *cfg);
 
    Return 0 on sucess, -1 on failure.
  */
+EVENT2_EXPORT_SYMBOL
 int bufferevent_set_rate_limit(struct bufferevent *bev,
     struct ev_token_bucket_cfg *cfg);
 
@@ -756,6 +795,7 @@ int bufferevent_set_rate_limit(struct bufferevent *bev,
    They are: socket-based bufferevents (normal and IOCP-based), and SSL-based
    bufferevents.
  */
+EVENT2_EXPORT_SYMBOL
 struct bufferevent_rate_limit_group *bufferevent_rate_limit_group_new(
 	struct event_base *base,
 	const struct ev_token_bucket_cfg *cfg);
@@ -764,6 +804,7 @@ struct bufferevent_rate_limit_group *bufferevent_rate_limit_group_new(
 
    Return 0 on success, -1 on failure.
 */
+EVENT2_EXPORT_SYMBOL
 int bufferevent_rate_limit_group_set_cfg(
 	struct bufferevent_rate_limit_group *,
 	const struct ev_token_bucket_cfg *);
@@ -784,6 +825,7 @@ int bufferevent_rate_limit_group_set_cfg(
 
    Returns 0 on success, -1 on faulre.
  */
+EVENT2_EXPORT_SYMBOL
 int bufferevent_rate_limit_group_set_min_share(
 	struct bufferevent_rate_limit_group *, size_t);
 
@@ -791,6 +833,7 @@ int bufferevent_rate_limit_group_set_min_share(
    Free a rate-limiting group.  The group must have no members when
    this function is called.
 */
+EVENT2_EXPORT_SYMBOL
 void bufferevent_rate_limit_group_free(struct bufferevent_rate_limit_group *);
 
 /**
@@ -803,10 +846,12 @@ void bufferevent_rate_limit_group_free(struct bufferevent_rate_limit_group *);
 
    Return 0 on success and -1 on failure.
  */
+EVENT2_EXPORT_SYMBOL
 int bufferevent_add_to_rate_limit_group(struct bufferevent *bev,
     struct bufferevent_rate_limit_group *g);
 
 /** Remove 'bev' from its current rate-limit group (if any). */
+EVENT2_EXPORT_SYMBOL
 int bufferevent_remove_from_rate_limit_group(struct bufferevent *bev);
 
 /**
@@ -816,6 +861,7 @@ int bufferevent_remove_from_rate_limit_group(struct bufferevent *bev);
 
    Return 0 on success and -1 on failure.
  */
+EVENT2_EXPORT_SYMBOL
 int bufferevent_set_max_single_read(struct bufferevent *bev, size_t size);
 
 /**
@@ -825,12 +871,15 @@ int bufferevent_set_max_single_read(struct bufferevent *bev, size_t size);
 
    Return 0 on success and -1 on failure.
  */
+EVENT2_EXPORT_SYMBOL
 int bufferevent_set_max_single_write(struct bufferevent *bev, size_t size);
 
 /** Get the current size limit for single read operation. */
+EVENT2_EXPORT_SYMBOL
 ev_ssize_t bufferevent_get_max_single_read(struct bufferevent *bev);
 
 /** Get the current size limit for single write operation. */
+EVENT2_EXPORT_SYMBOL
 ev_ssize_t bufferevent_get_max_single_write(struct bufferevent *bev);
 
 /**
@@ -844,13 +893,18 @@ ev_ssize_t bufferevent_get_max_single_write(struct bufferevent *bev);
 
    @{
  */
+EVENT2_EXPORT_SYMBOL
 ev_ssize_t bufferevent_get_read_limit(struct bufferevent *bev);
+EVENT2_EXPORT_SYMBOL
 ev_ssize_t bufferevent_get_write_limit(struct bufferevent *bev);
 /*@}*/
 
+EVENT2_EXPORT_SYMBOL
 ev_ssize_t bufferevent_get_max_to_read(struct bufferevent *bev);
+EVENT2_EXPORT_SYMBOL
 ev_ssize_t bufferevent_get_max_to_write(struct bufferevent *bev);
 
+EVENT2_EXPORT_SYMBOL
 const struct ev_token_bucket_cfg *bufferevent_get_token_bucket_cfg(const struct bufferevent * bev);
 
 /**
@@ -862,8 +916,10 @@ const struct ev_token_bucket_cfg *bufferevent_get_token_bucket_cfg(const struct
 
    @{
  */
+EVENT2_EXPORT_SYMBOL
 ev_ssize_t bufferevent_rate_limit_group_get_read_limit(
 	struct bufferevent_rate_limit_group *);
+EVENT2_EXPORT_SYMBOL
 ev_ssize_t bufferevent_rate_limit_group_get_write_limit(
 	struct bufferevent_rate_limit_group *);
 /*@}*/
@@ -882,7 +938,9 @@ ev_ssize_t bufferevent_rate_limit_group_get_write_limit(
 
    @{
  */
+EVENT2_EXPORT_SYMBOL
 int bufferevent_decrement_read_limit(struct bufferevent *bev, ev_ssize_t decr);
+EVENT2_EXPORT_SYMBOL
 int bufferevent_decrement_write_limit(struct bufferevent *bev, ev_ssize_t decr);
 /*@}*/
 
@@ -899,8 +957,10 @@ int bufferevent_decrement_write_limit(struct bufferevent *bev, ev_ssize_t decr);
 
    @{
  */
+EVENT2_EXPORT_SYMBOL
 int bufferevent_rate_limit_group_decrement_read(
 	struct bufferevent_rate_limit_group *, ev_ssize_t);
+EVENT2_EXPORT_SYMBOL
 int bufferevent_rate_limit_group_decrement_write(
 	struct bufferevent_rate_limit_group *, ev_ssize_t);
 /*@}*/
@@ -912,6 +972,7 @@ int bufferevent_rate_limit_group_decrement_write(
  * Set the variable pointed to by total_read_out to the total number of bytes
  * ever read on grp, and the variable pointed to by total_written_out to the
  * total number of bytes ever written on grp. */
+EVENT2_EXPORT_SYMBOL
 void bufferevent_rate_limit_group_get_totals(
     struct bufferevent_rate_limit_group *grp,
     ev_uint64_t *total_read_out, ev_uint64_t *total_written_out);
@@ -921,6 +982,7 @@ void bufferevent_rate_limit_group_get_totals(
  *
  * Reset the number of bytes read or written on grp as given by
  * bufferevent_rate_limit_group_reset_totals(). */
+EVENT2_EXPORT_SYMBOL
 void
 bufferevent_rate_limit_group_reset_totals(
 	struct bufferevent_rate_limit_group *grp);
diff --git a/include/event2/bufferevent_ssl.h b/include/event2/bufferevent_ssl.h
index 2b7e6141..bf39b844 100644
--- a/include/event2/bufferevent_ssl.h
+++ b/include/event2/bufferevent_ssl.h
@@ -30,7 +30,7 @@
 
     OpenSSL support for bufferevents.
  */
-
+#include <event2/visibility.h>
 #include <event2/event-config.h>
 #include <event2/bufferevent.h>
 #include <event2/util.h>
@@ -64,6 +64,7 @@ enum bufferevent_ssl_state {
    @param options One or more bufferevent_options
    @return A new bufferevent on success, or NULL on failure
 */
+EVENT2_EXPORT_SYMBOL
 struct bufferevent *
 bufferevent_openssl_filter_new(struct event_base *base,
     struct bufferevent *underlying,
@@ -81,6 +82,7 @@ bufferevent_openssl_filter_new(struct event_base *base,
    @param options One or more bufferevent_options
    @return A new bufferevent on success, or NULL on failure.
 */
+EVENT2_EXPORT_SYMBOL
 struct bufferevent *
 bufferevent_openssl_socket_new(struct event_base *base,
     evutil_socket_t fd,
@@ -104,18 +106,23 @@ bufferevent_openssl_socket_new(struct event_base *base,
     not to use SSL 2.)
 */
 
+EVENT2_EXPORT_SYMBOL
 int bufferevent_openssl_get_allow_dirty_shutdown(struct bufferevent *bev);
+EVENT2_EXPORT_SYMBOL
 void bufferevent_openssl_set_allow_dirty_shutdown(struct bufferevent *bev,
     int allow_dirty_shutdown);
 
 /** Return the underlying openssl SSL * object for an SSL bufferevent. */
+EVENT2_EXPORT_SYMBOL
 struct ssl_st *
 bufferevent_openssl_get_ssl(struct bufferevent *bufev);
 
 /** Tells a bufferevent to begin SSL renegotiation. */
+EVENT2_EXPORT_SYMBOL
 int bufferevent_ssl_renegotiate(struct bufferevent *bev);
 
 /** Return the most recent OpenSSL error reported on an SSL bufferevent. */
+EVENT2_EXPORT_SYMBOL
 unsigned long bufferevent_get_openssl_error(struct bufferevent *bev);
 
 #endif
diff --git a/include/event2/dns.h b/include/event2/dns.h
index fd4dec68..a00c83e6 100644
--- a/include/event2/dns.h
+++ b/include/event2/dns.h
@@ -135,6 +135,8 @@
 #ifndef EVENT2_DNS_H_INCLUDED_
 #define EVENT2_DNS_H_INCLUDED_
 
+#include <event2/visibility.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -220,6 +222,7 @@ struct event_base;
   @return evdns_base object if successful, or NULL if an error occurred.
   @see evdns_base_free()
  */
+EVENT2_EXPORT_SYMBOL
 struct evdns_base * evdns_base_new(struct event_base *event_base, int initialize_nameservers);
 
 
@@ -235,6 +238,7 @@ struct evdns_base * evdns_base_new(struct event_base *event_base, int initialize
 		active requests will return DNS_ERR_SHUTDOWN.
   @see evdns_base_new()
  */
+EVENT2_EXPORT_SYMBOL
 void evdns_base_free(struct evdns_base *base, int fail_requests);
 
 /**
@@ -243,6 +247,7 @@ void evdns_base_free(struct evdns_base *base, int fail_requests);
 
    @param evdns_base the evdns base to remove outdated host addresses from
  */
+EVENT2_EXPORT_SYMBOL
 void evdns_base_clear_host_addresses(struct evdns_base *base);
 
 /**
@@ -251,6 +256,7 @@ void evdns_base_clear_host_addresses(struct evdns_base *base);
   @param err the DNS error code
   @return a string containing an explanation of the error code
 */
+EVENT2_EXPORT_SYMBOL
 const char *evdns_err_to_string(int err);
 
 
@@ -265,6 +271,7 @@ const char *evdns_err_to_string(int err);
   @return 0 if successful, or -1 if an error occurred
   @see evdns_base_nameserver_ip_add()
  */
+EVENT2_EXPORT_SYMBOL
 int evdns_base_nameserver_add(struct evdns_base *base,
     unsigned long int address);
 
@@ -280,6 +287,7 @@ int evdns_base_nameserver_add(struct evdns_base *base,
   @return the number of configured nameservers
   @see evdns_base_nameserver_add()
  */
+EVENT2_EXPORT_SYMBOL
 int evdns_base_count_nameservers(struct evdns_base *base);
 
 /**
@@ -291,6 +299,7 @@ int evdns_base_count_nameservers(struct evdns_base *base);
   @return 0 if successful, or -1 if an error occurred
   @see evdns_base_resume()
  */
+EVENT2_EXPORT_SYMBOL
 int evdns_base_clear_nameservers_and_suspend(struct evdns_base *base);
 
 
@@ -304,6 +313,7 @@ int evdns_base_clear_nameservers_and_suspend(struct evdns_base *base);
   @return 0 if successful, or -1 if an error occurred
   @see evdns_base_clear_nameservers_and_suspend()
  */
+EVENT2_EXPORT_SYMBOL
 int evdns_base_resume(struct evdns_base *base);
 
 /**
@@ -323,12 +333,14 @@ int evdns_base_resume(struct evdns_base *base);
   @return 0 if successful, or -1 if an error occurred
   @see evdns_base_nameserver_add()
  */
+EVENT2_EXPORT_SYMBOL
 int evdns_base_nameserver_ip_add(struct evdns_base *base,
     const char *ip_as_string);
 
 /**
    Add a nameserver by sockaddr.
  **/
+EVENT2_EXPORT_SYMBOL
 int
 evdns_base_nameserver_sockaddr_add(struct evdns_base *base,
     const struct sockaddr *sa, ev_socklen_t len, unsigned flags);
@@ -346,6 +358,7 @@ struct evdns_request;
   @return an evdns_request object if successful, or NULL if an error occurred.
   @see evdns_resolve_ipv6(), evdns_resolve_reverse(), evdns_resolve_reverse_ipv6(), evdns_cancel_request()
  */
+EVENT2_EXPORT_SYMBOL
 struct evdns_request *evdns_base_resolve_ipv4(struct evdns_base *base, const char *name, int flags, evdns_callback_type callback, void *ptr);
 
 /**
@@ -359,6 +372,7 @@ struct evdns_request *evdns_base_resolve_ipv4(struct evdns_base *base, const cha
   @return an evdns_request object if successful, or NULL if an error occurred.
   @see evdns_resolve_ipv4(), evdns_resolve_reverse(), evdns_resolve_reverse_ipv6(), evdns_cancel_request()
  */
+EVENT2_EXPORT_SYMBOL
 struct evdns_request *evdns_base_resolve_ipv6(struct evdns_base *base, const char *name, int flags, evdns_callback_type callback, void *ptr);
 
 struct in_addr;
@@ -375,6 +389,7 @@ struct in6_addr;
   @return an evdns_request object if successful, or NULL if an error occurred.
   @see evdns_resolve_reverse_ipv6(), evdns_cancel_request()
  */
+EVENT2_EXPORT_SYMBOL
 struct evdns_request *evdns_base_resolve_reverse(struct evdns_base *base, const struct in_addr *in, int flags, evdns_callback_type callback, void *ptr);
 
 
@@ -389,6 +404,7 @@ struct evdns_request *evdns_base_resolve_reverse(struct evdns_base *base, const
   @return an evdns_request object if successful, or NULL if an error occurred.
   @see evdns_resolve_reverse_ipv6(), evdns_cancel_request()
  */
+EVENT2_EXPORT_SYMBOL
 struct evdns_request *evdns_base_resolve_reverse_ipv6(struct evdns_base *base, const struct in6_addr *in, int flags, evdns_callback_type callback, void *ptr);
 
 /**
@@ -398,6 +414,7 @@ struct evdns_request *evdns_base_resolve_reverse_ipv6(struct evdns_base *base, c
   @param req the evdns_request that was returned by calling a resolve function
   @see evdns_base_resolve_ipv4(), evdns_base_resolve_ipv6, evdns_base_resolve_reverse
 */
+EVENT2_EXPORT_SYMBOL
 void evdns_cancel_request(struct evdns_base *base, struct evdns_request *req);
 
 /**
@@ -416,6 +433,7 @@ void evdns_cancel_request(struct evdns_base *base, struct evdns_request *req);
   @param val the value to be set
   @return 0 if successful, or -1 if an error occurred
  */
+EVENT2_EXPORT_SYMBOL
 int evdns_base_set_option(struct evdns_base *base, const char *option, const char *val);
 
 
@@ -441,6 +459,7 @@ int evdns_base_set_option(struct evdns_base *base, const char *option, const cha
     occurred (see above)
   @see resolv.conf(3), evdns_config_windows_nameservers()
  */
+EVENT2_EXPORT_SYMBOL
 int evdns_base_resolv_conf_parse(struct evdns_base *base, int flags, const char *const filename);
 
 /**
@@ -456,6 +475,7 @@ int evdns_base_resolv_conf_parse(struct evdns_base *base, int flags, const char
 
    Return 0 on success, negative on failure.
 */
+EVENT2_EXPORT_SYMBOL
 int evdns_base_load_hosts(struct evdns_base *base, const char *hosts_fname);
 
 /**
@@ -469,6 +489,7 @@ int evdns_base_load_hosts(struct evdns_base *base, const char *hosts_fname);
   @see evdns_resolv_conf_parse()
  */
 #ifdef _WIN32
+EVENT2_EXPORT_SYMBOL
 int evdns_base_config_windows_nameservers(struct evdns_base *);
 #define EVDNS_BASE_CONFIG_WINDOWS_NAMESERVERS_IMPLEMENTED
 #endif
@@ -477,6 +498,7 @@ int evdns_base_config_windows_nameservers(struct evdns_base *);
 /**
   Clear the list of search domains.
  */
+EVENT2_EXPORT_SYMBOL
 void evdns_base_search_clear(struct evdns_base *base);
 
 
@@ -485,6 +507,7 @@ void evdns_base_search_clear(struct evdns_base *base);
 
   @param domain the domain to be added to the search list
  */
+EVENT2_EXPORT_SYMBOL
 void evdns_base_search_add(struct evdns_base *base, const char *domain);
 
 
@@ -496,6 +519,7 @@ void evdns_base_search_add(struct evdns_base *base, const char *domain);
 
   @param ndots the new ndots parameter
  */
+EVENT2_EXPORT_SYMBOL
 void evdns_base_search_ndots_set(struct evdns_base *base, const int ndots);
 
 /**
@@ -514,6 +538,7 @@ typedef void (*evdns_debug_log_fn_type)(int is_warning, const char *msg);
 
   @param fn the callback to be invoked when a log message is generated
  */
+EVENT2_EXPORT_SYMBOL
 void evdns_set_log_fn(evdns_debug_log_fn_type fn);
 
 /**
@@ -526,6 +551,7 @@ void evdns_set_log_fn(evdns_debug_log_fn_type fn);
    NOTE: This function has no effect in Libevent 2.0.4-alpha and later,
    since Libevent now provides its own secure RNG.
  */
+EVENT2_EXPORT_SYMBOL
 void evdns_set_transaction_id_fn(ev_uint16_t (*fn)(void));
 
 /**
@@ -537,6 +563,7 @@ void evdns_set_transaction_id_fn(ev_uint16_t (*fn)(void));
    NOTE: This function has no effect in Libevent 2.0.4-alpha and later,
    since Libevent now provides its own secure RNG.
 */
+EVENT2_EXPORT_SYMBOL
 void evdns_set_random_bytes_fn(void (*fn)(char *, size_t));
 
 /*
@@ -590,35 +617,46 @@ typedef void (*evdns_request_callback_fn_type)(struct evdns_server_request *, vo
     @param user_data Data to pass to the callback.
     @return an evdns_server_port structure for this server port.
  */
+EVENT2_EXPORT_SYMBOL
 struct evdns_server_port *evdns_add_server_port_with_base(struct event_base *base, evutil_socket_t socket, int flags, evdns_request_callback_fn_type callback, void *user_data);
 /** Close down a DNS server port, and free associated structures. */
+EVENT2_EXPORT_SYMBOL
 void evdns_close_server_port(struct evdns_server_port *port);
 
 /** Sets some flags in a reply we're building.
     Allows setting of the AA or RD flags
  */
+EVENT2_EXPORT_SYMBOL
 void evdns_server_request_set_flags(struct evdns_server_request *req, int flags);
 
 /* Functions to add an answer to an in-progress DNS reply.
  */
+EVENT2_EXPORT_SYMBOL
 int evdns_server_request_add_reply(struct evdns_server_request *req, int section, const char *name, int type, int dns_class, int ttl, int datalen, int is_name, const char *data);
+EVENT2_EXPORT_SYMBOL
 int evdns_server_request_add_a_reply(struct evdns_server_request *req, const char *name, int n, const void *addrs, int ttl);
+EVENT2_EXPORT_SYMBOL
 int evdns_server_request_add_aaaa_reply(struct evdns_server_request *req, const char *name, int n, const void *addrs, int ttl);
+EVENT2_EXPORT_SYMBOL
 int evdns_server_request_add_ptr_reply(struct evdns_server_request *req, struct in_addr *in, const char *inaddr_name, const char *hostname, int ttl);
+EVENT2_EXPORT_SYMBOL
 int evdns_server_request_add_cname_reply(struct evdns_server_request *req, const char *name, const char *cname, int ttl);
 
 /**
    Send back a response to a DNS request, and free the request structure.
 */
+EVENT2_EXPORT_SYMBOL
 int evdns_server_request_respond(struct evdns_server_request *req, int err);
 /**
    Free a DNS request without sending back a reply.
 */
+EVENT2_EXPORT_SYMBOL
 int evdns_server_request_drop(struct evdns_server_request *req);
 struct sockaddr;
 /**
     Get the address that made a DNS request.
  */
+EVENT2_EXPORT_SYMBOL
 int evdns_server_request_get_requesting_addr(struct evdns_server_request *req, struct sockaddr *sa, int addr_len);
 
 /** Callback for evdns_getaddrinfo. */
@@ -643,6 +681,7 @@ struct evdns_getaddrinfo_request;
  * - For ai_socktype, we only handle SOCKTYPE_STREAM, SOCKTYPE_UDP, and 0.
  * - For ai_protocol, we only handle IPPROTO_TCP, IPPROTO_UDP, and 0.
  */
+EVENT2_EXPORT_SYMBOL
 struct evdns_getaddrinfo_request *evdns_getaddrinfo(
     struct evdns_base *dns_base,
     const char *nodename, const char *servname,
@@ -652,6 +691,7 @@ struct evdns_getaddrinfo_request *evdns_getaddrinfo(
 /* Cancel an in-progress evdns_getaddrinfo.  This MUST NOT be called after the
  * getaddrinfo's callback has been invoked.  The resolves will be canceled,
  * and the callback will be invoked with the error EVUTIL_EAI_CANCEL. */
+EVENT2_EXPORT_SYMBOL
 void evdns_getaddrinfo_cancel(struct evdns_getaddrinfo_request *req);
 
 #ifdef __cplusplus
diff --git a/include/event2/event.h b/include/event2/event.h
index 2864e61e..6e2b884d 100644
--- a/include/event2/event.h
+++ b/include/event2/event.h
@@ -182,6 +182,8 @@
   Core functions for waiting for and receiving events, and using event bases.
 */
 
+#include <event2/visibility.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -316,6 +318,7 @@ struct event_config
  *
  * @see event_debug_unassign()
  */
+EVENT2_EXPORT_SYMBOL
 void event_enable_debug_mode(void);
 
 /**
@@ -327,6 +330,7 @@ void event_enable_debug_mode(void);
  *
  * @see event_enable_debug_mode()
  */
+EVENT2_EXPORT_SYMBOL
 void event_debug_unassign(struct event *);
 
 /**
@@ -336,6 +340,7 @@ void event_debug_unassign(struct event *);
  *
  * @see event_base_free(), event_base_new_with_config()
  */
+EVENT2_EXPORT_SYMBOL
 struct event_base *event_base_new(void);
 
 /**
@@ -348,6 +353,7 @@ struct event_base *event_base_new(void);
   @return 0 if successful, or -1 if some events could not be re-added.
   @see event_base_new()
 */
+EVENT2_EXPORT_SYMBOL
 int event_reinit(struct event_base *base);
 
 /**
@@ -363,6 +369,7 @@ int event_reinit(struct event_base *base);
      no events were pending or active.
   @see event_base_loop()
  */
+EVENT2_EXPORT_SYMBOL
 int event_base_dispatch(struct event_base *);
 
 /**
@@ -371,6 +378,7 @@ int event_base_dispatch(struct event_base *);
  @param eb the event_base structure returned by event_base_new()
  @return a string identifying the kernel event mechanism (kqueue, epoll, etc.)
  */
+EVENT2_EXPORT_SYMBOL
 const char *event_base_get_method(const struct event_base *);
 
 /**
@@ -385,6 +393,7 @@ const char *event_base_get_method(const struct event_base *);
      The end of the array is indicated by a NULL pointer.  If an
      error is encountered NULL is returned.
 */
+EVENT2_EXPORT_SYMBOL
 const char **event_get_supported_methods(void);
 
 /**
@@ -422,6 +431,7 @@ const char **event_get_supported_methods(void);
        counts for
    @return the number of events specified in the flags
 */
+EVENT2_EXPORT_SYMBOL
 int event_base_get_num_events(struct event_base *, unsigned int);
 
 /**
@@ -434,6 +444,7 @@ int event_base_get_num_events(struct event_base *, unsigned int);
   @param clear option used to reset the maximum count.
   @return the number of events specified in the flags
  */
+EVENT2_EXPORT_SYMBOL
 int event_base_get_max_events(struct event_base *, unsigned int, int);
 
 /**
@@ -446,6 +457,7 @@ int event_base_get_max_events(struct event_base *, unsigned int, int);
      NULL if an error is encountered.
    @see event_base_new_with_config(), event_config_free(), event_config
 */
+EVENT2_EXPORT_SYMBOL
 struct event_config *event_config_new(void);
 
 /**
@@ -453,6 +465,7 @@ struct event_config *event_config_new(void);
 
    @param cfg the event configuration object to be freed.
 */
+EVENT2_EXPORT_SYMBOL
 void event_config_free(struct event_config *cfg);
 
 /**
@@ -467,6 +480,7 @@ void event_config_free(struct event_config *cfg);
    @param method the name of the event method to avoid
    @return 0 on success, -1 on failure.
 */
+EVENT2_EXPORT_SYMBOL
 int event_config_avoid_method(struct event_config *cfg, const char *method);
 
 /**
@@ -560,6 +574,7 @@ enum event_base_config_flag {
 
    @see event_method_feature
  */
+EVENT2_EXPORT_SYMBOL
 int event_base_get_features(const struct event_base *base);
 
 /**
@@ -584,6 +599,7 @@ int event_base_get_features(const struct event_base *base);
    @return 0 on success, -1 on failure.
    @see event_method_feature, event_base_new_with_config()
 */
+EVENT2_EXPORT_SYMBOL
 int event_config_require_features(struct event_config *cfg, int feature);
 
 /**
@@ -592,6 +608,7 @@ int event_config_require_features(struct event_config *cfg, int feature);
  *
  * @see event_base_config_flags, event_base_new_with_config()
  **/
+EVENT2_EXPORT_SYMBOL
 int event_config_set_flag(struct event_config *cfg, int flag);
 
 /**
@@ -603,6 +620,7 @@ int event_config_set_flag(struct event_config *cfg, int flag);
  * @param cpus the number of cpus
  * @return 0 on success, -1 on failure.
  */
+EVENT2_EXPORT_SYMBOL
 int event_config_set_num_cpus_hint(struct event_config *cfg, int cpus);
 
 /**
@@ -633,6 +651,7 @@ int event_config_set_num_cpus_hint(struct event_config *cfg, int cpus);
  *     for events of priority 1 and above, and so on.
  * @return 0 on success, -1 on failure.
  **/
+EVENT2_EXPORT_SYMBOL
 int event_config_set_max_dispatch_interval(struct event_config *cfg,
     const struct timeval *max_interval, int max_callbacks,
     int min_priority);
@@ -649,6 +668,7 @@ int event_config_set_max_dispatch_interval(struct event_config *cfg,
      or NULL if no event base can be created with the requested event_config.
   @see event_base_new(), event_base_free(), event_init(), event_assign()
 */
+EVENT2_EXPORT_SYMBOL
 struct event_base *event_base_new_with_config(const struct event_config *);
 
 /**
@@ -662,6 +682,7 @@ struct event_base *event_base_new_with_config(const struct event_config *);
 
   @param eb an event_base to be freed
  */
+EVENT2_EXPORT_SYMBOL
 void event_base_free(struct event_base *);
 
 /**
@@ -670,6 +691,7 @@ void event_base_free(struct event_base *);
    THIS IS AN EXPERIMENTAL API. IT MIGHT CHANGE BEFORE THE LIBEVENT 2.1 SERIES
    BECOMES STABLE.
  */
+EVENT2_EXPORT_SYMBOL
 void event_base_free_nofinalize(struct event_base *);
 
 /** @name Log severities
@@ -704,6 +726,7 @@ typedef void (*event_log_cb)(int severity, const char *msg);
   NOTE: The function you provide *must not* call any other libevent
   functionality.  Doing so can produce undefined behavior.
   */
+EVENT2_EXPORT_SYMBOL
 void event_set_log_callback(event_log_cb cb);
 
 /**
@@ -725,6 +748,7 @@ typedef void (*event_fatal_cb)(int err);
  Libevent will (almost) always log an EVENT_LOG_ERR message before calling
  this function; look at the last log message to see why Libevent has died.
  */
+EVENT2_EXPORT_SYMBOL
 void event_set_fatal_callback(event_fatal_cb cb);
 
 #define EVENT_DBG_ALL 0xffffffffu
@@ -744,6 +768,7 @@ void event_set_fatal_callback(event_fatal_cb cb);
    "EVENT_DBG_ALL" to turn debugging logs on, or "EVENT_DBG_NONE" to turn
    debugging logs off.
  */
+EVENT2_EXPORT_SYMBOL
 void event_enable_debug_logging(ev_uint32_t which);
 
 /**
@@ -755,6 +780,7 @@ void event_enable_debug_logging(ev_uint32_t which);
   @param ev the event
   @return 0 on success, -1 on failure.
  */
+EVENT2_EXPORT_SYMBOL
 int event_base_set(struct event_base *, struct event *);
 
 /** @name Loop flags
@@ -793,6 +819,7 @@ int event_base_set(struct event_base *, struct event *);
   @see event_base_loopexit(), event_base_dispatch(), EVLOOP_ONCE,
      EVLOOP_NONBLOCK
   */
+EVENT2_EXPORT_SYMBOL
 int event_base_loop(struct event_base *, int);
 
 /**
@@ -810,6 +837,7 @@ int event_base_loop(struct event_base *, int);
   @return 0 if successful, or -1 if an error occurred
   @see event_base_loopbreak()
  */
+EVENT2_EXPORT_SYMBOL
 int event_base_loopexit(struct event_base *, const struct timeval *);
 
 /**
@@ -825,6 +853,7 @@ int event_base_loopexit(struct event_base *, const struct timeval *);
   @return 0 if successful, or -1 if an error occurred
   @see event_base_loopexit()
  */
+EVENT2_EXPORT_SYMBOL
 int event_base_loopbreak(struct event_base *);
 
 /**
@@ -844,6 +873,7 @@ int event_base_loopbreak(struct event_base *);
   @return 0 if successful, or -1 if an error occurred
   @see event_base_loopbreak()
  */
+EVENT2_EXPORT_SYMBOL
 int event_base_loopcontinue(struct event_base *);
 
 /**
@@ -858,6 +888,7 @@ int event_base_loopcontinue(struct event_base *);
   @see event_base_loopexit()
   @see event_base_got_break()
  */
+EVENT2_EXPORT_SYMBOL
 int event_base_got_exit(struct event_base *);
 
 /**
@@ -872,6 +903,7 @@ int event_base_got_exit(struct event_base *);
   @see event_base_loopbreak()
   @see event_base_got_exit()
  */
+EVENT2_EXPORT_SYMBOL
 int event_base_got_break(struct event_base *);
 
 /**
@@ -987,6 +1019,7 @@ typedef void (*event_callback_fn)(evutil_socket_t, short, void *);
   event_assign().
   @see event_new(), event_assign()
  */
+EVENT2_EXPORT_SYMBOL
 void *event_self_cbarg(void);
 
 /**
@@ -1037,6 +1070,7 @@ void *event_self_cbarg(void);
     event_free().
   @see event_free(), event_add(), event_del(), event_assign()
  */
+EVENT2_EXPORT_SYMBOL
 struct event *event_new(struct event_base *, evutil_socket_t, short, event_callback_fn, void *);
 
 
@@ -1078,6 +1112,7 @@ struct event *event_new(struct event_base *, evutil_socket_t, short, event_callb
   @see event_new(), event_add(), event_del(), event_base_once(),
     event_get_struct_event_size()
   */
+EVENT2_EXPORT_SYMBOL
 int event_assign(struct event *, struct event_base *, evutil_socket_t, short, event_callback_fn, void *);
 
 /**
@@ -1086,6 +1121,7 @@ int event_assign(struct event *, struct event_base *, evutil_socket_t, short, ev
    If the event is pending or active, first make it non-pending and
    non-active.
  */
+EVENT2_EXPORT_SYMBOL
 void event_free(struct event *);
 
 /**
@@ -1130,7 +1166,9 @@ typedef void (*event_finalize_callback_fn)(struct event *, void *);
    @return 0 on succes, -1 on failure.
  */
 /**@{*/
+EVENT2_EXPORT_SYMBOL
 int event_finalize(unsigned, struct event *, event_finalize_callback_fn);
+EVENT2_EXPORT_SYMBOL
 int event_free_finalize(unsigned, struct event *, event_finalize_callback_fn);
 /**@}*/
 
@@ -1158,6 +1196,7 @@ int event_free_finalize(unsigned, struct event *, event_finalize_callback_fn);
         EV_TIMEOUT event succees immediately.
   @return 0 if successful, or -1 if an error occurred
  */
+EVENT2_EXPORT_SYMBOL
 int event_base_once(struct event_base *, evutil_socket_t, short, event_callback_fn, void *, const struct timeval *);
 
 /**
@@ -1181,6 +1220,7 @@ int event_base_once(struct event_base *, evutil_socket_t, short, event_callback_
   @return 0 if successful, or -1 if an error occurred
   @see event_del(), event_assign(), event_new()
   */
+EVENT2_EXPORT_SYMBOL
 int event_add(struct event *ev, const struct timeval *timeout);
 
 /**
@@ -1192,6 +1232,7 @@ int event_add(struct event *ev, const struct timeval *timeout);
    @param ev an event struct initialized via event_assign() or event_new()
    @return 0 on success, or -1 if  an error occurrect.
 */
+EVENT2_EXPORT_SYMBOL
 int event_remove_timer(struct event *ev);
 
 /**
@@ -1205,6 +1246,7 @@ int event_remove_timer(struct event *ev);
   @return 0 if successful, or -1 if an error occurred
   @see event_add()
  */
+EVENT2_EXPORT_SYMBOL
 int event_del(struct event *);
 
 /**
@@ -1215,6 +1257,7 @@ int event_del(struct event *);
    THIS IS AN EXPERIMENTAL API. IT MIGHT CHANGE BEFORE THE LIBEVENT 2.1 SERIES
    BECOMES STABLE.
  */
+EVENT2_EXPORT_SYMBOL
 int event_del_noblock(struct event *ev);
 /**
    As event_del(), but always blocks while the event's callback is running
@@ -1224,6 +1267,7 @@ int event_del_noblock(struct event *ev);
    THIS IS AN EXPERIMENTAL API. IT MIGHT CHANGE BEFORE THE LIBEVENT 2.1 SERIES
    BECOMES STABLE.
  */
+EVENT2_EXPORT_SYMBOL
 int event_del_block(struct event *ev);
 
 /**
@@ -1240,6 +1284,7 @@ int event_del_block(struct event *ev);
   @param res a set of flags to pass to the event's callback.
   @param ncalls an obsolete argument: this is ignored.
  **/
+EVENT2_EXPORT_SYMBOL
 void event_active(struct event *ev, int res, short ncalls);
 
 /**
@@ -1255,6 +1300,7 @@ void event_active(struct event *ev, int res, short ncalls);
   @return true if the event is pending on any of the events in 'what', (that
   is to say, it has been added), or 0 if the event is not added.
  */
+EVENT2_EXPORT_SYMBOL
 int event_pending(const struct event *ev, short events, struct timeval *tv);
 
 /**
@@ -1263,6 +1309,7 @@ int event_pending(const struct event *ev, short events, struct timeval *tv);
    The behavior of this function is not defined when called from outside the
    callback function for an event.
  */
+EVENT2_EXPORT_SYMBOL
 struct event *event_base_get_running_event(struct event_base *base);
 
 /**
@@ -1280,6 +1327,7 @@ struct event *event_base_get_running_event(struct event_base *base);
   @return 1 if the structure might be initialized, or 0 if it has not been
           initialized
  */
+EVENT2_EXPORT_SYMBOL
 int event_initialized(const struct event *ev);
 
 /**
@@ -1291,32 +1339,38 @@ int event_initialized(const struct event *ev);
    Get the socket or signal assigned to an event, or -1 if the event has
    no socket.
 */
+EVENT2_EXPORT_SYMBOL
 evutil_socket_t event_get_fd(const struct event *ev);
 
 /**
    Get the event_base associated with an event.
 */
+EVENT2_EXPORT_SYMBOL
 struct event_base *event_get_base(const struct event *ev);
 
 /**
    Return the events (EV_READ, EV_WRITE, etc) assigned to an event.
 */
+EVENT2_EXPORT_SYMBOL
 short event_get_events(const struct event *ev);
 
 /**
    Return the callback assigned to an event.
 */
+EVENT2_EXPORT_SYMBOL
 event_callback_fn event_get_callback(const struct event *ev);
 
 /**
    Return the callback argument assigned to an event.
 */
+EVENT2_EXPORT_SYMBOL
 void *event_get_callback_arg(const struct event *ev);
 
 /**
    Return the priority of an event.
    @see event_priority_init(), event_get_priority()
 */
+EVENT2_EXPORT_SYMBOL
 int event_get_priority(const struct event *ev);
 
 /**
@@ -1326,6 +1380,7 @@ int event_get_priority(const struct event *ev);
 
    If any of the "_out" arguments is NULL, it will be ignored.
  */
+EVENT2_EXPORT_SYMBOL
 void event_get_assignment(const struct event *event,
     struct event_base **base_out, evutil_socket_t *fd_out, short *events_out,
     event_callback_fn *callback_out, void **arg_out);
@@ -1343,6 +1398,7 @@ void event_get_assignment(const struct event *event,
    We might do this to help ensure ABI-compatibility between different
    versions of Libevent.
  */
+EVENT2_EXPORT_SYMBOL
 size_t event_get_struct_event_size(void);
 
 /**
@@ -1354,6 +1410,7 @@ size_t event_get_struct_event_size(void);
 
    @return a string containing the version number of Libevent
 */
+EVENT2_EXPORT_SYMBOL
 const char *event_get_version(void);
 
 /**
@@ -1367,6 +1424,7 @@ const char *event_get_version(void);
    the version number.  The low-order byte is unused.  For example, version
    2.0.1-alpha has a numeric representation of 0x02000100
 */
+EVENT2_EXPORT_SYMBOL
 ev_uint32_t event_get_version_number(void);
 
 /** As event_get_version, but gives the version of Libevent's headers. */
@@ -1404,6 +1462,7 @@ ev_uint32_t event_get_version_number(void);
   @return 0 if successful, or -1 if an error occurred
   @see event_priority_set()
  */
+EVENT2_EXPORT_SYMBOL
 int	event_base_priority_init(struct event_base *, int);
 
 /**
@@ -1413,6 +1472,7 @@ int	event_base_priority_init(struct event_base *, int);
   @return Number of different event priorities
   @see event_base_priority_init()
 */
+EVENT2_EXPORT_SYMBOL
 int	event_base_get_npriorities(struct event_base *eb);
 
 /**
@@ -1423,6 +1483,7 @@ int	event_base_get_npriorities(struct event_base *eb);
   @return 0 if successful, or -1 if an error occurred
   @see event_priority_init(), event_get_priority()
   */
+EVENT2_EXPORT_SYMBOL
 int	event_priority_set(struct event *, int);
 
 /**
@@ -1444,6 +1505,7 @@ int	event_priority_set(struct event *, int);
    (This optimization probably will not be worthwhile until you have thousands
    or tens of thousands of events with the same timeout.)
  */
+EVENT2_EXPORT_SYMBOL
 const struct timeval *event_base_init_common_timeout(struct event_base *base,
     const struct timeval *duration);
 
@@ -1470,6 +1532,7 @@ const struct timeval *event_base_init_common_timeout(struct event_base *base,
  @param realloc_fn A replacement for realloc
  @param free_fn A replacement for free.
  **/
+EVENT2_EXPORT_SYMBOL
 void event_set_mem_functions(
 	void *(*malloc_fn)(size_t sz),
 	void *(*realloc_fn)(void *ptr, size_t sz),
@@ -1489,6 +1552,7 @@ void event_set_mem_functions(
    @param base An event_base on which to scan the events.
    @param output A stdio file to write on.
  */
+EVENT2_EXPORT_SYMBOL
 void event_base_dump_events(struct event_base *, FILE *);
 
 
@@ -1502,6 +1566,7 @@ void event_base_dump_events(struct event_base *, FILE *);
    @param fd An fd to active events on.
    @param events One or more of EV_{READ,WRITE}.
  */
+EVENT2_EXPORT_SYMBOL
 void event_base_active_by_fd(struct event_base *base, evutil_socket_t fd, short events);
 
 /**
@@ -1513,6 +1578,7 @@ void event_base_active_by_fd(struct event_base *base, evutil_socket_t fd, short
    @param base the event_base on which to activate the events.
    @param fd The signal to active events on.
  */
+EVENT2_EXPORT_SYMBOL
 void event_base_active_by_signal(struct event_base *base, int sig);
 
 /**
@@ -1545,6 +1611,7 @@ typedef int (*event_base_foreach_event_cb)(const struct event_base *, const stru
    @return 0 if we iterated over every event, or the value returned by the
       callback function if the loop exited early.
 */
+EVENT2_EXPORT_SYMBOL
 int event_base_foreach_event(struct event_base *base, event_base_foreach_event_cb fn, void *arg);
 
 
@@ -1559,6 +1626,7 @@ int event_base_foreach_event(struct event_base *base, event_base_foreach_event_c
 
     Returns 0 on success, negative on failure.
  */
+EVENT2_EXPORT_SYMBOL
 int event_base_gettimeofday_cached(struct event_base *base,
     struct timeval *tv);
 
@@ -1574,6 +1642,7 @@ int event_base_gettimeofday_cached(struct event_base *base,
  *
  * @return 0 on success, -1 on failure
  */
+EVENT2_EXPORT_SYMBOL
 int event_base_update_cache_time(struct event_base *base);
 
 /** Release up all globally-allocated resources allocated by Libevent.
@@ -1590,6 +1659,7 @@ int event_base_update_cache_time(struct event_base *base);
     You should only call this function when no other Libevent functions will
     be invoked -- e.g., when cleanly exiting a program.
  */
+EVENT2_EXPORT_SYMBOL
 void libevent_global_shutdown(void);
 
 #ifdef __cplusplus
diff --git a/include/event2/event_compat.h b/include/event2/event_compat.h
index 87403a4d..5110175a 100644
--- a/include/event2/event_compat.h
+++ b/include/event2/event_compat.h
@@ -41,6 +41,7 @@
 
   @deprecated All functions in this file are by definition deprecated.
  */
+#include <event2/visibility.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -70,6 +71,7 @@ extern "C" {
 
   @see event_base_set(), event_base_new()
  */
+EVENT2_EXPORT_SYMBOL
 struct event_base *event_init(void);
 
 /**
@@ -83,6 +85,7 @@ struct event_base *event_init(void);
 
   @see event_base_dispatch(), event_init()
  */
+EVENT2_EXPORT_SYMBOL
 int event_dispatch(void);
 
 /**
@@ -96,6 +99,7 @@ int event_dispatch(void);
 
   @see event_base_loop(), event_init()
 */
+EVENT2_EXPORT_SYMBOL
 int event_loop(int);
 
 
@@ -111,6 +115,7 @@ int event_loop(int);
 
   @see event_init, event_base_loopexit()
   */
+EVENT2_EXPORT_SYMBOL
 int event_loopexit(const struct timeval *);
 
 
@@ -126,6 +131,7 @@ int event_loopexit(const struct timeval *);
 
   @see event_base_loopbreak(), event_init()
  */
+EVENT2_EXPORT_SYMBOL
 int event_loopbreak(void);
 
 /**
@@ -137,6 +143,7 @@ int event_loopbreak(void);
 
   @see event_base_once()
  */
+EVENT2_EXPORT_SYMBOL
 int event_once(evutil_socket_t , short,
     void (*)(evutil_socket_t, short, void *), void *, const struct timeval *);
 
@@ -150,6 +157,7 @@ int event_once(evutil_socket_t , short,
 
   @see event_base_get_method()
  */
+EVENT2_EXPORT_SYMBOL
 const char *event_get_method(void);
 
 
@@ -162,6 +170,7 @@ const char *event_get_method(void);
 
   @see event_base_priority_init()
  */
+EVENT2_EXPORT_SYMBOL
 int	event_priority_init(int);
 
 /**
@@ -171,6 +180,7 @@ int	event_priority_init(int);
      a subsequent call to event_base_set() to be safe under most circumstances.
      Use event_assign() or event_new() instead.
  */
+EVENT2_EXPORT_SYMBOL
 void event_set(struct event *, evutil_socket_t, short, void (*)(evutil_socket_t, short, void *), void *);
 
 #define evtimer_set(ev, cb, arg)	event_set((ev), -1, 0, (cb), (arg))
diff --git a/include/event2/http.h b/include/event2/http.h
index 08b70f52..81f44b85 100644
--- a/include/event2/http.h
+++ b/include/event2/http.h
@@ -29,6 +29,7 @@
 
 /* For int types. */
 #include <event2/util.h>
+#include <event2/visibility.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -80,6 +81,7 @@ struct evdns_base;
  * @return a pointer to a newly initialized evhttp server structure
  * @see evhttp_free()
  */
+EVENT2_EXPORT_SYMBOL
 struct evhttp *evhttp_new(struct event_base *base);
 
 /**
@@ -94,6 +96,7 @@ struct evhttp *evhttp_new(struct event_base *base);
  * @return 0 on success, -1 on failure.
  * @see evhttp_accept_socket()
  */
+EVENT2_EXPORT_SYMBOL
 int evhttp_bind_socket(struct evhttp *http, const char *address, ev_uint16_t port);
 
 /**
@@ -107,6 +110,7 @@ int evhttp_bind_socket(struct evhttp *http, const char *address, ev_uint16_t por
  * @return Handle for the socket on success, NULL on failure.
  * @see evhttp_bind_socket(), evhttp_del_accept_socket()
  */
+EVENT2_EXPORT_SYMBOL
 struct evhttp_bound_socket *evhttp_bind_socket_with_handle(struct evhttp *http, const char *address, ev_uint16_t port);
 
 /**
@@ -125,6 +129,7 @@ struct evhttp_bound_socket *evhttp_bind_socket_with_handle(struct evhttp *http,
  * @return 0 on success, -1 on failure.
  * @see evhttp_bind_socket()
  */
+EVENT2_EXPORT_SYMBOL
 int evhttp_accept_socket(struct evhttp *http, evutil_socket_t fd);
 
 /**
@@ -137,6 +142,7 @@ int evhttp_accept_socket(struct evhttp *http, evutil_socket_t fd);
  * @return Handle for the socket on success, NULL on failure.
  * @see evhttp_accept_socket(), evhttp_del_accept_socket()
  */
+EVENT2_EXPORT_SYMBOL
 struct evhttp_bound_socket *evhttp_accept_socket_with_handle(struct evhttp *http, evutil_socket_t fd);
 
 /**
@@ -144,11 +150,13 @@ struct evhttp_bound_socket *evhttp_accept_socket_with_handle(struct evhttp *http
  * returns an evhttp_bound_socket.  The listener will be freed when the bound
  * socket is freed.
  */
+EVENT2_EXPORT_SYMBOL
 struct evhttp_bound_socket *evhttp_bind_listener(struct evhttp *http, struct evconnlistener *listener);
 
 /**
  * Return the listener used to implement a bound socket.
  */
+EVENT2_EXPORT_SYMBOL
 struct evconnlistener *evhttp_bound_socket_get_listener(struct evhttp_bound_socket *bound);
 
 typedef void evhttp_bound_socket_foreach_fn(struct evhttp_bound_socket *, void *);
@@ -162,6 +170,7 @@ typedef void evhttp_bound_socket_foreach_fn(struct evhttp_bound_socket *, void *
  * @param function function to apply to every bound socket
  * @param argument pointer value passed to function for every socket iterated
  */
+EVENT2_EXPORT_SYMBOL
 void evhttp_foreach_bound_socket(struct evhttp *http, evhttp_bound_socket_foreach_fn *function, void *argument);
 
 /**
@@ -181,6 +190,7 @@ void evhttp_foreach_bound_socket(struct evhttp *http, evhttp_bound_socket_foreac
  * @param bound_socket a handle returned by evhttp_{bind,accept}_socket_with_handle
  * @see evhttp_bind_socket_with_handle(), evhttp_accept_socket_with_handle()
  */
+EVENT2_EXPORT_SYMBOL
 void evhttp_del_accept_socket(struct evhttp *http, struct evhttp_bound_socket *bound_socket);
 
 /**
@@ -190,6 +200,7 @@ void evhttp_del_accept_socket(struct evhttp *http, struct evhttp_bound_socket *b
  * @return the file descriptor used by the bound socket
  * @see evhttp_bind_socket_with_handle(), evhttp_accept_socket_with_handle()
  */
+EVENT2_EXPORT_SYMBOL
 evutil_socket_t evhttp_bound_socket_get_fd(struct evhttp_bound_socket *bound_socket);
 
 /**
@@ -200,11 +211,14 @@ evutil_socket_t evhttp_bound_socket_get_fd(struct evhttp_bound_socket *bound_soc
  * @param http the evhttp server object to be freed
  * @see evhttp_start()
  */
+EVENT2_EXPORT_SYMBOL
 void evhttp_free(struct evhttp* http);
 
 /** XXX Document. */
+EVENT2_EXPORT_SYMBOL
 void evhttp_set_max_headers_size(struct evhttp* http, ev_ssize_t max_headers_size);
 /** XXX Document. */
+EVENT2_EXPORT_SYMBOL
 void evhttp_set_max_body_size(struct evhttp* http, ev_ssize_t max_body_size);
 
 /**
@@ -215,6 +229,7 @@ void evhttp_set_max_body_size(struct evhttp* http, ev_ssize_t max_body_size);
   @param http the http server on which to set the default content type
   @param content_type the value for the Content-Type header
 */
+EVENT2_EXPORT_SYMBOL
 void evhttp_set_default_content_type(struct evhttp *http,
 	const char *content_type);
 
@@ -229,6 +244,7 @@ void evhttp_set_default_content_type(struct evhttp *http,
   @param http the http server on which to set the methods
   @param methods bit mask constructed from evhttp_cmd_type values
 */
+EVENT2_EXPORT_SYMBOL
 void evhttp_set_allowed_methods(struct evhttp* http, ev_uint16_t methods);
 
 /**
@@ -240,10 +256,12 @@ void evhttp_set_allowed_methods(struct evhttp* http, ev_uint16_t methods);
    @param cb_arg an additional context argument for the callback
    @return 0 on success, -1 if the callback existed already, -2 on failure
 */
+EVENT2_EXPORT_SYMBOL
 int evhttp_set_cb(struct evhttp *http, const char *path,
     void (*cb)(struct evhttp_request *, void *), void *cb_arg);
 
 /** Removes the callback for a specified URI */
+EVENT2_EXPORT_SYMBOL
 int evhttp_del_cb(struct evhttp *, const char *);
 
 /**
@@ -257,6 +275,7 @@ int evhttp_del_cb(struct evhttp *, const char *);
     @param cb the callback to invoke for any unmatched requests
     @param arg an context argument for the callback
 */
+EVENT2_EXPORT_SYMBOL
 void evhttp_set_gencb(struct evhttp *http,
     void (*cb)(struct evhttp_request *, void *), void *arg);
 
@@ -274,6 +293,7 @@ void evhttp_set_gencb(struct evhttp *http,
    @param cb the callback to invoke for incoming connections
    @param arg an context argument for the callback
  */
+EVENT2_EXPORT_SYMBOL
 void evhttp_set_bevcb(struct evhttp *http,
     struct bufferevent *(*cb)(struct event_base *, void *), void *arg);
 
@@ -299,6 +319,7 @@ void evhttp_set_bevcb(struct evhttp *http,
    @return 0 on success, -1 on failure
    @see evhttp_remove_virtual_host()
 */
+EVENT2_EXPORT_SYMBOL
 int evhttp_add_virtual_host(struct evhttp* http, const char *pattern,
     struct evhttp* vhost);
 
@@ -310,6 +331,7 @@ int evhttp_add_virtual_host(struct evhttp* http, const char *pattern,
    @return 0 on success, -1 on failure
    @see evhttp_add_virtual_host()
 */
+EVENT2_EXPORT_SYMBOL
 int evhttp_remove_virtual_host(struct evhttp* http, struct evhttp* vhost);
 
 /**
@@ -320,6 +342,7 @@ int evhttp_remove_virtual_host(struct evhttp* http, struct evhttp* vhost);
    @param alias the alias to add
    @see evhttp_add_remove_alias()
 */
+EVENT2_EXPORT_SYMBOL
 int evhttp_add_server_alias(struct evhttp *http, const char *alias);
 
 /**
@@ -329,6 +352,7 @@ int evhttp_add_server_alias(struct evhttp *http, const char *alias);
    @param alias the alias to remove
    @see evhttp_add_server_alias()
 */
+EVENT2_EXPORT_SYMBOL
 int evhttp_remove_server_alias(struct evhttp *http, const char *alias);
 
 /**
@@ -337,6 +361,7 @@ int evhttp_remove_server_alias(struct evhttp *http, const char *alias);
  * @param http an evhttp object
  * @param timeout_in_secs the timeout, in seconds
  */
+EVENT2_EXPORT_SYMBOL
 void evhttp_set_timeout(struct evhttp *http, int timeout_in_secs);
 
 /**
@@ -345,6 +370,7 @@ void evhttp_set_timeout(struct evhttp *http, int timeout_in_secs);
  * @param http an evhttp object
  * @param tv the timeout, or NULL
  */
+EVENT2_EXPORT_SYMBOL
 void evhttp_set_timeout_tv(struct evhttp *http, const struct timeval* tv);
 
 /* Request/Response functionality */
@@ -357,6 +383,7 @@ void evhttp_set_timeout_tv(struct evhttp *http, const struct timeval* tv);
  * @param reason a brief explanation of the error.  If this is NULL, we'll
  *    just use the standard meaning of the error code.
  */
+EVENT2_EXPORT_SYMBOL
 void evhttp_send_error(struct evhttp_request *req, int error,
     const char *reason);
 
@@ -373,6 +400,7 @@ void evhttp_send_error(struct evhttp_request *req, int error,
  * @param reason a brief message to send with the response code
  * @param databuf the body of the response
  */
+EVENT2_EXPORT_SYMBOL
 void evhttp_send_reply(struct evhttp_request *req, int code,
     const char *reason, struct evbuffer *databuf);
 
@@ -392,6 +420,7 @@ void evhttp_send_reply(struct evhttp_request *req, int code,
    @param code the HTTP response code to send
    @param reason a brief message to send with the response code
 */
+EVENT2_EXPORT_SYMBOL
 void evhttp_send_reply_start(struct evhttp_request *req, int code,
     const char *reason);
 
@@ -406,6 +435,7 @@ void evhttp_send_reply_start(struct evhttp_request *req, int code,
    @param req a request object
    @param databuf the data chunk to send as part of the reply.
 */
+EVENT2_EXPORT_SYMBOL
 void evhttp_send_reply_chunk(struct evhttp_request *req,
     struct evbuffer *databuf);
 
@@ -422,6 +452,7 @@ void evhttp_send_reply_chunk(struct evhttp_request *req,
    @param cb callback funcion
    @param call back's argument.
 */
+EVENT2_EXPORT_SYMBOL
 void evhttp_send_reply_chunk_with_cb(struct evhttp_request *, struct evbuffer *,
     void (*cb)(struct evhttp_connection *, void *), void *arg);
 
@@ -430,6 +461,7 @@ void evhttp_send_reply_chunk_with_cb(struct evhttp_request *, struct evbuffer *,
 
    @param req a request object
 */
+EVENT2_EXPORT_SYMBOL
 void evhttp_send_reply_end(struct evhttp_request *req);
 
 /*
@@ -473,17 +505,20 @@ enum evhttp_request_kind { EVHTTP_REQUEST, EVHTTP_RESPONSE };
  * @param port the port to connect to
  * @return an evhttp_connection object that can be used for making requests
  */
+EVENT2_EXPORT_SYMBOL
 struct evhttp_connection *evhttp_connection_base_bufferevent_new(
 	struct event_base *base, struct evdns_base *dnsbase, struct bufferevent* bev, const char *address, unsigned short port);
 
 /**
  * Return the bufferevent that an evhttp_connection is using.
  */
+EVENT2_EXPORT_SYMBOL
 struct bufferevent* evhttp_connection_get_bufferevent(struct evhttp_connection *evcon);
 
 /**
  * Return the HTTP server associated with this connection, or NULL.
  */
+EVENT2_EXPORT_SYMBOL
 struct evhttp *evhttp_connection_get_server(struct evhttp_connection *evcon);
 
 /**
@@ -491,6 +526,7 @@ struct evhttp *evhttp_connection_get_server(struct evhttp_connection *evcon);
  * parameters.  The callback is executed when the request completed or an
  * error occurred.
  */
+EVENT2_EXPORT_SYMBOL
 struct evhttp_request *evhttp_request_new(
 	void (*cb)(struct evhttp_request *, void *), void *arg);
 
@@ -501,6 +537,7 @@ struct evhttp_request *evhttp_request_new(
  *           response. May drain the input buffer; it will be drained
  *           automatically on return.
  */
+EVENT2_EXPORT_SYMBOL
 void evhttp_request_set_chunked_cb(struct evhttp_request *,
     void (*cb)(struct evhttp_request *, void *));
 
@@ -510,6 +547,7 @@ void evhttp_request_set_chunked_cb(struct evhttp_request *,
  * It allows analyzing the header and possibly closing the connection
  * by returning a value < 0.
  */
+EVENT2_EXPORT_SYMBOL
 void evhttp_request_set_header_cb(struct evhttp_request *,
     int (*cb)(struct evhttp_request *, void *));
 
@@ -551,6 +589,7 @@ enum evhttp_request_error {
  * On error, both the error callback and the regular callback will be called,
  * error callback is called before the regular callback.
  **/
+EVENT2_EXPORT_SYMBOL
 void evhttp_request_set_error_cb(struct evhttp_request *,
     void (*)(enum evhttp_request_error, void *));
 
@@ -566,10 +605,12 @@ void evhttp_request_set_error_cb(struct evhttp_request *,
  * @param cb callback function that will be called on request completion
  * @param cb_arg an additional context argument for the callback
  */
+EVENT2_EXPORT_SYMBOL
 void evhttp_request_set_on_complete_cb(struct evhttp_request *req,
     void (*cb)(struct evhttp_request *, void *), void *cb_arg);
 
 /** Frees the request object and removes associated events. */
+EVENT2_EXPORT_SYMBOL
 void evhttp_request_free(struct evhttp_request *req);
 
 /**
@@ -584,6 +625,7 @@ void evhttp_request_free(struct evhttp_request *req);
  * @param port the port to connect to
  * @return an evhttp_connection object that can be used for making requests
  */
+EVENT2_EXPORT_SYMBOL
 struct evhttp_connection *evhttp_connection_base_new(
 	struct event_base *base, struct evdns_base *dnsbase,
 	const char *address, unsigned short port);
@@ -593,9 +635,11 @@ struct evhttp_connection *evhttp_connection_base_new(
  * Can be used in a request callback to keep onto the request until
  * evhttp_request_free() is explicitly called by the user.
  */
+EVENT2_EXPORT_SYMBOL
 void evhttp_request_own(struct evhttp_request *req);
 
 /** Returns 1 if the request is owned by the user */
+EVENT2_EXPORT_SYMBOL
 int evhttp_request_is_owned(struct evhttp_request *req);
 
 /**
@@ -604,36 +648,45 @@ int evhttp_request_is_owned(struct evhttp_request *req);
  * The user needs to either free the request explicitly or call
  * evhttp_send_reply_end().
  */
+EVENT2_EXPORT_SYMBOL
 struct evhttp_connection *evhttp_request_get_connection(struct evhttp_request *req);
 
 /**
  * Returns the underlying event_base for this connection
  */
+EVENT2_EXPORT_SYMBOL
 struct event_base *evhttp_connection_get_base(struct evhttp_connection *req);
 
+EVENT2_EXPORT_SYMBOL
 void evhttp_connection_set_max_headers_size(struct evhttp_connection *evcon,
     ev_ssize_t new_max_headers_size);
 
+EVENT2_EXPORT_SYMBOL
 void evhttp_connection_set_max_body_size(struct evhttp_connection* evcon,
     ev_ssize_t new_max_body_size);
 
 /** Frees an http connection */
+EVENT2_EXPORT_SYMBOL
 void evhttp_connection_free(struct evhttp_connection *evcon);
 
 /** sets the ip address from which http connections are made */
+EVENT2_EXPORT_SYMBOL
 void evhttp_connection_set_local_address(struct evhttp_connection *evcon,
     const char *address);
 
 /** sets the local port from which http connections are made */
+EVENT2_EXPORT_SYMBOL
 void evhttp_connection_set_local_port(struct evhttp_connection *evcon,
     ev_uint16_t port);
 
 /** Sets the timeout in seconds for events related to this connection */
+EVENT2_EXPORT_SYMBOL
 void evhttp_connection_set_timeout(struct evhttp_connection *evcon,
     int timeout_in_secs);
 
 /** Sets the timeout for events related to this connection.  Takes a struct
  * timeval. */
+EVENT2_EXPORT_SYMBOL
 void evhttp_connection_set_timeout_tv(struct evhttp_connection *evcon,
     const struct timeval *tv);
 
@@ -641,18 +694,22 @@ void evhttp_connection_set_timeout_tv(struct evhttp_connection *evcon,
  * used if evhttp_connection_set_retries is used to make the number of retries
  * at least one. Each retry after the first is twice as long as the one before
  * it. */
+EVENT2_EXPORT_SYMBOL
 void evhttp_connection_set_initial_retry_tv(struct evhttp_connection *evcon,
     const struct timeval *tv);
 
 /** Sets the retry limit for this connection - -1 repeats indefinitely */
+EVENT2_EXPORT_SYMBOL
 void evhttp_connection_set_retries(struct evhttp_connection *evcon,
     int retry_max);
 
 /** Set a callback for connection close. */
+EVENT2_EXPORT_SYMBOL
 void evhttp_connection_set_closecb(struct evhttp_connection *evcon,
     void (*)(struct evhttp_connection *, void *), void *);
 
 /** Get the remote address and port associated with this connection. */
+EVENT2_EXPORT_SYMBOL
 void evhttp_connection_get_peer(struct evhttp_connection *evcon,
     char **address, ev_uint16_t *port);
 
@@ -662,6 +719,7 @@ void evhttp_connection_get_peer(struct evhttp_connection *evcon,
  * @return NULL if getpeername() return non success,
  * or connection is not connected,
  * otherwise it return pointer to struct sockaddr_storage */
+EVENT2_EXPORT_SYMBOL
 const struct sockaddr*
 evhttp_connection_get_addr(struct evhttp_connection *evcon);
 
@@ -678,6 +736,7 @@ evhttp_connection_get_addr(struct evhttp_connection *evcon);
     @return 0 on success, -1 on failure
     @see evhttp_cancel_request()
 */
+EVENT2_EXPORT_SYMBOL
 int evhttp_make_request(struct evhttp_connection *evcon,
     struct evhttp_request *req,
     enum evhttp_cmd_type type, const char *uri);
@@ -695,6 +754,7 @@ int evhttp_make_request(struct evhttp_connection *evcon,
 
    @param req the evhttp_request to cancel; req becomes invalid after this call.
 */
+EVENT2_EXPORT_SYMBOL
 void evhttp_cancel_request(struct evhttp_request *req);
 
 /**
@@ -703,27 +763,37 @@ void evhttp_cancel_request(struct evhttp_request *req);
 struct evhttp_uri;
 
 /** Returns the request URI */
+EVENT2_EXPORT_SYMBOL
 const char *evhttp_request_get_uri(const struct evhttp_request *req);
 /** Returns the request URI (parsed) */
+EVENT2_EXPORT_SYMBOL
 const struct evhttp_uri *evhttp_request_get_evhttp_uri(const struct evhttp_request *req);
 /** Returns the request command */
+EVENT2_EXPORT_SYMBOL
 enum evhttp_cmd_type evhttp_request_get_command(const struct evhttp_request *req);
 
+EVENT2_EXPORT_SYMBOL
 int evhttp_request_get_response_code(const struct evhttp_request *req);
+EVENT2_EXPORT_SYMBOL
 const char * evhttp_request_get_response_code_line(const struct evhttp_request *req);
 
 /** Returns the input headers */
+EVENT2_EXPORT_SYMBOL
 struct evkeyvalq *evhttp_request_get_input_headers(struct evhttp_request *req);
 /** Returns the output headers */
+EVENT2_EXPORT_SYMBOL
 struct evkeyvalq *evhttp_request_get_output_headers(struct evhttp_request *req);
 /** Returns the input buffer */
+EVENT2_EXPORT_SYMBOL
 struct evbuffer *evhttp_request_get_input_buffer(struct evhttp_request *req);
 /** Returns the output buffer */
+EVENT2_EXPORT_SYMBOL
 struct evbuffer *evhttp_request_get_output_buffer(struct evhttp_request *req);
 /** Returns the host associated with the request. If a client sends an absolute
     URI, the host part of that is preferred. Otherwise, the input headers are
     searched for a Host: header. NULL is returned if no absolute URI or Host:
     header is provided. */
+EVENT2_EXPORT_SYMBOL
 const char *evhttp_request_get_host(struct evhttp_request *req);
 
 /* Interfaces for dealing with HTTP headers */
@@ -737,6 +807,7 @@ const char *evhttp_request_get_host(struct evhttp_request *req);
      could not be found.
    @see evhttp_add_header(), evhttp_remove_header()
 */
+EVENT2_EXPORT_SYMBOL
 const char *evhttp_find_header(const struct evkeyvalq *headers,
     const char *key);
 
@@ -748,6 +819,7 @@ const char *evhttp_find_header(const struct evkeyvalq *headers,
    @returns 0 if the header was removed, -1  otherwise.
    @see evhttp_find_header(), evhttp_add_header()
 */
+EVENT2_EXPORT_SYMBOL
 int evhttp_remove_header(struct evkeyvalq *headers, const char *key);
 
 /**
@@ -759,6 +831,7 @@ int evhttp_remove_header(struct evkeyvalq *headers, const char *key);
    @returns 0 on success, -1  otherwise.
    @see evhttp_find_header(), evhttp_clear_headers()
 */
+EVENT2_EXPORT_SYMBOL
 int evhttp_add_header(struct evkeyvalq *headers, const char *key, const char *value);
 
 /**
@@ -766,6 +839,7 @@ int evhttp_add_header(struct evkeyvalq *headers, const char *key, const char *va
 
    @param headers the evkeyvalq object from which to remove all headers
 */
+EVENT2_EXPORT_SYMBOL
 void evhttp_clear_headers(struct evkeyvalq *headers);
 
 /* Miscellaneous utility functions */
@@ -782,6 +856,7 @@ void evhttp_clear_headers(struct evkeyvalq *headers);
    @param str an unencoded string
    @return a newly allocated URI-encoded string or NULL on failure
  */
+EVENT2_EXPORT_SYMBOL
 char *evhttp_encode_uri(const char *str);
 
 /**
@@ -798,6 +873,7 @@ char *evhttp_encode_uri(const char *str);
       as +, not %20.
    @return a newly allocate URI-encoded string, or NULL on failure.
  */
+EVENT2_EXPORT_SYMBOL
 char *evhttp_uriencode(const char *str, ev_ssize_t size, int space_to_plus);
 
 /**
@@ -814,6 +890,7 @@ char *evhttp_uriencode(const char *str, ev_ssize_t size, int space_to_plus);
   @param uri an encoded URI
   @return a newly allocated unencoded URI or NULL on failure
  */
+EVENT2_EXPORT_SYMBOL
 char *evhttp_decode_uri(const char *uri);
 
 /**
@@ -831,6 +908,7 @@ char *evhttp_decode_uri(const char *uri);
      returned string
   @return a newly allocated unencoded URI or NULL on failure
  */
+EVENT2_EXPORT_SYMBOL
 char *evhttp_uridecode(const char *uri, int decode_plus,
     size_t *size_out);
 
@@ -853,6 +931,7 @@ char *evhttp_uridecode(const char *uri, int decode_plus,
    @param headers the head of the evkeyval queue
    @return 0 on success, -1 on failure
  */
+EVENT2_EXPORT_SYMBOL
 int evhttp_parse_query(const char *uri, struct evkeyvalq *headers);
 
 /**
@@ -872,6 +951,7 @@ int evhttp_parse_query(const char *uri, struct evkeyvalq *headers);
    @param headers the head of the evkeyval queue
    @return 0 on success, -1 on failure
  */
+EVENT2_EXPORT_SYMBOL
 int evhttp_parse_query_str(const char *uri, struct evkeyvalq *headers);
 
 /**
@@ -885,26 +965,31 @@ int evhttp_parse_query_str(const char *uri, struct evkeyvalq *headers);
  * @param html an unescaped HTML string
  * @return an escaped HTML string or NULL on error
  */
+EVENT2_EXPORT_SYMBOL
 char *evhttp_htmlescape(const char *html);
 
 /**
  * Return a new empty evhttp_uri with no fields set.
  */
+EVENT2_EXPORT_SYMBOL
 struct evhttp_uri *evhttp_uri_new(void);
 
 /**
  * Changes the flags set on a given URI.  See EVHTTP_URI_* for
  * a list of flags.
  **/
+EVENT2_EXPORT_SYMBOL
 void evhttp_uri_set_flags(struct evhttp_uri *uri, unsigned flags);
 
 /** Return the scheme of an evhttp_uri, or NULL if there is no scheme has
  * been set and the evhttp_uri contains a Relative-Ref. */
+EVENT2_EXPORT_SYMBOL
 const char *evhttp_uri_get_scheme(const struct evhttp_uri *uri);
 /**
  * Return the userinfo part of an evhttp_uri, or NULL if it has no userinfo
  * set.
  */
+EVENT2_EXPORT_SYMBOL
 const char *evhttp_uri_get_userinfo(const struct evhttp_uri *uri);
 /**
  * Return the host part of an evhttp_uri, or NULL if it has no host set.
@@ -918,40 +1003,52 @@ const char *evhttp_uri_get_userinfo(const struct evhttp_uri *uri);
  * "mailto:user@example.com" has a host of NULL, but "file:///etc/motd"
  * has a host of "".
  */
+EVENT2_EXPORT_SYMBOL
 const char *evhttp_uri_get_host(const struct evhttp_uri *uri);
 /** Return the port part of an evhttp_uri, or -1 if there is no port set. */
+EVENT2_EXPORT_SYMBOL
 int evhttp_uri_get_port(const struct evhttp_uri *uri);
 /** Return the path part of an evhttp_uri, or NULL if it has no path set */
+EVENT2_EXPORT_SYMBOL
 const char *evhttp_uri_get_path(const struct evhttp_uri *uri);
 /** Return the query part of an evhttp_uri (excluding the leading "?"), or
  * NULL if it has no query set */
+EVENT2_EXPORT_SYMBOL
 const char *evhttp_uri_get_query(const struct evhttp_uri *uri);
 /** Return the fragment part of an evhttp_uri (excluding the leading "#"),
  * or NULL if it has no fragment set */
+EVENT2_EXPORT_SYMBOL
 const char *evhttp_uri_get_fragment(const struct evhttp_uri *uri);
 
 /** Set the scheme of an evhttp_uri, or clear the scheme if scheme==NULL.
  * Returns 0 on success, -1 if scheme is not well-formed. */
+EVENT2_EXPORT_SYMBOL
 int evhttp_uri_set_scheme(struct evhttp_uri *uri, const char *scheme);
 /** Set the userinfo of an evhttp_uri, or clear the userinfo if userinfo==NULL.
  * Returns 0 on success, -1 if userinfo is not well-formed. */
+EVENT2_EXPORT_SYMBOL
 int evhttp_uri_set_userinfo(struct evhttp_uri *uri, const char *userinfo);
 /** Set the host of an evhttp_uri, or clear the host if host==NULL.
  * Returns 0 on success, -1 if host is not well-formed. */
+EVENT2_EXPORT_SYMBOL
 int evhttp_uri_set_host(struct evhttp_uri *uri, const char *host);
 /** Set the port of an evhttp_uri, or clear the port if port==-1.
  * Returns 0 on success, -1 if port is not well-formed. */
+EVENT2_EXPORT_SYMBOL
 int evhttp_uri_set_port(struct evhttp_uri *uri, int port);
 /** Set the path of an evhttp_uri, or clear the path if path==NULL.
  * Returns 0 on success, -1 if path is not well-formed. */
+EVENT2_EXPORT_SYMBOL
 int evhttp_uri_set_path(struct evhttp_uri *uri, const char *path);
 /** Set the query of an evhttp_uri, or clear the query if query==NULL.
  * The query should not include a leading "?".
  * Returns 0 on success, -1 if query is not well-formed. */
+EVENT2_EXPORT_SYMBOL
 int evhttp_uri_set_query(struct evhttp_uri *uri, const char *query);
 /** Set the fragment of an evhttp_uri, or clear the fragment if fragment==NULL.
  * The fragment should not include a leading "#".
  * Returns 0 on success, -1 if fragment is not well-formed. */
+EVENT2_EXPORT_SYMBOL
 int evhttp_uri_set_fragment(struct evhttp_uri *uri, const char *fragment);
 
 /**
@@ -988,6 +1085,7 @@ int evhttp_uri_set_fragment(struct evhttp_uri *uri, const char *fragment);
  * @return uri container to hold parsed data, or NULL if there is error
  * @see evhttp_uri_free()
  */
+EVENT2_EXPORT_SYMBOL
 struct evhttp_uri *evhttp_uri_parse_with_flags(const char *source_uri,
     unsigned flags);
 
@@ -1006,6 +1104,7 @@ struct evhttp_uri *evhttp_uri_parse_with_flags(const char *source_uri,
 #define EVHTTP_URI_NONCONFORMANT 0x01
 
 /** Alias for evhttp_uri_parse_with_flags(source_uri, 0) */
+EVENT2_EXPORT_SYMBOL
 struct evhttp_uri *evhttp_uri_parse(const char *source_uri);
 
 /**
@@ -1015,6 +1114,7 @@ struct evhttp_uri *evhttp_uri_parse(const char *source_uri);
  * @param uri container with parsed data
  * @see evhttp_uri_parse()
  */
+EVENT2_EXPORT_SYMBOL
 void evhttp_uri_free(struct evhttp_uri *uri);
 
 /**
@@ -1030,6 +1130,7 @@ void evhttp_uri_free(struct evhttp_uri *uri);
  * @return an joined uri as string or NULL on error
  * @see evhttp_uri_parse()
  */
+EVENT2_EXPORT_SYMBOL
 char *evhttp_uri_join(struct evhttp_uri *uri, char *buf, size_t limit);
 
 #ifdef __cplusplus
diff --git a/include/event2/listener.h b/include/event2/listener.h
index 3ad52c52..8c77803d 100644
--- a/include/event2/listener.h
+++ b/include/event2/listener.h
@@ -27,6 +27,8 @@
 #ifndef EVENT2_LISTENER_H_INCLUDED_
 #define EVENT2_LISTENER_H_INCLUDED_
 
+#include <event2/visibility.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -104,6 +106,7 @@ typedef void (*evconnlistener_errorcb)(struct evconnlistener *, void *);
       file descriptor, and it should already be bound to an appropriate
       port and address.
 */
+EVENT2_EXPORT_SYMBOL
 struct evconnlistener *evconnlistener_new(struct event_base *base,
     evconnlistener_cb cb, void *ptr, unsigned flags, int backlog,
     evutil_socket_t fd);
@@ -122,34 +125,42 @@ struct evconnlistener *evconnlistener_new(struct event_base *base,
    @param addr The address to listen for connections on.
    @param socklen The length of the address.
  */
+EVENT2_EXPORT_SYMBOL
 struct evconnlistener *evconnlistener_new_bind(struct event_base *base,
     evconnlistener_cb cb, void *ptr, unsigned flags, int backlog,
     const struct sockaddr *sa, int socklen);
 /**
    Disable and deallocate an evconnlistener.
  */
+EVENT2_EXPORT_SYMBOL
 void evconnlistener_free(struct evconnlistener *lev);
 /**
    Re-enable an evconnlistener that has been disabled.
  */
+EVENT2_EXPORT_SYMBOL
 int evconnlistener_enable(struct evconnlistener *lev);
 /**
    Stop listening for connections on an evconnlistener.
  */
+EVENT2_EXPORT_SYMBOL
 int evconnlistener_disable(struct evconnlistener *lev);
 
 /** Return an evconnlistener's associated event_base. */
+EVENT2_EXPORT_SYMBOL
 struct event_base *evconnlistener_get_base(struct evconnlistener *lev);
 
 /** Return the socket that an evconnlistner is listening on. */
+EVENT2_EXPORT_SYMBOL
 evutil_socket_t evconnlistener_get_fd(struct evconnlistener *lev);
 
 /** Change the callback on the listener to cb and its user_data to arg.
  */
+EVENT2_EXPORT_SYMBOL
 void evconnlistener_set_cb(struct evconnlistener *lev,
     evconnlistener_cb cb, void *arg);
 
 /** Set an evconnlistener's error callback. */
+EVENT2_EXPORT_SYMBOL
 void evconnlistener_set_error_cb(struct evconnlistener *lev,
     evconnlistener_errorcb errorcb);
 
diff --git a/include/event2/tag.h b/include/event2/tag.h
index 7632bd58..2f73bfc0 100644
--- a/include/event2/tag.h
+++ b/include/event2/tag.h
@@ -33,6 +33,8 @@
 
  */
 
+#include <event2/visibility.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -56,6 +58,7 @@ struct evbuffer;
  * known ones - and we can just ignore the end of an event buffer.
  */
 
+EVENT2_EXPORT_SYMBOL
 void evtag_init(void);
 
 /**
@@ -65,10 +68,13 @@ void evtag_init(void);
    @param ptag a pointer in which the tag id is being stored
    @returns -1 on failure or the number of bytes in the remaining payload.
 */
+EVENT2_EXPORT_SYMBOL
 int evtag_unmarshal_header(struct evbuffer *evbuf, ev_uint32_t *ptag);
 
+EVENT2_EXPORT_SYMBOL
 void evtag_marshal(struct evbuffer *evbuf, ev_uint32_t tag, const void *data,
     ev_uint32_t len);
+EVENT2_EXPORT_SYMBOL
 void evtag_marshal_buffer(struct evbuffer *evbuf, ev_uint32_t tag,
     struct evbuffer *data);
 
@@ -82,38 +88,54 @@ void evtag_marshal_buffer(struct evbuffer *evbuf, ev_uint32_t tag,
   @param evbuf evbuffer to store the encoded number
   @param number a 32-bit integer
  */
+EVENT2_EXPORT_SYMBOL
 void evtag_encode_int(struct evbuffer *evbuf, ev_uint32_t number);
+EVENT2_EXPORT_SYMBOL
 void evtag_encode_int64(struct evbuffer *evbuf, ev_uint64_t number);
 
+EVENT2_EXPORT_SYMBOL
 void evtag_marshal_int(struct evbuffer *evbuf, ev_uint32_t tag,
     ev_uint32_t integer);
+EVENT2_EXPORT_SYMBOL
 void evtag_marshal_int64(struct evbuffer *evbuf, ev_uint32_t tag,
     ev_uint64_t integer);
 
+EVENT2_EXPORT_SYMBOL
 void evtag_marshal_string(struct evbuffer *buf, ev_uint32_t tag,
     const char *string);
 
+EVENT2_EXPORT_SYMBOL
 void evtag_marshal_timeval(struct evbuffer *evbuf, ev_uint32_t tag,
     struct timeval *tv);
 
+EVENT2_EXPORT_SYMBOL
 int evtag_unmarshal(struct evbuffer *src, ev_uint32_t *ptag,
     struct evbuffer *dst);
+EVENT2_EXPORT_SYMBOL
 int evtag_peek(struct evbuffer *evbuf, ev_uint32_t *ptag);
+EVENT2_EXPORT_SYMBOL
 int evtag_peek_length(struct evbuffer *evbuf, ev_uint32_t *plength);
+EVENT2_EXPORT_SYMBOL
 int evtag_payload_length(struct evbuffer *evbuf, ev_uint32_t *plength);
+EVENT2_EXPORT_SYMBOL
 int evtag_consume(struct evbuffer *evbuf);
 
+EVENT2_EXPORT_SYMBOL
 int evtag_unmarshal_int(struct evbuffer *evbuf, ev_uint32_t need_tag,
     ev_uint32_t *pinteger);
+EVENT2_EXPORT_SYMBOL
 int evtag_unmarshal_int64(struct evbuffer *evbuf, ev_uint32_t need_tag,
     ev_uint64_t *pinteger);
 
+EVENT2_EXPORT_SYMBOL
 int evtag_unmarshal_fixed(struct evbuffer *src, ev_uint32_t need_tag,
     void *data, size_t len);
 
+EVENT2_EXPORT_SYMBOL
 int evtag_unmarshal_string(struct evbuffer *evbuf, ev_uint32_t need_tag,
     char **pstring);
 
+EVENT2_EXPORT_SYMBOL
 int evtag_unmarshal_timeval(struct evbuffer *evbuf, ev_uint32_t need_tag,
     struct timeval *ptv);
 
diff --git a/include/event2/thread.h b/include/event2/thread.h
index f9f51500..b5199863 100644
--- a/include/event2/thread.h
+++ b/include/event2/thread.h
@@ -46,6 +46,8 @@
 
  */
 
+#include <event2/visibility.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -124,6 +126,7 @@ struct evthread_lock_callbacks {
  * probably shouldn't call this function; instead, use
  * evthread_use_windows_threads() or evthread_use_posix_threads() if you can.
  */
+EVENT2_EXPORT_SYMBOL
 int evthread_set_lock_callbacks(const struct evthread_lock_callbacks *);
 
 #define EVTHREAD_CONDITION_API_VERSION 1
@@ -174,6 +177,7 @@ struct evthread_condition_callbacks {
  * probably shouldn't call this function; instead, use
  * evthread_use_windows_threads() or evthread_use_pthreads() if you can.
  */
+EVENT2_EXPORT_SYMBOL
 int evthread_set_condition_callbacks(
 	const struct evthread_condition_callbacks *);
 
@@ -184,6 +188,7 @@ int evthread_set_condition_callbacks(
    @param id_fn the identify function Libevent should invoke to
      determine the identity of a thread.
 */
+EVENT2_EXPORT_SYMBOL
 void evthread_set_id_callback(
     unsigned long (*id_fn)(void));
 
@@ -192,6 +197,7 @@ void evthread_set_id_callback(
     functions.  Unavailable if Libevent is not built for Windows.
 
     @return 0 on success, -1 on failure. */
+EVENT2_EXPORT_SYMBOL
 int evthread_use_windows_threads(void);
 /**
    Defined if Libevent was built with support for evthread_use_windows_threads()
@@ -205,6 +211,7 @@ int evthread_use_windows_threads(void);
     libraries to link against Libevent_pthreads as well as Libevent.
 
     @return 0 on success, -1 on failure. */
+EVENT2_EXPORT_SYMBOL
 int evthread_use_pthreads(void);
 /** Defined if Libevent was built with support for evthread_use_pthreads() */
 #define EVTHREAD_USE_PTHREADS_IMPLEMENTED 1
@@ -217,10 +224,12 @@ int evthread_use_pthreads(void);
  * If you're going to call this function, you must do so before any locks are
  * allocated.
  **/
+EVENT2_EXPORT_SYMBOL
 void evthread_enable_lock_debugging(void);
 
 /* Old (misspelled) version: This is deprecated; use
  * evthread_enable_log_debugging instead. */
+EVENT2_EXPORT_SYMBOL
 void evthread_enable_lock_debuging(void);
 
 #endif /* EVENT__DISABLE_THREAD_SUPPORT */
@@ -234,6 +243,7 @@ struct event_base;
 
     @return 0 on success, -1 on failure.
  */
+EVENT2_EXPORT_SYMBOL
 int evthread_make_base_notifiable(struct event_base *base);
 
 #ifdef __cplusplus
diff --git a/include/event2/util.h b/include/event2/util.h
index 8ffc4a2e..14c6a25d 100644
--- a/include/event2/util.h
+++ b/include/event2/util.h
@@ -32,6 +32,7 @@
   related socket manipulations.
 
  */
+#include <event2/visibility.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -302,12 +303,14 @@ extern "C" {
 
     Parameters and return values are as for socketpair()
 */
+EVENT2_EXPORT_SYMBOL
 int evutil_socketpair(int d, int type, int protocol, evutil_socket_t sv[2]);
 /** Do platform-specific operations as needed to make a socket nonblocking.
 
     @param sock The socket to make nonblocking
     @return 0 on success, -1 on failure
  */
+EVENT2_EXPORT_SYMBOL
 int evutil_make_socket_nonblocking(evutil_socket_t sock);
 
 /** Do platform-specific operations to make a listener socket reusable.
@@ -321,6 +324,7 @@ int evutil_make_socket_nonblocking(evutil_socket_t sock);
     @param sock The socket to make reusable
     @return 0 on success, -1 on failure
  */
+EVENT2_EXPORT_SYMBOL
 int evutil_make_listen_socket_reuseable(evutil_socket_t sock);
 
 /** Do platform-specific operations as needed to close a socket upon a
@@ -329,6 +333,7 @@ int evutil_make_listen_socket_reuseable(evutil_socket_t sock);
     @param sock The socket to be closed
     @return 0 on success, -1 on failure
  */
+EVENT2_EXPORT_SYMBOL
 int evutil_make_socket_closeonexec(evutil_socket_t sock);
 
 /** Do the platform-specific call needed to close a socket returned from
@@ -337,6 +342,7 @@ int evutil_make_socket_closeonexec(evutil_socket_t sock);
     @param sock The socket to be closed
     @return 0 on success, -1 on failure
  */
+EVENT2_EXPORT_SYMBOL
 int evutil_closesocket(evutil_socket_t sock);
 #define EVUTIL_CLOSESOCKET(s) evutil_closesocket(s)
 
@@ -351,6 +357,7 @@ int evutil_closesocket(evutil_socket_t sock);
  *  @return 0 on success (whether the operation is supported or not),
  *       -1 on failure
 */ 
+EVENT2_EXPORT_SYMBOL
 int evutil_make_tcp_listen_socket_deferred(evutil_socket_t sock);
 
 #ifdef _WIN32
@@ -360,8 +367,10 @@ int evutil_make_tcp_listen_socket_deferred(evutil_socket_t sock);
 #define EVUTIL_SET_SOCKET_ERROR(errcode)		\
 	do { WSASetLastError(errcode); } while (0)
 /** Return the most recent socket error to occur on sock. */
+EVENT2_EXPORT_SYMBOL
 int evutil_socket_geterror(evutil_socket_t sock);
 /** Convert a socket error to a string. */
+EVENT2_EXPORT_SYMBOL
 const char *evutil_socket_error_to_string(int errcode);
 #elif defined(EVENT_IN_DOXYGEN_)
 /**
@@ -457,6 +466,7 @@ const char *evutil_socket_error_to_string(int errcode);
 
 /* big-int related functions */
 /** Parse a 64-bit value from a string.  Arguments are as for strtol. */
+EVENT2_EXPORT_SYMBOL
 ev_int64_t evutil_strtoll(const char *s, char **endptr, int base);
 
 /** Replacement for gettimeofday on platforms that lack it. */
@@ -464,12 +474,14 @@ ev_int64_t evutil_strtoll(const char *s, char **endptr, int base);
 #define evutil_gettimeofday(tv, tz) gettimeofday((tv), (tz))
 #else
 struct timezone;
+EVENT2_EXPORT_SYMBOL
 int evutil_gettimeofday(struct timeval *tv, struct timezone *tz);
 #endif
 
 /** Replacement for snprintf to get consistent behavior on platforms for
     which the return value of snprintf does not conform to C99.
  */
+EVENT2_EXPORT_SYMBOL
 int evutil_snprintf(char *buf, size_t buflen, const char *format, ...)
 #ifdef __GNUC__
 	__attribute__((format(printf, 3, 4)))
@@ -478,6 +490,7 @@ int evutil_snprintf(char *buf, size_t buflen, const char *format, ...)
 /** Replacement for vsnprintf to get consistent behavior on platforms for
     which the return value of snprintf does not conform to C99.
  */
+EVENT2_EXPORT_SYMBOL
 int evutil_vsnprintf(char *buf, size_t buflen, const char *format, va_list ap)
 #ifdef __GNUC__
 	__attribute__((format(printf, 3, 0)))
@@ -485,8 +498,10 @@ int evutil_vsnprintf(char *buf, size_t buflen, const char *format, va_list ap)
 ;
 
 /** Replacement for inet_ntop for platforms which lack it. */
+EVENT2_EXPORT_SYMBOL
 const char *evutil_inet_ntop(int af, const void *src, char *dst, size_t len);
 /** Replacement for inet_pton for platforms which lack it. */
+EVENT2_EXPORT_SYMBOL
 int evutil_inet_pton(int af, const char *src, void *dst);
 struct sockaddr;
 
@@ -510,6 +525,7 @@ struct sockaddr;
        or if out is not large enough to hold the result.  Otherwise returns
        0 on success.
 */
+EVENT2_EXPORT_SYMBOL
 int evutil_parse_sockaddr_port(const char *str, struct sockaddr *out, int *outlen);
 
 /** Compare two sockaddrs; return 0 if they are equal, or less than 0 if sa1
@@ -517,16 +533,19 @@ int evutil_parse_sockaddr_port(const char *str, struct sockaddr *out, int *outle
  * true, consider the port as well as the address.  Only implemented for
  * AF_INET and AF_INET6 addresses. The ordering is not guaranteed to remain
  * the same between Libevent versions. */
+EVENT2_EXPORT_SYMBOL
 int evutil_sockaddr_cmp(const struct sockaddr *sa1, const struct sockaddr *sa2,
     int include_port);
 
 /** As strcasecmp, but always compares the characters in locale-independent
     ASCII.  That's useful if you're handling data in ASCII-based protocols.
  */
+EVENT2_EXPORT_SYMBOL
 int evutil_ascii_strcasecmp(const char *str1, const char *str2);
 /** As strncasecmp, but always compares the characters in locale-independent
     ASCII.  That's useful if you're handling data in ASCII-based protocols.
  */
+EVENT2_EXPORT_SYMBOL
 int evutil_ascii_strncasecmp(const char *str1, const char *str2, size_t n);
 
 /* Here we define evutil_addrinfo to the native addrinfo type, or redefine it
@@ -667,12 +686,15 @@ struct evutil_addrinfo;
  *
  * For a nonblocking variant, see evdns_getaddrinfo.
  */
+EVENT2_EXPORT_SYMBOL
 int evutil_getaddrinfo(const char *nodename, const char *servname,
     const struct evutil_addrinfo *hints_in, struct evutil_addrinfo **res);
 
 /** Release storage allocated by evutil_getaddrinfo or evdns_getaddrinfo. */
+EVENT2_EXPORT_SYMBOL
 void evutil_freeaddrinfo(struct evutil_addrinfo *ai);
 
+EVENT2_EXPORT_SYMBOL
 const char *evutil_gai_strerror(int err);
 
 /** Generate n bytes of secure pseudorandom data, and store them in buf.
@@ -684,6 +706,7 @@ const char *evutil_gai_strerror(int err);
  * provides only rudimentary prediction- and backtracking-resistance.  Don't
  * use this for serious cryptographic applications.
  */
+EVENT2_EXPORT_SYMBOL
 void evutil_secure_rng_get_bytes(void *buf, size_t n);
 
 /**
@@ -702,6 +725,7 @@ void evutil_secure_rng_get_bytes(void *buf, size_t n);
  * whatever), and you want to make sure that seeding happens before your
  * program loses the ability to do it.
  */
+EVENT2_EXPORT_SYMBOL
 int evutil_secure_rng_init(void);
 
 /**
@@ -717,6 +741,7 @@ int evutil_secure_rng_init(void);
  *
  * This API is unstable, and might change in a future libevent version.
  */
+EVENT2_EXPORT_SYMBOL
 int evutil_secure_rng_set_urandom_device_file(char *fname);
 
 /** Seed the random number generator with extra random bytes.
@@ -733,6 +758,7 @@ int evutil_secure_rng_set_urandom_device_file(char *fname);
     @param dat a buffer full of a strong source of random numbers
     @param datlen the number of bytes to read from datlen
  */
+EVENT2_EXPORT_SYMBOL
 void evutil_secure_rng_add_bytes(const char *dat, size_t datlen);
 
 #ifdef __cplusplus
diff --git a/include/event2/visibility.h b/include/event2/visibility.h
new file mode 100644
index 00000000..5e7163a1
--- /dev/null
+++ b/include/event2/visibility.h
@@ -0,0 +1,55 @@
+/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef EVENT2_VISIBILITY_H_INCLUDED_
+#define EVENT2_VISIBILITY_H_INCLUDED_
+
+#include <event2/event-config.h>
+
+#if defined(event_EXPORTS) || defined(event_extra_EXPORTS) || defined(event_core_EXPORTS)
+
+#if defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550)
+#define EVENT2_EXPORT_SYMBOL __global
+#elif defined __GNUC__
+#define EVENT2_EXPORT_SYMBOL __attribute__ ((visibility("default")))
+#elif defined(_MSC_VER)
+#define EVENT2_EXPORT_SYMBOL extern __declspec(dllexport)
+#else
+/* unknown compiler */
+#define EVENT2_EXPORT_SYMBOL
+#endif
+
+#else
+
+#if defined(EVENT__NEED_DLLIMPORT) && defined(_MSC_VER) && !defined(EVENT_BUILDING_REGRESS_TEST)
+#define EVENT2_EXPORT_SYMBOL extern __declspec(dllimport)
+#else
+#define EVENT2_EXPORT_SYMBOL
+#endif
+
+#endif
+
+#endif /* EVENT2_VISIBILITY_H_INCLUDED_ */
diff --git a/include/include.am b/include/include.am
index 5d2012eb..9aad2dba 100644
--- a/include/include.am
+++ b/include/include.am
@@ -30,7 +30,8 @@ EVENT2_EXPORT = \
 	include/event2/tag.h \
 	include/event2/tag_compat.h \
 	include/event2/thread.h \
-	include/event2/util.h
+	include/event2/util.h \
+	include/event2/visibility.h
 
 ## Without the nobase_ prefixing, Automake would strip "include/event2/" from
 ## the source header filename to derive the installed header filename.
diff --git a/util-internal.h b/util-internal.h
index 0ab8a257..5866dbc5 100644
--- a/util-internal.h
+++ b/util-internal.h
@@ -443,6 +443,9 @@ HANDLE evutil_load_windows_system_library_(const TCHAR *library_name);
 evutil_socket_t evutil_socket_(int domain, int type, int protocol);
 evutil_socket_t evutil_accept4_(evutil_socket_t sockfd, struct sockaddr *addr,
     ev_socklen_t *addrlen, int flags);
+
+    /* used by one of the test programs.. */
+EVENT2_EXPORT_SYMBOL
 int evutil_make_internal_pipe_(evutil_socket_t fd[2]);
 evutil_socket_t evutil_eventfd_(unsigned initval, int flags);
 
-- 
2.40.0