File indexing completed on 2024-05-12 04:44:33
0001 // SPDX-FileCopyrightText: Lukas Sommer <sommerluk@gmail.com> 0002 // SPDX-License-Identifier: BSD-2-Clause OR MIT 0003 0004 /** @file importexport.h 0005 * 0006 * This file provides support for C++ symbol import and export. */ 0007 0008 #ifndef IMPORTEXPORT_H 0009 #define IMPORTEXPORT_H 0010 0011 #include <qglobal.h> 0012 0013 /** @def PERCEPTUALCOLOR_IMPORTEXPORT 0014 * 0015 * @brief A macro that either exports dynamic library symbols or imports 0016 * dynamic library symbols or does nothing. 0017 * 0018 * This approach is proposed in Qt’s documentation (chapter “Creating 0019 * Shared Libraries”) – see there for more details. In short: 0020 * 0021 * @section buildappdynamic Build an application using the dynamic library 0022 * 0023 * When your application is build <em>using</em> the dynamic 0024 * library and includes the header files of the library, the 0025 * macro <em>imports</em> the corresponding symbols of the library 0026 * for you by expanding to Qt’s <tt>Q_DECL_IMPORT</tt> macro. This 0027 * is the default behaviour of this macro. 0028 * 0029 * @section buildlibdynamic Build the dynamic library 0030 * 0031 * When the dynamic library <em>itself</em> is build, the macro 0032 * <em>exports</em> the corresponding symbol by expanding to Qt’s 0033 * <tt>Q_DECL_EXPORT</tt> macro. Exported symbols will be visible 0034 * symbols in the dynamic library. To get this behaviour, it is 0035 * necessary to define <tt>PERCEPTUALCOLORLIB_BUILD_DYNAMIC_LIBRARY</tt> 0036 * always when this library itself is build. 0037 * 0038 * @section buildstatic Build either the static library itself or an application using it 0039 * 0040 * When either 0041 * 0042 * - building the static library itself 0043 * 0044 * or 0045 * 0046 * - your application is build <em>using</em> the static 0047 * library and includes the header files of the library, 0048 * 0049 * the macro expands to <em>nothing</em>, because for static libraries 0050 * no import nor export must happen. To get this behaviour, it is 0051 * necessary to define <tt>PERCEPTUALCOLORLIB_STATIC</tt>. 0052 * 0053 * @section cmakeimportexport CMake code 0054 * 0055 * The definition can be made within CMake: 0056 * 0057 * @code{.unparsed} 0058 * if(BUILD_SHARED_LIBS) 0059 * target_compile_definitions( 0060 * my_target_name 0061 * PRIVATE PERCEPTUALCOLORLIB_BUILD_DYNAMIC_LIBRARY) 0062 * else() 0063 * target_compile_definitions( 0064 * my_target_name 0065 * PUBLIC PERCEPTUALCOLORLIB_STATIC) 0066 * endif() 0067 * @endcode 0068 * 0069 * <tt>PERCEPTUALCOLORLIB_BUILD_DYNAMIC_LIBRARY</tt> is defined 0070 * <tt>PRIVATE</tt>, so it only becomes available when building 0071 * the library <em>itself</em> dynamically, and not when building 0072 * an application <em>using</em> the dynamic library. 0073 * 0074 * <tt>PERCEPTUALCOLORLIB_STATIC</tt> however is defined 0075 * <tt>PUBLIC</tt>, so it only becomes available both, when building 0076 * the library <em>itself</em> statically, and also when building 0077 * an application <em>using</em> the static library. 0078 * 0079 * And you also have to make sure that all symbols that are <em>not</em> 0080 * explicitly exported will be actually hidden on all platforms: 0081 * 0082 * @code{.unparsed} 0083 * set_target_properties( 0084 * my_target_name PROPERTIES 0085 * # By default, on Windows all symbols are hidden except those that are 0086 * # explicitly marked for export using the "__declspec(dllexport)" 0087 * # or "__declspec(dllimport)" keywords in the code. On Unix-based systems, 0088 * # however, all symbols are exported by default unless they are explicitly 0089 * # marked as hidden. To achieve the same behavior as on Windows, set 0090 * # the "CXX_VISIBILITY_PRESET" property to "hidden" in CMake to hide all 0091 * # symbols by default, unless they are explicitly marked for export using 0092 * # compiler-specific attributes. 0093 * CXX_VISIBILITY_PRESET "hidden" 0094 * VISIBILITY_INLINES_HIDDEN TRUE) 0095 * @endcode 0096 * 0097 * For your information: The opposite would look like this: 0098 * 0099 * @code{.unparsed} 0100 * set_target_properties( 0101 * my_target_name PROPERTIES 0102 * # We want all symbols to be publicly available. On Unix-based systems, this 0103 * # is the default behavior, and no additional configuration is required. 0104 * CXX_VISIBILITY_PRESET "default" 0105 * # However, on Windows, all symbols are hidden by default except for those 0106 * # that are explicitly marked for export using "__declspec(dllexport)" or 0107 * # "__declspec(dllimport)" keywords. To achieve the same behavior on Windows 0108 * # as on Unix-based systems, CMake provides the "WINDOWS_EXPORT_ALL_SYMBOLS" 0109 * # property, which can be set to "TRUE" to automatically generate the 0110 * # necessary export symbols for all classes and functions on Windows. 0111 * # However, please note that this option does not work for global variables. 0112 * WINDOWS_EXPORT_ALL_SYMBOLS TRUE 0113 * VISIBILITY_INLINES_HIDDEN FALSE) 0114 * @endcode 0115 * 0116 * @section importexportlinks Further reading 0117 * 0118 * @note CMake also offers support for symbol import and export. 0119 * It can generate a corresponding header by using the <tt><a 0120 * href="https://cmake.org/cmake/help/latest/module/GenerateExportHeader.html"> 0121 * generate_export_header()</a></tt> command. However, this is always 0122 * an additional step and makes the build and install configuration 0123 * more complex. Furthermore, we produce a second internal library 0124 * target out of the same source code, which has a different symbol 0125 * visibility for unit tests. As CMake-generated import-export headers 0126 * use the name of the target as part of the macro names it defines, this 0127 * would get complicated. Having our own macro is easier. 0128 * 0129 * @note CMake’s <a 0130 * href="https://cmake.org/cmake/help/latest/module/GenerateExportHeader.html"> 0131 * <tt>generate_export_header()</tt></a> command also has portable 0132 * support for deprecating symbols. However, since C++14 there is 0133 * <a href="https://en.cppreference.com/w/cpp/language/attributes/deprecated"> 0134 * <tt>[[deprecated(string-literal)]]</tt></a> part of the standard. 0135 * As we require even C++17 anyway, we can use this as a portable standard 0136 * instead of CMake’s macros. 0137 * 0138 * @sa https://doc.qt.io/qt-5/sharedlibrary.html#using-symbols-from-shared-libraries 0139 * @sa http://anadoxin.org/blog/control-over-symbol-exports-in-gcc.html 0140 * @sa https://labjack.com/news/simple-cpp-symbol-visibility-demo */ 0141 0142 #ifdef PERCEPTUALCOLORLIB_STATIC 0143 0144 #ifndef PERCEPTUALCOLOR_IMPORTEXPORT 0145 #define PERCEPTUALCOLOR_IMPORTEXPORT 0146 #endif 0147 0148 #else 0149 0150 #ifndef PERCEPTUALCOLOR_IMPORTEXPORT 0151 #ifdef PERCEPTUALCOLORLIB_BUILD_DYNAMIC_LIBRARY 0152 #define PERCEPTUALCOLOR_IMPORTEXPORT Q_DECL_EXPORT 0153 #else 0154 #define PERCEPTUALCOLOR_IMPORTEXPORT Q_DECL_IMPORT 0155 #endif 0156 #endif 0157 0158 #endif 0159 0160 #endif // IMPORTEXPORT_H