diff --git a/src/plugins/qtsupport/baseqtversion.cpp b/src/plugins/qtsupport/baseqtversion.cpp index 4fdf25da2eb..12f1786f433 100644 --- a/src/plugins/qtsupport/baseqtversion.cpp +++ b/src/plugins/qtsupport/baseqtversion.cpp @@ -69,21 +69,23 @@ #include using namespace Core; -using namespace QtSupport; -using namespace QtSupport::Internal; using namespace ProjectExplorer; +using namespace QtSupport::Internal; using namespace Utils; -static const char QTVERSIONAUTODETECTED[] = "isAutodetected"; -static const char QTVERSIONAUTODETECTIONSOURCE[] = "autodetectionSource"; -static const char QTVERSION_OVERRIDE_FEATURES[] = "overrideFeatures"; -static const char QTVERSIONQMAKEPATH[] = "QMakePath"; -static const char QTVERSIONSOURCEPATH[] = "SourcePath"; +namespace QtSupport { +namespace Internal { -static const char QTVERSION_ABIS[] = "Abis"; +const char QTVERSIONAUTODETECTED[] = "isAutodetected"; +const char QTVERSIONAUTODETECTIONSOURCE[] = "autodetectionSource"; +const char QTVERSION_OVERRIDE_FEATURES[] = "overrideFeatures"; +const char QTVERSIONQMAKEPATH[] = "QMakePath"; +const char QTVERSIONSOURCEPATH[] = "SourcePath"; -static const char MKSPEC_VALUE_LIBINFIX[] = "QT_LIBINFIX"; -static const char MKSPEC_VALUE_NAMESPACE[] = "QT_NAMESPACE"; +const char QTVERSION_ABIS[] = "Abis"; + +const char MKSPEC_VALUE_LIBINFIX[] = "QT_LIBINFIX"; +const char MKSPEC_VALUE_NAMESPACE[] = "QT_NAMESPACE"; static QSet versionedIds(const QByteArray &prefix, int major, int minor) { @@ -109,6 +111,96 @@ static QSet versionedIds(const QByteArray &prefix, int major, int minor) return result; } +// Wrapper to make the std::unique_ptr "copyable": +class MacroExpanderWrapper +{ +public: + MacroExpanderWrapper() = default; + MacroExpanderWrapper(const MacroExpanderWrapper &other) { Q_UNUSED(other) } + MacroExpanderWrapper(MacroExpanderWrapper &&other) = default; + + MacroExpander *macroExpander(const BaseQtVersion *qtversion) const; +private: + mutable std::unique_ptr m_expander; +}; + +enum HostBinaries { Designer, Linguist, Uic, QScxmlc }; + +class BaseQtVersionPrivate +{ +public: + BaseQtVersionPrivate(BaseQtVersion *parent) : q(parent) {} + + void setupQmakePathAndId(const FilePath &path); + void updateVersionInfo(); + + QString findHostBinary(HostBinaries binary) const; + void updateMkspec(); + QHash versionInfo(); + static bool queryQMakeVariables(const FilePath &binary, + const Environment &env, + QHash *versionInfo, + QString *error = nullptr); + static QString qmakeProperty(const QHash &versionInfo, + const QByteArray &name, + BaseQtVersion::PropertyVariant variant = BaseQtVersion::PropertyVariantGet); + static FilePath mkspecDirectoryFromVersionInfo(const QHash &versionInfo); + static FilePath mkspecFromVersionInfo(const QHash &versionInfo); + static FilePath sourcePath(const QHash &versionInfo); + void setId(int id); // used by the qtversionmanager for legacy restore + // and by the qtoptionspage to replace Qt versions + + FilePathList qtCorePaths(); + +public: + BaseQtVersion *q; + int m_id = -1; + bool m_isAutodetected = false; + QString m_type; + + bool m_hasQmlDump = false; // controlled by m_versionInfoUpToDate + bool m_mkspecUpToDate = false; + bool m_mkspecReadUpToDate = false; + bool m_defaultConfigIsDebug = true; + bool m_defaultConfigIsDebugAndRelease = true; + bool m_frameworkBuild = false; + bool m_versionInfoUpToDate = false; + bool m_installed = true; + bool m_hasExamples = false; + bool m_hasDemos = false; + bool m_hasDocumentation = false; + bool m_qmakeIsExecutable = true; + bool m_hasQtAbis = false; + + QStringList m_configValues; + QStringList m_qtConfigValues; + + QString m_unexpandedDisplayName; + QString m_autodetectionSource; + QSet m_overrideFeatures; + FilePath m_sourcePath; + FilePath m_qtSources; + + FilePath m_mkspec; + FilePath m_mkspecFullPath; + + QHash m_mkspecValues; + + QHash m_versionInfo; + + FilePath m_qmakeCommand; + QString m_qtVersionString; + QString m_uicCommand; + QString m_designerCommand; + QString m_linguistCommand; + QString m_qscxmlcCommand; + QString m_qmlsceneCommand; + + Abis m_qtAbis; + + MacroExpanderWrapper m_expander; +}; + /////////////// // MacroExpanderWrapper /////////////// @@ -119,6 +211,8 @@ MacroExpander *MacroExpanderWrapper::macroExpander(const BaseQtVersion *qtversio return m_expander.get(); } +} // Internal + /////////////// // QtVersionNumber /////////////// @@ -195,16 +289,22 @@ bool QtVersionNumber::operator >=(const QtVersionNumber &b) const // BaseQtVersion /////////////// -BaseQtVersion::BaseQtVersion() = default; +BaseQtVersion::BaseQtVersion() + : d(new BaseQtVersionPrivate(this)) +{} -BaseQtVersion::~BaseQtVersion() = default; -void BaseQtVersion::setupQmakePathAndId(const FilePath &qmakeCommand) +BaseQtVersion::~BaseQtVersion() +{ + delete d; +} + +void BaseQtVersionPrivate::setupQmakePathAndId(const FilePath &qmakeCommand) { m_id = QtVersionManager::getUniqueId(); QTC_CHECK(m_qmakeCommand.isEmpty()); // Should only be used once. m_qmakeCommand = qmakeCommand; - setUnexpandedDisplayName(defaultUnexpandedDisplayName(m_qmakeCommand, false)); + m_unexpandedDisplayName = BaseQtVersion::defaultUnexpandedDisplayName(m_qmakeCommand, false); } QString BaseQtVersion::defaultUnexpandedDisplayName(const FilePath &qmakePath, bool fromPath) @@ -452,7 +552,7 @@ FilePath BaseQtVersion::mkspecsPath() const FilePath BaseQtVersion::qmlBinPath() const { - return FilePath::fromUserInput(m_mkspecValues.value("QT.qml.bins")); + return FilePath::fromUserInput(d->m_mkspecValues.value("QT.qml.bins")); } FilePath BaseQtVersion::librarySearchPath() const @@ -480,63 +580,52 @@ FilePathList BaseQtVersion::directoriesToIgnoreInProjectTree() const QString BaseQtVersion::qtNamespace() const { ensureMkSpecParsed(); - return m_mkspecValues.value(MKSPEC_VALUE_NAMESPACE); + return d->m_mkspecValues.value(MKSPEC_VALUE_NAMESPACE); } QString BaseQtVersion::qtLibInfix() const { ensureMkSpecParsed(); - return m_mkspecValues.value(MKSPEC_VALUE_LIBINFIX); + return d->m_mkspecValues.value(MKSPEC_VALUE_LIBINFIX); } bool BaseQtVersion::isFrameworkBuild() const { ensureMkSpecParsed(); - return m_frameworkBuild; + return d->m_frameworkBuild; } bool BaseQtVersion::hasDebugBuild() const { - return m_defaultConfigIsDebug || m_defaultConfigIsDebugAndRelease; + return d->m_defaultConfigIsDebug || d->m_defaultConfigIsDebugAndRelease; } bool BaseQtVersion::hasReleaseBuild() const { - return !m_defaultConfigIsDebug || m_defaultConfigIsDebugAndRelease; -} - -void BaseQtVersion::setId(int id) -{ - m_id = id; -} - -void BaseQtVersion::setIsAutodetected(bool isAutodetected) -{ - m_isAutodetected = isAutodetected; + return !d->m_defaultConfigIsDebug || d->m_defaultConfigIsDebugAndRelease; } void BaseQtVersion::fromMap(const QVariantMap &map) { - m_id = map.value(Constants::QTVERSIONID).toInt(); - if (m_id == -1) // this happens on adding from installer, see updateFromInstaller => get a new unique id - m_id = QtVersionManager::getUniqueId(); - m_unexpandedDisplayName = map.value(Constants::QTVERSIONNAME).toString(); - m_isAutodetected = map.value(QTVERSIONAUTODETECTED).toBool(); - if (m_isAutodetected) - m_autodetectionSource = map.value(QTVERSIONAUTODETECTIONSOURCE).toString(); - m_overrideFeatures = Core::Id::fromStringList(map.value(QTVERSION_OVERRIDE_FEATURES).toStringList()); + d->m_id = map.value(Constants::QTVERSIONID).toInt(); + if (d->m_id == -1) // this happens on adding from installer, see updateFromInstaller => get a new unique id + d->m_id = QtVersionManager::getUniqueId(); + d->m_unexpandedDisplayName = map.value(Constants::QTVERSIONNAME).toString(); + d->m_isAutodetected = map.value(QTVERSIONAUTODETECTED).toBool(); + if (d->m_isAutodetected) + d->m_autodetectionSource = map.value(QTVERSIONAUTODETECTIONSOURCE).toString(); + d->m_overrideFeatures = Core::Id::fromStringList(map.value(QTVERSION_OVERRIDE_FEATURES).toStringList()); QString string = map.value(QTVERSIONQMAKEPATH).toString(); if (string.startsWith('~')) string.remove(0, 1).prepend(QDir::homePath()); - m_qtSources = Utils::FilePath::fromUserInput( - map.value(QTVERSIONSOURCEPATH).toString()); + d->m_qtSources = FilePath::fromUserInput(map.value(QTVERSIONSOURCEPATH).toString()); // Handle ABIs provided by the SDKTool: // Note: Creator does not write these settings itself, so it has to come from the SDKTool! - m_qtAbis = Utils::transform(map.value(QTVERSION_ABIS).toStringList(), &Abi::fromString); - m_qtAbis = Utils::filtered(m_qtAbis, &Abi::isValid); - m_hasQtAbis = !m_qtAbis.isEmpty(); + d->m_qtAbis = Utils::transform(map.value(QTVERSION_ABIS).toStringList(), &Abi::fromString); + d->m_qtAbis = Utils::filtered(d->m_qtAbis, &Abi::isValid); + d->m_hasQtAbis = !d->m_qtAbis.isEmpty(); QFileInfo fi(string); if (BuildableHelperLibrary::isQtChooser(fi)) { @@ -546,10 +635,10 @@ void BaseQtVersion::fromMap(const QVariantMap &map) string = BuildableHelperLibrary::qtChooserToQmakePath(fi.symLinkTarget()); } - m_qmakeCommand = Utils::FilePath::fromString(string); + d->m_qmakeCommand = FilePath::fromString(string); // Clear the cached qmlscene command, it might not match the restored path anymore. - m_qmlsceneCommand.clear(); + d->m_qmlsceneCommand.clear(); } QVariantMap BaseQtVersion::toMap() const @@ -560,8 +649,8 @@ QVariantMap BaseQtVersion::toMap() const result.insert(QTVERSIONAUTODETECTED, isAutodetected()); if (isAutodetected()) result.insert(QTVERSIONAUTODETECTIONSOURCE, autodetectionSource()); - if (!m_overrideFeatures.isEmpty()) - result.insert(QTVERSION_OVERRIDE_FEATURES, Core::Id::toStringList(m_overrideFeatures)); + if (!d->m_overrideFeatures.isEmpty()) + result.insert(QTVERSION_OVERRIDE_FEATURES, Core::Id::toStringList(d->m_overrideFeatures)); result.insert(QTVERSIONQMAKEPATH, qmakeCommand().toString()); return result; @@ -571,14 +660,14 @@ bool BaseQtVersion::isValid() const { if (uniqueId() == -1 || displayName().isEmpty()) return false; - updateVersionInfo(); - updateMkspec(); + d->updateVersionInfo(); + d->updateMkspec(); return !qmakeCommand().isEmpty() - && m_installed + && d->m_installed && !qmakeProperty("QT_HOST_BINS").isNull() - && !m_mkspecFullPath.isEmpty() - && m_qmakeIsExecutable; + && !d->m_mkspecFullPath.isEmpty() + && d->m_qmakeIsExecutable; } BaseQtVersion::Predicate BaseQtVersion::isValidPredicate(const BaseQtVersion::Predicate &predicate) @@ -594,14 +683,14 @@ QString BaseQtVersion::invalidReason() const return QCoreApplication::translate("QtVersion", "Qt version has no name"); if (qmakeCommand().isEmpty()) return QCoreApplication::translate("QtVersion", "No qmake path set"); - if (!m_qmakeIsExecutable) + if (!d->m_qmakeIsExecutable) return QCoreApplication::translate("QtVersion", "qmake does not exist or is not executable"); - if (!m_installed) + if (!d->m_installed) return QCoreApplication::translate("QtVersion", "Qt version is not properly installed, please run make install"); if (qmakeProperty("QT_HOST_BINS").isNull()) return QCoreApplication::translate("QtVersion", "Could not determine the path to the binaries of the Qt installation, maybe the qmake path is wrong?"); - if (m_mkspecUpToDate && m_mkspecFullPath.isEmpty()) + if (d->m_mkspecUpToDate && d->m_mkspecFullPath.isEmpty()) return QCoreApplication::translate("QtVersion", "The default mkspec symlink is broken."); return QString(); } @@ -611,8 +700,8 @@ QStringList BaseQtVersion::warningReason() const QStringList ret; if (qtAbis().isEmpty()) ret << QCoreApplication::translate("QtVersion", "ABI detection failed: Make sure to use a matching compiler when building."); - if (m_versionInfo.value(ProKey("QT_INSTALL_PREFIX/get")) - != m_versionInfo.value(ProKey("QT_INSTALL_PREFIX"))) { + if (d->m_versionInfo.value(ProKey("QT_INSTALL_PREFIX/get")) + != d->m_versionInfo.value(ProKey("QT_INSTALL_PREFIX"))) { ret << QCoreApplication::translate("QtVersion", "Non-installed -prefix build - for internal development only."); } return ret; @@ -620,26 +709,26 @@ QStringList BaseQtVersion::warningReason() const FilePath BaseQtVersion::qmakeCommand() const { - return m_qmakeCommand; + return d->m_qmakeCommand; } Abis BaseQtVersion::qtAbis() const { - if (!m_hasQtAbis) { - m_qtAbis = detectQtAbis(); - m_hasQtAbis = true; + if (!d->m_hasQtAbis) { + d->m_qtAbis = detectQtAbis(); + d->m_hasQtAbis = true; } - return m_qtAbis; + return d->m_qtAbis; } Abis BaseQtVersion::detectQtAbis() const { - return qtAbisFromLibrary(qtCorePaths()); + return qtAbisFromLibrary(d->qtCorePaths()); } bool BaseQtVersion::equals(BaseQtVersion *other) { - if (m_qmakeCommand != other->m_qmakeCommand) + if (d->m_qmakeCommand != other->d->m_qmakeCommand) return false; if (type() != other->type()) return false; @@ -655,43 +744,37 @@ bool BaseQtVersion::equals(BaseQtVersion *other) int BaseQtVersion::uniqueId() const { - return m_id; + return d->m_id; } QString BaseQtVersion::type() const { - QTC_ASSERT(m_factory, return QString()); - return m_factory->supportedType(); + return d->m_type; } bool BaseQtVersion::isAutodetected() const { - return m_isAutodetected; + return d->m_isAutodetected; } QString BaseQtVersion::autodetectionSource() const { - return m_autodetectionSource; -} - -void BaseQtVersion::setAutoDetectionSource(const QString &autodetectionSource) -{ - m_autodetectionSource = autodetectionSource; + return d->m_autodetectionSource; } QString BaseQtVersion::displayName() const { - return macroExpander()->expand(m_unexpandedDisplayName); + return macroExpander()->expand(d->m_unexpandedDisplayName); } QString BaseQtVersion::unexpandedDisplayName() const { - return m_unexpandedDisplayName; + return d->m_unexpandedDisplayName; } void BaseQtVersion::setUnexpandedDisplayName(const QString &name) { - m_unexpandedDisplayName = name; + d->m_unexpandedDisplayName = name; } QString BaseQtVersion::toHtml(bool verbose) const @@ -723,13 +806,13 @@ QString BaseQtVersion::toHtml(bool verbose) const str << "" << QCoreApplication::translate("BaseQtVersion", "mkspec:") << "" << QDir::toNativeSeparators(mkspec()) << ""; str << "" << QCoreApplication::translate("BaseQtVersion", "qmake:") - << "" << m_qmakeCommand.toUserOutput() << ""; + << "" << d->m_qmakeCommand.toUserOutput() << ""; ensureMkSpecParsed(); if (!mkspecPath().isEmpty()) { - if (m_defaultConfigIsDebug || m_defaultConfigIsDebugAndRelease) { + if (d->m_defaultConfigIsDebug || d->m_defaultConfigIsDebugAndRelease) { str << "" << QCoreApplication::translate("BaseQtVersion", "Default:") << "" - << (m_defaultConfigIsDebug ? "debug" : "release"); - if (m_defaultConfigIsDebugAndRelease) + << (d->m_defaultConfigIsDebug ? "debug" : "release"); + if (d->m_defaultConfigIsDebugAndRelease) str << " debug_and_release"; str << ""; } // default config. @@ -737,7 +820,7 @@ QString BaseQtVersion::toHtml(bool verbose) const str << "" << QCoreApplication::translate("BaseQtVersion", "Version:") << "" << qtVersionString() << ""; if (verbose) { - const QHash vInfo = versionInfo(); + const QHash vInfo = d->versionInfo(); if (!vInfo.isEmpty()) { QList keys = vInfo.keys(); Utils::sort(keys); @@ -777,34 +860,34 @@ QString BaseQtVersion::toHtml(bool verbose) const FilePath BaseQtVersion::sourcePath() const { - if (m_sourcePath.isEmpty()) { - updateVersionInfo(); - m_sourcePath = sourcePath(m_versionInfo); + if (d->m_sourcePath.isEmpty()) { + d->updateVersionInfo(); + d->m_sourcePath = d->sourcePath(d->m_versionInfo); } - return m_sourcePath; + return d->m_sourcePath; } FilePath BaseQtVersion::qtPackageSourcePath() const { - return m_qtSources; + return d->m_qtSources; } QString BaseQtVersion::designerCommand() const { if (!isValid()) return QString(); - if (m_designerCommand.isNull()) - m_designerCommand = findHostBinary(Designer); - return m_designerCommand; + if (d->m_designerCommand.isNull()) + d->m_designerCommand = d->findHostBinary(Designer); + return d->m_designerCommand; } QString BaseQtVersion::linguistCommand() const { if (!isValid()) return QString(); - if (m_linguistCommand.isNull()) - m_linguistCommand = findHostBinary(Linguist); - return m_linguistCommand; + if (d->m_linguistCommand.isNull()) + d->m_linguistCommand = d->findHostBinary(Linguist); + return d->m_linguistCommand; } QString BaseQtVersion::qscxmlcCommand() const @@ -812,9 +895,9 @@ QString BaseQtVersion::qscxmlcCommand() const if (!isValid()) return QString(); - if (m_qscxmlcCommand.isNull()) - m_qscxmlcCommand = findHostBinary(QScxmlc); - return m_qscxmlcCommand; + if (d->m_qscxmlcCommand.isNull()) + d->m_qscxmlcCommand = d->findHostBinary(QScxmlc); + return d->m_qscxmlcCommand; } QString BaseQtVersion::qmlsceneCommand() const @@ -822,26 +905,26 @@ QString BaseQtVersion::qmlsceneCommand() const if (!isValid()) return QString(); - if (!m_qmlsceneCommand.isNull()) - return m_qmlsceneCommand; + if (!d->m_qmlsceneCommand.isNull()) + return d->m_qmlsceneCommand; ensureMkSpecParsed(); const QString path = - qmlBinPath().pathAppended(Utils::HostOsInfo::withExecutableSuffix("qmlscene")).toString(); + qmlBinPath().pathAppended(HostOsInfo::withExecutableSuffix("qmlscene")).toString(); - m_qmlsceneCommand = QFileInfo(path).isFile() ? path : QString(); + d->m_qmlsceneCommand = QFileInfo(path).isFile() ? path : QString(); - return m_qmlsceneCommand; + return d->m_qmlsceneCommand; } -QString BaseQtVersion::findHostBinary(HostBinaries binary) const +QString BaseQtVersionPrivate::findHostBinary(HostBinaries binary) const { QString baseDir; - if (qtVersion() < QtVersionNumber(5, 0, 0)) { - baseDir = qmakeProperty("QT_HOST_BINS"); + if (q->qtVersion() < QtVersionNumber(5, 0, 0)) { + baseDir = q->qmakeProperty("QT_HOST_BINS"); } else { - ensureMkSpecParsed(); + q->ensureMkSpecParsed(); switch (binary) { case Designer: case Linguist: @@ -849,7 +932,7 @@ QString BaseQtVersion::findHostBinary(HostBinaries binary) const break; case Uic: case QScxmlc: - baseDir = qmakeProperty("QT_HOST_BINS"); + baseDir = q->qmakeProperty("QT_HOST_BINS"); break; default: // Can't happen @@ -901,15 +984,15 @@ QString BaseQtVersion::uicCommand() const { if (!isValid()) return QString(); - if (!m_uicCommand.isNull()) - return m_uicCommand; - m_uicCommand = findHostBinary(Uic); - return m_uicCommand; + if (!d->m_uicCommand.isNull()) + return d->m_uicCommand; + d->m_uicCommand = d->findHostBinary(Uic); + return d->m_uicCommand; } -void BaseQtVersion::updateMkspec() const +void BaseQtVersionPrivate::updateMkspec() { - if (uniqueId() == -1 || m_mkspecUpToDate) + if (m_id == -1 || m_mkspecUpToDate) return; m_mkspecUpToDate = true; @@ -925,7 +1008,7 @@ void BaseQtVersion::updateMkspec() const m_mkspec = m_mkspec.relativeChildPath(baseMkspecDir); // qDebug() << "Setting mkspec to"<sourcePath().pathAppended("mkspecs"); if (m_mkspec.isChildOf(sourceMkSpecPath)) { m_mkspec = m_mkspec.relativeChildPath(sourceMkSpecPath); } else { @@ -936,9 +1019,9 @@ void BaseQtVersion::updateMkspec() const void BaseQtVersion::ensureMkSpecParsed() const { - if (m_mkspecReadUpToDate) + if (d->m_mkspecReadUpToDate) return; - m_mkspecReadUpToDate = true; + d->m_mkspecReadUpToDate = true; if (mkspecPath().isEmpty()) return; @@ -960,36 +1043,41 @@ void BaseQtVersion::ensureMkSpecParsed() const void BaseQtVersion::parseMkSpec(ProFileEvaluator *evaluator) const { - m_configValues = evaluator->values("CONFIG"); - m_qtConfigValues = evaluator->values("QT_CONFIG"); - m_defaultConfigIsDebugAndRelease = false; - m_frameworkBuild = false; - foreach (const QString &value, m_configValues) { + d->m_configValues = evaluator->values("CONFIG"); + d->m_qtConfigValues = evaluator->values("QT_CONFIG"); + d->m_defaultConfigIsDebugAndRelease = false; + d->m_frameworkBuild = false; + for (const QString &value : qAsConst(d->m_configValues)) { if (value == "debug") - m_defaultConfigIsDebug = true; + d->m_defaultConfigIsDebug = true; else if (value == "release") - m_defaultConfigIsDebug = false; + d->m_defaultConfigIsDebug = false; else if (value == "build_all") - m_defaultConfigIsDebugAndRelease = true; + d->m_defaultConfigIsDebugAndRelease = true; else if (value == "qt_framework") - m_frameworkBuild = true; + d->m_frameworkBuild = true; } const QString designerBins = "QT.designer.bins"; const QString qmlBins = "QT.qml.bins"; const QString declarativeBins = "QT.declarative.bins"; const QString libinfix = MKSPEC_VALUE_LIBINFIX; const QString ns = MKSPEC_VALUE_NAMESPACE; - m_mkspecValues.insert(designerBins, evaluator->value(designerBins)); - m_mkspecValues.insert(qmlBins, evaluator->value(qmlBins)); - m_mkspecValues.insert(declarativeBins, evaluator->value(declarativeBins)); - m_mkspecValues.insert(libinfix, evaluator->value(libinfix)); - m_mkspecValues.insert(ns, evaluator->value(ns)); + d->m_mkspecValues.insert(designerBins, evaluator->value(designerBins)); + d->m_mkspecValues.insert(qmlBins, evaluator->value(qmlBins)); + d->m_mkspecValues.insert(declarativeBins, evaluator->value(declarativeBins)); + d->m_mkspecValues.insert(libinfix, evaluator->value(libinfix)); + d->m_mkspecValues.insert(ns, evaluator->value(ns)); +} + +void BaseQtVersion::setId(int id) +{ + d->m_id = id; } QString BaseQtVersion::mkspec() const { - updateMkspec(); - return m_mkspec.toString(); + d->updateMkspec(); + return d->m_mkspec.toString(); } QString BaseQtVersion::mkspecFor(ToolChain *tc) const @@ -1012,8 +1100,8 @@ QString BaseQtVersion::mkspecFor(ToolChain *tc) const FilePath BaseQtVersion::mkspecPath() const { - updateMkspec(); - return m_mkspecFullPath; + d->updateMkspec(); + return d->m_mkspecFullPath; } bool BaseQtVersion::hasMkspec(const QString &spec) const @@ -1038,17 +1126,17 @@ BaseQtVersion::QmakeBuildConfigs BaseQtVersion::defaultBuildConfig() const ensureMkSpecParsed(); BaseQtVersion::QmakeBuildConfigs result = BaseQtVersion::QmakeBuildConfig(0); - if (m_defaultConfigIsDebugAndRelease) + if (d->m_defaultConfigIsDebugAndRelease) result = BaseQtVersion::BuildAll; - if (m_defaultConfigIsDebug) + if (d->m_defaultConfigIsDebug) result = result | BaseQtVersion::DebugBuild; return result; } QString BaseQtVersion::qtVersionString() const { - updateVersionInfo(); - return m_qtVersionString; + d->updateVersionInfo(); + return d->m_qtVersionString; } QtVersionNumber BaseQtVersion::qtVersion() const @@ -1056,7 +1144,7 @@ QtVersionNumber BaseQtVersion::qtVersion() const return QtVersionNumber(qtVersionString()); } -void BaseQtVersion::updateVersionInfo() const +void BaseQtVersionPrivate::updateVersionInfo() { if (m_versionInfoUpToDate) return; @@ -1070,10 +1158,10 @@ void BaseQtVersion::updateVersionInfo() const m_hasDocumentation = false; m_hasQmlDump = false; - if (!queryQMakeVariables(qmakeCommand(), qmakeRunEnvironment(), &m_versionInfo)) { + if (!queryQMakeVariables(m_qmakeCommand, q->qmakeRunEnvironment(), &m_versionInfo)) { m_qmakeIsExecutable = false; qWarning("Cannot update Qt version information: %s cannot be run.", - qPrintable(qmakeCommand().toString())); + qPrintable(m_qmakeCommand.toString())); return; } m_qmakeIsExecutable = true; @@ -1124,18 +1212,18 @@ void BaseQtVersion::updateVersionInfo() const m_versionInfoUpToDate = true; } -QHash BaseQtVersion::versionInfo() const +QHash BaseQtVersionPrivate::versionInfo() { updateVersionInfo(); return m_versionInfo; } -QString BaseQtVersion::qmakeProperty(const QHash &versionInfo, const QByteArray &name, - PropertyVariant variant) +QString BaseQtVersionPrivate::qmakeProperty(const QHash &versionInfo, const QByteArray &name, + BaseQtVersion::PropertyVariant variant) { QString val = versionInfo.value(ProKey(QString::fromLatin1( - name + (variant == PropertyVariantDev ? "/dev" : - variant == PropertyVariantGet ? "/get" : "/src")))).toQString(); + name + (variant == BaseQtVersion::PropertyVariantDev ? "/dev" : + variant == BaseQtVersion::PropertyVariantGet ? "/get" : "/src")))).toQString(); if (!val.isNull()) return val; return versionInfo.value(ProKey(name)).toQString(); @@ -1143,19 +1231,19 @@ QString BaseQtVersion::qmakeProperty(const QHash &versionInfo, QString BaseQtVersion::qmakeProperty(const QByteArray &name, PropertyVariant variant) const { - updateVersionInfo(); - return qmakeProperty(m_versionInfo, name, variant); + d->updateVersionInfo(); + return d->qmakeProperty(d->m_versionInfo, name, variant); } void BaseQtVersion::applyProperties(QMakeGlobals *qmakeGlobals) const { - qmakeGlobals->setProperties(versionInfo()); + qmakeGlobals->setProperties(d->versionInfo()); } bool BaseQtVersion::hasDocumentation() const { - updateVersionInfo(); - return m_hasDocumentation; + d->updateVersionInfo(); + return d->m_hasDocumentation; } QString BaseQtVersion::documentationPath() const @@ -1165,8 +1253,8 @@ QString BaseQtVersion::documentationPath() const bool BaseQtVersion::hasDemos() const { - updateVersionInfo(); - return m_hasDemos; + d->updateVersionInfo(); + return d->m_hasDemos; } QString BaseQtVersion::demosPath() const @@ -1183,8 +1271,8 @@ QString BaseQtVersion::frameworkInstallPath() const bool BaseQtVersion::hasExamples() const { - updateVersionInfo(); - return m_hasExamples; + d->updateVersionInfo(); + return d->m_hasExamples; } QString BaseQtVersion::examplesPath() const @@ -1195,18 +1283,18 @@ QString BaseQtVersion::examplesPath() const QStringList BaseQtVersion::configValues() const { ensureMkSpecParsed(); - return m_configValues; + return d->m_configValues; } QStringList BaseQtVersion::qtConfigValues() const { ensureMkSpecParsed(); - return m_qtConfigValues; + return d->m_qtConfigValues; } MacroExpander *BaseQtVersion::macroExpander() const { - return m_expander.macroExpander(this); + return d->m_expander.macroExpander(this); } std::unique_ptr @@ -1219,7 +1307,7 @@ BaseQtVersion::createMacroExpander(const std::function return version ? property(version) : QString(); }; }; - std::unique_ptr expander(new Utils::MacroExpander); + std::unique_ptr expander(new MacroExpander); expander->setDisplayName(QtKitAspect::tr("Qt version")); expander->registerVariable( @@ -1247,119 +1335,119 @@ BaseQtVersion::createMacroExpander(const std::function "Qt:QT_INSTALL_PREFIX", QtKitAspect::tr("The installation prefix of the current Qt version."), versionProperty([](const BaseQtVersion *version) { - return version->qmakeProperty(version->m_versionInfo, "QT_INSTALL_PREFIX"); + return version->d->qmakeProperty(version->d->m_versionInfo, "QT_INSTALL_PREFIX"); })); expander->registerVariable( "Qt:QT_INSTALL_DATA", QtKitAspect::tr("The installation location of the current Qt version's data."), versionProperty([](const BaseQtVersion *version) { - return version->qmakeProperty(version->m_versionInfo, "QT_INSTALL_DATA"); + return version->d->qmakeProperty(version->d->m_versionInfo, "QT_INSTALL_DATA"); })); expander->registerVariable( "Qt:QT_INSTALL_HEADERS", QtKitAspect::tr("The installation location of the current Qt version's header files."), versionProperty([](const BaseQtVersion *version) { - return version->qmakeProperty(version->m_versionInfo, "QT_INSTALL_HEADERS"); + return version->d->qmakeProperty(version->d->m_versionInfo, "QT_INSTALL_HEADERS"); })); expander->registerVariable( "Qt:QT_INSTALL_LIBS", QtKitAspect::tr("The installation location of the current Qt version's library files."), versionProperty([](const BaseQtVersion *version) { - return version->qmakeProperty(version->m_versionInfo, "QT_INSTALL_LIBS"); + return version->d->qmakeProperty(version->d->m_versionInfo, "QT_INSTALL_LIBS"); })); expander->registerVariable( "Qt:QT_INSTALL_DOCS", QtKitAspect::tr("The installation location of the current Qt version's documentation files."), versionProperty([](const BaseQtVersion *version) { - return version->qmakeProperty(version->m_versionInfo, "QT_INSTALL_DOCS"); + return version->d->qmakeProperty(version->d->m_versionInfo, "QT_INSTALL_DOCS"); })); expander->registerVariable( "Qt:QT_INSTALL_BINS", QtKitAspect::tr("The installation location of the current Qt version's executable files."), versionProperty([](const BaseQtVersion *version) { - return version->qmakeProperty(version->m_versionInfo, "QT_INSTALL_BINS"); + return version->d->qmakeProperty(version->d->m_versionInfo, "QT_INSTALL_BINS"); })); expander->registerVariable( "Qt:QT_INSTALL_PLUGINS", QtKitAspect::tr("The installation location of the current Qt version's plugins."), versionProperty([](const BaseQtVersion *version) { - return version->qmakeProperty(version->m_versionInfo, "QT_INSTALL_PLUGINS"); + return version->d->qmakeProperty(version->d->m_versionInfo, "QT_INSTALL_PLUGINS"); })); expander->registerVariable( "Qt:QT_INSTALL_QML", QtKitAspect::tr("The installation location of the current Qt version's QML files."), versionProperty([](const BaseQtVersion *version) { - return version->qmakeProperty(version->m_versionInfo, "QT_INSTALL_QML"); + return version->d->qmakeProperty(version->d->m_versionInfo, "QT_INSTALL_QML"); })); expander->registerVariable( "Qt:QT_INSTALL_IMPORTS", QtKitAspect::tr("The installation location of the current Qt version's imports."), versionProperty([](const BaseQtVersion *version) { - return version->qmakeProperty(version->m_versionInfo, "QT_INSTALL_IMPORTS"); + return version->d->qmakeProperty(version->d->m_versionInfo, "QT_INSTALL_IMPORTS"); })); expander->registerVariable( "Qt:QT_INSTALL_TRANSLATIONS", QtKitAspect::tr("The installation location of the current Qt version's translation files."), versionProperty([](const BaseQtVersion *version) { - return version->qmakeProperty(version->m_versionInfo, "QT_INSTALL_TRANSLATIONS"); + return version->d->qmakeProperty(version->d->m_versionInfo, "QT_INSTALL_TRANSLATIONS"); })); expander->registerVariable( "Qt:QT_INSTALL_CONFIGURATION", QtKitAspect::tr("The installation location of the current Qt version's translation files."), versionProperty([](const BaseQtVersion *version) { - return version->qmakeProperty(version->m_versionInfo, "QT_INSTALL_CONFIGURATION"); + return version->d->qmakeProperty(version->d->m_versionInfo, "QT_INSTALL_CONFIGURATION"); })); expander->registerVariable( "Qt:QT_INSTALL_EXAMPLES", QtKitAspect::tr("The installation location of the current Qt version's examples."), versionProperty([](const BaseQtVersion *version) { - return version->qmakeProperty(version->m_versionInfo, "QT_INSTALL_EXAMPLES"); + return version->d->qmakeProperty(version->d->m_versionInfo, "QT_INSTALL_EXAMPLES"); })); expander->registerVariable( "Qt:QT_INSTALL_DEMOS", QtKitAspect::tr("The installation location of the current Qt version's demos."), versionProperty([](const BaseQtVersion *version) { - return version->qmakeProperty(version->m_versionInfo, "QT_INSTALL_DEMOS"); + return version->d->qmakeProperty(version->d->m_versionInfo, "QT_INSTALL_DEMOS"); })); expander->registerVariable( "Qt:QMAKE_MKSPECS", QtKitAspect::tr("The current Qt version's default mkspecs (Qt 4)."), versionProperty([](const BaseQtVersion *version) { - return version->qmakeProperty(version->m_versionInfo, "QMAKE_MKSPECS"); + return version->d->qmakeProperty(version->d->m_versionInfo, "QMAKE_MKSPECS"); })); expander->registerVariable( "Qt:QMAKE_SPEC", QtKitAspect::tr("The current Qt version's default mkspec (Qt 5; host system)."), versionProperty([](const BaseQtVersion *version) { - return version->qmakeProperty(version->m_versionInfo, "QMAKE_SPEC"); + return version->d->qmakeProperty(version->d->m_versionInfo, "QMAKE_SPEC"); })); expander->registerVariable( "Qt:QMAKE_XSPEC", QtKitAspect::tr("The current Qt version's default mkspec (Qt 5; target system)."), versionProperty([](const BaseQtVersion *version) { - return version->qmakeProperty(version->m_versionInfo, "QMAKE_XSPEC"); + return version->d->qmakeProperty(version->d->m_versionInfo, "QMAKE_XSPEC"); })); expander->registerVariable( "Qt:QMAKE_VERSION", QtKitAspect::tr("The current Qt's qmake version."), versionProperty([](const BaseQtVersion *version) { - return version->qmakeProperty(version->m_versionInfo, "QMAKE_VERSION"); + return version->d->qmakeProperty(version->d->m_versionInfo, "QMAKE_VERSION"); })); // FIXME: Re-enable once we can detect expansion loops. @@ -1375,29 +1463,29 @@ BaseQtVersion::createMacroExpander(const std::function void BaseQtVersion::populateQmlFileFinder(FileInProjectFinder *finder, const Target *target) { // If target given, then use the project associated with that ... - const ProjectExplorer::Project *startupProject = target ? target->project() : nullptr; + const Project *startupProject = target ? target->project() : nullptr; // ... else try the session manager's global startup project ... if (!startupProject) - startupProject = ProjectExplorer::SessionManager::startupProject(); + startupProject = SessionManager::startupProject(); // ... and if that is null, use the first project available. - const QList projects = ProjectExplorer::SessionManager::projects(); + const QList projects = SessionManager::projects(); QTC_CHECK(projects.isEmpty() || startupProject); - Utils::FilePath projectDirectory; - Utils::FilePathList sourceFiles; + FilePath projectDirectory; + FilePathList sourceFiles; // Sort files from startupProject to the front of the list ... if (startupProject) { projectDirectory = startupProject->projectDirectory(); - sourceFiles.append(startupProject->files(ProjectExplorer::Project::SourceFiles)); + sourceFiles.append(startupProject->files(Project::SourceFiles)); } // ... then add all the other projects' files. - for (const ProjectExplorer::Project *project : projects) { + for (const Project *project : projects) { if (project != startupProject) - sourceFiles.append(project->files(ProjectExplorer::Project::SourceFiles)); + sourceFiles.append(project->files(Project::SourceFiles)); } // If no target was given, but we've found a startupProject, then try to deduce a @@ -1406,22 +1494,22 @@ void BaseQtVersion::populateQmlFileFinder(FileInProjectFinder *finder, const Tar target = startupProject->activeTarget(); // ... and find the sysroot and qml directory if we have any target at all. - const ProjectExplorer::Kit *kit = target ? target->kit() : nullptr; - const Utils::FilePath activeSysroot = ProjectExplorer::SysRootKitAspect::sysRoot(kit); - const QtSupport::BaseQtVersion *qtVersion = QtVersionManager::isLoaded() - ? QtSupport::QtKitAspect::qtVersion(kit) : nullptr; - Utils::FilePathList additionalSearchDirectories = qtVersion - ? Utils::FilePathList({qtVersion->qmlPath()}) : Utils::FilePathList(); + const Kit *kit = target ? target->kit() : nullptr; + const FilePath activeSysroot = SysRootKitAspect::sysRoot(kit); + const BaseQtVersion *qtVersion = QtVersionManager::isLoaded() + ? QtKitAspect::qtVersion(kit) : nullptr; + FilePathList additionalSearchDirectories = qtVersion + ? FilePathList({qtVersion->qmlPath()}) : FilePathList(); if (target) { - for (const ProjectExplorer::DeployableFile &file : target->deploymentData().allFiles()) + for (const DeployableFile &file : target->deploymentData().allFiles()) finder->addMappedPath(file.localFilePath(), file.remoteFilePath()); } // Add resource paths to the mapping if (startupProject) { - if (ProjectExplorer::ProjectNode *rootNode = startupProject->rootProjectNode()) { - rootNode->forEachNode([&](ProjectExplorer::FileNode *node) { + if (ProjectNode *rootNode = startupProject->rootProjectNode()) { + rootNode->forEachNode([&](FileNode *node) { if (auto resourceNode = dynamic_cast(node)) finder->addMappedPath(node->filePath(), ":" + resourceNode->qrcPath()); }); @@ -1439,9 +1527,9 @@ void BaseQtVersion::populateQmlFileFinder(FileInProjectFinder *finder, const Tar QSet BaseQtVersion::features() const { - if (m_overrideFeatures.isEmpty()) + if (d->m_overrideFeatures.isEmpty()) return availableFeatures(); - return m_overrideFeatures; + return d->m_overrideFeatures; } void BaseQtVersion::addToEnvironment(const Kit *k, Environment &env) const @@ -1462,8 +1550,8 @@ Environment BaseQtVersion::qmakeRunEnvironment() const bool BaseQtVersion::hasQmlDump() const { - updateVersionInfo(); - return m_hasQmlDump; + d->updateVersionInfo(); + return d->m_hasQmlDump; } bool BaseQtVersion::hasQmlDumpWithRelocatableFlag() const @@ -1485,7 +1573,7 @@ QString BaseQtVersion::qmlDumpTool(bool debugVersion) const void BaseQtVersion::recheckDumper() { - m_versionInfoUpToDate = false; + d->m_versionInfoUpToDate = false; } Tasks BaseQtVersion::reportIssuesImpl(const QString &proFile, const QString &buildDir) const @@ -1558,8 +1646,8 @@ static QByteArray runQmakeQuery(const FilePath &binary, const Environment &env, return process.readAllStandardOutput(); } -bool BaseQtVersion::queryQMakeVariables(const FilePath &binary, const Environment &env, - QHash *versionInfo, QString *error) +bool BaseQtVersionPrivate::queryQMakeVariables(const FilePath &binary, const Environment &env, + QHash *versionInfo, QString *error) { QString tmp; if (!error) @@ -1600,15 +1688,15 @@ bool BaseQtVersion::queryQMakeVariables(const FilePath &binary, const Environmen return true; } -FilePath BaseQtVersion::mkspecDirectoryFromVersionInfo(const QHash &versionInfo) +FilePath BaseQtVersionPrivate::mkspecDirectoryFromVersionInfo(const QHash &versionInfo) { - QString dataDir = qmakeProperty(versionInfo, "QT_HOST_DATA", PropertyVariantSrc); + QString dataDir = qmakeProperty(versionInfo, "QT_HOST_DATA", BaseQtVersion::PropertyVariantSrc); if (dataDir.isEmpty()) return FilePath(); return FilePath::fromUserInput(dataDir + "/mkspecs"); } -FilePath BaseQtVersion::mkspecFromVersionInfo(const QHash &versionInfo) +FilePath BaseQtVersionPrivate::mkspecFromVersionInfo(const QHash &versionInfo) { FilePath baseMkspecDir = mkspecDirectoryFromVersionInfo(versionInfo); if (baseMkspecDir.isEmpty()) @@ -1687,11 +1775,11 @@ FilePath BaseQtVersion::mkspecFromVersionInfo(const QHash &ve return mkspecFullPath; } -FilePath BaseQtVersion::sourcePath(const QHash &versionInfo) +FilePath BaseQtVersionPrivate::sourcePath(const QHash &versionInfo) { const QString qt5Source = qmakeProperty(versionInfo, "QT_INSTALL_PREFIX/src"); if (!qt5Source.isEmpty()) - return Utils::FilePath::fromString(QFileInfo(qt5Source).canonicalFilePath()); + return FilePath::fromString(QFileInfo(qt5Source).canonicalFilePath()); const QString installData = qmakeProperty(versionInfo, "QT_INSTALL_PREFIX"); QString sourcePath = installData; @@ -1713,9 +1801,9 @@ FilePath BaseQtVersion::sourcePath(const QHash &versionInfo) return FilePath::fromUserInput(QFileInfo(sourcePath).canonicalFilePath()); } -bool BaseQtVersion::isInSourceDirectory(const Utils::FilePath &filePath) +bool BaseQtVersion::isInSourceDirectory(const FilePath &filePath) { - const Utils::FilePath &source = sourcePath(); + const FilePath &source = sourcePath(); if (source.isEmpty()) return false; QDir dir = QDir(source.toString()); @@ -1724,9 +1812,9 @@ bool BaseQtVersion::isInSourceDirectory(const Utils::FilePath &filePath) return filePath.isChildOf(dir); } -bool BaseQtVersion::isSubProject(const Utils::FilePath &filePath) const +bool BaseQtVersion::isSubProject(const FilePath &filePath) const { - const Utils::FilePath &source = sourcePath(); + const FilePath &source = sourcePath(); if (!source.isEmpty()) { QDir dir = QDir(source.toString()); if (dir.dirName() == "qtbase") @@ -1812,7 +1900,7 @@ bool BaseQtVersion::isQtQuickCompilerSupported(QString *reason) const return true; } -FilePathList BaseQtVersion::qtCorePaths() const +FilePathList BaseQtVersionPrivate::qtCorePaths() { updateVersionInfo(); const QString &versionString = m_qtVersionString; @@ -2017,7 +2105,7 @@ static Abi refineAbiFromBuildString(const QByteArray &buildString, const Abi &pr static Abi scanQtBinaryForBuildStringAndRefineAbi(const FilePath &library, const Abi &probableAbi) { - static QHash results; + static QHash results; if (!results.contains(library)) { const QByteArray buildString = scanQtBinaryForBuildString(library); @@ -2041,12 +2129,143 @@ Abis BaseQtVersion::qtAbisFromLibrary(const FilePathList &coreLibraries) return res; } + +// QtVersionFactory + +static QList g_qtVersionFactories; + +BaseQtVersion *QtVersionFactory::createQtVersionFromQMakePath + (const FilePath &qmakePath, bool isAutoDetected, const QString &autoDetectionSource, QString *error) +{ + QHash versionInfo; + if (!BaseQtVersionPrivate::queryQMakeVariables(qmakePath, Environment::systemEnvironment(), &versionInfo, error)) + return nullptr; + FilePath mkspec = BaseQtVersionPrivate::mkspecFromVersionInfo(versionInfo); + + QMakeVfs vfs; + QMakeGlobals globals; + globals.setProperties(versionInfo); + ProMessageHandler msgHandler(false); + ProFileCacheManager::instance()->incRefCount(); + QMakeParser parser(ProFileCacheManager::instance()->cache(), &vfs, &msgHandler); + ProFileEvaluator evaluator(&globals, &parser, &vfs, &msgHandler); + evaluator.loadNamedSpec(mkspec.toString(), false); + + QList 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()) + return nullptr; + + QtVersionFactory::SetupData setup; + setup.config = evaluator.values("CONFIG"); + setup.platforms = evaluator.values("QMAKE_PLATFORM"); // It's a list in general. + setup.isQnx = !evaluator.value("QNX_CPUDIR").isEmpty(); + + foreach (QtVersionFactory *factory, factories) { + if (!factory->m_restrictionChecker || factory->m_restrictionChecker(setup)) { + BaseQtVersion *ver = factory->create(); + QTC_ASSERT(ver, continue); + ver->d->setupQmakePathAndId(qmakePath); + ver->d->m_autodetectionSource = autoDetectionSource; + ver->d->m_isAutodetected = isAutoDetected; + ProFileCacheManager::instance()->decRefCount(); + return ver; + } + } + ProFileCacheManager::instance()->decRefCount(); + if (error) { + *error = QCoreApplication::translate("QtSupport::QtVersionFactory", + "No factory found for qmake: \"%1\"").arg(qmakePath.toUserOutput()); + } + return nullptr; +} + +QtVersionFactory::QtVersionFactory() +{ + g_qtVersionFactories.append(this); +} + +QtVersionFactory::~QtVersionFactory() +{ + g_qtVersionFactories.removeOne(this); +} + +const QList QtVersionFactory::allQtVersionFactories() +{ + return g_qtVersionFactories; +} + +bool QtVersionFactory::canRestore(const QString &type) +{ + return type == m_supportedType; +} + +BaseQtVersion *QtVersionFactory::restore(const QString &type, const QVariantMap &data) +{ + QTC_ASSERT(canRestore(type), return nullptr); + QTC_ASSERT(m_creator, return nullptr); + BaseQtVersion *version = create(); + version->fromMap(data); + return version; +} + +BaseQtVersion *QtVersionFactory::create() const +{ + QTC_ASSERT(m_creator, return nullptr); + BaseQtVersion *version = m_creator(); + version->d->m_type = m_supportedType; + return version; +} + +BaseQtVersion *BaseQtVersion::clone() const +{ + for (QtVersionFactory *factory : g_qtVersionFactories) { + if (factory->m_supportedType == d->m_type) { + BaseQtVersion *version = factory->create(); + QTC_ASSERT(version, return nullptr); + version->fromMap(toMap()); + return version; + } + } + QTC_CHECK(false); + return nullptr; +} + +void QtVersionFactory::setQtVersionCreator(const std::function &creator) +{ + m_creator = creator; +} + +void QtVersionFactory::setRestrictionChecker(const std::function &checker) +{ + m_restrictionChecker = checker; +} + +void QtVersionFactory::setSupportedType(const QString &type) +{ + m_supportedType = type; +} + +void QtVersionFactory::setPriority(int priority) +{ + m_priority = priority; +} + +} // QtSupport + #if defined(WITH_TESTS) #include #include "qtsupportplugin.h" +namespace QtSupport { +namespace Internal { + void QtSupportPlugin::testQtBuildStringParsing_data() { QTest::addColumn("buildString"); @@ -2093,4 +2312,7 @@ void QtSupportPlugin::testQtBuildStringParsing() QCOMPARE(expectedList, actual); } +} // Internal +} // QtSupport + #endif // WITH_TESTS diff --git a/src/plugins/qtsupport/baseqtversion.h b/src/plugins/qtsupport/baseqtversion.h index 2b94894cfd5..f1ac769b9ef 100644 --- a/src/plugins/qtsupport/baseqtversion.h +++ b/src/plugins/qtsupport/baseqtversion.h @@ -37,47 +37,26 @@ #include #include +QT_BEGIN_NAMESPACE +class ProFileEvaluator; +class QMakeGlobals; +QT_END_NAMESPACE + namespace Utils { class Environment; class FileInProjectFinder; -} -namespace Core { class Id; } +} // Utils namespace ProjectExplorer { -class IOutputParser; class Kit; class ToolChain; -class HeaderPath; class Target; -} // namespace ProjectExplorer +} // ProjectExplorer -QT_BEGIN_NAMESPACE -class ProKey; -class ProString; -class ProFileEvaluator; -class QMakeGlobals; -class QSettings; -QT_END_NAMESPACE +namespace QtSupport { -namespace QtSupport -{ class QtConfigWidget; - class BaseQtVersion; -class QtVersionFactory; - -// Wrapper to make the std::unique_ptr "copyable": -class MacroExpanderWrapper -{ -public: - MacroExpanderWrapper() = default; - MacroExpanderWrapper(const MacroExpanderWrapper &other) { Q_UNUSED(other) } - MacroExpanderWrapper(MacroExpanderWrapper &&other) = default; - - Utils::MacroExpander *macroExpander(const BaseQtVersion *qtversion) const; -private: - mutable std::unique_ptr m_expander; -}; class QTSUPPORT_EXPORT QtVersionNumber { @@ -101,13 +80,13 @@ public: bool operator ==(const QtVersionNumber &b) const; }; -namespace Internal { class QtOptionsPageWidget; } +namespace Internal { +class QtOptionsPageWidget; +class BaseQtVersionPrivate; +} class QTSUPPORT_EXPORT BaseQtVersion { - friend class QtVersionFactory; - friend class QtVersionManager; - friend class QtSupport::Internal::QtOptionsPageWidget; public: using Predicate = std::function; @@ -254,90 +233,33 @@ public: const ProjectExplorer::Target *target); QSet features() const; - void setIsAutodetected(bool isAutodetected); + protected: - virtual QSet availableFeatures() const; - BaseQtVersion(); BaseQtVersion(const BaseQtVersion &other) = delete; + virtual QSet availableFeatures() const; virtual ProjectExplorer::Tasks reportIssuesImpl(const QString &proFile, const QString &buildDir) const; // helper function for desktop and simulator to figure out the supported abis based on the libraries - Utils::FilePathList qtCorePaths() const; static ProjectExplorer::Abis qtAbisFromLibrary(const Utils::FilePathList &coreLibraries); void ensureMkSpecParsed() const; virtual void parseMkSpec(ProFileEvaluator *) const; private: - void setupQmakePathAndId(const Utils::FilePath &path); - void setAutoDetectionSource(const QString &autodetectionSource); - void updateVersionInfo() const; - enum HostBinaries { Designer, Linguist, Uic, QScxmlc }; - QString findHostBinary(HostBinaries binary) const; - void updateMkspec() const; - QHash versionInfo() const; - static bool queryQMakeVariables(const Utils::FilePath &binary, - const Utils::Environment &env, - QHash *versionInfo, - QString *error = nullptr); - static QString qmakeProperty(const QHash &versionInfo, - const QByteArray &name, - PropertyVariant variant = PropertyVariantGet); - static Utils::FilePath mkspecDirectoryFromVersionInfo(const QHash &versionInfo); - static Utils::FilePath mkspecFromVersionInfo(const QHash &versionInfo); - static Utils::FilePath sourcePath(const QHash &versionInfo); - void setId(int id); // used by the qtversionmanager for legacy restore - // and by the qtoptionspage to replace Qt versions + friend class QtVersionFactory; + friend class QtVersionManager; + friend class Internal::BaseQtVersionPrivate; + friend class Internal::QtOptionsPageWidget; - int m_id = -1; - const QtVersionFactory *m_factory = nullptr; // The factory that created us. + void setId(int id); + BaseQtVersion *clone() const; - bool m_isAutodetected = false; - mutable bool m_hasQmlDump = false; // controlled by m_versionInfoUpToDate - mutable bool m_mkspecUpToDate = false; - mutable bool m_mkspecReadUpToDate = false; - mutable bool m_defaultConfigIsDebug = true; - mutable bool m_defaultConfigIsDebugAndRelease = true; - mutable bool m_frameworkBuild = false; - mutable bool m_versionInfoUpToDate = false; - mutable bool m_installed = true; - mutable bool m_hasExamples = false; - mutable bool m_hasDemos = false; - mutable bool m_hasDocumentation = false; - mutable bool m_qmakeIsExecutable = true; - mutable bool m_hasQtAbis = false; - - mutable QStringList m_configValues; - mutable QStringList m_qtConfigValues; - - QString m_unexpandedDisplayName; - QString m_autodetectionSource; - QSet m_overrideFeatures; - mutable Utils::FilePath m_sourcePath; - mutable Utils::FilePath m_qtSources; - - mutable Utils::FilePath m_mkspec; - mutable Utils::FilePath m_mkspecFullPath; - - mutable QHash m_mkspecValues; - - mutable QHash m_versionInfo; - - Utils::FilePath m_qmakeCommand; - mutable QString m_qtVersionString; - mutable QString m_uicCommand; - mutable QString m_designerCommand; - mutable QString m_linguistCommand; - mutable QString m_qscxmlcCommand; - mutable QString m_qmlsceneCommand; - - mutable ProjectExplorer::Abis m_qtAbis; - - MacroExpanderWrapper m_expander; + Internal::BaseQtVersionPrivate *d = nullptr; }; -} + +} // QtSupport Q_DECLARE_OPERATORS_FOR_FLAGS(QtSupport::BaseQtVersion::QmakeBuildConfigs) diff --git a/src/plugins/qtsupport/qtoptionspage.cpp b/src/plugins/qtsupport/qtoptionspage.cpp index baab24860c5..51e7a29679a 100644 --- a/src/plugins/qtsupport/qtoptionspage.cpp +++ b/src/plugins/qtsupport/qtoptionspage.cpp @@ -522,7 +522,7 @@ void QtOptionsPageWidget::updateQtVersions(const QList &additions, const QL // Add changed/added items: foreach (int a, toAdd) { - BaseQtVersion *version = QtVersionFactory::cloneQtVersion(QtVersionManager::version(a)); + BaseQtVersion *version = QtVersionManager::version(a)->clone(); auto *item = new QtVersionItem(version); // Insert in the right place: @@ -753,7 +753,7 @@ void QtOptionsPageWidget::apply() m_model->forItemsAtLevel<2>([&versions](QtVersionItem *item) { item->setChanged(false); - versions.append(QtVersionFactory::cloneQtVersion(item->version())); + versions.append(item->version()->clone()); }); QtVersionManager::setNewQtVersions(versions); diff --git a/src/plugins/qtsupport/qtversionfactory.cpp b/src/plugins/qtsupport/qtversionfactory.cpp index 8c05bb6bcb5..e69de29bb2d 100644 --- a/src/plugins/qtsupport/qtversionfactory.cpp +++ b/src/plugins/qtsupport/qtversionfactory.cpp @@ -1,171 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** 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 General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** 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-3.0.html. -** -****************************************************************************/ - -#include "qtversionfactory.h" -#include "profilereader.h" -#include "baseqtversion.h" - -#include - -#include - -#include -#include -#include - -#include - -using namespace QtSupport; -using namespace QtSupport::Internal; - -static QList g_qtVersionFactories; - -QtVersionFactory::QtVersionFactory() -{ - g_qtVersionFactories.append(this); -} - -QtVersionFactory::~QtVersionFactory() -{ - g_qtVersionFactories.removeOne(this); -} - -const QList QtVersionFactory::allQtVersionFactories() -{ - return g_qtVersionFactories; -} - -bool QtVersionFactory::canRestore(const QString &type) -{ - return type == m_supportedType; -} - -BaseQtVersion *QtVersionFactory::restore(const QString &type, const QVariantMap &data) -{ - QTC_ASSERT(canRestore(type), return nullptr); - QTC_ASSERT(m_creator, return nullptr); - BaseQtVersion *version = create(); - version->fromMap(data); - return version; -} - -BaseQtVersion *QtVersionFactory::createQtVersionFromQMakePath(const Utils::FilePath &qmakePath, bool isAutoDetected, const QString &autoDetectionSource, QString *error) -{ - QHash versionInfo; - if (!BaseQtVersion::queryQMakeVariables(qmakePath, Utils::Environment::systemEnvironment(), - &versionInfo, error)) - return nullptr; - Utils::FilePath mkspec = BaseQtVersion::mkspecFromVersionInfo(versionInfo); - - QMakeVfs vfs; - QMakeGlobals globals; - globals.setProperties(versionInfo); - ProMessageHandler msgHandler(false); - ProFileCacheManager::instance()->incRefCount(); - QMakeParser parser(ProFileCacheManager::instance()->cache(), &vfs, &msgHandler); - ProFileEvaluator evaluator(&globals, &parser, &vfs, &msgHandler); - evaluator.loadNamedSpec(mkspec.toString(), false); - - QList factories = g_qtVersionFactories; - Utils::sort(factories, [](const QtVersionFactory *l, const QtVersionFactory *r) { - return l->priority() > r->priority(); - }); - - QFileInfo fi = qmakePath.toFileInfo(); - if (!fi.exists() || !fi.isExecutable() || !fi.isFile()) - return nullptr; - - SetupData setup; - setup.config = evaluator.values("CONFIG"); - setup.platforms = evaluator.values("QMAKE_PLATFORM"); // It's a list in general. - setup.isQnx = !evaluator.value("QNX_CPUDIR").isEmpty(); - - foreach (QtVersionFactory *factory, factories) { - if (!factory->m_restrictionChecker || factory->m_restrictionChecker(setup)) { - BaseQtVersion *ver = factory->create(); - QTC_ASSERT(ver, continue); - ver->setupQmakePathAndId(qmakePath); - ver->setAutoDetectionSource(autoDetectionSource); - ver->setIsAutodetected(isAutoDetected); - ProFileCacheManager::instance()->decRefCount(); - return ver; - } - } - ProFileCacheManager::instance()->decRefCount(); - if (error) { - *error = QCoreApplication::translate("QtSupport::QtVersionFactory", - "No factory found for qmake: \"%1\"").arg(qmakePath.toUserOutput()); - } - return nullptr; -} - -BaseQtVersion *QtVersionFactory::create() const -{ - QTC_ASSERT(m_creator, return nullptr); - BaseQtVersion *version = m_creator(); - version->m_factory = this; - return version; -} - -QString QtVersionFactory::supportedType() const -{ - return m_supportedType; -} - -BaseQtVersion *QtVersionFactory::cloneQtVersion(const BaseQtVersion *source) -{ - QTC_ASSERT(source, return nullptr); - const QString sourceType = source->type(); - for (QtVersionFactory *factory : g_qtVersionFactories) { - if (factory->m_supportedType == sourceType) { - BaseQtVersion *version = factory->create(); - QTC_ASSERT(version, return nullptr); - version->fromMap(source->toMap()); - return version; - } - } - QTC_CHECK(false); - return nullptr; -} - -void QtVersionFactory::setQtVersionCreator(const std::function &creator) -{ - m_creator = creator; -} - -void QtVersionFactory::setRestrictionChecker(const std::function &checker) -{ - m_restrictionChecker = checker; -} - -void QtVersionFactory::setSupportedType(const QString &type) -{ - m_supportedType = type; -} - -void QtVersionFactory::setPriority(int priority) -{ - m_priority = priority; -} diff --git a/src/plugins/qtsupport/qtversionfactory.h b/src/plugins/qtsupport/qtversionfactory.h index 4bafe40c148..9f055ea1cc9 100644 --- a/src/plugins/qtsupport/qtversionfactory.h +++ b/src/plugins/qtsupport/qtversionfactory.h @@ -51,14 +51,10 @@ public: /// the desktop factory claims to handle all paths int priority() const { return m_priority; } - QString supportedType() const; - static BaseQtVersion *createQtVersionFromQMakePath( const Utils::FilePath &qmakePath, bool isAutoDetected = false, const QString &autoDetectionSource = QString(), QString *error = nullptr); - static BaseQtVersion *cloneQtVersion(const BaseQtVersion *source); - protected: struct SetupData { @@ -73,6 +69,7 @@ protected: void setPriority(int priority); private: + friend class BaseQtVersion; BaseQtVersion *create() const; std::function m_creator; diff --git a/src/plugins/qtsupport/qtversionmanager.h b/src/plugins/qtsupport/qtversionmanager.h index 4a9d0777523..0d5cfe15562 100644 --- a/src/plugins/qtsupport/qtversionmanager.h +++ b/src/plugins/qtsupport/qtversionmanager.h @@ -35,6 +35,7 @@ class QTSUPPORT_EXPORT QtVersionManager : public QObject Q_OBJECT // for getUniqueId(); friend class BaseQtVersion; + friend class Internal::BaseQtVersionPrivate; friend class Internal::QtOptionsPageWidget; public: static QtVersionManager *instance();