Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qversiontagging.h
Go to the documentation of this file.
1// Copyright (C) 2022 Intel Corporation.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#if !defined(QVERSIONTAGGING_H)
5#define QVERSIONTAGGING_H
6
7#if 0
8#pragma qt_no_master_include
9#endif
10
11#include <QtCore/qcompilerdetection.h>
12#include <QtCore/qtconfigmacros.h>
13#include <QtCore/qtversionchecks.h>
14#include <QtCore/qtypes.h>
15
16QT_REQUIRE_CONFIG(version_tagging);
17
19
20/*
21 * Explanation
22 *
23 * This file causes all libraries, plugins, and applications that #include this
24 * file to automatically pull in a symbol found in QtCore that encodes the
25 * current Qt version number at the time of compilation. The relocation is
26 * designed so that it's impossible for the dynamic linker to perform lazy
27 * binding. Instead, it must resolve at load time or fail. That way, attempting
28 * to load such a library or plugin while an older QtCore is loaded will fail.
29 * Similarly, if an older QtCore is found when launching an application, the
30 * application will fail to launch.
31 *
32 * It's also possible to inspect which version is required by decoding the
33 * .qtversion section. The second pointer-sized variable is the required
34 * version, for example, for Qt 6.4.1:
35 *
36 * Hex dump of section [18] '.qtversion', 16 bytes at offset 0x1ee48:
37 * 0x00000000 b0ffffff ffffffff 01040600 00000000 ................
38 * ^^^^^^^^ ^^^^^^^^
39 *
40 * There will only be one copy of the section in the output library or application.
41 *
42 * This functionality can be disabled by defining QT_NO_VERSION_TAGGING. It's
43 * disabled if Qt was built statically.
44 *
45 * Windows notes:
46 *
47 * On Windows, the address of a __declspec(dllimport) variable is not a
48 * constant expression, unlike Unix systems. So we instead use the address of
49 * the import variable, which is created by prefixing the external name with
50 * "__imp_". Using that variable causes an import of the corresponding symbol
51 * from QtCore DLL.
52 *
53 * With MinGW (GCC and Clang), we use a C++17 inline variable, so the compiler
54 * and linker automatically merge the variables. The "used" __attribute__
55 * tells the compiler to always emit that variable, whether it's used or not.
56 *
57 * MSVC has no equivalent to that attribute, so instead we create an extern
58 * const variable and tell the linker to merge them all via
59 * __declspec(selectany).
60 *
61 * Unix notes:
62 *
63 * On Unix, we use the same C++17 inline variable solution as MinGW, but we
64 * don't need the "__imp_" trick.
65 *
66 * Additionally, on ELF systems like Linux and FreeBSD, the symbol in question
67 * is simply "qt_version_tag" in both QtCore and in this ELF module, but it
68 * has an ELF version attached to it (see qversiontagging.cpp and
69 * QtFlagHandlingHelpers.cmake). That way, the error message from the dynamic
70 * linker will say it can't find version "Qt_6.x".
71 */
72
73namespace QtPrivate {
75{
76 const void *symbol;
78 constexpr QVersionTag(const void *sym, int currentVersion = QT_VERSION)
79 : symbol(sym), version(currentVersion)
80 {}
81};
82}
83
84#if !defined(QT_NO_VERSION_TAGGING) && (defined(QT_BUILD_CORE_LIB) || defined(QT_BOOTSTRAPPED) || defined(QT_STATIC))
85// don't make tags in QtCore, bootstrapped systems or if the user asked not to
86# define QT_NO_VERSION_TAGGING
87#endif
88
89#if defined(Q_OS_WIN)
90# ifdef Q_PROCESSOR_X86_32
91// 32-bit x86 convention does prepend a _
92# define QT_MANGLE_IMPORT_PREFIX _imp__
93# else
94// Calling convention on other architectures does not prepend a _
95# define QT_MANGLE_IMPORT_PREFIX __imp_
96# endif
97# if defined(Q_CC_MSVC_ONLY)
98# pragma section(".qtversion",read,shared)
99# define QT_VERSION_TAG_SECTION __declspec(allocate(".qtversion"))
100# define QT_VERSION_TAG_ATTRIBUTE __declspec(selectany) extern const
101# else
102# define QT_VERSION_TAG_ATTRIBUTE __attribute__((used)) constexpr inline
103# endif
104# define QT_VERSION_TAG2(sym, imp) \
105 extern "C" const char * const imp; \
106 QT_VERSION_TAG_ATTRIBUTE QT_VERSION_TAG_SECTION QtPrivate::QVersionTag sym ## _used(&imp)
107# define QT_VERSION_TAG(sym, imp) QT_VERSION_TAG2(sym, imp)
108#elif defined(Q_CC_GNU) && __has_attribute(used)
109# ifdef Q_OS_DARWIN
110# define QT_VERSION_TAG_SECTION __attribute__((section("__DATA,.qtversion")))
111# endif
112# define QT_VERSION_TAG_ATTRIBUTE __attribute__((visibility("hidden"), used))
113# define QT_VERSION_TAG2(sym, imp) \
114 extern "C" Q_DECL_IMPORT const char sym; \
115 QT_VERSION_TAG_ATTRIBUTE QT_VERSION_TAG_SECTION constexpr inline QtPrivate::QVersionTag sym ## _use(&sym)
116# define QT_VERSION_TAG(sym, imp) QT_VERSION_TAG2(sym, imp)
117#endif
118
119#ifdef Q_OF_ELF
120# define QT_VERSION_TAG_SYMBOL(prefix, sym, m, n) sym
121#else
122# define QT_VERSION_TAG_SYMBOL2(prefix, sym, m, n) prefix ## sym ## _ ## m ## _ ## n
123# define QT_VERSION_TAG_SYMBOL(prefix, sym, m, n) QT_VERSION_TAG_SYMBOL2(prefix, sym, m, n)
124#endif
125
126#if defined(QT_VERSION_TAG) && !defined(QT_NO_VERSION_TAGGING)
127# ifndef QT_VERSION_TAG_SECTION
128# define QT_VERSION_TAG_SECTION __attribute__((section(".qtversion")))
129# endif
130# 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)
131# define QT_MANGLED_VERSION_TAG QT_VERSION_TAG_SYMBOL(, QT_MANGLE_NAMESPACE(qt_version_tag), QT_VERSION_MAJOR, QT_VERSION_MINOR)
132
133QT_VERSION_TAG(QT_MANGLED_VERSION_TAG, QT_MANGLED_VERSION_TAG_IMPORT);
134
135# undef QT_MANGLED_VERSION_TAG
136# undef QT_MANGLED_VERSION_TAG_IMPORT
137# undef QT_VERSION_TAG_SECTION
138#endif
139
141
142#endif // QVERSIONTAGGING_H
Combined button and popup list for selecting options.
\macro QT_NO_KEYWORDS >
#define QT_REQUIRE_CONFIG(feature)
#define QT_VERSION
size_t quintptr
Definition qtypes.h:167
constexpr QVersionTag(const void *sym, int currentVersion=QT_VERSION)