Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 09:09:39

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