diff --git a/src/plugins/projectexplorer/gcctoolchain.cpp b/src/plugins/projectexplorer/gcctoolchain.cpp index 5626e08f12b..75ab1bc995c 100644 --- a/src/plugins/projectexplorer/gcctoolchain.cpp +++ b/src/plugins/projectexplorer/gcctoolchain.cpp @@ -1023,10 +1023,11 @@ Toolchains GccToolChainFactory::detectForImport(const ToolChainDescription &tcd) || fileName == "cc")) || (tcd.language == Constants::CXX_LANGUAGE_ID && (fileName.startsWith("g++") || fileName.endsWith("g++") - || fileName == "c++"))) + || fileName == "c++"))) { return autoDetectToolChain(tcd, [](const ToolChain *tc) { return tc->targetAbi().osFlavor() != Abi::WindowsMSysFlavor; }); + } return {}; } @@ -1164,11 +1165,15 @@ Toolchains GccToolChainFactory::autoDetectToolChain(const ToolChainDescription & Environment systemEnvironment = Environment::systemEnvironment(); GccToolChain::addCommandPathToEnvironment(tcd.compilerPath, systemEnvironment); const FilePath localCompilerPath = findLocalCompiler(tcd.compilerPath, systemEnvironment); + if (ToolChainManager::isBadToolchain(localCompilerPath)) + return result; Macros macros = gccPredefinedMacros(localCompilerPath, gccPredefinedMacrosOptions(tcd.language), systemEnvironment); - if (macros.isEmpty()) + if (macros.isEmpty()) { + ToolChainManager::addBadToolchain(localCompilerPath); return result; + } const GccToolChain::DetectedAbisResult detectedAbis = guessGccAbi(localCompilerPath, systemEnvironment, macros); @@ -1640,8 +1645,9 @@ Toolchains ClangToolChainFactory::detectForImport(const ToolChainDescription &tc { const QString fileName = tcd.compilerPath.toString(); if ((tcd.language == Constants::C_LANGUAGE_ID && fileName.startsWith("clang") && !fileName.startsWith("clang++")) - || (tcd.language == Constants::CXX_LANGUAGE_ID && fileName.startsWith("clang++"))) + || (tcd.language == Constants::CXX_LANGUAGE_ID && fileName.startsWith("clang++"))) { return autoDetectToolChain(tcd); + } return {}; } @@ -1820,10 +1826,11 @@ Toolchains MingwToolChainFactory::detectForImport(const ToolChainDescription &tc if ((tcd.language == Constants::C_LANGUAGE_ID && (fileName.startsWith("gcc") || fileName.endsWith("gcc"))) || (tcd.language == Constants::CXX_LANGUAGE_ID && (fileName.startsWith("g++") - || fileName.endsWith("g++")))) + || fileName.endsWith("g++")))) { return autoDetectToolChain(tcd, [](const ToolChain *tc) { return tc->targetAbi().osFlavor() == Abi::WindowsMSysFlavor; }); + } return {}; } @@ -1896,8 +1903,9 @@ Toolchains LinuxIccToolChainFactory::detectForImport(const ToolChainDescription { const QString fileName = tcd.compilerPath.toString(); if ((tcd.language == Constants::CXX_LANGUAGE_ID && fileName.startsWith("icpc")) || - (tcd.language == Constants::C_LANGUAGE_ID && fileName.startsWith("icc"))) + (tcd.language == Constants::C_LANGUAGE_ID && fileName.startsWith("icc"))) { return autoDetectToolChain(tcd); + } return {}; } diff --git a/src/plugins/projectexplorer/toolchain.cpp b/src/plugins/projectexplorer/toolchain.cpp index b3ad7cea475..51a4e00665e 100644 --- a/src/plugins/projectexplorer/toolchain.cpp +++ b/src/plugins/projectexplorer/toolchain.cpp @@ -39,6 +39,8 @@ #include #include +#include + using namespace Utils; static const char ID_KEY[] = "ProjectExplorer.ToolChain.Id"; @@ -652,4 +654,62 @@ ToolchainDetector::ToolchainDetector(const Toolchains &alreadyKnown, const IDevi : alreadyKnown(alreadyKnown), device(device) {} +BadToolchain::BadToolchain(const Utils::FilePath &filePath) + : BadToolchain(filePath, filePath.symLinkTarget(), filePath.lastModified()) +{} + +BadToolchain::BadToolchain(const Utils::FilePath &filePath, const Utils::FilePath &symlinkTarget, + const QDateTime ×tamp) + : filePath(filePath), symlinkTarget(symlinkTarget), timestamp(timestamp) +{} + + +static QString badToolchainFilePathKey() { return {"FilePath"}; } +static QString badToolchainSymlinkTargetKey() { return {"TargetFilePath"}; } +static QString badToolchainTimestampKey() { return {"Timestamp"}; } + +QVariantMap BadToolchain::toMap() const +{ + return { + std::make_pair(badToolchainFilePathKey(), filePath.toVariant()), + std::make_pair(badToolchainSymlinkTargetKey(), symlinkTarget.toVariant()), + std::make_pair(badToolchainTimestampKey(), timestamp.toMSecsSinceEpoch()), + }; +} + +BadToolchain BadToolchain::fromMap(const QVariantMap &map) +{ + return { + FilePath::fromVariant(map.value(badToolchainFilePathKey())), + FilePath::fromVariant(map.value(badToolchainSymlinkTargetKey())), + QDateTime::fromMSecsSinceEpoch(map.value(badToolchainTimestampKey()).toLongLong()) + }; +} + +BadToolchains::BadToolchains(const QList &toolchains) + : toolchains(Utils::filtered(toolchains, [](const BadToolchain &badTc) { + return badTc.filePath.lastModified() == badTc.timestamp + && badTc.filePath.symLinkTarget() == badTc.symlinkTarget; + })) +{} + +bool BadToolchains::isBadToolchain(const FilePath &toolchain) const +{ + return Utils::contains(toolchains, [toolchain](const BadToolchain &badTc) { + return badTc.filePath == toolchain.absoluteFilePath() + || badTc.symlinkTarget == toolchain.absoluteFilePath(); + }); +} + +QVariant BadToolchains::toVariant() const +{ + return Utils::transform(toolchains, &BadToolchain::toMap); +} + +BadToolchains BadToolchains::fromVariant(const QVariant &v) +{ + return Utils::transform>(v.toList(), + [](const QVariant &e) { return BadToolchain::fromMap(e.toMap()); }); +} + } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/toolchain.h b/src/plugins/projectexplorer/toolchain.h index 1c4b1a09fb2..82e9b299f27 100644 --- a/src/plugins/projectexplorer/toolchain.h +++ b/src/plugins/projectexplorer/toolchain.h @@ -39,6 +39,7 @@ #include #include +#include #include #include #include @@ -214,11 +215,41 @@ private: using Toolchains = QList; +class PROJECTEXPLORER_EXPORT BadToolchain +{ +public: + BadToolchain(const Utils::FilePath &filePath); + BadToolchain(const Utils::FilePath &filePath, const Utils::FilePath &symlinkTarget, + const QDateTime ×tamp); + + QVariantMap toMap() const; + static BadToolchain fromMap(const QVariantMap &map); + + Utils::FilePath filePath; + Utils::FilePath symlinkTarget; + QDateTime timestamp; +}; + +class PROJECTEXPLORER_EXPORT BadToolchains +{ +public: + BadToolchains(const QList &toolchains = {}); + bool isBadToolchain(const Utils::FilePath &toolchain) const; + + QVariant toVariant() const; + static BadToolchains fromVariant(const QVariant &v); + + QList toolchains; +}; + class PROJECTEXPLORER_EXPORT ToolchainDetector { public: ToolchainDetector(const Toolchains &alreadyKnown, const IDevice::ConstPtr &device); + bool isBadToolchain(const Utils::FilePath &toolchain) const; + void addBadToolchain(const Utils::FilePath &toolchain) const; + const Toolchains alreadyKnown; const IDevice::ConstPtr device; }; diff --git a/src/plugins/projectexplorer/toolchainmanager.cpp b/src/plugins/projectexplorer/toolchainmanager.cpp index 545601f2b87..012800a18eb 100644 --- a/src/plugins/projectexplorer/toolchainmanager.cpp +++ b/src/plugins/projectexplorer/toolchainmanager.cpp @@ -63,6 +63,7 @@ public: std::unique_ptr m_accessor; Toolchains m_toolChains; // prioritized List + BadToolchains m_badToolchains; // to be skipped when auto-detecting QVector m_languages; ToolchainDetectionSettings m_detectionSettings; bool m_loaded = false; @@ -83,6 +84,8 @@ using namespace Internal; const char DETECT_X64_AS_X32_KEY[] = "ProjectExplorer/Toolchains/DetectX64AsX32"; +static QString badToolchainsKey() { return {"BadToolChains"}; } + // -------------------------------------------------------------------------- // ToolChainManager // -------------------------------------------------------------------------- @@ -104,6 +107,7 @@ ToolChainManager::ToolChainManager(QObject *parent) : QSettings * const s = Core::ICore::settings(); d->m_detectionSettings.detectX64AsX32 = s->value(DETECT_X64_AS_X32_KEY, ToolchainDetectionSettings().detectX64AsX32).toBool(); + d->m_badToolchains = BadToolchains::fromVariant(s->value(badToolchainsKey())); } ToolChainManager::~ToolChainManager() @@ -139,6 +143,7 @@ void ToolChainManager::saveToolChains() s->setValueWithDefault(DETECT_X64_AS_X32_KEY, d->m_detectionSettings.detectX64AsX32, ToolchainDetectionSettings().detectX64AsX32); + s->setValue(badToolchainsKey(), d->m_badToolchains.toVariant()); } const Toolchains &ToolChainManager::toolchains() @@ -278,4 +283,19 @@ void ToolChainManager::setDetectionSettings(const ToolchainDetectionSettings &se d->m_detectionSettings = settings; } +void ToolChainManager::resetBadToolchains() +{ + d->m_badToolchains.toolchains.clear(); +} + +bool ToolChainManager::isBadToolchain(const Utils::FilePath &toolchain) +{ + return d->m_badToolchains.isBadToolchain(toolchain); +} + +void ToolChainManager::addBadToolchain(const Utils::FilePath &toolchain) +{ + d->m_badToolchains.toolchains << toolchain; +} + } // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/toolchainmanager.h b/src/plugins/projectexplorer/toolchainmanager.h index d755176fc7f..31d546f595e 100644 --- a/src/plugins/projectexplorer/toolchainmanager.h +++ b/src/plugins/projectexplorer/toolchainmanager.h @@ -83,6 +83,10 @@ public: static ToolchainDetectionSettings detectionSettings(); static void setDetectionSettings(const ToolchainDetectionSettings &settings); + static void resetBadToolchains(); + static bool isBadToolchain(const Utils::FilePath &toolchain); + static void addBadToolchain(const Utils::FilePath &toolchain); + void saveToolChains(); signals: diff --git a/src/plugins/projectexplorer/toolchainoptionspage.cpp b/src/plugins/projectexplorer/toolchainoptionspage.cpp index 7a0674c3728..f00043fb192 100644 --- a/src/plugins/projectexplorer/toolchainoptionspage.cpp +++ b/src/plugins/projectexplorer/toolchainoptionspage.cpp @@ -412,6 +412,7 @@ void ToolChainOptionsWidget::redetectToolchains() }); Toolchains toAdd; QSet toDelete; + ToolChainManager::resetBadToolchains(); for (ToolChainFactory *f : ToolChainFactory::allToolChainFactories()) { const ToolchainDetector detector(knownTcs, {}); // FIXME: Pass device. for (ToolChain * const tc : f->autoDetect(detector)) {