summaryrefslogtreecommitdiffstats
path: root/src/corelib/global/qlibraryinfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/global/qlibraryinfo.cpp')
-rw-r--r--src/corelib/global/qlibraryinfo.cpp177
1 files changed, 120 insertions, 57 deletions
diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp
index 92729b06f1..6ffaef8f7c 100644
--- a/src/corelib/global/qlibraryinfo.cpp
+++ b/src/corelib/global/qlibraryinfo.cpp
@@ -516,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();
- }
-
- qsizetype startIndex = 0;
- 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}.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
@@ -592,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