diff options
Diffstat (limited to 'qmake/qmakelibraryinfo.cpp')
-rw-r--r-- | qmake/qmakelibraryinfo.cpp | 272 |
1 files changed, 119 insertions, 153 deletions
diff --git a/qmake/qmakelibraryinfo.cpp b/qmake/qmakelibraryinfo.cpp index e8bb70071e..a840036613 100644 --- a/qmake/qmakelibraryinfo.cpp +++ b/qmake/qmakelibraryinfo.cpp @@ -1,42 +1,6 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** Copyright (C) 2016 Intel Corporation. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// Copyright (C) 2016 Intel Corporation. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "qmakelibraryinfo.h" @@ -46,62 +10,27 @@ #include <qsettings.h> #include <qscopedpointer.h> #include <qstringlist.h> +#include <private/qlibraryinfo_p.h> -#include <qmakeconfig.cpp> +#include <utility> QT_BEGIN_NAMESPACE -QString QMakeLibraryInfo::binaryAbsLocation; -QString QMakeLibraryInfo::qtconfManualPath; - struct QMakeLibrarySettings { QMakeLibrarySettings() { load(); } - void load(); - QScopedPointer<QSettings> settings; bool haveDevicePaths; bool haveEffectiveSourcePaths; bool haveEffectivePaths; bool havePaths; - bool reloadOnQAppAvailable; }; Q_GLOBAL_STATIC(QMakeLibrarySettings, qmake_library_settings) -QSettings *QMakeLibraryInfo::findConfiguration() -{ - QString qtconfig = libraryInfoFile(); - if (!qtconfig.isEmpty()) - return new QSettings(qtconfig, QSettings::IniFormat); - return nullptr; // no luck -} - -QSettings *QMakeLibraryInfo::configuration() -{ - QMakeLibrarySettings *ls = qmake_library_settings(); - return ls ? ls->settings.data() : nullptr; -} - -void QMakeLibraryInfo::reload() -{ - if (qmake_library_settings.exists()) - qmake_library_settings->load(); -} - -bool QMakeLibraryInfo::haveGroup(PathGroup group) -{ - QMakeLibrarySettings *ls = qmake_library_settings(); - return ls - && (group == EffectiveSourcePaths ? ls->haveEffectiveSourcePaths - : group == EffectivePaths ? ls->haveEffectivePaths - : group == DevicePaths ? ls->haveDevicePaths - : ls->havePaths); -} - void QMakeLibrarySettings::load() { - settings.reset(QMakeLibraryInfo::findConfiguration()); + QSettings *settings = QLibraryInfoPrivate::configuration(); if (settings) { QStringList children = settings->childGroups(); haveDevicePaths = children.contains(QLatin1String("DevicePaths")); @@ -110,7 +39,7 @@ void QMakeLibrarySettings::load() haveEffectiveSourcePaths || children.contains(QLatin1String("EffectivePaths")); // Backwards compat: an existing but empty file is claimed to contain the Paths section. havePaths = (!haveDevicePaths && !haveEffectivePaths - && !children.contains(QLatin1String(platformsSection))) + && !children.contains(QLatin1String("Platforms"))) || children.contains(QLatin1String("Paths")); } else { haveDevicePaths = false; @@ -120,6 +49,23 @@ void QMakeLibrarySettings::load() } } +void QMakeLibraryInfo::reload() +{ + QLibraryInfoPrivate::reload(); + if (qmake_library_settings.exists()) + qmake_library_settings->load(); +} + +bool QMakeLibraryInfo::haveGroup(PathGroup group) +{ + QMakeLibrarySettings *ls = qmake_library_settings(); + return ls + && (group == EffectiveSourcePaths ? ls->haveEffectiveSourcePaths + : group == EffectivePaths ? ls->haveEffectivePaths + : group == DevicePaths ? ls->haveDevicePaths + : ls->havePaths); +} + void QMakeLibraryInfo::sysrootify(QString &path) { // Acceptable values for SysrootifyPrefixPath are "true" and "false" @@ -130,7 +76,7 @@ void QMakeLibraryInfo::sysrootify(QString &path) if (sysroot.isEmpty()) return; - if (path.length() > 2 && path.at(1) == QLatin1Char(':') + if (path.size() > 2 && path.at(1) == QLatin1Char(':') && (path.at(2) == QLatin1Char('/') || path.at(2) == QLatin1Char('\\'))) { path.replace(0, 2, sysroot); // Strip out the drive on Windows targets } else { @@ -138,24 +84,84 @@ void QMakeLibraryInfo::sysrootify(QString &path) } } -QString QMakeLibraryInfo::getPrefix() -{ - const QString canonicalQMakePath = QFileInfo(binaryAbsLocation).canonicalPath(); - return QDir::cleanPath(canonicalQMakePath + QLatin1Char('/') - + QLatin1String(QT_CONFIGURE_RELATIVE_PREFIX_PATH)); -} - QString QMakeLibraryInfo::path(int loc) { QString ret = rawLocation(loc, QMakeLibraryInfo::FinalPaths); // Automatically prepend the sysroot to target paths - if (loc < QMakeLibraryInfo::SysrootPath || loc > QMakeLibraryInfo::LastHostPath) + if (loc < QMakeLibraryInfo::FirstHostPath) sysrootify(ret); return ret; } +static QLibraryInfo::LibraryPath hostToTargetPathEnum(int loc) +{ + static std::pair<int, QLibraryInfo::LibraryPath> mapping[] = { + { QMakeLibraryInfo::HostBinariesPath, QLibraryInfo::BinariesPath }, + { QMakeLibraryInfo::HostLibraryExecutablesPath, QLibraryInfo::LibraryExecutablesPath }, + { QMakeLibraryInfo::HostLibrariesPath, QLibraryInfo::LibrariesPath }, + { QMakeLibraryInfo::HostDataPath, QLibraryInfo::DataPath }, + { QMakeLibraryInfo::HostPrefixPath, QLibraryInfo::PrefixPath } + }; + for (size_t i = 0; i < sizeof(mapping) / sizeof(mapping[0]); ++i) { + if (mapping[i].first == loc) + return mapping[i].second; + } + qFatal("Unhandled host path %d in hostToTargetPathEnum.", loc); + Q_UNREACHABLE(); +} + +static QLibraryInfoPrivate::LocationInfo defaultLocationInfo(int loc) +{ + QLibraryInfoPrivate::LocationInfo result; + + if (loc < QMakeLibraryInfo::FirstHostPath) { + result = QLibraryInfoPrivate::locationInfo(static_cast<QLibraryInfo::LibraryPath>(loc)); + } else if (loc <= QMakeLibraryInfo::LastHostPath) { + result = QLibraryInfoPrivate::locationInfo(hostToTargetPathEnum(loc)); + result.key.prepend(QStringLiteral("Host")); + } else if (loc == QMakeLibraryInfo::SysrootPath) { + result.key = QStringLiteral("Sysroot"); + } else if (loc == QMakeLibraryInfo::SysrootifyPrefixPath) { + result.key = QStringLiteral("SysrootifyPrefix"); + } else if (loc == QMakeLibraryInfo::TargetSpecPath) { + result.key = QStringLiteral("TargetSpec"); + } else if (loc == QMakeLibraryInfo::HostSpecPath) { + result.key = QStringLiteral("HostSpec"); + } + return result; +} + +static QString libraryInfoPath(QLibraryInfo::LibraryPath location) +{ + return QLibraryInfoPrivate::path(location, QLibraryInfoPrivate::UsedFromQtBinDir); +} + +static QString storedPath(int loc) +{ + QString result; + if (loc < QMakeLibraryInfo::FirstHostPath) { + result = libraryInfoPath(static_cast<QLibraryInfo::LibraryPath>(loc)); + } else if (loc <= QMakeLibraryInfo::LastHostPath) { + if (loc == QMakeLibraryInfo::HostDataPath) { + // Handle QT_HOST_DATADIR specially. It is not necessarily equal to QT_INSTALL_DATA. + result = QT_HOST_DATADIR; + } else { + result = libraryInfoPath(hostToTargetPathEnum(loc)); + } + } else if (loc == QMakeLibraryInfo::SysrootPath) { + // empty result + } else if (loc == QMakeLibraryInfo::SysrootifyPrefixPath) { + result = QStringLiteral("false"); + } else if (loc == QMakeLibraryInfo::TargetSpecPath) { + result = QT_TARGET_MKSPEC; + } else if (loc == QMakeLibraryInfo::HostSpecPath) { + result = QT_HOST_MKSPEC; + } + return result; +} + QString QMakeLibraryInfo::rawLocation(int loc, QMakeLibraryInfo::PathGroup group) { QString ret; @@ -175,37 +181,32 @@ QString QMakeLibraryInfo::rawLocation(int loc, QMakeLibraryInfo::PathGroup group || (group = orig_group, false)) { fromConf = true; - QString key; - QString defaultValue; - if (unsigned(loc) < sizeof(qtConfEntries) / sizeof(qtConfEntries[0])) { - key = QLatin1String(qtConfEntries[loc].key); - defaultValue = QLatin1String(qtConfEntries[loc].value); - } -#ifndef Q_OS_WIN // On Windows we use the registry - else if (loc == QLibraryInfo::SettingsPath) { - key = QLatin1String("Settings"); - defaultValue = QLatin1String("."); - } -#endif - if (!key.isNull()) { - QSettings *config = QMakeLibraryInfo::configuration(); + QLibraryInfoPrivate::LocationInfo locinfo = defaultLocationInfo(loc); + if (!locinfo.key.isNull()) { + QSettings *config = QLibraryInfoPrivate::configuration(); + Q_ASSERT(config != nullptr); config->beginGroup(QLatin1String(group == DevicePaths ? "DevicePaths" : group == EffectiveSourcePaths ? "EffectiveSourcePaths" : group == EffectivePaths ? "EffectivePaths" : "Paths")); - ret = config->value(key, defaultValue).toString(); + if (locinfo.fallbackKey.isNull()) { + ret = config->value(locinfo.key).toString(); + } else { + QVariant v = config->value(locinfo.key); + if (!v.isValid()) + v = config->value(locinfo.fallbackKey); + ret = v.toString(); + } if (ret.isEmpty()) { - if (loc == HostPrefixPath) - ret = config->value(QLatin1String(qtConfEntries[QLibraryInfo::PrefixPath].key), - QLatin1String( - qtConfEntries[QLibraryInfo::PrefixPath].value)) - .toString(); - else if (loc == TargetSpecPath || loc == HostSpecPath - || loc == SysrootifyPrefixPath) + if (loc == HostPrefixPath || loc == TargetSpecPath || loc == HostSpecPath + || loc == SysrootifyPrefixPath || loc == QLibraryInfo::PrefixPath) { fromConf = false; + } else { + ret = locinfo.defaultValue; + } // The last case here is SysrootPath, which can be legitimately empty. // All other keys have non-empty fallbacks to start with. } @@ -216,7 +217,7 @@ QString QMakeLibraryInfo::rawLocation(int loc, QMakeLibraryInfo::PathGroup group startIndex = ret.indexOf(QLatin1Char('$'), startIndex); if (startIndex < 0) break; - if (ret.length() < startIndex + 3) + if (ret.size() < startIndex + 3) break; if (ret.at(startIndex + 1) != QLatin1Char('(')) { startIndex++; @@ -230,7 +231,7 @@ QString QMakeLibraryInfo::rawLocation(int loc, QMakeLibraryInfo::PathGroup group QString value = QString::fromLocal8Bit(qgetenv(envVarName.toLocal8Bit().constData())); ret.replace(startIndex, endIndex - startIndex + 1, value); - startIndex += value.length(); + startIndex += value.size(); } config->endGroup(); @@ -238,30 +239,8 @@ QString QMakeLibraryInfo::rawLocation(int loc, QMakeLibraryInfo::PathGroup group } } - if (!fromConf) { - // "volatile" here is a hack to prevent compilers from doing a - // compile-time strlen() on "path". The issue is that Qt installers - // will binary-patch the Qt installation paths -- in such scenarios, Qt - // will be built with a dummy path, thus the compile-time result of - // strlen is meaningless. - const char *volatile path = nullptr; - if (loc == QLibraryInfo::PrefixPath) { - ret = getPrefix(); - } else if (unsigned(loc) - <= sizeof(qt_configure_str_offsets) / sizeof(qt_configure_str_offsets[0])) { - path = qt_configure_strs + qt_configure_str_offsets[loc - 1]; -#ifndef Q_OS_WIN // On Windows we use the registry - } else if (loc == QLibraryInfo::SettingsPath) { - path = QT_CONFIGURE_SETTINGS_PATH; -#endif - } else if (loc == HostPrefixPath) { - static const QByteArray hostPrefixPath = getPrefix().toLatin1(); - path = hostPrefixPath.constData(); - } - - if (path) - ret = QString::fromLocal8Bit(path); - } + if (!fromConf) + ret = storedPath(loc); // These values aren't actually paths and thus need to be returned verbatim. if (loc == TargetSpecPath || loc == HostSpecPath || loc == SysrootifyPrefixPath) @@ -273,8 +252,11 @@ QString QMakeLibraryInfo::rawLocation(int loc, QMakeLibraryInfo::PathGroup group // We make the prefix/sysroot path absolute to the executable's directory. // loc == PrefixPath while a sysroot is set would make no sense here. // loc == SysrootPath only makes sense if qmake lives inside the sysroot itself. - baseDir = QFileInfo(libraryInfoFile()).absolutePath(); - } else if (loc > SysrootPath && loc <= LastHostPath) { + QSettings *config = QLibraryInfoPrivate::configuration(); + if (config != nullptr) { + baseDir = QFileInfo(config->fileName()).absolutePath(); + } + } else if (loc >= FirstHostPath && loc <= LastHostPath) { // We make any other host path absolute to the host prefix directory. baseDir = rawLocation(HostPrefixPath, group); } else { @@ -288,20 +270,4 @@ QString QMakeLibraryInfo::rawLocation(int loc, QMakeLibraryInfo::PathGroup group return ret; } -QString QMakeLibraryInfo::libraryInfoFile() -{ - if (!qtconfManualPath.isEmpty()) - return qtconfManualPath; - if (!binaryAbsLocation.isEmpty()) { - QDir dir(QFileInfo(binaryAbsLocation).absolutePath()); - QString qtconfig = dir.filePath("qt" QT_STRINGIFY(QT_VERSION_MAJOR) ".conf"); - if (QFile::exists(qtconfig)) - return qtconfig; - qtconfig = dir.filePath("qt.conf"); - if (QFile::exists(qtconfig)) - return qtconfig; - } - return QString(); -} - QT_END_NAMESPACE |