Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:07:42

0001 // Copyright (C) 2022 Intel Corporation.
0002 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
0003 
0004 #if !defined(QVERSIONTAGGING_H)
0005 #define QVERSIONTAGGING_H
0006 
0007 #include <QtCore/qcompilerdetection.h>
0008 #include <QtCore/qtconfigmacros.h>
0009 #include <QtCore/qtversionchecks.h>
0010 #include <QtCore/qtypes.h>
0011 
0012 QT_BEGIN_NAMESPACE
0013 
0014 /*
0015  * Explanation
0016  *
0017  * This file causes all libraries, plugins, and applications that #include this
0018  * file to automatically pull in a symbol found in QtCore that encodes the
0019  * current Qt version number at the time of compilation. The relocation is
0020  * designed so that it's impossible for the dynamic linker to perform lazy
0021  * binding. Instead, it must resolve at load time or fail. That way, attempting
0022  * to load such a library or plugin while an older QtCore is loaded will fail.
0023  * Similarly, if an older QtCore is found when launching an application, the
0024  * application will fail to launch.
0025  *
0026  * It's also possible to inspect which version is required by decoding the
0027  * .qtversion section. The second pointer-sized variable is the required
0028  * version, for example, for Qt 6.4.1:
0029  *
0030  *      Hex dump of section [18] '.qtversion', 16 bytes at offset 0x1ee48:
0031  *        0x00000000 b0ffffff ffffffff 01040600 00000000 ................
0032  *                                     ^^^^^^^^ ^^^^^^^^
0033  *
0034  * There will only be one copy of the section in the output library or application.
0035  *
0036  * This functionality can be disabled by defining QT_NO_VERSION_TAGGING. It's
0037  * disabled if Qt was built statically.
0038  *
0039  * Windows notes:
0040  *
0041  *  On Windows, the address of a __declspec(dllimport) variable is not a
0042  *  constant expression, unlike Unix systems. So we instead use the address of
0043  *  the import variable, which is created by prefixing the external name with
0044  *  "__imp_". Using that variable causes an import of the corresponding symbol
0045  *  from QtCore DLL.
0046  *
0047  *  With MinGW (GCC and Clang), we use a C++17 inline variable, so the compiler
0048  *  and linker automatically merge the variables. The "used" __attribute__
0049  *  tells the compiler to always emit that variable, whether it's used or not.
0050  *
0051  *  MSVC has no equivalent to that attribute, so instead we create an extern
0052  *  const variable and tell the linker to merge them all via
0053  *  __declspec(selectany).
0054  *
0055  * Unix notes:
0056  *
0057  *  On Unix, we use the same C++17 inline variable solution as MinGW, but we
0058  *  don't need the "__imp_" trick.
0059  *
0060  *  Additionally, on ELF systems like Linux and FreeBSD, the symbol in question
0061  *  is simply "qt_version_tag" in both QtCore and in this ELF module, but it
0062  *  has an ELF version attached to it (see qversiontagging.cpp and
0063  *  QtFlagHandlingHelpers.cmake). That way, the error message from the dynamic
0064  *  linker will say it can't find version "Qt_6.x".
0065  */
0066 
0067 namespace QtPrivate {
0068 struct QVersionTag
0069 {
0070     const void *symbol;
0071     quintptr version;
0072     constexpr QVersionTag(const void *sym, int currentVersion = QT_VERSION)
0073         : symbol(sym), version(currentVersion)
0074     {}
0075 };
0076 }
0077 
0078 #if !defined(QT_NO_VERSION_TAGGING) && (defined(QT_BUILD_CORE_LIB) || defined(QT_BOOTSTRAPPED) || defined(QT_STATIC))
0079 // don't make tags in QtCore, bootstrapped systems or if the user asked not to
0080 #  define QT_NO_VERSION_TAGGING
0081 #endif
0082 
0083 #if defined(Q_OS_WIN)
0084 #  ifdef Q_PROCESSOR_X86_32
0085 //   32-bit x86 convention does prepend a _
0086 #    define QT_MANGLE_IMPORT_PREFIX     _imp__
0087 #  else
0088 //   Calling convention on other architectures does not prepend a _
0089 #    define QT_MANGLE_IMPORT_PREFIX     __imp_
0090 #  endif
0091 #  if defined(Q_CC_MSVC_ONLY)
0092 #    pragma section(".qtversion",read,shared)
0093 #    define QT_VERSION_TAG_SECTION      __declspec(allocate(".qtversion"))
0094 #    define QT_VERSION_TAG_ATTRIBUTE    __declspec(selectany) extern const
0095 #  else
0096 #    define QT_VERSION_TAG_ATTRIBUTE    __attribute__((used)) constexpr inline
0097 #  endif
0098 #  define QT_VERSION_TAG2(sym, imp)     \
0099     extern "C" const char * const imp;  \
0100     QT_VERSION_TAG_ATTRIBUTE QT_VERSION_TAG_SECTION QtPrivate::QVersionTag sym ## _used(&imp)
0101 #  define QT_VERSION_TAG(sym, imp)       QT_VERSION_TAG2(sym, imp)
0102 #elif defined(Q_CC_GNU) && __has_attribute(used)
0103 #  ifdef Q_OS_DARWIN
0104 #    define QT_VERSION_TAG_SECTION      __attribute__((section("__DATA,.qtversion")))
0105 #  endif
0106 #  define QT_VERSION_TAG_ATTRIBUTE    __attribute__((visibility("hidden"), used))
0107 #  define QT_VERSION_TAG2(sym, imp)     \
0108     extern "C" Q_DECL_IMPORT const char sym; \
0109     QT_VERSION_TAG_ATTRIBUTE QT_VERSION_TAG_SECTION constexpr inline QtPrivate::QVersionTag sym ## _use(&sym)
0110 #  define QT_VERSION_TAG(sym, imp)       QT_VERSION_TAG2(sym, imp)
0111 #endif
0112 
0113 #ifdef Q_OF_ELF
0114 #  define QT_VERSION_TAG_SYMBOL(prefix, sym, m, n)      sym
0115 #else
0116 #  define QT_VERSION_TAG_SYMBOL2(prefix, sym, m, n)     prefix ## sym ## _ ## m ## _ ## n
0117 #  define QT_VERSION_TAG_SYMBOL(prefix, sym, m, n)      QT_VERSION_TAG_SYMBOL2(prefix, sym, m, n)
0118 #endif
0119 
0120 #if defined(QT_VERSION_TAG) && !defined(QT_NO_VERSION_TAGGING)
0121 #  ifndef QT_VERSION_TAG_SECTION
0122 #    define QT_VERSION_TAG_SECTION          __attribute__((section(".qtversion")))
0123 #  endif
0124 #  define QT_MANGLED_VERSION_TAG_IMPORT     QT_VERSION_TAG_SYMBOL(QT_MANGLE_IMPORT_PREFIX, QT_MANGLE_NAMESPACE(qt_version_tag), QT_VERSION_MAJOR, QT_VERSION_MINOR)
0125 #  define QT_MANGLED_VERSION_TAG            QT_VERSION_TAG_SYMBOL(, QT_MANGLE_NAMESPACE(qt_version_tag), QT_VERSION_MAJOR, QT_VERSION_MINOR)
0126 
0127 QT_VERSION_TAG(QT_MANGLED_VERSION_TAG, QT_MANGLED_VERSION_TAG_IMPORT);
0128 
0129 #  undef QT_MANGLED_VERSION_TAG
0130 #  undef QT_MANGLED_VERSION_TAG_IMPORT
0131 #  undef QT_VERSION_TAG_SECTION
0132 #endif
0133 
0134 QT_END_NAMESPACE
0135 
0136 #endif // QVERSIONTAGGING_H