/* Copyright (c) 2005-2023 Jay Berkenbilt
 *
 * This file is part of qpdf.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Versions of qpdf prior to version 7 were released under the terms
 * of version 2.0 of the Artistic License. At your option, you may
 * continue to consider qpdf to be licensed under those terms. Please
 * see the manual for additional information.
 */

#ifndef QPDF_DLL_HH
#define QPDF_DLL_HH

/* The first version of qpdf to include the version constants is 10.6.0. */
#define QPDF_MAJOR_VERSION 11
#define QPDF_MINOR_VERSION 3
#define QPDF_PATCH_VERSION 0
#define QPDF_VERSION "11.3.0"

/*
 * 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
#elif defined __GNUC__
# define QPDF_DLL __attribute__((visibility("default")))
# define QPDF_DLL_PRIVATE __attribute__((visibility("hidden")))
#else
# define QPDF_DLL
# define QPDF_DLL_PRIVATE
#endif
#ifdef __GNUC__
# define QPDF_DLL_CLASS QPDF_DLL
#else
# 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_class. 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.

  * If we don't export base classes with mingw, the vtables don't end
    up in the DLL.

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