aboutsummaryrefslogtreecommitdiffstats
path: root/include/qpdf/DLL.h
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2022-04-10 14:17:35 +0200
committerJay Berkenbilt <ejb@ql.org>2022-04-10 22:52:36 +0200
commit90cfe80bacdd0d398631afce76c4182e08cc78b9 (patch)
tree369c3b9dfb0f8f8dac6181267b843934e976e40a /include/qpdf/DLL.h
parent8c504c9a905dc1cddbcbb32b368afe91f340984f (diff)
downloadqpdf-90cfe80bacdd0d398631afce76c4182e08cc78b9.tar.zst
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
Diffstat (limited to 'include/qpdf/DLL.h')
-rw-r--r--include/qpdf/DLL.h96
1 files changed, 90 insertions, 6 deletions
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 */