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