c-strtof, c-strtod, c-strtold: Make multithread-safe.
[gnulib.git] / doc / lib-symbol-visibility.texi
blob6d835abc6688581f0551323e8401e22133e9e923
1 @node Exported Symbols of Shared Libraries
2 @section Controlling the Exported Symbols of Shared Libraries
4 @c Documentation of gnulib module 'lib-symbol-visibility'.
6 @c Copyright (C) 2005--2006, 2009--2024 Free Software Foundation, Inc.
8 @c Permission is granted to copy, distribute and/or modify this document
9 @c under the terms of the GNU Free Documentation License, Version 1.3 or
10 @c any later version published by the Free Software Foundation; with no
11 @c Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.  A
12 @c copy of the license is at <https://www.gnu.org/licenses/fdl-1.3.en.html>.
14 The @code{lib-symbol-visibility} module allows precise control of the
15 symbols exported by a shared library.  This is useful because
17 @itemize @bullet
18 @item
19 It prevents abuse of undocumented APIs of your library.  Symbols that
20 are not exported from the library cannot be used.  This eliminates the
21 problem that when the maintainer of the library changes internals of the
22 library, maintainers of other projects cry ``breakage''.  Instead, these
23 maintainers are forced to negotiate the desired API from the maintainer
24 of the library.
26 @item
27 It reduces the risk of symbol collision between your library and other
28 libraries.  For example, the symbol @samp{readline} is defined in several
29 libraries, most of which don't have the same semantics and the same calling
30 convention as the GNU readline library.
32 @item
33 It reduces the startup time of programs linked to the library.  This is
34 because the dynamic loader has less symbols to process.
36 @item
37 It allows the compiler to generate better code.  Within a shared library,
38 a call to a function that is a global symbol costs a ``call'' instruction
39 to a code location in the so-called PLT (procedure linkage table) which
40 contains a ``jump'' instruction to the actual function's code.  (This is
41 needed so that the function can be overridden, for example by a function
42 with the same name in the executable or in a shared library interposed
43 with @code{LD_PRELOAD}.) Whereas a call to a function for which the compiler
44 can assume that it is in the same shared library is just a direct ``call''
45 instructions.  Similarly for variables: A reference to a global variable
46 fetches a pointer in the so-called GOT (global offset table); this is a
47 pointer to the variable's memory.  So the code to access it is two memory
48 load instructions.  Whereas for a variable which is known to reside in the
49 same shared library, it is just a direct memory access: one memory load
50 instruction.
51 @end itemize
53 There are traditionally three ways to specify the exported symbols of a
54 shared library.
56 @itemize @bullet
57 @item
58 The programmer specifies the list of symbols to be exported when the
59 shared library is created.  Usually a command-line option is passed
60 to the linker, with the name of a file containing the symbols.
62 The upside of this approach is flexibility: it allows the same code to
63 be used in different libraries with different export lists.  The downsides
64 are: 1. it's a lot of maintenance overhead when the symbol list is platform
65 dependent, 2. it doesn't work well with C++, due to name mangling.
67 @item
68 The programmer specifies a ``hidden'' attribute for every variable and
69 function that shall not be exported.
71 The drawbacks of this approach are: Symbols are still exported from
72 the library by default.  It's a lot of maintenance work to mark every non-
73 exported variable and function.  But usually the exported API is quite small,
74 compared to the internal API of the library.  And it's the wrong paradigm:
75 It doesn't force thinking when introducing new exported API.
77 @item
78 The programmer specifies a ``hidden'' attribute for all files that make up
79 the shared library, and an ``exported'' attribute for those symbols in these
80 files that shall be exported.
82 This is perfect: It burdens the maintainer only for exported API, not
83 for library-internal API@.  And it keeps the annotations in the source code.
84 @end itemize
86 GNU libtool's @option{-export-symbols} option implements the first approach.
87 The script @code{declared.sh} from Gnulib can help to produce the list of
88 symbols.
90 This gnulib module implements the third approach.  For this it relies on
91 GNU GCC 4.0 or newer, namely on its @samp{-fvisibility=hidden} command-line
92 option and the ``visibility'' attribute.  (The ``visibility'' attribute
93 was already supported in GCC 3.4, but without the command line option,
94 introduced in GCC 4.0, the third approach could not be used.)
96 More explanations on this subject can be found in
97 @url{https://gcc.gnu.org/wiki/Visibility}, which contains more details
98 on the GCC features and additional advice for C++ libraries, and in
99 Ulrich Drepper's paper @url{https://www.akkadia.org/drepper/dsohowto.pdf},
100 which also explains other tricks for reducing the startup time impact
101 of shared libraries.
103 The gnulib autoconf macro @code{gl_VISIBILITY} tests for GCC 4.0 or newer.
104 It defines a Makefile variable @code{@@CFLAG_VISIBILITY@@} containing
105 @samp{-fvisibility=hidden} or nothing.  It also defines as a C macro and
106 as a substituted variable: @@HAVE_VISIBILITY@@.  Its value is 1 when symbol
107 visibility control is supported, and 0 otherwise.
109 As of 2022, symbol visibility control is supported on
110 @itemize @bullet
111 @item
112 ELF platforms (glibc, Linux, *BSD, Solaris) with GCC or clang,
113 @item
114 macOS,
115 @item
116 AIX with gcc or xlclang.
117 @end itemize
118 @noindent
119 It is not supported on
120 @itemize @bullet
121 @item
122 Other compilers on ELF platforms or AIX,
123 @item
124 Windows.
125 @end itemize
127 To use this module in a library, say libfoo, you will do these steps:
129 @enumerate
130 @item
131 Add @code{@@CFLAG_VISIBILITY@@} or (in a Makefile.am)
132 @code{$(CFLAG_VISIBILITY)} to the CFLAGS for the compilation of the sources
133 that make up the library.
135 @item
136 Add a C macro definition, say @samp{-DBUILDING_LIBFOO}, to the CPPFLAGS
137 for the compilation of the sources that make up the library.
139 @item
140 Define a macro specific to your library like this.
141 @smallexample
142 #if HAVE_VISIBILITY && BUILDING_LIBFOO
143 # define LIBFOO_SHLIB_EXPORTED __attribute__((__visibility__("default")))
144 #else
145 # define LIBFOO_SHLIB_EXPORTED
146 #endif
147 @end smallexample
148 This macro should be enabled in all public header files of your library.
150 @item
151 Annotate all variable, function and class declarations in all public header
152 files of your library with @samp{LIBFOO_SHLIB_EXPORTED}.  This annotation
153 can occur at different locations: between the @samp{extern} and the
154 type or return type, or just before the entity being declared, or after
155 the entire declarator.  My preference is to put it right after @samp{extern},
156 so that the declarations in the header files remain halfway readable.
157 @end enumerate
159 Note that the precise control of the exported symbols will not work with
160 other compilers than GCC >= 4.0, and will not work on systems where the
161 assembler or linker lack the support of ``hidden'' visibility.  Therefore,
162 it's good if, in order to reduce the risk of collisions with symbols in
163 other libraries, you continue to use a prefix specific to your library
164 for all non-static variables and functions and for all C++ classes in
165 your library.
167 Note about other compilers: MSVC support can be added easily, by extending
168 the definition of the macro mentioned above, to something like this:
169 @smallexample
170 #if HAVE_VISIBILITY && BUILDING_LIBFOO
171 # define LIBFOO_SHLIB_EXPORTED __attribute__((__visibility__("default")))
172 #elif (defined _WIN32 && !defined __CYGWIN__) && @@BUILDING_SHARED@@ && BUILDING_LIBFOO
173 # if defined DLL_EXPORT
174 #  define LIBFOO_SHLIB_EXPORTED __declspec(dllexport)
175 # else
176 #  define LIBFOO_SHLIB_EXPORTED
177 # endif
178 #elif (defined _WIN32 && !defined __CYGWIN__) && @@BUILDING_SHARED@@
179 # define LIBFOO_SHLIB_EXPORTED __declspec(dllimport)
180 #else
181 # define LIBFOO_SHLIB_EXPORTED
182 #endif
183 @end smallexample
184 @noindent
185 Here @code{BUILDING_SHARED} is an Autoconf variable that you have to define.
186 It ought to evaluate to 1 in a build configured with @samp{--enable-shared},
187 or to 0 in a build configured with @samp{--disable-shared}.
188 You may use the following @samp{configure.ac} snippet:
190 @smallexample
191   if test "$enable_shared" = yes; then
192     BUILDING_SHARED=1
193   else
194     BUILDING_SHARED=0
195   fi
196   AC_SUBST([BUILDING_SHARED])
197 @end smallexample
199 @noindent
200 And @code{DLL_EXPORT} is defined by Libtool, on Windows platforms, when
201 compiling for a shared library (called DLL under Windows).
202 It is not defined when Libtool compiles an object file meant to be linked
203 statically into some executable.