diff options
Diffstat (limited to 'src/plugins/projectexplorer/msvctoolchain.cpp')
-rw-r--r-- | src/plugins/projectexplorer/msvctoolchain.cpp | 169 |
1 files changed, 69 insertions, 100 deletions
diff --git a/src/plugins/projectexplorer/msvctoolchain.cpp b/src/plugins/projectexplorer/msvctoolchain.cpp index 9748b52f7f..2b46aaff67 100644 --- a/src/plugins/projectexplorer/msvctoolchain.cpp +++ b/src/plugins/projectexplorer/msvctoolchain.cpp @@ -67,7 +67,6 @@ using namespace Utils; static const char varsBatKeyC[] = KEY_ROOT "VarsBat"; static const char varsBatArgKeyC[] = KEY_ROOT "VarsBatArg"; static const char supportedAbiKeyC[] = KEY_ROOT "SupportedAbi"; -static const char supportedAbisKeyC[] = KEY_ROOT "SupportedAbis"; static const char environModsKeyC[] = KEY_ROOT "environmentModifications"; enum { debug = 0 }; @@ -653,7 +652,7 @@ Macros MsvcToolChain::msvcPredefinedMacros(const QStringList &cxxflags, // For _MSV_VER values, see https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros?view=vs-2017. // Utils::LanguageVersion MsvcToolChain::msvcLanguageVersion(const QStringList & /*cxxflags*/, - const Core::Id &language, + const Utils::Id &language, const Macros ¯os) const { using Utils::LanguageVersion; @@ -775,55 +774,6 @@ void MsvcToolChain::updateEnvironmentModifications(Utils::EnvironmentItems modif } } -void MsvcToolChain::detectInstalledAbis() -{ - static QMap<QString, Abis> abiCache; - const QString vcVarsBase - = QDir::fromNativeSeparators(m_vcvarsBat).left(m_vcvarsBat.lastIndexOf('/')); - if (abiCache.contains(vcVarsBase)) { - m_supportedAbis = abiCache.value(vcVarsBase); - } else { - // Clear previously detected m_supportedAbis to repopulate it. - m_supportedAbis.clear(); - const Abi baseAbi = targetAbi(); - for (MsvcPlatform platform : platforms) { - bool toolchainInstalled = false; - QString perhapsVcVarsPath = vcVarsBase + QLatin1Char('/') + QLatin1String(platform.bat); - const Platform p = platform.platform; - if (QFileInfo(perhapsVcVarsPath).isFile()) { - toolchainInstalled = true; - } else { - // MSVC 2015 and below had various versions of vcvars scripts in subfolders. Try these - // as fallbacks. - perhapsVcVarsPath = vcVarsBase + platform.prefix + QLatin1Char('/') - + QLatin1String(platform.bat); - toolchainInstalled = QFileInfo(perhapsVcVarsPath).isFile(); - } - if (hostSupportsPlatform(platform.platform) && toolchainInstalled) { - Abi newAbi(archForPlatform(p), - baseAbi.os(), - baseAbi.osFlavor(), - baseAbi.binaryFormat(), - wordWidthForPlatform(p)); - if (!m_supportedAbis.contains(newAbi)) - m_supportedAbis.append(newAbi); - } - } - - abiCache.insert(vcVarsBase, m_supportedAbis); - } - - // Always add targetAbi in supportedAbis if it is empty. - // targetAbi is the abi with which the toolchain was detected. - // This is necessary for toolchains that don't have vcvars32.bat and the like in their - // vcVarsBase path, like msvc2010. - // Also, don't include that one in abiCache to avoid polluting it with values specific - // to one toolchain as the cache is global for a vcVarsBase path. For this reason, the - // targetAbi needs to be added manually. - if (m_supportedAbis.empty()) - m_supportedAbis.append(targetAbi()); -} - Utils::Environment MsvcToolChain::readEnvironmentSetting(const Utils::Environment &env) const { Utils::Environment resultEnv = env; @@ -858,11 +808,12 @@ static void addToAvailableMsvcToolchains(const MsvcToolChain *toolchain) g_availableMsvcToolchains.push_back(toolchain); } -MsvcToolChain::MsvcToolChain(Core::Id typeId) +MsvcToolChain::MsvcToolChain(Utils::Id typeId) : ToolChain(typeId) { setDisplayName("Microsoft Visual C++ Compiler"); - setTypeDisplayName(MsvcToolChainFactory::tr("MSVC")); + setTypeDisplayName(tr("MSVC")); + addToAvailableMsvcToolchains(this); } void MsvcToolChain::inferWarningsForLevel(int warningLevel, WarningFlags &flags) @@ -894,11 +845,6 @@ Abi MsvcToolChain::targetAbi() const return m_abi; } -Abis MsvcToolChain::supportedAbis() const -{ - return m_supportedAbis; -} - void MsvcToolChain::setTargetAbi(const Abi &abi) { m_abi = abi; @@ -978,7 +924,6 @@ QVariantMap MsvcToolChain::toMap() const if (!m_varsBatArg.isEmpty()) data.insert(QLatin1String(varsBatArgKeyC), m_varsBatArg); data.insert(QLatin1String(supportedAbiKeyC), m_abi.toString()); - data.insert(supportedAbisKeyC, Utils::transform<QStringList>(m_supportedAbis, &Abi::toString)); Utils::EnvironmentItem::sort(&m_environmentModifications); data.insert(QLatin1String(environModsKeyC), Utils::EnvironmentItem::toVariantList(m_environmentModifications)); @@ -987,21 +932,15 @@ QVariantMap MsvcToolChain::toMap() const bool MsvcToolChain::fromMap(const QVariantMap &data) { - if (!ToolChain::fromMap(data)) + if (!ToolChain::fromMap(data)) { + g_availableMsvcToolchains.removeOne(this); return false; + } m_vcvarsBat = QDir::fromNativeSeparators(data.value(QLatin1String(varsBatKeyC)).toString()); m_varsBatArg = data.value(QLatin1String(varsBatArgKeyC)).toString(); const QString abiString = data.value(QLatin1String(supportedAbiKeyC)).toString(); m_abi = Abi::fromString(abiString); - const QStringList abiList = data.value(supportedAbisKeyC).toStringList(); - m_supportedAbis.clear(); - for (const QString &a : abiList) { - Abi abi = Abi::fromString(a); - if (!abi.isValid()) - continue; - m_supportedAbis.append(abi); - } m_environmentModifications = Utils::EnvironmentItem::itemsFromVariantList( data.value(QLatin1String(environModsKeyC)).toList()); rescanForCompiler(); @@ -1011,13 +950,9 @@ bool MsvcToolChain::fromMap(const QVariantMap &data) m_vcvarsBat, m_varsBatArg)); - // supported Abis were not stored in the map in previous versions of the settings. Re-detect - if (m_supportedAbis.isEmpty()) - detectInstalledAbis(); - - const bool valid = !m_vcvarsBat.isEmpty() && m_abi.isValid() && !m_supportedAbis.isEmpty(); - if (valid) - addToAvailableMsvcToolchains(this); + const bool valid = !m_vcvarsBat.isEmpty() && m_abi.isValid(); + if (!valid) + g_availableMsvcToolchains.removeOne(this); return valid; } @@ -1046,7 +981,7 @@ ToolChain::MacroInspectionRunner MsvcToolChain::createMacroInspectionRunner() co Utils::Environment env(m_lastEnvironment); addToEnvironment(env); MacrosCache macroCache = predefinedMacrosCache(); - const Core::Id lang = language(); + const Utils::Id lang = language(); // This runner must be thread-safe! return [this, env, macroCache, lang](const QStringList &cxxflags) { @@ -1237,9 +1172,9 @@ void MsvcToolChain::rescanForCompiler() }); } -IOutputParser *MsvcToolChain::outputParser() const +QList<OutputLineParser *> MsvcToolChain::createOutputParsers() const { - return new MsvcParser; + return {new MsvcParser}; } void MsvcToolChain::setupVarsBat(const Abi &abi, const QString &varsBat, const QString &varsBatArg) @@ -1250,7 +1185,6 @@ void MsvcToolChain::setupVarsBat(const Abi &abi, const QString &varsBat, const Q m_varsBatArg = varsBatArg; if (!varsBat.isEmpty()) { - detectInstalledAbis(); initEnvModWatcher(Utils::runAsync(envModThreadPool(), &MsvcToolChain::environmentModifications, varsBat, @@ -1410,34 +1344,66 @@ void MsvcToolChainConfigWidget::setFromMsvcToolChain() m_abiWidget->setAbis(tc->supportedAbis(), tc->targetAbi()); } -void MsvcToolChainConfigWidget::handleVcVarsChange(const QString &vcVars) +void MsvcToolChainConfigWidget::updateAbis() { - const QString normalizedVcVars = QDir::fromNativeSeparators(vcVars); + const QString normalizedVcVars = QDir::fromNativeSeparators(m_varsBatPathCombo->currentText()); const auto *currentTc = static_cast<const MsvcToolChain *>(toolChain()); QTC_ASSERT(currentTc, return ); const MsvcToolChain::Platform platform = m_varsBatArchCombo->currentData().value<MsvcToolChain::Platform>(); const Abi::Architecture arch = archForPlatform(platform); const unsigned char wordWidth = wordWidthForPlatform(platform); + // Search the selected vcVars bat file in already detected MSVC compilers. + // For each variant of MSVC found, add its supported ABIs to the ABI widget so the user can + // choose one appropriately. + Abis supportedAbis; + Abi targetAbi; for (const MsvcToolChain *tc : g_availableMsvcToolchains) { if (tc->varsBat() == normalizedVcVars && tc->targetAbi().wordWidth() == wordWidth - && tc->targetAbi().architecture() == arch) { - m_abiWidget->setAbis(tc->supportedAbis(), tc->targetAbi()); - break; + && tc->targetAbi().architecture() == arch && tc->language() == currentTc->language()) { + // We need to filter out duplicates as there might be multiple toolchains with + // same abi (like x86, amd64_x86 for example). + for (const Abi &abi : tc->supportedAbis()) { + if (!supportedAbis.contains(abi)) + supportedAbis.append(abi); + } + targetAbi = tc->targetAbi(); + } + } + + // If we didn't find an exact match, try to find a fallback according to varsBat only. + // This can happen when the toolchain does not support user-selected arch/wordWidth. + if (!targetAbi.isValid()) { + const MsvcToolChain *tc = Utils::findOrDefault(g_availableMsvcToolchains, + [normalizedVcVars](const MsvcToolChain *tc) { + return tc->varsBat() == normalizedVcVars; + }); + if (tc) { + targetAbi = Abi(arch, + tc->targetAbi().os(), + tc->targetAbi().osFlavor(), + tc->targetAbi().binaryFormat(), + wordWidth); } } + + // Always set ABIs, even if none was found, to prevent stale data in the ABI widget. + // In that case, a custom ABI will be selected according to targetAbi. + m_abiWidget->setAbis(supportedAbis, targetAbi); + emit dirty(); } +void MsvcToolChainConfigWidget::handleVcVarsChange(const QString &) +{ + updateAbis(); +} + void MsvcToolChainConfigWidget::handleVcVarsArchChange(const QString &) { - Abi currentAbi = m_abiWidget->currentAbi(); - const MsvcToolChain::Platform platform = m_varsBatArchCombo->currentData().value<MsvcToolChain::Platform>(); - Abi newAbi(archForPlatform(platform), currentAbi.os(), currentAbi.osFlavor(), - currentAbi.binaryFormat(), wordWidthForPlatform(platform)); - if (currentAbi != newAbi) - m_abiWidget->setAbis(m_abiWidget->supportedAbis(), newAbi); - emit dirty(); + // supportedAbi list in the widget only contains matching ABIs to whatever arch was selected. + // We need to reupdate it from scratch with new arch parameters + updateAbis(); } QString MsvcToolChainConfigWidget::vcVarsArguments() const @@ -1503,7 +1469,7 @@ void ClangClToolChainConfigWidget::setFromClangClToolChain() if (clangClToolChain->isAutoDetected()) m_llvmDirLabel->setText(QDir::toNativeSeparators(clangClToolChain->clangPath())); else - m_compilerCommand->setFileName(Utils::FilePath::fromString(clangClToolChain->clangPath())); + m_compilerCommand->setFilePath(Utils::FilePath::fromString(clangClToolChain->clangPath())); } static const MsvcToolChain *findMsvcToolChain(unsigned char wordWidth, Abi::OSFlavor flavor) @@ -1551,8 +1517,11 @@ static const MsvcToolChain *selectMsvcToolChain(const QString &displayedVarsBat, QTC_CHECK(displayedVarsBat.isEmpty()); const QVersionNumber version = clangClVersion(clangClPath); - if (version.majorVersion() >= 6) - toolChain = findMsvcToolChain(wordWidth, Abi::WindowsMsvc2017Flavor); + if (version.majorVersion() >= 6) { + toolChain = findMsvcToolChain(wordWidth, Abi::WindowsMsvc2019Flavor); + if (!toolChain) + toolChain = findMsvcToolChain(wordWidth, Abi::WindowsMsvc2017Flavor); + } if (!toolChain) { toolChain = findMsvcToolChain(wordWidth, Abi::WindowsMsvc2015Flavor); if (!toolChain) @@ -1616,7 +1585,7 @@ static QString compilerFromPath(const QString &path) void ClangClToolChainConfigWidget::applyImpl() { - Utils::FilePath clangClPath = m_compilerCommand->fileName(); + Utils::FilePath clangClPath = m_compilerCommand->filePath(); auto clangClToolChain = static_cast<ClangClToolChain *>(toolChain()); clangClToolChain->setClangPath(clangClPath.toString()); @@ -1693,9 +1662,9 @@ QStringList ClangClToolChain::suggestedMkspecList() const return {mkspec, "win32-clang-msvc"}; } -IOutputParser *ClangClToolChain::outputParser() const +QList<OutputLineParser *> ClangClToolChain::createOutputParsers() const { - return new ClangClParser; + return {new ClangClParser}; } static inline QString llvmDirKey() @@ -1759,7 +1728,7 @@ Macros ClangClToolChain::msvcPredefinedMacros(const QStringList &cxxflags, } Utils::LanguageVersion ClangClToolChain::msvcLanguageVersion(const QStringList &cxxflags, - const Core::Id &language, + const Utils::Id &language, const Macros ¯os) const { if (cxxflags.contains("--driver-mode=g++")) @@ -1784,7 +1753,7 @@ ClangClToolChain::BuiltInHeaderPathsRunner ClangClToolChain::createBuiltInHeader MsvcToolChainFactory::MsvcToolChainFactory() { - setDisplayName(tr("MSVC")); + setDisplayName(MsvcToolChain::tr("MSVC")); setSupportedToolChainType(Constants::MSVC_TOOLCHAIN_TYPEID); setSupportedLanguages({Constants::C_LANGUAGE_ID, Constants::CXX_LANGUAGE_ID}); setToolchainConstructor([] { return new MsvcToolChain(Constants::MSVC_TOOLCHAIN_TYPEID); }); @@ -1966,7 +1935,7 @@ QList<ToolChain *> MsvcToolChainFactory::autoDetect(const QList<ToolChain *> &al ClangClToolChainFactory::ClangClToolChainFactory() { - setDisplayName(tr("clang-cl")); + setDisplayName(ClangClToolChain::tr("clang-cl")); setSupportedLanguages({Constants::C_LANGUAGE_ID, Constants::CXX_LANGUAGE_ID}); setSupportedToolChainType(Constants::CLANG_CL_TOOLCHAIN_TYPEID); setToolchainConstructor([] { return new ClangClToolChain; }); |