aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.dir-locals.el3
-rw-r--r--TODO3
-rw-r--r--include/qpdf/DLL.h96
-rw-r--r--libqpdf/CMakeLists.txt6
-rw-r--r--manual/installation.rst8
5 files changed, 104 insertions, 12 deletions
diff --git a/.dir-locals.el b/.dir-locals.el
index d3c0b626..18e38e8d 100644
--- a/.dir-locals.el
+++ b/.dir-locals.el
@@ -20,7 +20,8 @@
)
)
)
- (c-noise-macro-names . ("QPDF_DLL" "QPDF_DLL_CLASS" "QPDF_DLL_LOCAL"))
+ (c-noise-macro-names
+ . ("QPDF_DLL" "QPDF_DLL_CLASS" "QPDF_DLL_PRIVATE"))
)
)
(c++-mode . ((eval . (progn
diff --git a/TODO b/TODO
index 971b018f..ef34096c 100644
--- a/TODO
+++ b/TODO
@@ -37,9 +37,6 @@ cmake
=====
* DLL.h
- * Change DLL_EXPORT to QPDF_EXPORT. Be sure to call attention to
- this in the release notes. There should be a "migrating to cmake"
- in the manual, and ./configure should draw attention to it.
* The effect of QPDF_DLL_CLASS is to export everything in the class,
not just the vtable. On MSVC, we don't need this as the vtable
gets exported automatically when needed. With gcc, we need it to
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 */
diff --git a/libqpdf/CMakeLists.txt b/libqpdf/CMakeLists.txt
index be333b12..e2dffbd3 100644
--- a/libqpdf/CMakeLists.txt
+++ b/libqpdf/CMakeLists.txt
@@ -398,6 +398,9 @@ endif()
# use PIC for the object library so we don't have to compile twice.
set(OBJECT_LIB libqpdf_object)
add_library(${OBJECT_LIB} OBJECT ${libqpdf_SOURCES})
+if(OBJECT_LIB_IS_PIC)
+ target_compile_definitions(${OBJECT_LIB} PRIVATE libqpdf_EXPORTS)
+endif()
set_target_properties(${OBJECT_LIB} PROPERTIES
POSITION_INDEPENDENT_CODE ${OBJECT_LIB_IS_PIC})
target_include_directories(${OBJECT_LIB}
@@ -446,8 +449,6 @@ if(NOT WIN32)
endif()
if(BUILD_SHARED_LIBS)
- add_compile_definitions(DLL_EXPORT)
-
set(SHARED_LIB libqpdf)
if(OBJECT_LIB_IS_PIC)
add_library(${SHARED_LIB} SHARED $<TARGET_OBJECTS:libqpdf_object>)
@@ -485,6 +486,7 @@ if(BUILD_SHARED_LIBS)
SOVERSION ${qpdf_SOVERSION}
POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS})
+ target_compile_definitions(${SHARED_LIB} PRIVATE libqpdf_EXPORTS)
target_include_directories(${SHARED_LIB}
SYSTEM PRIVATE ${dep_include_directories})
target_include_directories(${SHARED_LIB}
diff --git a/manual/installation.rst b/manual/installation.rst
index 315b4bd8..64aa7921 100644
--- a/manual/installation.rst
+++ b/manual/installation.rst
@@ -617,6 +617,14 @@ and cmake options. There are a few exceptions:
``QPDF_TEST_COMPARE_IMAGES`` to ``1`` to *enable* image comparison
tests. Either way, they are off by default.
+- Non-user-visible change: the preprocessor symbol that triggers the
+ export of functions into the public ABI (application binary
+ interface) has been changed from ``DLL_EXPORT`` to
+ ``libqpdf_EXPORTS``. This detail is encapsulated in the build and is
+ only relevant to people who are building qpdf on their own or who
+ may have previously needed to work around a collision between qpdf's
+ use of ``DLL_EXPORT`` and someone else's use of the same symbol.
+
- A handful of options that were specific to autoconf or the old build
system have been dropped.