BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bsls_linkcoercion.h
Go to the documentation of this file.
1/// @file bsls_linkcoercion.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bsls_linkcoercion.h -*-C++-*-
8#ifndef INCLUDED_BSLS_LINKCOERCION
9#define INCLUDED_BSLS_LINKCOERCION
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bsls_linkcoercion bsls_linkcoercion
15/// @brief Provide a way to force a link-time dependency into an object.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bsls
19/// @{
20/// @addtogroup bsls_linkcoercion
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bsls_linkcoercion-purpose"> Purpose</a>
25/// * <a href="#bsls_linkcoercion-macros"> Macros </a>
26/// * <a href="#bsls_linkcoercion-description"> Description </a>
27/// * <a href="#bsls_linkcoercion-macro-summary"> Macro Summary </a>
28/// * <a href="#bsls_linkcoercion-link-coercion-mechanism"> Link coercion mechanism </a>
29/// * <a href="#bsls_linkcoercion-linker-garbage-collection"> Linker garbage collection </a>
30/// * <a href="#bsls_linkcoercion-usage"> Usage </a>
31/// * <a href="#bsls_linkcoercion-example-1-prevent-linking-debug-and-optimized-translation-units"> Example 1: Prevent Linking Debug and Optimized Translation Units </a>
32///
33/// # Purpose {#bsls_linkcoercion-purpose}
34/// Provide a way to force a link-time dependency into an object.
35///
36/// # Macros {#bsls_linkcoercion-macros}
37///
38/// - BSLS_LINKCOERCION_FORCE_SYMBOL_DEPENDENCY
39///
40/// # Description {#bsls_linkcoercion-description}
41/// This component provides a facility to force a link-time
42/// dependency on a symbol of the name supplied to the macro into the
43/// translation unit being compiled. This macro can be useful for generating
44/// link-time failures if a library version mismatch occurs.
45///
46/// ## Macro Summary {#bsls_linkcoercion-macro-summary}
47///
48///
49/// This section provides a brief description of the macros defined in this
50/// component.
51/// @code
52/// BSLS_LINKCOERCION_FORCE_SYMBOL_DEPENDENCY(type, refName, referredSymbol);
53/// Force a link-time dependency into an object by creating a "symbol" (a
54/// static variable with external linkage) having specified 'type'
55/// (typically 'const char *'), the specified 'name' (which should be
56/// unique), and that will be given the value of the address of the
57/// specified 'referredSymbol'.
58/// @endcode
59/// Notice that this macro is typically used to prevent to binary incompatible
60/// object files from being successfully linked together. This is achieved by
61/// calling this macro in a way that `referredSymbol` will have a different
62/// symbol name for incompatible builds.
63///
64/// ## Link coercion mechanism {#bsls_linkcoercion-link-coercion-mechanism}
65///
66///
67/// Link-time coersion is implemented by creating a static variable that
68/// references an external symbol defined by the library. The actual name of
69/// this external symbol should be different for different build flavors. When
70/// the executable is linked against the libraries with link-coercion symbols,
71/// the linker needs to resolve the symbol name and will fail the link step if
72/// the required symbol name is not present in the linked library (i.e. the
73/// library was built with a different set of flags that control the coercion
74/// symbol creation). For example, we can create different coercion symbols for
75/// code built with c++17 and c++20 flags, effectively preventing translation
76/// units compiled with different c++ standard flags from being linked into an
77/// working program.
78///
79/// ## Linker garbage collection {#bsls_linkcoercion-linker-garbage-collection}
80///
81///
82/// Modern linkers may implement link-time garbage collection. In order to
83/// minimize the size of the final executable the linker can remove sections of
84/// object files that are not referenced anywhere from the code being linked.
85/// Unfortunately, the link coercion symbols are not referenced directly and may
86/// be garbage collected and, if removed, lead to a silent failure and
87/// successful linkage of a potentially binary incompatible executable. To
88/// avoid such a failure, coercion symbols are placed in the dedicated data
89/// section (if supported by the compiler) and this section is marked in-use to
90/// avoid it being garbage collected by the linker.
91///
92/// More information on details on linker garbage collection can be found here:
93/// https://maskray.me/blog/2021-02-28-linker-garbage-collection
94///
95/// ## Usage {#bsls_linkcoercion-usage}
96///
97///
98/// In this section we show intended use of this component.
99///
100/// ### Example 1: Prevent Linking Debug and Optimized Translation Units {#bsls_linkcoercion-example-1-prevent-linking-debug-and-optimized-translation-units}
101///
102///
103/// In this example we use a link coercion symbol to prevent linking a
104/// translation unit built against the header in debug mode, with a translation
105/// unit built against the header in optimized mode.
106///
107/// First we define a macro such that our symbol name will be different for
108/// debug and optimized builds of our library:
109/// @code
110/// mylib_safecompile.h
111/// #ifdef NDEBUG
112/// #define MYLIB_DEBUG_SYMBOL_NAME mylib_BuiltWithNDebugMode
113/// #else
114/// #define MYLIB_DEBUG_SYMBOL_NAME mylib_BuiltWithoutNDebugMode
115/// #endif
116/// @endcode
117/// Now we use the `BSLS_LINKCOERCION_FORCE_SYMBOL_DEPENDENCY` macro to require
118/// translation units to link against a library having a matching symbol name:
119/// @code
120/// extern const char* MYLIB_DEBUG_SYMBOL_NAME;
121/// BSLS_LINKCOERCION_FORCE_SYMBOL_DEPENDENCY(const char *,
122/// mylib_coercebasedondebugmode,
123/// MYLIB_DEBUG_SYMBOL_NAME )
124/// @endcode
125/// Note that the referred symbol will have a different name depending on
126/// whether `NDEBUG` is defined or not.
127///
128/// Finally, in the corresponding `.cpp` file we must define the appropriate
129/// symbol name for the library:
130/// @code
131/// mylib_safecompile.cpp
132/// const char *MYLIB_DEBUG_SYMBOL_NAME = "debug compatibility check: "
133/// #MYLIB_DEBUG_SYMBOL_NAME;
134/// @endcode
135/// @}
136/** @} */
137/** @} */
138
139/** @addtogroup bsl
140 * @{
141 */
142/** @addtogroup bsls
143 * @{
144 */
145/** @addtogroup bsls_linkcoercion
146 * @{
147 */
148
149#include <bsls_platform.h>
150
151
152
153#if defined(BSLS_PLATFORM_OS_LINUX)
154 // Note: we cannot detect the version of the binutils here, so we
155 // tie those specific attributes to the version of the compilers that
156 // should support them.
157 // Please see the "Linker garbage collection" section for details.
158 #if (defined(BSLS_PLATFORM_CMP_GNU) \
159 && BSLS_PLATFORM_CMP_VERSION >= 110000) \
160 || (defined(BSLS_PLATFORM_CMP_CLANG) \
161 && BSLS_PLATFORM_CMP_VERSION >= 130000)
162 #define BSLS_LINKCOERCION_FORCE_SYMBOL_DEPENDENCY(type, \
163 refName, \
164 referredSymbol) \
165 _Pragma("GCC diagnostic push") \
166 _Pragma("GCC diagnostic ignored \"-Wattributes\"") \
167 static type *refName __attribute__((retain,used,section("coercion"))) \
168 = &referredSymbol; \
169 _Pragma("GCC diagnostic pop")
170 #else
171 #define BSLS_LINKCOERCION_FORCE_SYMBOL_DEPENDENCY(type, \
172 refName, \
173 referredSymbol) \
174 static type *refName __attribute__((used)) = &referredSymbol;
175 #endif
176
177#elif defined(BSLS_PLATFORM_OS_DARWIN)
178 #define BSLS_LINKCOERCION_FORCE_SYMBOL_DEPENDENCY(type, \
179 refName, \
180 referredSymbol) \
181 static type *refName __attribute__((used)) = &referredSymbol;
182#elif defined(BSLS_PLATFORM_CMP_IBM)
183 #define BSLS_LINKCOERCION_FORCE_SYMBOL_DEPENDENCY(type, \
184 refName, \
185 referredSymbol) \
186 static type *refName = &referredSymbol;
187#elif defined(BSLS_PLATFORM_CMP_SUN)
188 #define BSLS_LINKCOERCION_FORCE_SYMBOL_DEPENDENCY(type, \
189 refName, \
190 referredSymbol) \
191 type refName() __attribute__((weak)); \
192 type refName() { return referredSymbol; }
193#else
194 #define BSLS_LINKCOERCION_FORCE_SYMBOL_DEPENDENCY(type, \
195 refName, \
196 referredSymbol) \
197 namespace { \
198 extern type *const refName = &referredSymbol; \
199 }
200#endif
201
202
203
204#endif
205
206// ----------------------------------------------------------------------------
207// Copyright 2013 Bloomberg Finance L.P.
208//
209// Licensed under the Apache License, Version 2.0 (the "License");
210// you may not use this file except in compliance with the License.
211// You may obtain a copy of the License at
212//
213// http://www.apache.org/licenses/LICENSE-2.0
214//
215// Unless required by applicable law or agreed to in writing, software
216// distributed under the License is distributed on an "AS IS" BASIS,
217// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
218// See the License for the specific language governing permissions and
219// limitations under the License.
220// ----------------------------- END-OF-FILE ----------------------------------
221
222/** @} */
223/** @} */
224/** @} */
#define BSLS_IDENT(str)
Definition bsls_ident.h:195