From 90cfe80bacdd0d398631afce76c4182e08cc78b9 Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Sun, 10 Apr 2022 08:17:35 -0400 Subject: Clean up/fix DLL.h * Change DLL_EXPORT to libqpdf_EXPORTS (internal to the build). The new name is cmake's default, is more conventional, and is less likely to clash with other symbols. * Add QPDF_DLL_PRIVATE for non-Windows * Make logic around when to define QPDF_DLL et al more explicit * Add detailed comments --- include/qpdf/DLL.h | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 90 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/include/qpdf/DLL.h b/include/qpdf/DLL.h index 528a4a03..42dc2fac 100644 --- a/include/qpdf/DLL.h +++ b/include/qpdf/DLL.h @@ -29,17 +29,101 @@ #define QPDF_PATCH_VERSION 0 #define QPDF_VERSION "11.0.0" -#if (defined _WIN32 || defined __CYGWIN__) && defined(DLL_EXPORT) -# define QPDF_DLL __declspec(dllexport) +/* + * This file defines symbols that control the which functions, + * classes, and methods are exposed to the public ABI (application + * binary interface). See below for a detailed explanation. + */ + +#if defined _WIN32 || defined __CYGWIN__ +# ifdef libqpdf_EXPORTS +# define QPDF_DLL __declspec(dllexport) +# else +# define QPDF_DLL +# endif +# define QPDF_DLL_PRIVATE +# define QPDF_DLL_CLASS #elif defined __GNUC__ # define QPDF_DLL __attribute__((visibility("default"))) -#else -# define QPDF_DLL -#endif -#ifdef __GNUC__ +# define QPDF_DLL_PRIVATE __attribute__((visibility("hidden"))) # define QPDF_DLL_CLASS QPDF_DLL #else +# define QPDF_DLL +# define QPDF_DLL_PRIVATE # define QPDF_DLL_CLASS #endif +/* + +Here's what's happening. See also https://gcc.gnu.org/wiki/Visibility +for a more in-depth discussion. + +* Everything in the public ABI must be exported. Things not in the + public ABI should not be exported. + +* A class's runtime type information is need if the class is going to + be used as an exception, inherited from, or tested with + dynamic_claass. To do these things across a shared object boundary, + runtime type information must be exported. + +* On Windows: + + * For a symbol (function, method, etc.) to be exported into the + public ABI, it must be explicitly marked for export. + + * If you mark a class for export, all symbols in the class, + including private methods, are exported into the DLL, and there is + no way to exclude something from export. + + * A class's run-time type information is made available based on the + presence of a compiler flag (with MSVC), which is always on for + qpdf builds. + + * Marking classes for export should be done only when *building* the + DLL, not when *using* the DLL. + + * It is possible to mark symbols for import for DLL users, but it is + not necessary, and doing it right is complex in our case of being + multi-platform and building both static and shared libraries that + use the same headers, so we don't bother. + +* On Linux (and other similar systems): + + * Common compilers such as gcc and clang export all symbols into the + public ABI by default. The qpdf build overrides this by using + "visibility=hidden", which makes it behave more like Windows in + that things have to be explicitly exported to appear in the public + ABI. + + * As with Windows, marking a class for export causes everything in + the class, including private methods, the be exported. However, + unlike in Windows: + + * It is possible to explicitly mark symbols as private + + * The only way to get the runtime type and vtable information into + the ABI is to mark the class as exported. + + * It is harmless and sometimes necessary to include the visibility + marks when using the library as well as when building it. In + particular, clang on MacOS requires the visibility marks to + match in both cases. + +What does this mean: + +* On Windows, we never have to export a class, and while there is no + way to "unexport" something, we also have no need to do it. + +* On non-Windows, we have to export some classes, and when we do, we + have to "unexport" some of their parts. + +* We only use the libqpdf_EXPORTS as a conditional for defining the + symbols for Windows builds. + +To achieve this, we use QPDF_DLL_CLASS to export classes, QPDF_DLL to +export methods, and QPDF_DLL_PRIVATE to unexport private methods in +exported classes. + +*/ + #endif /* QPDF_DLL_HH */ -- cgit v1.2.3-70-g09d2