[build] Improve visibility support of library function names. * include/freetype/config/public-macros.h (FT_PUBLIC_FUNCTION_ATTRIBUTE): New macro to tag functions as public (and thus exportable). (FT_EXPORT): Use it. * include/freetype/config/compiler-macros.h (FT_INTERNAL_FUNCTION_ATTRIBUTE): New macro to tag functions as internal to the library (and thus hidden). Note that on ELF systems, all internal functions have hidden visibility, which avoids the need to enforce this when invoking the compiler (e.g., with an option like `-fvisibility=hidden'). (FT_FUNCTION_DECLARATION, FT_FUNCTION_DEFINITION): New base macros to deal with C and C++ linkage issues at the same time. (FT_LOCAL, FT_LOCAL_DEF, FT_LOCAL_ARRAY, FT_LOCAL_ARRAY_DEF, FT_BASE, FT_BASE_DEF, FT_EXPORT_VAR, FT_BASE_CALLBACK, FT_BASE_CALLBACK_DEF): Redefined using new macros.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397
diff --git a/ChangeLog b/ChangeLog
index a2c80f5..2b3bb3a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,28 @@
2020-07-05 David Turner <david@freetype.org>
+ [build] Improve visibility support of library function names.
+
+ * include/freetype/config/public-macros.h
+ (FT_PUBLIC_FUNCTION_ATTRIBUTE): New macro to tag functions as
+ public (and thus exportable).
+ (FT_EXPORT): Use it.
+
+ * include/freetype/config/compiler-macros.h
+ (FT_INTERNAL_FUNCTION_ATTRIBUTE): New macro to tag functions as
+ internal to the library (and thus hidden). Note that on ELF
+ systems, all internal functions have hidden visibility, which avoids
+ the need to enforce this when invoking the compiler (e.g., with an
+ option like `-fvisibility=hidden').
+
+ (FT_FUNCTION_DECLARATION, FT_FUNCTION_DEFINITION): New base macros
+ to deal with C and C++ linkage issues at the same time.
+
+ (FT_LOCAL, FT_LOCAL_DEF, FT_LOCAL_ARRAY, FT_LOCAL_ARRAY_DEF,
+ FT_BASE, FT_BASE_DEF, FT_EXPORT_VAR, FT_BASE_CALLBACK,
+ FT_BASE_CALLBACK_DEF): Redefined using new macros.
+
+2020-07-05 David Turner <david@freetype.org>
+
[build] Split off more stuff from `ftconfig.h'.
* builds/unix/ftconfig.h.in, builds/vms/ftconfig.h,
diff --git a/include/freetype/config/public-macros.h b/include/freetype/config/public-macros.h
index b62092b..b1fa0f2 100644
--- a/include/freetype/config/public-macros.h
+++ b/include/freetype/config/public-macros.h
@@ -49,39 +49,42 @@
FT_BEGIN_HEADER
-/* Define a public FreeType API function. This ensures it is properly exported
- * or imported at build time.
+/* Mark a function declaration as public. This ensures it will be properly
+ * exported to client code. Place this before a function declaration.
+ *
+ * NOTE: This macro should be considered an internal implementation detail, and
+ * not part of the FreeType API. It is only defined here because it is needed
+ * by FT_EXPORT()
*/
-#ifndef FT_EXPORT
-
-#ifdef FT2_BUILD_LIBRARY
-
-#if defined( _WIN32 ) && defined( DLL_EXPORT )
-#define FT_EXPORT( x ) __declspec( dllexport ) x
-#elif defined( __GNUC__ ) && __GNUC__ >= 4
-#define FT_EXPORT( x ) __attribute__(( visibility( "default" ) )) x
-#elif defined( __SUNPRO_C ) && __SUNPRO_C >= 0x550
-#define FT_EXPORT( x ) __global x
-#elif defined( __cplusplus )
-#define FT_EXPORT( x ) extern "C" x
-#else
-#define FT_EXPORT( x ) extern x
+#if defined(_WIN32)
+# if defined(FT2_BUILD_LIBRARY) && defined( DLL_EXPORT )
+# define FT_PUBLIC_FUNCTION_ATTRIBUTE __declspec( dllexport )
+# elif defined( DLL_IMPORT )
+# define FT_PUBLIC_FUNCTION_ATTRIBUTE __declspec( dllimport )
+# endif
+#elif (defined(__GNUC__) && __GNUC__ >= 4) || defined(__clang__)
+# define FT_PUBLIC_FUNCTION_ATTRIBUTE __attribute__((visibility("default")))
+#elif defined(__SUNPRO_C) && __SUNPRO_C >= 0x550
+# define FT_PUBLIC_FUNCTION_ATTRIBUTE __global
#endif
-#else /* !FT2_BUILD_LIBRARY */
+#ifndef FT_PUBLIC_FUNCTION_ATTRIBUTE
+# define FT_PUBLIC_FUNCTION_ATTRIBUTE /* nothing */
+#endif
-#if defined( _WIN32 ) && defined( DLL_IMPORT )
-#define FT_EXPORT( x ) __declspec( dllimport ) x
-#elif defined( __cplusplus )
-#define FT_EXPORT( x ) extern "C" x
+/* Define a public FreeType API function. This ensures it is properly exported
+ * or imported at build time. The macro parameter is the function's return type
+ * as in:
+ *
+ * FT_EXPORT( FT_Bool ) FT_Object_Method( FT_Object obj, ... );
+ *
+ */
+#ifdef __cplusplus
+#define FT_EXPORT( x ) FT_PUBLIC_FUNCTION_ATTRIBUTE extern "C" x
#else
-#define FT_EXPORT( x ) extern x
+#define FT_EXPORT( x ) FT_PUBLIC_FUNCTION_ATTRIBUTE extern x
#endif
-#endif /* !FT2_BUILD_LIBRARY */
-
-#endif /* !FT_EXPORT */
-
FT_END_HEADER
#endif /* FREETYPE_CONFIG_PUBLIC_MACROS_H_ */
diff --git a/include/freetype/internal/compiler-macros.h b/include/freetype/internal/compiler-macros.h
index d7b6cfa..1f432bc 100644
--- a/include/freetype/internal/compiler-macros.h
+++ b/include/freetype/internal/compiler-macros.h
@@ -22,42 +22,70 @@
FT_BEGIN_HEADER
+ /* Fix compiler warning with sgi compiler. */
+#if defined( __sgi ) && !defined( __GNUC__ )
+# if defined( _COMPILER_VERSION ) && ( _COMPILER_VERSION >= 730 )
+# pragma set woff 3505
+# endif
+#endif
+
/* `FT_UNUSED` indicates that a given parameter is not used -- */
/* this is only used to get rid of unpleasant compiler warnings. */
#ifndef FT_UNUSED
#define FT_UNUSED( arg ) ( (arg) = (arg) )
#endif
-
/* Fix compiler warning with sgi compiler. */
#if defined( __sgi ) && !defined( __GNUC__ )
-#if defined( _COMPILER_VERSION ) && ( _COMPILER_VERSION >= 730 )
-#pragma set woff 3505
-#endif
+# if defined( _COMPILER_VERSION ) && ( _COMPILER_VERSION >= 730 )
+# pragma set woff 3505
+# endif
#endif
+/* When defining a macro that expands to a non-trivial C statement, use
+ * FT_BEGIN_STMNT and FT_END_STMNT to enclose the macro's body. This ensures
+ * there are no surprises when the macro is invoked in conditional branches.
+ *
+ * E.g.:
+ * #define LOG(...) \
+ * FT_BEGIN_STMNT \
+ * if (logging_enabled) \
+ * log(__VA_ARGS__); \
+ * FT_END_STMNT
+ */
+#define FT_BEGIN_STMNT do {
+#define FT_END_STMNT } while ( 0 )
+
+/* FT_DUMMY_STMNT expands to an empty C statement. Useful for conditionally
+ * define statement macros, as in:
+ *
+ * #ifdef BUILD_CONFIG_LOGGING
+ * # define LOG(...) \
+ * FT_BEGIN_STMNT \
+ * if (logging_enabled) \
+ * log(__VA_ARGS__); \
+ * FT_END_STMNT
+ * #else
+ * # define LOG(...) FT_DUMMY_STMNT
+ * #endif
+ */
+#define FT_DUMMY_STMNT FT_BEGIN_STMNT FT_END_STMNT
+
#ifdef _WIN64
- /* only 64bit Windows uses the LLP64 data model, i.e., */
- /* 32bit integers, 64bit pointers */
+ /* only 64bit Windows uses the LLP64 data model, i.e., */
+ /* 32-bit integers, 64-bit pointers. */
#define FT_UINT_TO_POINTER( x ) (void*)(unsigned __int64)(x)
#else
#define FT_UINT_TO_POINTER( x ) (void*)(unsigned long)(x)
#endif
-
- /**************************************************************************
- *
- * miscellaneous
- *
- */
-
-
-#define FT_BEGIN_STMNT do {
-#define FT_END_STMNT } while ( 0 )
-#define FT_DUMMY_STMNT FT_BEGIN_STMNT FT_END_STMNT
-
-
- /* `typeof` condition taken from gnulib's `intprops.h` header file */
+/* Use FT_TYPEOF(type) to cast a value to |type|. This is useful to suppress
+ * signedness compilation warnings in macros as in:
+ *
+ * #define PAD_(x, n) ( (x) & ~FT_TYPEOF( x )( (n) - 1 ) )
+ *
+ * `typeof` condition taken from gnulib's `intprops.h` header file
+ */
#if ( ( defined( __GNUC__ ) && __GNUC__ >= 2 ) || \
( defined( __IBMC__ ) && __IBMC__ >= 1210 && \
defined( __IBM__TYPEOF__ ) ) || \
@@ -67,63 +95,97 @@ FT_BEGIN_HEADER
#define FT_TYPEOF( type ) /* empty */
#endif
+/* Mark a function declaration as internal to the library. This ensures that
+ * it will not be exposed by default to client code, and helps generate smaller
+ * and faster code on ELF-based platforms. Place this before a function
+ * declaration.
+ */
+#if (defined(__GNUC__) && __GNUC__ >= 4) || defined(__clang__)
+#define FT_INTERNAL_FUNCTION_ATTRIBUTE __attribute__((visibility("hidden")))
+#else
+#define FT_INTERNAL_FUNCTION_ATTRIBUTE /* nothing */
+#endif
- /* Use `FT_LOCAL` and `FT_LOCAL_DEF` to declare and define, */
- /* respectively, a function that gets used only within the scope of a */
- /* module. Normally, both the header and source code files for such a */
- /* function are within a single module directory. */
- /* */
- /* Intra-module arrays should be tagged with `FT_LOCAL_ARRAY` and */
- /* `FT_LOCAL_ARRAY_DEF`. */
- /* */
-#ifdef FT_MAKE_OPTION_SINGLE_OBJECT
-
-#define FT_LOCAL( x ) static x
-#define FT_LOCAL_DEF( x ) static x
+/* FreeType supports compiling its C sources to be compiled as C++ instead,
+ * this introduces a number of subtle issues.
+ *
+ * The main one is that a C++ function declaration and its definition must have
+ * the same 'linkage'. Because all FreeType headers declare their function with
+ * C linkage (i.e. within an extern "C" { .. } block, due to the magic of
+ * FT_BEGIN_HEADER and FT_END_HEADER), then their definition in FreeType
+ * sources should also be prefixed with 'extern "C"' when compiled in C++ mode.
+ *
+ * The FT_FUNCTION_DECLARATION() and FT_FUNCTION_DEFINITION() macros are
+ * provided to deal with this case, as well as FT_CALLBACK_DEF et al below.
+ */
+/* FT_FUNCTION_DECLARATION(type) can be used to write a C function declaration,
+ * and ensure it will have C linkage when the library is built with a C++
+ * compiler. The parameter is the function's return type, so a declaration
+ * would look like:
+ *
+ * FT_FUNCTION_DECLARATION(int) foo(int x);
+ *
+ * NOTE: Technically, all FreeType headers put their function declarations
+ * inside an extern "C" block, giving them C linkage. This means that using
+ * this macro is only necessary within internal source files, but using it in
+ * a header will be harmless.
+ *
+ * NOTE: Do not use directly, use FT_LOCAL()/FT_BASE()/FT_EXPORT() instead.
+ */
+#ifdef __cplusplus
+#define FT_FUNCTION_DECLARATION( x ) extern "C" x
#else
+#define FT_FUNCTION_DECLARATION( x ) extern x
+#endif
+/* Same as FT_FUNCTION_DECLARATION(), but for function definitions instead.
+ * NOTE: Do not use directly, use FT_LOCAL_DEF()/FT_BASE_DEF()/FT_EXPORT_DEF()
+ * instead.
+ */
#ifdef __cplusplus
-#define FT_LOCAL( x ) extern "C" x
-#define FT_LOCAL_DEF( x ) extern "C" x
+#define FT_FUNCTION_DEFINITION( x ) extern "C" x
#else
-#define FT_LOCAL( x ) extern x
-#define FT_LOCAL_DEF( x ) x
+#define FT_FUNCTION_DEFINITION( x ) x
#endif
-#endif /* FT_MAKE_OPTION_SINGLE_OBJECT */
-
-#define FT_LOCAL_ARRAY( x ) extern const x
-#define FT_LOCAL_ARRAY_DEF( x ) const x
-
+/* Use FT_LOCAL()/FT_LOCAL_DEF() to declare and define an internal FreeType
+ * function that is only used by the sources of a single src/module/ directory.
+ * This ensures the functions are turned into static ones at build time,
+ * resulting in smaller and faster code.
+ */
+#ifdef FT_MAKE_OPTION_SINGLE_OBJECT
- /* Use `FT_BASE` and `FT_BASE_DEF` to declare and define, respectively, */
- /* functions that are used in more than a single module. In the */
- /* current setup this implies that the declaration is in a header file */
- /* in the `include/freetype/internal` directory, and the function body */
- /* is in a file in `src/base`. */
- /* */
-#ifndef FT_BASE
+# define FT_LOCAL( x ) static x
+# define FT_LOCAL_DEF( x ) static x
-#ifdef __cplusplus
-#define FT_BASE( x ) extern "C" x
#else
-#define FT_BASE( x ) extern x
-#endif
-#endif /* !FT_BASE */
+#define FT_LOCAL( x ) FT_INTERNAL_FUNCTION_ATTRIBUTE FT_FUNCTION_DECLARATION( x )
+#define FT_LOCAL_DEF( x ) FT_FUNCTION_DEFINITION( x )
+#endif /* FT_MAKE_OPTION_SINGLE_OBJECT */
-#ifndef FT_BASE_DEF
+/* Use FT_LOCAL_ARRAY()/FT_LOCAL_ARRAY_DEF() to declare and define a constant
+ * array that must be accessed from several sources in the same src/module/
+ * sub-directory, but are otherwise internal to the library.
+ */
+#define FT_LOCAL_ARRAY( x ) FT_INTERNAL_FUNCTION_ATTRIBUTE extern const x
+#define FT_LOCAL_ARRAY_DEF( x ) const x
-#ifdef __cplusplus
-#define FT_BASE_DEF( x ) x
-#else
-#define FT_BASE_DEF( x ) x
-#endif
+/* Use FT_BASE()/FT_BASE_DEF() to declare or define an internal library
+ * function that are used by more than one single module.
+ */
+#define FT_BASE( x ) FT_INTERNAL_FUNCTION_ATTRIBUTE FT_FUNCTION_DECLARATION( x )
+#define FT_BASE_DEF( x ) FT_FUNCTION_DEFINITION( x )
-#endif /* !FT_BASE_DEF */
+/* NOTE: Conditionally define FT_EXPORT_VAR() due to its definition in
+ * src/smooth/ftgrays.h to make the header more portable.
+ */
+#ifndef FT_EXPORT_VAR
+#define FT_EXPORT_VAR( x ) FT_FUNCTION_DECLARATION( x )
+#endif
/* When compiling FreeType as a DLL or DSO with hidden visibility */
/* some systems/compilers need a special attribute in front OR after */
@@ -160,29 +222,8 @@ FT_BEGIN_HEADER
/* To export a variable, use `FT_EXPORT_VAR`. */
/* */
-/* NOTE: See <freetype/config/public-macros.h> for FT_EXPORT() definition */
-
-#ifndef FT_EXPORT_DEF
-
-#ifdef __cplusplus
-#define FT_EXPORT_DEF( x ) extern "C" x
-#else
-#define FT_EXPORT_DEF( x ) extern x
-#endif
-
-#endif /* !FT_EXPORT_DEF */
-
-
-#ifndef FT_EXPORT_VAR
-
-#ifdef __cplusplus
-#define FT_EXPORT_VAR( x ) extern "C" x
-#else
-#define FT_EXPORT_VAR( x ) extern x
-#endif
-
-#endif /* !FT_EXPORT_VAR */
-
+/* See <freetype/config/compiler_macros.h> for the FT_EXPORT() definition */
+#define FT_EXPORT_DEF( x ) FT_FUNCTION_DEFINITION( x )
/* The following macros are needed to compile the library with a */
/* C++ compiler and with 16bit compilers. */
@@ -213,23 +254,14 @@ FT_BEGIN_HEADER
/* Some 16bit compilers have to redefine these macros to insert */
/* the infamous `_cdecl` or `__fastcall` declarations. */
/* */
-#ifndef FT_CALLBACK_DEF
#ifdef __cplusplus
#define FT_CALLBACK_DEF( x ) extern "C" x
#else
#define FT_CALLBACK_DEF( x ) static x
#endif
-#endif /* FT_CALLBACK_DEF */
-#ifndef FT_BASE_CALLBACK
-#ifdef __cplusplus
-#define FT_BASE_CALLBACK( x ) extern "C" x
-#define FT_BASE_CALLBACK_DEF( x ) extern "C" x
-#else
-#define FT_BASE_CALLBACK( x ) extern x
-#define FT_BASE_CALLBACK_DEF( x ) x
-#endif
-#endif /* FT_BASE_CALLBACK */
+#define FT_BASE_CALLBACK( x ) FT_FUNCTION_DECLARATION( x )
+#define FT_BASE_CALLBACK_DEF( x ) FT_FUNCTION_DEFINITION( x )
#ifndef FT_CALLBACK_TABLE
#ifdef __cplusplus