shithub: freetype+ttf2subf

Download patch

ref: b0667d2d36fb134d48030b2a560eaaa37810d6ba
parent: bb66c8d8cf1eb86309273d7c53c44522d35941d4
author: David Turner <david@freetype.org>
date: Thu Jul 2 07:20:10 EDT 2020

[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.

git/fs: mount .git/fs: mount/attach disallowed
--- 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,
--- a/include/freetype/config/public-macros.h
+++ b/include/freetype/config/public-macros.h
@@ -49,38 +49,41 @@
 
 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
+#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
 
-#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
+#ifndef FT_PUBLIC_FUNCTION_ATTRIBUTE
+#  define FT_PUBLIC_FUNCTION_ATTRIBUTE  /* nothing */
 #endif
 
-#else  /* !FT2_BUILD_LIBRARY */
-
-#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
 
--- a/include/freetype/internal/compiler-macros.h
+++ b/include/freetype/internal/compiler-macros.h
@@ -22,6 +22,13 @@
 
 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
@@ -28,36 +35,57 @@
 #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
+#  if defined( _COMPILER_VERSION ) && ( _COMPILER_VERSION >= 730 )
+#    pragma set woff 3505
+#  endif
 #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,64 +95,98 @@
 #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
+/* 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.
+ */
 
-#define FT_LOCAL( x )      static  x
-#define FT_LOCAL_DEF( x )  static  x
-
+/* 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 */
+/* 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
 
-#define FT_LOCAL_ARRAY( x )      extern const  x
-#define FT_LOCAL_ARRAY_DEF( x )  const  x
+#  define FT_LOCAL( x )  static x
+#  define FT_LOCAL_DEF( x )  static x
 
+#else
 
-  /* 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 )      FT_INTERNAL_FUNCTION_ATTRIBUTE FT_FUNCTION_DECLARATION( x )
+#define FT_LOCAL_DEF( x )  FT_FUNCTION_DEFINITION( x )
 
-#ifdef __cplusplus
-#define FT_BASE( x )  extern "C"  x
-#else
-#define FT_BASE( x )  extern  x
-#endif
+#endif  /* FT_MAKE_OPTION_SINGLE_OBJECT */
 
-#endif /* !FT_BASE */
+/* 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
 
+/* 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 )
 
-#ifndef FT_BASE_DEF
 
-#ifdef __cplusplus
-#define FT_BASE_DEF( x )  x
-#else
-#define FT_BASE_DEF( x )  x
+/* 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
 
-#endif /* !FT_BASE_DEF */
-
-
   /* When compiling FreeType as a DLL or DSO with hidden visibility    */
   /* some systems/compilers need a special attribute in front OR after */
   /* the return type of function declarations.                         */
@@ -160,30 +222,9 @@
   /* To export a variable, use `FT_EXPORT_VAR`.                        */
   /*                                                                   */
 
-/* NOTE: See <freetype/config/public-macros.h> for FT_EXPORT() definition */
+/* See <freetype/config/compiler_macros.h> for the FT_EXPORT() definition */
+#define FT_EXPORT_DEF( x ) FT_FUNCTION_DEFINITION( x )
 
-#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 */
-
-
   /* The following macros are needed to compile the library with a   */
   /* C++ compiler and with 16bit compilers.                          */
   /*                                                                 */
@@ -213,23 +254,14 @@
   /* 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