freetype-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[freetype2] master b0667d2 5/5: [build] Improve visibility support of li


From: Werner LEMBERG
Subject: [freetype2] master b0667d2 5/5: [build] Improve visibility support of library function names.
Date: Sun, 5 Jul 2020 05:24:59 -0400 (EDT)

branch: master
commit b0667d2d36fb134d48030b2a560eaaa37810d6ba
Author: David Turner <david@freetype.org>
Commit: Werner Lemberg <wl@gnu.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.
---
 ChangeLog                                   |  23 +++
 include/freetype/config/public-macros.h     |  55 +++----
 include/freetype/internal/compiler-macros.h | 220 ++++++++++++++++------------
 3 files changed, 178 insertions(+), 120 deletions(-)

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



reply via email to

[Prev in Thread] Current Thread [Next in Thread]