diff options
Diffstat (limited to 'src/corelib/global/qlibraryinfo.cpp')
-rw-r--r-- | src/corelib/global/qlibraryinfo.cpp | 256 |
1 files changed, 190 insertions, 66 deletions
diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index d931dfac48..6ffaef8f7c 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -87,10 +87,19 @@ void QLibrarySettings::load() } } +namespace { +const QString *qtconfManualPath = nullptr; +} + +void QLibraryInfoPrivate::setQtconfManualPath(const QString *path) +{ + qtconfManualPath = path; +} + static QSettings *findConfiguration() { - if (QLibraryInfoPrivate::qtconfManualPath) - return new QSettings(*QLibraryInfoPrivate::qtconfManualPath, QSettings::IniFormat); + if (qtconfManualPath) + return new QSettings(*qtconfManualPath, QSettings::IniFormat); QString qtconfig = QStringLiteral(":/qt/etc/qt.conf"); if (QFile::exists(qtconfig)) @@ -122,8 +131,6 @@ static QSettings *findConfiguration() return nullptr; //no luck } -const QString *QLibraryInfoPrivate::qtconfManualPath = nullptr; - QSettings *QLibraryInfoPrivate::configuration() { QLibrarySettings *ls = qt_library_settings(); @@ -236,6 +243,19 @@ QLibraryInfo::isDebugBuild() noexcept } /*! + \since 6.5 + Returns \c true if this is a shared (dynamic) build of Qt. +*/ +bool QLibraryInfo::isSharedBuild() noexcept +{ +#ifdef QT_SHARED + return true; +#else + return false; +#endif +} + +/*! \since 5.8 Returns the version of the Qt library. @@ -352,6 +372,11 @@ static QString getRelocatablePrefix(QLibraryInfoPrivate::UsageMode usageMode) const QString prefixDir = QString(libDirCFString) + "/" QT_CONFIGURE_LIBLOCATION_TO_PREFIX_PATH; prefixPath = QDir::cleanPath(prefixDir); +#elif defined(Q_OS_WASM) + // Emscripten expects to find shared libraries at the root of the in-memory + // file system when resolving dependencies for for dlopen() calls. So that's + // where libqt6core.so would be. + prefixPath = QStringLiteral("/"); #elif QT_CONFIG(dlopen) Q_UNUSED(usageMode); Dl_info info; @@ -462,9 +487,8 @@ QLibraryInfoPrivate::LocationInfo QLibraryInfoPrivate::locationInfo(QLibraryInfo "Examples", "examples", "Tests", "tests" ); - static constexpr QByteArrayView dot = qtConfEntries.viewAt(1); - static_assert(dot.size() == 1); - static_assert(dot[0] == '.'); + [[maybe_unused]] + constexpr QByteArrayView dot{"."}; LocationInfo result; @@ -492,75 +516,123 @@ QLibraryInfoPrivate::LocationInfo QLibraryInfoPrivate::locationInfo(QLibraryInfo /*! \since 6.0 Returns the path specified by \a p. + + If there is more than one path listed in qt.conf, it will + only return the first one. + \sa paths */ QString QLibraryInfo::path(LibraryPath p) { return QLibraryInfoPrivate::path(p); } +/*! + \since 6.8 + Returns all paths specificied by \a p. -/* - Returns the path specified by \a p. - - The usage mode can be set to UsedFromQtBinDir to enable special handling for executables that - live in <install-prefix>/bin. + \sa path */ -QString QLibraryInfoPrivate::path(QLibraryInfo::LibraryPath p, UsageMode usageMode) +QStringList QLibraryInfo::paths(LibraryPath p) +{ + return QLibraryInfoPrivate::paths(p); +} + + +static QString normalizePath(QString ret) +{ + qsizetype startIndex = 0; + /* We support placeholders of the form $(<ENV_VAR>) in qt.conf. + The loop below tries to find all such placeholders, and replaces + them with the actual value of the ENV_VAR environment variable + */ + while (true) { + startIndex = ret.indexOf(u'$', startIndex); + if (startIndex < 0) + break; + if (ret.size() < startIndex + 3) + break; + if (ret.at(startIndex + 1) != u'(') { + startIndex++; + continue; + } + qsizetype endIndex = ret.indexOf(u')', startIndex + 2); + if (endIndex < 0) + break; + auto envVarName = QStringView{ret}.sliced(startIndex + 2, endIndex - startIndex - 2); + QString value = qEnvironmentVariable(envVarName.toLocal8Bit().constData()); + ret.replace(startIndex, endIndex - startIndex + 1, value); + startIndex += value.size(); + } + return QDir::fromNativeSeparators(ret); +}; + +static bool keepQtBuildDefaults() +{ +#if QT_CONFIG(settings) + QSettings *config = QLibraryInfoPrivate::configuration(); + Q_ASSERT(config != nullptr); + return config->value("Config/MergeQtConf", false).toBool(); +#else + return false; +#endif +} + +#if QT_CONFIG(settings) +static QVariant libraryPathToValue(QLibraryInfo::LibraryPath loc) +{ + QVariant value; + auto li = QLibraryInfoPrivate::locationInfo(loc); + if (li.key.isNull()) + return value; + QSettings *config = QLibraryInfoPrivate::configuration(); + Q_ASSERT(config != nullptr); + // if keepQtBuildDefaults returns true, + // we only consider explicit values listed in qt.conf + QVariant defaultValue = keepQtBuildDefaults() + ? QVariant() + : QVariant(li.defaultValue); + config->beginGroup("Paths"_L1); + auto cleanup = qScopeGuard([&]() { config->endGroup(); }); + if (li.fallbackKey.isNull()) { + value = config->value(li.key, defaultValue); + } else { + value = config->value(li.key); + if (!value.isValid()) + value = config->value(li.fallbackKey, defaultValue); + } + return value; +} +#endif // settings + +QStringList QLibraryInfoPrivate::paths(QLibraryInfo::LibraryPath p, + UsageMode usageMode) { const QLibraryInfo::LibraryPath loc = p; - QString ret; + QList<QString> ret; bool fromConf = false; #if QT_CONFIG(settings) if (havePaths()) { fromConf = true; - auto li = QLibraryInfoPrivate::locationInfo(loc); - if (!li.key.isNull()) { - QSettings *config = QLibraryInfoPrivate::configuration(); - Q_ASSERT(config != nullptr); - config->beginGroup("Paths"_L1); - - if (li.fallbackKey.isNull()) { - ret = config->value(li.key, li.defaultValue).toString(); - } else { - QVariant v = config->value(li.key); - if (!v.isValid()) - v = config->value(li.fallbackKey, li.defaultValue); - ret = v.toString(); - } - - int startIndex = 0; - forever { - startIndex = ret.indexOf(u'$', startIndex); - if (startIndex < 0) - break; - if (ret.length() < startIndex + 3) - break; - if (ret.at(startIndex + 1) != u'(') { - startIndex++; - continue; - } - int endIndex = ret.indexOf(u')', startIndex + 2); - if (endIndex < 0) - break; - auto envVarName = QStringView{ret}.mid(startIndex + 2, endIndex - startIndex - 2); - QString value = QString::fromLocal8Bit(qgetenv(envVarName.toLocal8Bit().constData())); - ret.replace(startIndex, endIndex - startIndex + 1, value); - startIndex += value.length(); - } - - config->endGroup(); + QVariant value = libraryPathToValue(loc); + if (value.isValid()) { - ret = QDir::fromNativeSeparators(ret); + if (auto *asList = get_if<QList<QString>>(&value)) + ret = std::move(*asList); + else + ret = QList<QString>({ std::move(value).toString()}); + for (qsizetype i = 0, end = ret.size(); i < end; ++i) + ret[i] = normalizePath(ret[i]); } } #endif // settings - if (!fromConf) { + if (!fromConf || keepQtBuildDefaults()) { + QString noConfResult; if (loc == QLibraryInfo::PrefixPath) { - ret = getPrefix(usageMode); + noConfResult = getPrefix(usageMode); } else if (int(loc) <= qt_configure_strs.count()) { - ret = QString::fromLocal8Bit(qt_configure_strs.viewAt(loc - 1)); + noConfResult = QString::fromLocal8Bit(qt_configure_strs.viewAt(loc - 1)); #ifndef Q_OS_WIN // On Windows we use the registry } else if (loc == QLibraryInfo::SettingsPath) { // Use of volatile is a hack to discourage compilers from calling @@ -568,24 +640,39 @@ QString QLibraryInfoPrivate::path(QLibraryInfo::LibraryPath p, UsageMode usageMo // compile-time, as Qt installers binary-patch the path, replacing // the dummy path seen at compile-time, typically changing length. const char *volatile path = QT_CONFIGURE_SETTINGS_PATH; - ret = QString::fromLocal8Bit(path); + noConfResult = QString::fromLocal8Bit(path); #endif } + if (!noConfResult.isEmpty()) + ret.push_back(std::move(noConfResult)); } + if (ret.isEmpty()) + return ret; - if (!ret.isEmpty() && QDir::isRelativePath(ret)) { - QString baseDir; - if (loc == QLibraryInfo::PrefixPath) { - baseDir = prefixFromAppDirHelper(); - } else { - // we make any other path absolute to the prefix directory - baseDir = path(QLibraryInfo::PrefixPath, usageMode); - } - ret = QDir::cleanPath(baseDir + u'/' + ret); + QString baseDir; + if (loc == QLibraryInfo::PrefixPath) { + baseDir = prefixFromAppDirHelper(); + } else { + // we make any other path absolute to the prefix directory + baseDir = QLibraryInfoPrivate::path(QLibraryInfo::PrefixPath, usageMode); } + for (qsizetype i = 0, end = ret.size(); i < end; ++i) + if (QDir::isRelativePath(ret[i])) + ret[i] = QDir::cleanPath(baseDir + u'/' + std::move(ret[i])); return ret; } +/* + Returns the path specified by \a p. + + The usage mode can be set to UsedFromQtBinDir to enable special handling for executables that + live in <install-prefix>/bin. + */ +QString QLibraryInfoPrivate::path(QLibraryInfo::LibraryPath p, UsageMode usageMode) +{ + return paths(p, usageMode).value(0, QString()); +} + /*! Returns additional arguments to the platform plugin matching \a platformName which can be specified as a string list using @@ -646,6 +733,42 @@ QStringList QLibraryInfo::platformPluginArguments(const QString &platformName) \deprecated Use LibraryPath with QLibraryInfo::path() instead. */ +/*! + \macro QT_VERSION_STR + \relates <QtVersion> + + This macro expands to a string that specifies Qt's version number (for + example, "6.1.2"). This is the version with which the application is + compiled. This may be a different version than the version the application + will find itself using at \e runtime. + + \sa qVersion(), QT_VERSION +*/ + +/*! + \relates <QtVersion> + + Returns the version number of Qt at runtime as a string (for example, + "6.1.2"). This is the version of the Qt library in use at \e runtime, + which need not be the version the application was \e compiled with. + + \sa QT_VERSION_STR, QLibraryInfo::version() +*/ + +const char *qVersion() noexcept +{ + return QT_VERSION_STR; +} + +#if QT_DEPRECATED_SINCE(6, 9) + +bool qSharedBuild() noexcept +{ + return QLibraryInfo::isSharedBuild(); +} + +#endif // QT_DEPRECATED_SINCE(6, 9) + QT_END_NAMESPACE #if defined(Q_CC_GNU) && defined(ELF_INTERPRETER) @@ -696,13 +819,14 @@ extern "C" void qt_core_boilerplate() __attribute__((force_align_arg_pointer)); void qt_core_boilerplate() { printf("This is the QtCore library version %s\n" - "Copyright (C) 2016 The Qt Company Ltd.\n" - "Contact: http://www.qt.io/licensing/\n" + "%s\n" + "Contact: https://www.qt.io/licensing/\n" "\n" "Installation prefix: %s\n" "Library path: %s\n" "Plugin path: %s\n", QT_PREPEND_NAMESPACE(qt_build_string)(), + QT_COPYRIGHT, QT_CONFIGURE_PREFIX_PATH, qt_configure_strs[QT_PREPEND_NAMESPACE(QLibraryInfo)::LibrariesPath - 1], qt_configure_strs[QT_PREPEND_NAMESPACE(QLibraryInfo)::PluginsPath - 1]); |