23f07566a6ac41c26bf2bc7ccee8f5e2bdf5b17d
[gnulib.git] / doc / visibility.texi
1 @c Documentation of gnulib module 'visibility'.
2
3 This module allows precise control of the symbols exported by a shared
4 library.  This is useful because
5
6 @itemize @bullet
7 @item
8 It prevents abuse of undocumented APIs of your library. Symbols that
9 are not exported from the library cannot be used. This eliminates the
10 problem that when the maintainer of the library changes internals of the
11 library, maintainers of other projects cry "breakage". Instead, these
12 maintainers are forced to negotiate the desired API from the maintainer
13 of the library.
14
15 @item
16 It reduces the risk of symbol collision between your library and other
17 libraries. For example, the symbol @samp{readline} is defined in several
18 libraries, most of which don't have the same semantics and the same calling
19 convention as the GNU readline library.
20
21 @item
22 It reduces the startup time of programs linked to the library. This is
23 because the dynamic loader has less symbols to process.
24
25 @item
26 It allows the compiler to generate better code. Within a shared library,
27 a call to a function that is a global symbol costs a "call" instruction
28 to a code location in the so-called PLT (procedure linkage table) which
29 contains a "jump" instruction to the actual function's code. (This is
30 needed so that the function can be overridden, for example by a function
31 with the same name in the executable or in a shared library interposed
32 with @code{LD_PRELOAD}.) Whereas a call to a function for which the compiler
33 can assume that it is in the same shared library is just a direct "call"
34 instructions. Similarly for variables: A reference to a global variable
35 fetches a pointer in the so-called GOT (global offset table); this pointer
36 pointer to the variable's memory. So the code to access it is two memory
37 load instructions. Whereas for a variable which is known to reside in the
38 same shared library, it is just a direct memory access: one memory load
39 instruction.
40 @end itemize
41
42 There are traditionally three ways to specify the exported symbols of a
43 shared library.
44
45 @itemize @bullet
46 @item
47 The programmer specifies the list of symbols to be exported when the
48 shared library is created. Usually a command-line option is passed
49 to the linker, with the name of a file containing the symbols.
50
51 The upside of this approach is flexibility: it allows the same code to
52 be used in different libraries with different export lists. The downsides
53 are: 1. it's a lot of maintenance overhead when the symbol list is platform
54 dependent, 2. it doesn't work well with C++, due to name mangling.
55
56 @item
57 The programmer specifies a "hidden" attribute for every variable and
58 function that shall not be exported.
59
60 The drawbacks of this approach are: Symbols are still exported from
61 the library by default. It's a lot of maintenance work to mark every non-
62 exported variable and function. But usually the exported API is quite small,
63 compared to the internal API of the library. And it's the wrong paradigm:
64 It doesn't force thinking when introducing new exported API.
65
66 @item
67 The programmer specifies a "hidden" attribute for all files that make up
68 the shared library, and an "exported" attribute for those symbols in these
69 files that shall be exported.
70
71 This is perfect: It burdens the maintainer only for exported API, not
72 for library-internal API. And it keeps the annotations in the source code.
73 @end itemize
74
75 This gnulib module implements the third approach. For this it relies on
76 GNU GCC 4.0 or newer, namely on its @samp{-fvisibility=hidden} command-line
77 option and the "visibility" attribute. (The "visibility" attribute
78 was already supported in GCC 3.4, but without the command line option,
79 introduced in GCC 4.0, the third approach could not be used.)
80
81 More explanations on this subject can be found in
82 @url{http://gcc.gnu.org/wiki/Visibility} - which contains more details
83 on the GCC features and additional advice for C++ libraries - and in
84 Ulrich Drepper's paper @url{http://people.redhat.com/drepper/dsohowto.pdf}
85 - which also explains other tricks for reducing the startup time impact
86 of shared libraries.
87
88 The gnulib autoconf macro @code{gl_VISIBILITY} tests for GCC 4.0 or newer.
89 It defines a Makefile variable @code{@@CFLAG_VISIBILITY@@} containing
90 @samp{-fvisibility=hidden} or nothing. It also defines as a C macro and
91 as a Makefile variable: @@HAVE_VISIBILITY@@. Its value is 1 when symbol
92 visibility control is supported, and 0 otherwise.
93
94 To use this module in a library, say libfoo, you will do these steps:
95
96 @enumerate
97 @item
98 Add @code{@@CFLAG_VISIBILITY@@} or (in a Makefile.am)
99 @code{$(CFLAG_VISIBILITY)} to the CFLAGS for the compilation of the sources
100 that make up the library.
101
102 @item
103 Add a C macro definition, say @samp{-DBUILDING_LIBFOO}, to the CPPFLAGS
104 for the compilation of the sources that make up the library.
105
106 @item
107 Define a macro specific to your library like this.
108 @smallexample
109 #if @@HAVE_VISIBILITY@@ && BUILDING_LIBFOO
110 #define LIBFOO_DLL_EXPORTED __attribute__((__visibility__("default")))
111 #else
112 #define LIBFOO_DLL_EXPORTED
113 #endif
114 @end smallexample
115 This macro should be enabled in all public header files of your library.
116
117 @item
118 Annotate all variable, function and class declarations in all public header
119 files of your library with @samp{LIBFOO_DLL_EXPORTED}. This annotation
120 can occur at different locations: between the @samp{extern} and the
121 type or return type, or just before the entity being declared, or after
122 the entire declarator. My preference is to put it right after @samp{extern},
123 so that the declarations in the header files remain halfway readable.
124 @end enumerate
125
126 Note that the precise control of the exported symbols will not work with
127 other compilers than GCC >= 4.0, and will not work on systems where the
128 assembler or linker lack the support of "hidden" visibility. Therefore,
129 it's good if, in order to reduce the risk of collisions with symbols in
130 other libraries, you continue to use a prefix specific to your library
131 for all non-static variables and functions and for all C++ classes in
132 your library.
133
134 Note about other compilers: MSVC support can be added easily, by extending
135 the definition of the macro mentioned above, to something like this:
136 @smallexample
137 #if @@HAVE_VISIBILITY@@ && BUILDING_LIBFOO
138 #define LIBFOO_DLL_EXPORTED __attribute__((__visibility__("default")))
139 #elif defined _MSC_VER && BUILDING_LIBFOO
140 #define LIBFOO_DLL_EXPORTED __declspec(dllexport)
141 #elif defined _MSC_VER
142 #define LIBFOO_DLL_EXPORTED __declspec(dllimport)
143 #else
144 #define LIBFOO_DLL_EXPORTED
145 #endif
146 @end smallexample