2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-12-22 10:58:58 +00:00

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
This commit is contained in:
Jay Berkenbilt 2022-04-10 08:17:35 -04:00
parent 8c504c9a90
commit 90cfe80bac
5 changed files with 104 additions and 12 deletions

View File

@ -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

3
TODO
View File

@ -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

View File

@ -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 */

View File

@ -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}

View File

@ -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.