summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog23
-rw-r--r--include/freetype/config/public-macros.h55
-rw-r--r--include/freetype/internal/compiler-macros.h220
3 files changed, 178 insertions, 120 deletions
diff --git a/ChangeLog b/ChangeLog
index a2c80f585..2b3bb3a0d 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 b62092ba6..b1fa0f2b3 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 d7b6cfa24..1f432bca5 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