diff options
Diffstat (limited to 'src/corelib/global/qlibraryinfo.cpp')
-rw-r--r-- | src/corelib/global/qlibraryinfo.cpp | 206 |
1 files changed, 140 insertions, 66 deletions
diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index 715bda488c..e09d2c72e1 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(); @@ -365,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; @@ -475,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; @@ -505,75 +516,122 @@ 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 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 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 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.size() < 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.size(); - } - - 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 @@ -581,24 +639,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 @@ -745,13 +818,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]); |