Next: , Previous: , Up: Build Infrastructure Modules   [Contents][Index]

19.2 Controlling the Exported Symbols of Shared Libraries

The lib-symbol-visibility module allows precise control of the symbols exported by a shared library. This is useful because

There are traditionally three ways to specify the exported symbols of a shared library.

GNU libtool’s -export-symbols option implements the first approach. The script from Gnulib can help to produce the list of symbols.

This gnulib module implements the third approach. For this it relies on GNU GCC 4.0 or newer, namely on its ‘-fvisibility=hidden’ command-line option and the “visibility” attribute. (The “visibility” attribute was already supported in GCC 3.4, but without the command line option, introduced in GCC 4.0, the third approach could not be used.)

More explanations on this subject can be found in, which contains more details on the GCC features and additional advice for C++ libraries, and in Ulrich Drepper’s paper, which also explains other tricks for reducing the startup time impact of shared libraries.

The gnulib autoconf macro gl_VISIBILITY tests for GCC 4.0 or newer. It defines a Makefile variable @CFLAG_VISIBILITY@ containing ‘-fvisibility=hidden’ or nothing. It also defines as a C macro and as a substituted variable: @HAVE_VISIBILITY@. Its value is 1 when symbol visibility control is supported, and 0 otherwise.

As of 2022, symbol visibility control is supported on

It is not supported on

To use this module in a library, say libfoo, you will do these steps:

  1. Add @CFLAG_VISIBILITY@ or (in a $(CFLAG_VISIBILITY) to the CFLAGS for the compilation of the sources that make up the library.
  2. Add a C macro definition, say ‘-DBUILDING_LIBFOO’, to the CPPFLAGS for the compilation of the sources that make up the library.
  3. Define a macro specific to your library like this.
    # define LIBFOO_SHLIB_EXPORTED __attribute__((__visibility__("default")))

    This macro should be enabled in all public header files of your library.

  4. Annotate all variable, function and class declarations in all public header files of your library with ‘LIBFOO_SHLIB_EXPORTED’. This annotation can occur at different locations: between the ‘extern’ and the type or return type, or just before the entity being declared, or after the entire declarator. My preference is to put it right after ‘extern’, so that the declarations in the header files remain halfway readable.

Note that the precise control of the exported symbols will not work with other compilers than GCC >= 4.0, and will not work on systems where the assembler or linker lack the support of “hidden” visibility. Therefore, it’s good if, in order to reduce the risk of collisions with symbols in other libraries, you continue to use a prefix specific to your library for all non-static variables and functions and for all C++ classes in your library.

Note about other compilers: MSVC support can be added easily, by extending the definition of the macro mentioned above, to something like this:

# define LIBFOO_SHLIB_EXPORTED __attribute__((__visibility__("default")))
#elif (defined _WIN32 && !defined __CYGWIN__) && @BUILDING_SHARED@ && BUILDING_LIBFOO
# if defined DLL_EXPORT
#  define LIBFOO_SHLIB_EXPORTED __declspec(dllexport)
# else
# endif
#elif (defined _WIN32 && !defined __CYGWIN__) && @BUILDING_SHARED@
# define LIBFOO_SHLIB_EXPORTED __declspec(dllimport)

Here BUILDING_SHARED is an Autoconf variable that you have to define. It ought to evaluate to 1 in a build configured with ‘--enable-shared’, or to 0 in a build configured with ‘--disable-shared’. You may use the following ‘’ snippet:

  if test "$enable_shared" = yes; then

And DLL_EXPORT is defined by Libtool, on Windows platforms, when compiling for a shared library (called DLL under Windows). It is not defined when Libtool compiles an object file meant to be linked statically into some executable.

Next: LD Version Scripts, Previous: Searching for Libraries, Up: Build Infrastructure Modules   [Contents][Index]