diff options
Diffstat (limited to 'src/plugins/qtsupport/baseqtversion.cpp')
-rw-r--r-- | src/plugins/qtsupport/baseqtversion.cpp | 217 |
1 files changed, 108 insertions, 109 deletions
diff --git a/src/plugins/qtsupport/baseqtversion.cpp b/src/plugins/qtsupport/baseqtversion.cpp index e9feec7f2a..85d71a9e0e 100644 --- a/src/plugins/qtsupport/baseqtversion.cpp +++ b/src/plugins/qtsupport/baseqtversion.cpp @@ -53,9 +53,9 @@ #include <utils/hostosinfo.h> #include <utils/macroexpander.h> #include <utils/qtcassert.h> +#include <utils/qtcprocess.h> #include <utils/runextensions.h> #include <utils/stringutils.h> -#include <utils/synchronousprocess.h> #include <utils/winutils.h> #include <resourceeditor/resourcenode.h> @@ -196,8 +196,10 @@ public: static QString qmakeProperty(const QHash<ProKey, ProString> &versionInfo, const QByteArray &name, PropertyVariant variant = PropertyVariantGet); - static FilePath mkspecDirectoryFromVersionInfo(const QHash<ProKey,ProString> &versionInfo); - static FilePath mkspecFromVersionInfo(const QHash<ProKey,ProString> &versionInfo); + static FilePath mkspecDirectoryFromVersionInfo(const QHash<ProKey, ProString> &versionInfo, + const FilePath &qmakeCommand); + static FilePath mkspecFromVersionInfo(const QHash<ProKey,ProString> &versionInfo, + const FilePath &qmakeCommand); static FilePath sourcePath(const QHash<ProKey,ProString> &versionInfo); void setId(int id); // used by the qtversionmanager for legacy restore // and by the qtoptionspage to replace Qt versions @@ -495,6 +497,10 @@ QSet<Id> BaseQtVersion::availableFeatures() const if (qtVersion().matches(5, 15)) return features; + // Qt 6 uses versionless imports + features.unite(versionedIds(Constants::FEATURE_QT_QUICK_PREFIX, 6, -1)); + features.unite(versionedIds(Constants::FEATURE_QT_QUICK_CONTROLS_2_PREFIX, 6, -1)); + return features; } @@ -718,11 +724,24 @@ void BaseQtVersion::fromMap(const QVariantMap &map) d->m_isAutodetected = map.value(QTVERSIONAUTODETECTED).toBool(); d->m_autodetectionSource = map.value(QTVERSIONAUTODETECTIONSOURCE).toString(); d->m_overrideFeatures = Utils::Id::fromStringList(map.value(QTVERSION_OVERRIDE_FEATURES).toStringList()); - QString string = map.value(QTVERSIONQMAKEPATH).toString(); + d->m_qmakeCommand = FilePath::fromVariant(map.value(QTVERSIONQMAKEPATH)); + + QString string = d->m_qmakeCommand.toString(); if (string.startsWith('~')) string.remove(0, 1).prepend(QDir::homePath()); + if (!d->m_qmakeCommand.needsDevice()) { + // FIXME: generalize for all devices. + QFileInfo fi(string); + if (BuildableHelperLibrary::isQtChooser(fi)) { + // we don't want to treat qtchooser as a normal qmake + // see e.g. QTCREATORBUG-9841, also this lead to users changing what + // qtchooser forwards too behind our backs, which will inadvertly lead to bugs + string = BuildableHelperLibrary::qtChooserToQmakePath(fi.symLinkTarget()); + d->m_qmakeCommand = FilePath::fromString(string); + } + } - d->m_data.qtSources = FilePath::fromUserInput(map.value(QTVERSIONSOURCEPATH).toString()); + d->m_data.qtSources = FilePath::fromVariant(map.value(QTVERSIONSOURCEPATH)); // Handle ABIs provided by the SDKTool: // Note: Creator does not write these settings itself, so it has to come from the SDKTool! @@ -731,15 +750,6 @@ void BaseQtVersion::fromMap(const QVariantMap &map) d->m_data.qtAbis = Utils::filtered(d->m_data.qtAbis, &Abi::isValid); d->m_data.hasQtAbis = !d->m_data.qtAbis.isEmpty(); - QFileInfo fi(string); - if (BuildableHelperLibrary::isQtChooser(fi)) { - // we don't want to treat qtchooser as a normal qmake - // see e.g. QTCREATORBUG-9841, also this lead to users changing what - // qtchooser forwards too behind our backs, which will inadvertly lead to bugs - string = BuildableHelperLibrary::qtChooserToQmakePath(fi.symLinkTarget()); - } - - d->m_qmakeCommand = FilePath::fromString(string); updateDefaultDisplayName(); // Clear the cached qmlscene command, it might not match the restored path anymore. @@ -751,12 +761,13 @@ QVariantMap BaseQtVersion::toMap() const QVariantMap result; result.insert(Constants::QTVERSIONID, uniqueId()); d->m_data.unexpandedDisplayName.toMap(result, Constants::QTVERSIONNAME); + result.insert(QTVERSIONAUTODETECTED, isAutodetected()); result.insert(QTVERSIONAUTODETECTIONSOURCE, autodetectionSource()); if (!d->m_overrideFeatures.isEmpty()) result.insert(QTVERSION_OVERRIDE_FEATURES, Utils::Id::toStringList(d->m_overrideFeatures)); - result.insert(QTVERSIONQMAKEPATH, qmakeCommand().toString()); + result.insert(QTVERSIONQMAKEPATH, qmakeCommand().toVariant()); return result; } @@ -1138,13 +1149,13 @@ void BaseQtVersionPrivate::updateMkspec() return; m_mkspecUpToDate = true; - m_mkspecFullPath = mkspecFromVersionInfo(versionInfo()); + m_mkspecFullPath = mkspecFromVersionInfo(versionInfo(), m_qmakeCommand); m_mkspec = m_mkspecFullPath; if (m_mkspecFullPath.isEmpty()) return; - FilePath baseMkspecDir = mkspecDirectoryFromVersionInfo(versionInfo()); + FilePath baseMkspecDir = mkspecDirectoryFromVersionInfo(versionInfo(), m_qmakeCommand); if (m_mkspec.isChildOf(baseMkspecDir)) { m_mkspec = m_mkspec.relativeChildPath(baseMkspecDir); @@ -1171,7 +1182,9 @@ void BaseQtVersion::ensureMkSpecParsed() const QMakeVfs vfs; QMakeGlobals option; applyProperties(&option); - option.environment = qmakeRunEnvironment().toProcessEnvironment(); + Environment env = Environment::systemEnvironment(); // FIXME: Use build device + setupQmakeRunEnvironment(env); + option.environment = env.toProcessEnvironment(); ProMessageHandler msgHandler(true); ProFileCacheManager::instance()->incRefCount(); QMakeParser parser(ProFileCacheManager::instance()->cache(), &vfs, &msgHandler); @@ -1299,60 +1312,49 @@ void BaseQtVersionPrivate::updateVersionInfo() } m_qmakeIsExecutable = true; - m_data.prefix = FilePath::fromUserInput(qmakeProperty("QT_INSTALL_PREFIX")); - - m_data.binPath = FilePath::fromUserInput(qmakeProperty("QT_INSTALL_BINS")); - m_data.libExecPath = FilePath::fromUserInput(qmakeProperty("QT_INSTALL_LIBEXECS")); - m_data.configurationPath = FilePath::fromUserInput(qmakeProperty("QT_INSTALL_CONFIGURATION")); - m_data.dataPath = FilePath::fromUserInput(qmakeProperty("QT_INSTALL_DATA")); - m_data.demosPath = FilePath::fromString( - QFileInfo(qmakeProperty("QT_INSTALL_DEMOS")).canonicalFilePath()); - m_data.docsPath = FilePath::fromUserInput(qmakeProperty("QT_INSTALL_DOCS")); - m_data.examplesPath = FilePath::fromString( - QFileInfo(qmakeProperty("QT_INSTALL_EXAMPLES")).canonicalFilePath()); - m_data.headerPath = FilePath::fromUserInput(qmakeProperty("QT_INSTALL_HEADERS")); - m_data.importsPath = FilePath::fromUserInput(qmakeProperty("QT_INSTALL_IMPORTS")); - m_data.libraryPath = FilePath::fromUserInput(qmakeProperty("QT_INSTALL_LIBS")); - m_data.pluginPath = FilePath::fromUserInput(qmakeProperty("QT_INSTALL_PLUGINS")); - m_data.qmlPath = FilePath::fromUserInput(qmakeProperty("QT_INSTALL_QML")); - m_data.translationsPath = FilePath::fromUserInput(qmakeProperty("QT_INSTALL_TRANSLATIONS")); - - m_data.hostBinPath = FilePath::fromUserInput(qmakeProperty("QT_HOST_BINS")); - m_data.hostLibexecPath = FilePath::fromUserInput(qmakeProperty("QT_HOST_LIBEXECS")); - m_data.hostDataPath = FilePath::fromUserInput(qmakeProperty("QT_HOST_DATA")); - m_data.hostPrefixPath = FilePath::fromUserInput(qmakeProperty("QT_HOST_PREFIX")); - - const QString qtHeaderData = q->headerPath().toString(); + auto fileProperty = [this](const QByteArray &name) { + return FilePath::fromUserInput(qmakeProperty(name)).onDevice(m_qmakeCommand); + }; + + m_data.prefix = fileProperty("QT_INSTALL_PREFIX"); + m_data.binPath = fileProperty("QT_INSTALL_BINS"); + m_data.libExecPath = fileProperty("QT_INSTALL_LIBEXECS"); + m_data.configurationPath = fileProperty("QT_INSTALL_CONFIGURATION"); + m_data.dataPath = fileProperty("QT_INSTALL_DATA"); + m_data.demosPath = fileProperty("QT_INSTALL_DEMOS"); + m_data.docsPath = fileProperty("QT_INSTALL_DOCS"); + m_data.examplesPath = fileProperty("QT_INSTALL_EXAMPLES"); + m_data.headerPath = fileProperty("QT_INSTALL_HEADERS"); + m_data.importsPath = fileProperty("QT_INSTALL_IMPORTS"); + m_data.libraryPath = fileProperty("QT_INSTALL_LIBS"); + m_data.pluginPath = fileProperty("QT_INSTALL_PLUGINS"); + m_data.qmlPath = fileProperty("QT_INSTALL_QML"); + m_data.translationsPath = fileProperty("QT_INSTALL_TRANSLATIONS"); + m_data.hostBinPath = fileProperty("QT_HOST_BINS"); + m_data.hostLibexecPath = fileProperty("QT_HOST_LIBEXECS"); + m_data.hostDataPath = fileProperty("QT_HOST_DATA"); + m_data.hostPrefixPath = fileProperty("QT_HOST_PREFIX"); // Now check for a qt that is configured with a prefix but not installed - QString installDir = q->hostBinPath().toString(); - if (!installDir.isNull()) { - if (!QFileInfo::exists(installDir)) - m_data.installed = false; - } + if (!m_data.hostBinPath.isReadableDir()) + m_data.installed = false; + // Framework builds for Qt 4.8 don't use QT_INSTALL_HEADERS // so we don't check on mac if (!HostOsInfo::isMacHost()) { - if (!qtHeaderData.isNull()) { - if (!QFileInfo::exists(qtHeaderData)) - m_data.installed = false; - } - } - const QString qtInstallDocs = q->docsPath().toString(); - if (!qtInstallDocs.isEmpty()) { - if (QFileInfo::exists(qtInstallDocs)) - m_data.hasDocumentation = true; - } - const QString qtInstallExamples = q->examplesPath().toString(); - if (!qtInstallExamples.isEmpty()) { - if (QFileInfo::exists(qtInstallExamples)) - m_data.hasExamples = true; - } - const QString qtInstallDemos = q->demosPath().toString(); - if (!qtInstallDemos.isEmpty()) { - if (QFileInfo::exists(qtInstallDemos)) - m_data.hasDemos = true; + if (!m_data.headerPath.isReadableDir()) + m_data.installed = false; } + + if (m_data.docsPath.isReadableDir()) + m_data.hasDocumentation = true; + + if (m_data.examplesPath.isReadableDir()) + m_data.hasExamples = true; + + if (m_data.demosPath.isReadableDir()) + m_data.hasDemos = true; + m_data.qtVersionString = qmakeProperty("QT_VERSION"); m_isUpdating = false; @@ -1706,9 +1708,17 @@ void BaseQtVersion::addToEnvironment(const Kit *k, Environment &env) const // One such example is Blackberry which for some reason decided to always use the same // qmake and use environment variables embedded in their mkspecs to make that point to // the different Qt installations. + Environment BaseQtVersion::qmakeRunEnvironment() const { - return Environment::systemEnvironment(); + Environment env = Environment::systemEnvironment(); // FIXME: Use build environment + setupQmakeRunEnvironment(env); + return env; +} + +void BaseQtVersion::setupQmakeRunEnvironment(Environment &env) const +{ + Q_UNUSED(env); } bool BaseQtVersion::hasQmlDumpWithRelocatableFlag() const @@ -1729,12 +1739,11 @@ Tasks BaseQtVersion::reportIssuesImpl(const QString &proFile, const QString &bui results.append(BuildSystemTask(Task::Error, msg)); } - QFileInfo qmakeInfo = qmakeCommand().toFileInfo(); - if (!qmakeInfo.exists() || - !qmakeInfo.isExecutable()) { + FilePath qmake = qmakeCommand(); + if (!qmake.isExecutableFile()) { //: %1: Path to qmake executable const QString msg = QCoreApplication::translate("QmakeProjectManager::QtVersion", - "The qmake command \"%1\" was not found or is not executable.").arg(qmakeCommand().toUserOutput()); + "The qmake command \"%1\" was not found or is not executable.").arg(qmake.toUserOutput()); results.append(BuildSystemTask(Task::Error, msg)); } @@ -1758,8 +1767,7 @@ QtConfigWidget *BaseQtVersion::createConfigurationWidget() const return nullptr; } -static QByteArray runQmakeQuery(const FilePath &binary, const Environment &env, - QString *error) +static QByteArray runQmakeQuery(const FilePath &binary, const Environment &env, QString *error) { QTC_ASSERT(error, return QByteArray()); @@ -1768,16 +1776,18 @@ static QByteArray runQmakeQuery(const FilePath &binary, const Environment &env, // Prevent e.g. qmake 4.x on MinGW to show annoying errors about missing dll's. WindowsCrashDialogBlocker crashDialogBlocker; - QProcess process; - process.setEnvironment(env.toStringList()); - process.start(binary.toString(), QStringList("-query"), QIODevice::ReadOnly); + QtcProcess process; + process.setEnvironment(env); + process.setOpenMode(QIODevice::ReadOnly); + process.setCommand({binary, {"-query"}}); + process.start(); if (!process.waitForStarted()) { *error = QCoreApplication::translate("QtVersion", "Cannot start \"%1\": %2").arg(binary.toUserOutput()).arg(process.errorString()); return QByteArray(); } if (!process.waitForFinished(timeOutMS)) { - SynchronousProcess::stopProcess(process); + process.stopProcess(); *error = QCoreApplication::translate("QtVersion", "Timeout running \"%1\" (%2 ms).").arg(binary.toUserOutput()).arg(timeOutMS); return QByteArray(); } @@ -1797,8 +1807,7 @@ bool BaseQtVersionPrivate::queryQMakeVariables(const FilePath &binary, const Env if (!error) error = &tmp; - const QFileInfo qmake = binary.toFileInfo(); - if (!qmake.exists() || !qmake.isExecutable() || qmake.isDir()) { + if (!binary.isExecutableFile()) { *error = QCoreApplication::translate("QtVersion", "qmake \"%1\" is not an executable.").arg(binary.toUserOutput()); return false; } @@ -1839,17 +1848,19 @@ QString BaseQtVersionPrivate::qmakeProperty(const QByteArray &name, return qmakeProperty(m_versionInfo, name, variant); } -FilePath BaseQtVersionPrivate::mkspecDirectoryFromVersionInfo(const QHash<ProKey, ProString> &versionInfo) +FilePath BaseQtVersionPrivate::mkspecDirectoryFromVersionInfo(const QHash<ProKey, ProString> &versionInfo, + const FilePath &qmakeCommand) { QString dataDir = qmakeProperty(versionInfo, "QT_HOST_DATA", PropertyVariantSrc); if (dataDir.isEmpty()) return FilePath(); - return FilePath::fromUserInput(dataDir + "/mkspecs"); + return FilePath::fromUserInput(dataDir + "/mkspecs").onDevice(qmakeCommand); } -FilePath BaseQtVersionPrivate::mkspecFromVersionInfo(const QHash<ProKey, ProString> &versionInfo) +FilePath BaseQtVersionPrivate::mkspecFromVersionInfo(const QHash<ProKey, ProString> &versionInfo, + const FilePath &qmakeCommand) { - FilePath baseMkspecDir = mkspecDirectoryFromVersionInfo(versionInfo); + FilePath baseMkspecDir = mkspecDirectoryFromVersionInfo(versionInfo, qmakeCommand); if (baseMkspecDir.isEmpty()) return FilePath(); @@ -2056,35 +2067,24 @@ FilePaths BaseQtVersionPrivate::qtCorePaths() updateVersionInfo(); const QString versionString = m_data.qtVersionString; - const QString installLibsDir = q->libraryPath().toString(); - const QString installBinDir = q->binPath().toString(); - const QDir::Filters filters = QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot; - const QFileInfoList entryInfoList = [&]() { - QFileInfoList result; - if (!installLibsDir.isEmpty()) - result += QDir(installLibsDir).entryInfoList(filters); - if (!installBinDir.isEmpty()) - result += QDir(installBinDir).entryInfoList(filters); - return result; - }(); + const FilePaths entries = m_data.libraryPath.dirEntries(filters) + + m_data.binPath.dirEntries(filters); + FilePaths staticLibs; FilePaths dynamicLibs; - for (const QFileInfo &info : entryInfoList) { - const QString file = info.fileName(); - if (info.isDir() - && file.startsWith("QtCore") - && file.endsWith(".framework")) { + for (const FilePath &entry : entries) { + const QString file = entry.fileName(); + if (file.startsWith("QtCore") && file.endsWith(".framework") && entry.isReadableDir()) { // handle Framework - const FilePath lib = FilePath::fromFileInfo(info); - dynamicLibs.append(lib.pathAppended(file.left(file.lastIndexOf('.')))); - } else if (info.isReadable()) { - if (file.startsWith("libQtCore") || file.startsWith("QtCore") + dynamicLibs.append(entry.pathAppended(file.left(file.lastIndexOf('.')))); + } else if (file.startsWith("libQtCore") || file.startsWith("QtCore") || file.startsWith("libQt5Core") || file.startsWith("Qt5Core") || file.startsWith("libQt6Core") || file.startsWith("Qt6Core")) { + if (entry.isReadableFile()) { if (file.endsWith(".a") || file.endsWith(".lib")) - staticLibs.append(FilePath::fromFileInfo(info)); + staticLibs.append(entry); else if (file.endsWith(".dll") || file.endsWith(QString::fromLatin1(".so.") + versionString) || file.endsWith(".so") @@ -2092,7 +2092,7 @@ FilePaths BaseQtVersionPrivate::qtCorePaths() || file.contains(QRegularExpression("\\.so\\.[0-9]+\\.[0-9]+$")) // QTCREATORBUG-23818 #endif || file.endsWith(QLatin1Char('.') + versionString + ".dylib")) - dynamicLibs.append(FilePath::fromFileInfo(info)); + dynamicLibs.append(entry); } } } @@ -2298,7 +2298,7 @@ BaseQtVersion *QtVersionFactory::createQtVersionFromQMakePath QHash<ProKey, ProString> versionInfo; if (!BaseQtVersionPrivate::queryQMakeVariables(qmakePath, Environment::systemEnvironment(), &versionInfo, error)) return nullptr; - FilePath mkspec = BaseQtVersionPrivate::mkspecFromVersionInfo(versionInfo); + FilePath mkspec = BaseQtVersionPrivate::mkspecFromVersionInfo(versionInfo, qmakePath); QMakeVfs vfs; QMakeGlobals globals; @@ -2307,15 +2307,14 @@ BaseQtVersion *QtVersionFactory::createQtVersionFromQMakePath ProFileCacheManager::instance()->incRefCount(); QMakeParser parser(ProFileCacheManager::instance()->cache(), &vfs, &msgHandler); ProFileEvaluator evaluator(&globals, &parser, &vfs, &msgHandler); - evaluator.loadNamedSpec(mkspec.toString(), false); + evaluator.loadNamedSpec(mkspec.path(), false); QList<QtVersionFactory *> factories = g_qtVersionFactories; Utils::sort(factories, [](const QtVersionFactory *l, const QtVersionFactory *r) { return l->m_priority > r->m_priority; }); - QFileInfo fi = qmakePath.toFileInfo(); - if (!fi.exists() || !fi.isExecutable() || !fi.isFile()) + if (!qmakePath.isExecutableFile()) return nullptr; QtVersionFactory::SetupData setup; |