18#include "private/qcoreapplication_p.h"
19#include "private/qfilesystementry_p.h"
24# include "private/qcore_mac_p.h"
27#if QT_CONFIG(relocatable) && QT_CONFIG(dlopen) && !QT_CONFIG(framework)
31#if QT_CONFIG(relocatable) && defined(Q_OS_WIN)
32# include <qt_windows.h>
39using namespace Qt::StringLiterals;
43#if QT_CONFIG(settings)
45static std::unique_ptr<QSettings> findConfiguration();
47struct QLibrarySettings
52 QSettings *configuration();
54 std::unique_ptr<QSettings> settings;
56 bool reloadOnQAppAvailable;
58Q_GLOBAL_STATIC(QLibrarySettings, qt_library_settings)
60QLibrarySettings::QLibrarySettings() : paths(
false), reloadOnQAppAvailable(
false)
65QSettings *QLibrarySettings::configuration()
67 if (reloadOnQAppAvailable && QCoreApplication::instanceExists())
69 return settings.get();
72bool QLibrarySettings::havePaths()
74 if (reloadOnQAppAvailable && QCoreApplication::instanceExists())
79void QLibrarySettings::load()
82 settings = findConfiguration();
83 reloadOnQAppAvailable = !settings && !QCoreApplication::instanceExists();
88 QStringList children = settings->childGroups();
89 paths = !children.contains(
"Platforms"_L1)
90 || children.contains(
"Paths"_L1);
95const QString *qtconfManualPath =
nullptr;
98void QLibraryInfoPrivate::setQtconfManualPath(
const QString *path)
100 qtconfManualPath = path;
103static std::unique_ptr<QSettings> findConfiguration()
105 if (qtconfManualPath)
106 return std::make_unique<QSettings>(*qtconfManualPath, QSettings::IniFormat);
108 QString qtconfig = QStringLiteral(
":/qt/etc/qt.conf");
109 if (QResource(qtconfig, QLocale::c()).isValid())
110 return std::make_unique<QSettings>(qtconfig, QSettings::IniFormat);
112 CFBundleRef bundleRef = CFBundleGetMainBundle();
114 QCFType<CFURLRef> urlRef = CFBundleCopyResourceURL(bundleRef,
115 QCFString(
"qt.conf"_L1),
119 QCFString path = CFURLCopyFileSystemPath(urlRef, kCFURLPOSIXPathStyle);
120 qtconfig = QDir::cleanPath(path);
121 if (QFile::exists(qtconfig))
122 return std::make_unique<QSettings>(qtconfig, QSettings::IniFormat);
126 if (QCoreApplication::instanceExists()) {
127 QString pwd = QCoreApplication::applicationDirPath();
128 qtconfig = pwd + u"/qt" QT_STRINGIFY(QT_VERSION_MAJOR)
".conf"_s;
129 if (QFile::exists(qtconfig))
130 return std::make_unique<QSettings>(qtconfig, QSettings::IniFormat);
131 qtconfig = pwd + u"/qt.conf";
132 if (QFile::exists(qtconfig))
133 return std::make_unique<QSettings>(qtconfig, QSettings::IniFormat);
138QSettings *QLibraryInfoPrivate::configuration()
140 QLibrarySettings *ls = qt_library_settings();
141 return ls ? ls->configuration() :
nullptr;
144void QLibraryInfoPrivate::reload()
146 if (qt_library_settings.exists())
147 qt_library_settings->load();
150static bool havePaths() {
151 QLibrarySettings *ls = qt_library_settings();
152 return ls && ls->havePaths();
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
176
177
178
179
180
182QLibraryInfo::QLibraryInfo()
185#if defined(Q_CC_CLANG)
186# define COMPILER_STRING __VERSION__
187#elif defined(Q_CC_GHS)
188# define COMPILER_STRING "GHS " QT_STRINGIFY(__GHS_VERSION_NUMBER)
189#elif defined(Q_CC_GNU)
190# define COMPILER_STRING "GCC " __VERSION__
191#elif defined(Q_CC_MSVC)
193# define COMPILER_STRING "MSVC 2015"
194# elif _MSC_VER < 1917
195# define COMPILER_STRING "MSVC 2017"
196# elif _MSC_VER < 1930
197# define COMPILER_STRING "MSVC 2019"
198# elif _MSC_VER < 1950
199# define COMPILER_STRING "MSVC 2022"
200# elif _MSC_VER < 2000
201# define COMPILER_STRING "MSVC 2026"
203# define COMPILER_STRING "MSVC _MSC_VER " QT_STRINGIFY(_MSC_VER)
206# define COMPILER_STRING "<unknown compiler>"
209# define DEBUG_STRING " release"
211# define DEBUG_STRING " debug"
214# define SHARED_STRING " shared (dynamic)"
216# define SHARED_STRING " static"
224
225
226
227
228
229
231const char *QLibraryInfo::build()
noexcept
233 return qt_build_string();
237
238
239
240
242QLibraryInfo::isDebugBuild()
noexcept
252
253
254
255bool QLibraryInfo::isSharedBuild()
noexcept
265
266
267
268
269
270QVersionNumber QLibraryInfo::version()
noexcept
272 return QVersionNumber(QT_VERSION_MAJOR, QT_VERSION_MINOR, QT_VERSION_PATCH);
277 if (QCoreApplication::instanceExists()) {
279 CFBundleRef bundleRef = CFBundleGetMainBundle();
281 QCFType<CFURLRef> urlRef = CFBundleCopyBundleURL(bundleRef);
283 QCFString path = CFURLCopyFileSystemPath(urlRef, kCFURLPOSIXPathStyle);
285 QString bundleContentsDir = QString(path) +
"/Contents/"_L1;
286 if (QDir(bundleContentsDir).exists())
287 return QDir::cleanPath(bundleContentsDir);
289 return QDir::cleanPath(QString(path));
295 return QCoreApplication::applicationDirPath();
297 return QDir::currentPath();
301#if QT_CONFIG(relocatable)
302#if !defined(QT_STATIC) && !(defined(Q_OS_DARWIN) && QT_CONFIG(framework))
303 && (QT_CONFIG(dlopen) || defined(Q_OS_WIN))
304static QString prefixFromQtCoreLibraryHelper(
const QString &qtCoreLibraryPath)
306 const QString qtCoreLibrary = QDir::fromNativeSeparators(qtCoreLibraryPath);
307 const QString libDir = QFileInfo(qtCoreLibrary).absolutePath();
308 const QString prefixDir = libDir +
"/" QT_CONFIGURE_LIBLOCATION_TO_PREFIX_PATH;
309 return QDir::cleanPath(prefixDir);
314static HMODULE getWindowsModuleHandle()
316 HMODULE hModule = NULL;
318 GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
319 (LPCTSTR)&QLibraryInfo::isDebugBuild, &hModule);
324static QString getRelocatablePrefix(QLibraryInfoPrivate::UsageMode usageMode)
330#if defined(QT_STATIC)
331 prefixPath = prefixFromAppDirHelper();
332 if (usageMode == QLibraryInfoPrivate::UsedFromQtBinDir) {
334 constexpr QByteArrayView binDir = qt_configure_strs.viewAt(QLibraryInfo::BinariesPath - 1);
335 constexpr size_t binDirLength = binDir.size() + 1;
336 prefixPath.chop(binDirLength);
338#elif defined(Q_OS_DARWIN) && QT_CONFIG(framework)
341 #define QT_LIBINFIX ""
343 auto qtCoreBundle = CFBundleGetBundleWithIdentifier(CFSTR(
"org.qt-project.QtCore" QT_LIBINFIX));
350 auto allBundles = CFBundleGetAllBundles();
351 auto bundleCount = CFArrayGetCount(allBundles);
352 for (
int i = 0; i < bundleCount; ++i) {
353 auto bundle = CFBundleRef(CFArrayGetValueAtIndex(allBundles, i));
354 auto url = QCFType<CFURLRef>(CFBundleCopyBundleURL(bundle));
355 auto path = QCFType<CFStringRef>(CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle));
356 if (CFStringHasSuffix(path, CFSTR(
"/QtCore" QT_LIBINFIX
".framework"))) {
357 qtCoreBundle = bundle;
362 Q_ASSERT(qtCoreBundle);
364 QCFType<CFURLRef> qtCorePath = CFBundleCopyBundleURL(qtCoreBundle);
365 Q_ASSERT(qtCorePath);
367 QCFType<CFURLRef> qtCorePathAbsolute = CFURLCopyAbsoluteURL(qtCorePath);
368 Q_ASSERT(qtCorePathAbsolute);
370 QCFType<CFURLRef> libDirCFPath = CFURLCreateCopyDeletingLastPathComponent(NULL, qtCorePathAbsolute);
372 const QCFString libDirCFString = CFURLCopyFileSystemPath(libDirCFPath, kCFURLPOSIXPathStyle);
374 const QString prefixDir = QString(libDirCFString) +
"/" QT_CONFIGURE_LIBLOCATION_TO_PREFIX_PATH;
376 prefixPath = QDir::cleanPath(prefixDir);
377#elif defined(Q_OS_WASM)
381 prefixPath = QStringLiteral(
"/");
382#elif QT_CONFIG(dlopen)
385 int result = dladdr(
reinterpret_cast<
void *>(&QLibraryInfo::isDebugBuild), &info);
386 if (result > 0 && info.dli_fname)
387 prefixPath = prefixFromQtCoreLibraryHelper(QString::fromLocal8Bit(info.dli_fname));
388#elif defined(Q_OS_WIN)
390 HMODULE hModule = getWindowsModuleHandle();
391 const int kBufferSize = 4096;
392 wchar_t buffer[kBufferSize];
393 DWORD pathSize = GetModuleFileName(hModule, buffer, kBufferSize);
394 const QString qtCoreFilePath = QString::fromWCharArray(buffer,
int(pathSize));
395 const QString qtCoreDirPath = QFileInfo(qtCoreFilePath).absolutePath();
397 hModule =
reinterpret_cast<HMODULE>(QCoreApplicationPrivate::mainInstanceHandle);
398 pathSize = GetModuleFileName(hModule, buffer, kBufferSize);
399 const QString exeDirPath = QFileInfo(QString::fromWCharArray(buffer,
int(pathSize))).absolutePath();
400 if (QFileInfo(exeDirPath) == QFileInfo(qtCoreDirPath)) {
404 const QString libdir = QString::fromLocal8Bit(
405 qt_configure_strs.viewAt(QLibraryInfo::LibrariesPath - 1));
406 const QLatin1Char slash(
'/');
407#if defined(Q_CC_MINGW)
408 const QString implibPrefix = QStringLiteral(
"lib");
409 const QString implibSuffix = QStringLiteral(
".a");
411 const QString implibPrefix;
412 const QString implibSuffix = QStringLiteral(
".lib");
414 const QString qtCoreImpLibFileName = implibPrefix
415 + QFileInfo(qtCoreFilePath).completeBaseName() + implibSuffix;
416 const QString qtCoreImpLibPath = qtCoreDirPath
417 + slash + QT_CONFIGURE_LIBLOCATION_TO_PREFIX_PATH
419 + slash + qtCoreImpLibFileName;
420 if (!QFileInfo::exists(qtCoreImpLibPath)) {
426 if (!qtCoreFilePath.isEmpty())
427 prefixPath = prefixFromQtCoreLibraryHelper(qtCoreFilePath);
429#error "The chosen platform / config does not support querying for a dynamic prefix."
432#if defined(Q_OS_LINUX) && !defined(QT_STATIC) && defined(__GLIBC__)
436 const QString libdir = QString::fromLocal8Bit(
437 qt_configure_strs.viewAt(QLibraryInfo::LibrariesPath - 1));
438 QDir prefixDir(prefixPath);
439 while (!prefixDir.exists(libdir)) {
441 prefixPath = prefixDir.absolutePath();
442 if (prefixDir.isRoot()) {
449 Q_ASSERT_X(!prefixPath.isEmpty(),
"getRelocatablePrefix",
450 "Failed to find the Qt prefix path.");
457#if QT_CONFIG(relocatable)
458 return getRelocatablePrefix(usageMode);
461 return QString::fromLocal8Bit(QT_CONFIGURE_PREFIX_PATH);
465QLibraryInfoPrivate::LocationInfo QLibraryInfoPrivate::locationInfo(QLibraryInfo::LibraryPath loc)
468
469
470
471
472
473 static constexpr auto qtConfEntries = qOffsetStringArray(
475 "Documentation",
"doc",
476 "Headers",
"include",
479 "LibraryExecutables",
"bin",
481 "LibraryExecutables",
"libexec",
484 "Plugins",
"plugins",
490 "Translations",
"translations",
491 "Examples",
"examples",
495 constexpr QByteArrayView dot{
"."};
499 if (
int(loc) < qtConfEntries.count()) {
500 result.key = QLatin1StringView(qtConfEntries.viewAt(loc * 2));
501 result.defaultValue = QLatin1StringView(qtConfEntries.viewAt(loc * 2 + 1));
502 if (result.key == u"QmlImports")
503 result.fallbackKey = u"Qml2Imports"_s;
505 }
else if (loc == QLibraryInfo::SettingsPath) {
506 result.key =
"Settings"_L1;
507 result.defaultValue = QLatin1StringView(dot);
515
516
517
518
521
522
523
524
525
526
527
528QString QLibraryInfo::path(LibraryPath p)
530 return QLibraryInfoPrivate::path(p);
534
535
536
537
538
539QStringList QLibraryInfo::paths(LibraryPath p)
541 return QLibraryInfoPrivate::paths(p);
546#if QT_CONFIG(settings)
547 QSettings *config = QLibraryInfoPrivate::configuration();
548 Q_ASSERT(config !=
nullptr);
549 return config->value(
"Config/MergeQtConf",
false).toBool();
555#if QT_CONFIG(settings)
556static QString normalizePath(QString ret)
558 qsizetype startIndex = 0;
560
561
562
564 startIndex = ret.indexOf(u'$', startIndex);
567 if (ret.size() < startIndex + 3)
569 if (ret.at(startIndex + 1) != u'(') {
573 qsizetype endIndex = ret.indexOf(u')', startIndex + 2);
576 auto envVarName = QStringView{ret}.sliced(startIndex + 2, endIndex - startIndex - 2);
577 QString value = qEnvironmentVariable(envVarName.toLocal8Bit().constData());
578 ret.replace(startIndex, endIndex - startIndex + 1, value);
579 startIndex += value.size();
581 return QDir::fromNativeSeparators(ret);
584static QVariant libraryPathToValue(QLibraryInfo::LibraryPath loc)
587 auto li = QLibraryInfoPrivate::locationInfo(loc);
590 QSettings *config = QLibraryInfoPrivate::configuration();
591 Q_ASSERT(config !=
nullptr);
594 QVariant defaultValue = keepQtBuildDefaults()
596 : QVariant(li.defaultValue);
597 config->beginGroup(
"Paths"_L1);
598 auto cleanup = qScopeGuard([&]() { config->endGroup(); });
599 if (li.fallbackKey.isNull()) {
600 value = config->value(li.key, defaultValue);
602 value = config->value(li.key);
603 if (!value.isValid())
604 value = config->value(li.fallbackKey, defaultValue);
615 using FromInternalPath = QFileSystemEntry::FromInternalPath;
616 return !path.startsWith(
':'_L1) && QFileSystemEntry(path, FromInternalPath{}).isRelative();
621 using FromInternalPath = QFileSystemEntry::FromInternalPath;
622 return path.startsWith(
':'_L1) || QFileSystemEntry(path, FromInternalPath{}).isAbsolute();
625QStringList QLibraryInfoPrivate::paths(QLibraryInfo::LibraryPath p,
628 const QLibraryInfo::LibraryPath loc = p;
630 bool fromConf =
false;
631 bool pathsAreAbsolute =
true;
632#if QT_CONFIG(settings)
636 QVariant value = libraryPathToValue(loc);
637 if (value.isValid()) {
638 if (
auto *asList = get_if<QList<QString>>(&value))
639 ret = std::move(*asList);
641 ret = QList<QString>({ std::move(value).toString()});
642 for (qsizetype i = 0, end = ret.size(); i < end; ++i) {
643 ret[i] = normalizePath(ret[i]);
644 pathsAreAbsolute = pathsAreAbsolute && pathIsAbsolute(ret[i]);
650 if (!fromConf || keepQtBuildDefaults()) {
651 QString noConfResult;
652 if (loc == QLibraryInfo::PrefixPath) {
653 noConfResult = getPrefix(usageMode);
654 }
else if (
int(loc) <= qt_configure_strs.count()) {
655 noConfResult = QString::fromLocal8Bit(qt_configure_strs.viewAt(loc - 1));
657 }
else if (loc == QLibraryInfo::SettingsPath) {
662 const char *
volatile path = QT_CONFIGURE_SETTINGS_PATH;
663 noConfResult = QString::fromLocal8Bit(path);
666 if (!noConfResult.isEmpty()) {
667 pathsAreAbsolute = pathsAreAbsolute && pathIsAbsolute(noConfResult);
668 ret.push_back(std::move(noConfResult));
671 if (ret.isEmpty() || pathsAreAbsolute)
675 if (loc == QLibraryInfo::PrefixPath) {
676 baseDir = prefixFromAppDirHelper();
679 baseDir = QLibraryInfoPrivate::path(QLibraryInfo::PrefixPath, usageMode);
681 for (qsizetype i = 0, end = ret.size(); i < end; ++i)
682 if (pathIsRelative(ret[i]))
683 ret[i] = QDir::cleanPath(baseDir + u'/' + std::move(ret[i]));
688
689
690
691
692
693QString QLibraryInfoPrivate::path(QLibraryInfo::LibraryPath p, UsageMode usageMode)
695 return paths(p, usageMode).value(0, QString());
699
700
701
702
703
704
705
706
707
708
709
711QStringList QLibraryInfo::platformPluginArguments(
const QString &platformName)
713#if QT_CONFIG(settings)
714 if (
const auto settings = findConfiguration()) {
715 const QString key =
"Platforms/"_L1
718 return settings->value(key).toStringList();
721 Q_UNUSED(platformName);
723 return QStringList();
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
753
754
755
758
759
760
761
762
763
766
767
768
769
770
771
772
773
774
775
778
779
780
781
782
783
784
785
787const char *qVersion()
noexcept
789 return QT_VERSION_STR;
792#if QT_DEPRECATED_SINCE(6
, 9
)
794bool qSharedBuild()
noexcept
796 return QLibraryInfo::isSharedBuild();
803#if defined(Q_CC_GNU) && defined(ELF_INTERPRETER)
808#include "private/qcoreapplication_p.h"
810QT_WARNING_DISABLE_GCC(
"-Wformat-overflow")
811QT_WARNING_DISABLE_GCC(
"-Wattributes")
812QT_WARNING_DISABLE_CLANG(
"-Wattributes")
813QT_WARNING_DISABLE_INTEL(2621)
815# if defined(Q_OS_LINUX)
816# include "minimum-linux_p.h"
818# ifdef QT_ELF_NOTE_OS_TYPE
821 static_assert(
sizeof(Elf32_Nhdr) ==
sizeof(Elf64_Nhdr),
822 "The size of an ELF note is wrong (should be 12 bytes)");
824 Elf32_Word ostype = QT_ELF_NOTE_OS_TYPE;
825 Elf32_Word major = QT_ELF_NOTE_OS_MAJOR;
826 Elf32_Word minor = QT_ELF_NOTE_OS_MINOR;
827# ifdef QT_ELF_NOTE_OS_PATCH
828 Elf32_Word patch = QT_ELF_NOTE_OS_PATCH;
832 Elf32_Nhdr header = {
833 .n_namesz =
sizeof(name),
834 .n_descsz =
sizeof(Payload),
835 .n_type = NT_GNU_ABI_TAG
837 char name[
sizeof ELF_NOTE_GNU] = ELF_NOTE_GNU;
838 Payload payload = {};
840__attribute__((section(
".note.ABI-tag"), aligned(4), used))
841extern constexpr ElfNoteAbiTag QT_MANGLE_NAMESPACE(qt_abi_tag) = {};
844extern const char qt_core_interpreter[]
__attribute__((section(
".interp")))
847extern "C" void qt_core_boilerplate()
__attribute__((force_align_arg_pointer));
848void qt_core_boilerplate()
850 printf(
"This is the QtCore library version %s\n"
852 "Contact: https://www.qt.io/licensing/\n"
854 "Installation prefix: %s\n"
857 QT_PREPEND_NAMESPACE(qt_build_string)(),
859 QT_CONFIGURE_PREFIX_PATH,
860 qt_configure_strs[QT_PREPEND_NAMESPACE(QLibraryInfo)::LibrariesPath - 1],
861 qt_configure_strs[QT_PREPEND_NAMESPACE(QLibraryInfo)::PluginsPath - 1]);
863 QT_PREPEND_NAMESPACE(qDumpCPUFeatures)();
static const char * qt_build_string() noexcept
static bool pathIsRelative(const QString &path)
static QString getPrefix(QLibraryInfoPrivate::UsageMode usageMode)
static bool pathIsAbsolute(const QString &path)
static QString prefixFromAppDirHelper()
static bool keepQtBuildDefaults()