diff options
author | Ivan Donchevskii <ivan.donchevskii@qt.io> | 2018-12-11 16:17:09 +0100 |
---|---|---|
committer | Ivan Donchevskii <ivan.donchevskii@qt.io> | 2019-01-10 08:37:23 +0000 |
commit | 4c191572044d4483f09b3b8d0f76ef164bd8f225 (patch) | |
tree | 8f12faf8927494d48a4e4c89a80f78265b76804a | |
parent | 03a042d5498215d3324451e5629f504b65e49daa (diff) | |
download | qt-creator-4c191572044d4483f09b3b8d0f76ef164bd8f225.tar.gz |
ProjectExplorer: Allow to select MSVC environment for clang-cl
clang-cl compiler can work with multiple MSVC toolchains.
Let's make a combobox out of all available MSVC scripts + vars
to switch the MSVC base for manual clang-cl toolchains.
Fixes: QTCREATORBUG-21604
Change-Id: Iac3c726a813bb593d4350886e98aa636c94b52cf
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
-rw-r--r-- | src/plugins/projectexplorer/msvctoolchain.cpp | 113 | ||||
-rw-r--r-- | src/plugins/projectexplorer/msvctoolchain.h | 15 |
2 files changed, 105 insertions, 23 deletions
diff --git a/src/plugins/projectexplorer/msvctoolchain.cpp b/src/plugins/projectexplorer/msvctoolchain.cpp index 004328c620..413f80a565 100644 --- a/src/plugins/projectexplorer/msvctoolchain.cpp +++ b/src/plugins/projectexplorer/msvctoolchain.cpp @@ -57,6 +57,7 @@ #include <QVersionNumber> #include <QLabel> +#include <QComboBox> #include <QFormLayout> #define KEY_ROOT "ProjectExplorer.MsvcToolChain." @@ -783,12 +784,12 @@ MsvcToolChain::MsvcToolChain(const QString &name, MsvcToolChain::MsvcToolChain(const MsvcToolChain &other) : ToolChain(other) + , m_headerPathsMutex(new QMutex) , m_environmentModifications(other.m_environmentModifications) , m_debuggerCommand(other.m_debuggerCommand) , m_predefinedMacrosCache(other.m_predefinedMacrosCache) , m_lastEnvironment(other.m_lastEnvironment) , m_resultEnvironment(other.m_resultEnvironment) - , m_headerPathsMutex(new QMutex) , m_abi(other.m_abi) , m_vcvarsBat(other.m_vcvarsBat) , m_varsBatArg(other.m_varsBatArg) @@ -810,6 +811,14 @@ MsvcToolChain::MsvcToolChain(const MsvcToolChain &other) setDisplayName(other.displayName()); } +static void addToAvailableMsvcToolchains(const MsvcToolChain *toolchain) +{ + if (toolchain->typeId() != Constants::MSVC_TOOLCHAIN_TYPEID) + return; + + g_availableMsvcToolchains.push_back(toolchain); +} + MsvcToolChain::MsvcToolChain(Core::Id typeId, const QString &name, const Abi &abi, @@ -818,13 +827,15 @@ MsvcToolChain::MsvcToolChain(Core::Id typeId, Core::Id l, Detection d) : ToolChain(typeId, d) + , m_headerPathsMutex(new QMutex) , m_predefinedMacrosCache(std::make_shared<Cache<MacroInspectionReport, 64>>()) , m_lastEnvironment(Utils::Environment::systemEnvironment()) - , m_headerPathsMutex(new QMutex) , m_abi(abi) , m_vcvarsBat(varsBat) , m_varsBatArg(varsBatArg) { + addToAvailableMsvcToolchains(this); + setLanguage(l); initEnvModWatcher(Utils::runAsync(envModThreadPool(), &MsvcToolChain::environmentModifications, @@ -872,6 +883,7 @@ MsvcToolChain::MsvcToolChain() MsvcToolChain::~MsvcToolChain() { + g_availableMsvcToolchains.removeOne(this); delete m_headerPathsMutex; } @@ -967,6 +979,8 @@ bool MsvcToolChain::fromMap(const QVariantMap &data) return false; m_vcvarsBat = QDir::fromNativeSeparators(data.value(QLatin1String(varsBatKeyC)).toString()); m_varsBatArg = data.value(QLatin1String(varsBatArgKeyC)).toString(); + addToAvailableMsvcToolchains(this); + const QString abiString = data.value(QLatin1String(supportedAbiKeyC)).toString(); m_abi = Abi::fromString(abiString); m_environmentModifications = Utils::EnvironmentItem::itemsFromVariantList( @@ -1218,17 +1232,22 @@ MsvcBasedToolChainConfigWidget::MsvcBasedToolChainConfigWidget(ToolChain *tc) m_mainLayout->addRow(tr("Initialization:"), m_varsBatDisplayLabel); } +static QString msvcVarsToDisplay(const MsvcToolChain &tc) +{ + QString varsBatDisplay = QDir::toNativeSeparators(tc.varsBat()); + if (!tc.varsBatArg().isEmpty()) { + varsBatDisplay += QLatin1Char(' '); + varsBatDisplay += tc.varsBatArg(); + } + return varsBatDisplay; +} + void MsvcBasedToolChainConfigWidget::setFromMsvcToolChain() { const auto *tc = static_cast<const MsvcToolChain *>(toolChain()); QTC_ASSERT(tc, return ); m_nameDisplayLabel->setText(tc->displayName()); - QString varsBatDisplay = QDir::toNativeSeparators(tc->varsBat()); - if (!tc->varsBatArg().isEmpty()) { - varsBatDisplay += QLatin1Char(' '); - varsBatDisplay += tc->varsBatArg(); - } - m_varsBatDisplayLabel->setText(varsBatDisplay); + m_varsBatDisplayLabel->setText(msvcVarsToDisplay(*tc)); } // -------------------------------------------------------------------------- @@ -1246,9 +1265,15 @@ MsvcToolChainConfigWidget::MsvcToolChainConfigWidget(ToolChain *tc) // ClangClToolChainConfigWidget // -------------------------------------------------------------------------- -ClangClToolChainConfigWidget::ClangClToolChainConfigWidget(ToolChain *tc) - : MsvcBasedToolChainConfigWidget(tc) +ClangClToolChainConfigWidget::ClangClToolChainConfigWidget(ToolChain *tc) : + MsvcBasedToolChainConfigWidget(tc), + m_varsBatDisplayCombo(new QComboBox(this)) { + m_mainLayout->removeRow(m_mainLayout->rowCount() - 1); + + m_varsBatDisplayCombo->setSizeAdjustPolicy(QComboBox::AdjustToContents); + m_mainLayout->addRow(tr("Initialization:"), m_varsBatDisplayCombo); + if (tc->isAutoDetected()) { m_llvmDirLabel = new QLabel(this); m_llvmDirLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); @@ -1274,7 +1299,16 @@ ClangClToolChainConfigWidget::ClangClToolChainConfigWidget(ToolChain *tc) void ClangClToolChainConfigWidget::setFromClangClToolChain() { - setFromMsvcToolChain(); + const auto *currentTC = static_cast<const MsvcToolChain *>(toolChain()); + m_nameDisplayLabel->setText(currentTC->displayName()); + m_varsBatDisplayCombo->clear(); + m_varsBatDisplayCombo->addItem(msvcVarsToDisplay(*currentTC)); + for (const MsvcToolChain *tc : g_availableMsvcToolchains) { + const QString varsToDisplay = msvcVarsToDisplay(*tc); + if (m_varsBatDisplayCombo->findText(varsToDisplay) == -1) + m_varsBatDisplayCombo->addItem(varsToDisplay); + } + const auto *clangClToolChain = static_cast<const ClangClToolChain *>(toolChain()); if (clangClToolChain->isAutoDetected()) m_llvmDirLabel->setText(QDir::toNativeSeparators(clangClToolChain->clangPath())); @@ -1291,6 +1325,14 @@ static const MsvcToolChain *findMsvcToolChain(unsigned char wordWidth, Abi::OSFl }); } +static const MsvcToolChain *findMsvcToolChain(const QString &displayedVarsBat) +{ + return Utils::findOrDefault(g_availableMsvcToolchains, + [&displayedVarsBat] (const MsvcToolChain *tc) { + return msvcVarsToDisplay(*tc) == displayedVarsBat; + }); +} + static QVersionNumber clangClVersion(const QString &clangClPath) { Utils::SynchronousProcess clangClProcess; @@ -1306,9 +1348,18 @@ static QVersionNumber clangClVersion(const QString &clangClPath) return QVersionNumber::fromString(match.captured(1)); } -static const MsvcToolChain *selectMsvcToolChain(const QString &clangClPath, unsigned char wordWidth) +static const MsvcToolChain *selectMsvcToolChain(const QString &displayedVarsBat, + const QString &clangClPath, + unsigned char wordWidth) { const MsvcToolChain *toolChain = nullptr; + if (!displayedVarsBat.isEmpty()) { + toolChain = findMsvcToolChain(displayedVarsBat); + if (toolChain) + return toolChain; + } + + QTC_CHECK(displayedVarsBat.isEmpty()); const QVersionNumber version = clangClVersion(clangClPath); if (version.majorVersion() >= 6) toolChain = findMsvcToolChain(wordWidth, Abi::WindowsMsvc2017Flavor); @@ -1322,11 +1373,12 @@ static const MsvcToolChain *selectMsvcToolChain(const QString &clangClPath, unsi static QList<ToolChain *> detectClangClToolChainInPath(const QString &clangClPath, const QList<ToolChain *> &alreadyKnown, + const QString &displayedVarsBat, bool isDefault = false) { QList<ToolChain *> res; const unsigned char wordWidth = Utils::is64BitWindowsBinary(clangClPath) ? 64 : 32; - const MsvcToolChain *toolChain = selectMsvcToolChain(clangClPath, wordWidth); + const MsvcToolChain *toolChain = selectMsvcToolChain(displayedVarsBat, clangClPath, wordWidth); if (!toolChain) { qWarning("Unable to find a suitable MSVC version for \"%s\".", @@ -1378,7 +1430,10 @@ void ClangClToolChainConfigWidget::applyImpl() return; } - QList<ToolChain *> results = detectClangClToolChainInPath(clangClPath.toString(), {}); + const QString displayedVarsBat = m_varsBatDisplayCombo->currentText(); + QList<ToolChain *> results = detectClangClToolChainInPath(clangClPath.toString(), + {}, + displayedVarsBat); if (results.isEmpty()) { clangClToolChain->resetMsvcToolChain(); @@ -1400,6 +1455,11 @@ void ClangClToolChainConfigWidget::discardImpl() setFromClangClToolChain(); } +void ClangClToolChainConfigWidget::makeReadOnlyImpl() +{ + m_varsBatDisplayCombo->setEnabled(false); +} + // -------------------------------------------------------------------------- // ClangClToolChain, piggy-backing on MSVC2015 and providing the compiler // clang-cl.exe as a [to some extent] compatible drop-in replacement for cl. @@ -1545,6 +1605,22 @@ LanguageVersion ClangClToolChain::msvcLanguageVersion(const QStringList &cxxflag return MsvcToolChain::msvcLanguageVersion(cxxflags, language, macros); } +void ClangClToolChain::toolChainUpdated() +{ + MsvcToolChain::toolChainUpdated(); + ToolChain::toolChainUpdated(); +} + +ClangClToolChain::BuiltInHeaderPathsRunner ClangClToolChain::createBuiltInHeaderPathsRunner() const +{ + { + QMutexLocker locker(m_headerPathsMutex); + m_headerPaths.clear(); + } + + return MsvcToolChain::createBuiltInHeaderPathsRunner(); +} + // -------------------------------------------------------------------------- // MsvcToolChainFactory // -------------------------------------------------------------------------- @@ -1725,9 +1801,6 @@ QList<ToolChain *> MsvcToolChainFactory::autoDetect(const QList<ToolChain *> &al detectCppBuildTools2015(&results); - for (const ToolChain *toolchain : results) - g_availableMsvcToolchains.append(static_cast<const MsvcToolChain *>(toolchain)); - return results; } @@ -1760,7 +1833,7 @@ QList<ToolChain *> ClangClToolChainFactory::autoDetect(const QList<ToolChain *> .parentDir() .appendPath("clang-cl.exe") .toString(); - results.append(detectClangClToolChainInPath(qtCreatorsClang, alreadyKnown, true)); + results.append(detectClangClToolChainInPath(qtCreatorsClang, alreadyKnown, "", true)); known.append(results); } @@ -1769,7 +1842,7 @@ QList<ToolChain *> ClangClToolChainFactory::autoDetect(const QList<ToolChain *> const QString path = QDir::cleanPath(registry.value(QStringLiteral(".")).toString()); const QString clangClPath = compilerFromPath(path); if (!path.isEmpty()) { - results.append(detectClangClToolChainInPath(clangClPath, known)); + results.append(detectClangClToolChainInPath(clangClPath, known, "")); known.append(results); } } @@ -1777,7 +1850,7 @@ QList<ToolChain *> ClangClToolChainFactory::autoDetect(const QList<ToolChain *> const Utils::Environment systemEnvironment = Utils::Environment::systemEnvironment(); const Utils::FileName clangClPath = systemEnvironment.searchInPath("clang-cl"); if (!clangClPath.isEmpty()) - results.append(detectClangClToolChainInPath(clangClPath.toString(), known)); + results.append(detectClangClToolChainInPath(clangClPath.toString(), known, "")); return results; } diff --git a/src/plugins/projectexplorer/msvctoolchain.h b/src/plugins/projectexplorer/msvctoolchain.h index f8cfefbead..90c941c412 100644 --- a/src/plugins/projectexplorer/msvctoolchain.h +++ b/src/plugins/projectexplorer/msvctoolchain.h @@ -36,6 +36,7 @@ #include <utils/optional.h> QT_FORWARD_DECLARE_CLASS(QLabel) +QT_FORWARD_DECLARE_CLASS(QComboBox) QT_FORWARD_DECLARE_CLASS(QVersionNumber) namespace Utils { @@ -153,6 +154,10 @@ protected: QString varsBatArg); void initEnvModWatcher(const QFuture<GenerateEnvResult> &future); +protected: + mutable QMutex *m_headerPathsMutex = nullptr; + mutable HeaderPaths m_headerPaths; + private: void updateEnvironmentModifications(QList<Utils::EnvironmentItem> modifications); @@ -165,8 +170,6 @@ private: mutable Utils::Environment m_lastEnvironment; // Last checked 'incoming' environment. mutable Utils::Environment m_resultEnvironment; // Resulting environment for VC - mutable QMutex *m_headerPathsMutex = nullptr; - mutable HeaderPaths m_headerPaths; protected: Abi m_abi; @@ -191,6 +194,7 @@ public: QVariantMap toMap() const override; bool fromMap(const QVariantMap &data) override; std::unique_ptr<ToolChainConfigWidget> createConfigurationWidget() override; + BuiltInHeaderPathsRunner createBuiltInHeaderPathsRunner() const override; const QList<MsvcToolChain *> &msvcToolchains() const; QString clangPath() const { return m_clangPath; } @@ -206,6 +210,9 @@ public: bool operator==(const ToolChain &) const override; private: + void toolChainUpdated() override; + +private: QString m_clangPath; }; @@ -266,7 +273,7 @@ protected: void setFromMsvcToolChain(); -private: +protected: QLabel *m_nameDisplayLabel; QLabel *m_varsBatDisplayLabel; }; @@ -297,11 +304,13 @@ public: protected: void applyImpl() override; void discardImpl() override; + void makeReadOnlyImpl() override; private: void setFromClangClToolChain(); QLabel *m_llvmDirLabel = nullptr; + QComboBox *m_varsBatDisplayCombo = nullptr; Utils::PathChooser *m_compilerCommand = nullptr; }; |