forked from qt-creator/qt-creator
ProjectExplorer: Collect and remember non-functional toolchains
It's not unusual for the toolchain auto-detection procedure to encounter binaries that turn out not to be valid toolchains only after running them, either because they are genuinely broken or because their names match a compiler name pattern, but they are not actually compilers. Until now, we would re-run such executables on every start of Qt Creator, potentially delaying start-up unnecessarily. Now we store them in the settings and do not try to run them again. For now, the collection of bad toolchains is done for GCC only. Follow- up patches will add support for more toolchain types. Change-Id: Icfa28de523737bdd88af3a2bfa8b947326c1bc70 Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -1023,10 +1023,11 @@ Toolchains GccToolChainFactory::detectForImport(const ToolChainDescription &tcd)
|
|||||||
|| fileName == "cc"))
|
|| fileName == "cc"))
|
||||||
|| (tcd.language == Constants::CXX_LANGUAGE_ID && (fileName.startsWith("g++")
|
|| (tcd.language == Constants::CXX_LANGUAGE_ID && (fileName.startsWith("g++")
|
||||||
|| fileName.endsWith("g++")
|
|| fileName.endsWith("g++")
|
||||||
|| fileName == "c++")))
|
|| fileName == "c++"))) {
|
||||||
return autoDetectToolChain(tcd, [](const ToolChain *tc) {
|
return autoDetectToolChain(tcd, [](const ToolChain *tc) {
|
||||||
return tc->targetAbi().osFlavor() != Abi::WindowsMSysFlavor;
|
return tc->targetAbi().osFlavor() != Abi::WindowsMSysFlavor;
|
||||||
});
|
});
|
||||||
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1164,11 +1165,15 @@ Toolchains GccToolChainFactory::autoDetectToolChain(const ToolChainDescription &
|
|||||||
Environment systemEnvironment = Environment::systemEnvironment();
|
Environment systemEnvironment = Environment::systemEnvironment();
|
||||||
GccToolChain::addCommandPathToEnvironment(tcd.compilerPath, systemEnvironment);
|
GccToolChain::addCommandPathToEnvironment(tcd.compilerPath, systemEnvironment);
|
||||||
const FilePath localCompilerPath = findLocalCompiler(tcd.compilerPath, systemEnvironment);
|
const FilePath localCompilerPath = findLocalCompiler(tcd.compilerPath, systemEnvironment);
|
||||||
|
if (ToolChainManager::isBadToolchain(localCompilerPath))
|
||||||
|
return result;
|
||||||
Macros macros
|
Macros macros
|
||||||
= gccPredefinedMacros(localCompilerPath, gccPredefinedMacrosOptions(tcd.language),
|
= gccPredefinedMacros(localCompilerPath, gccPredefinedMacrosOptions(tcd.language),
|
||||||
systemEnvironment);
|
systemEnvironment);
|
||||||
if (macros.isEmpty())
|
if (macros.isEmpty()) {
|
||||||
|
ToolChainManager::addBadToolchain(localCompilerPath);
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
const GccToolChain::DetectedAbisResult detectedAbis = guessGccAbi(localCompilerPath,
|
const GccToolChain::DetectedAbisResult detectedAbis = guessGccAbi(localCompilerPath,
|
||||||
systemEnvironment,
|
systemEnvironment,
|
||||||
macros);
|
macros);
|
||||||
@@ -1640,8 +1645,9 @@ Toolchains ClangToolChainFactory::detectForImport(const ToolChainDescription &tc
|
|||||||
{
|
{
|
||||||
const QString fileName = tcd.compilerPath.toString();
|
const QString fileName = tcd.compilerPath.toString();
|
||||||
if ((tcd.language == Constants::C_LANGUAGE_ID && fileName.startsWith("clang") && !fileName.startsWith("clang++"))
|
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 autoDetectToolChain(tcd);
|
||||||
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1820,10 +1826,11 @@ Toolchains MingwToolChainFactory::detectForImport(const ToolChainDescription &tc
|
|||||||
if ((tcd.language == Constants::C_LANGUAGE_ID && (fileName.startsWith("gcc")
|
if ((tcd.language == Constants::C_LANGUAGE_ID && (fileName.startsWith("gcc")
|
||||||
|| fileName.endsWith("gcc")))
|
|| fileName.endsWith("gcc")))
|
||||||
|| (tcd.language == Constants::CXX_LANGUAGE_ID && (fileName.startsWith("g++")
|
|| (tcd.language == Constants::CXX_LANGUAGE_ID && (fileName.startsWith("g++")
|
||||||
|| fileName.endsWith("g++"))))
|
|| fileName.endsWith("g++")))) {
|
||||||
return autoDetectToolChain(tcd, [](const ToolChain *tc) {
|
return autoDetectToolChain(tcd, [](const ToolChain *tc) {
|
||||||
return tc->targetAbi().osFlavor() == Abi::WindowsMSysFlavor;
|
return tc->targetAbi().osFlavor() == Abi::WindowsMSysFlavor;
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@@ -1896,8 +1903,9 @@ Toolchains LinuxIccToolChainFactory::detectForImport(const ToolChainDescription
|
|||||||
{
|
{
|
||||||
const QString fileName = tcd.compilerPath.toString();
|
const QString fileName = tcd.compilerPath.toString();
|
||||||
if ((tcd.language == Constants::CXX_LANGUAGE_ID && fileName.startsWith("icpc")) ||
|
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 autoDetectToolChain(tcd);
|
||||||
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -39,6 +39,8 @@
|
|||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
using namespace Utils;
|
using namespace Utils;
|
||||||
|
|
||||||
static const char ID_KEY[] = "ProjectExplorer.ToolChain.Id";
|
static const char ID_KEY[] = "ProjectExplorer.ToolChain.Id";
|
||||||
@@ -652,4 +654,62 @@ ToolchainDetector::ToolchainDetector(const Toolchains &alreadyKnown, const IDevi
|
|||||||
: alreadyKnown(alreadyKnown), device(device)
|
: 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<BadToolchain> &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<QVariantList>(toolchains, &BadToolchain::toMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
BadToolchains BadToolchains::fromVariant(const QVariant &v)
|
||||||
|
{
|
||||||
|
return Utils::transform<QList<BadToolchain>>(v.toList(),
|
||||||
|
[](const QVariant &e) { return BadToolchain::fromMap(e.toMap()); });
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ProjectExplorer
|
} // namespace ProjectExplorer
|
||||||
|
@@ -39,6 +39,7 @@
|
|||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
#include <utils/id.h>
|
#include <utils/id.h>
|
||||||
|
|
||||||
|
#include <QDateTime>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QVariantMap>
|
#include <QVariantMap>
|
||||||
@@ -214,11 +215,41 @@ private:
|
|||||||
|
|
||||||
using Toolchains = QList<ToolChain *>;
|
using Toolchains = QList<ToolChain *>;
|
||||||
|
|
||||||
|
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<BadToolchain> &toolchains = {});
|
||||||
|
bool isBadToolchain(const Utils::FilePath &toolchain) const;
|
||||||
|
|
||||||
|
QVariant toVariant() const;
|
||||||
|
static BadToolchains fromVariant(const QVariant &v);
|
||||||
|
|
||||||
|
QList<BadToolchain> toolchains;
|
||||||
|
};
|
||||||
|
|
||||||
class PROJECTEXPLORER_EXPORT ToolchainDetector
|
class PROJECTEXPLORER_EXPORT ToolchainDetector
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ToolchainDetector(const Toolchains &alreadyKnown, const IDevice::ConstPtr &device);
|
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 Toolchains alreadyKnown;
|
||||||
const IDevice::ConstPtr device;
|
const IDevice::ConstPtr device;
|
||||||
};
|
};
|
||||||
|
@@ -63,6 +63,7 @@ public:
|
|||||||
std::unique_ptr<ToolChainSettingsAccessor> m_accessor;
|
std::unique_ptr<ToolChainSettingsAccessor> m_accessor;
|
||||||
|
|
||||||
Toolchains m_toolChains; // prioritized List
|
Toolchains m_toolChains; // prioritized List
|
||||||
|
BadToolchains m_badToolchains; // to be skipped when auto-detecting
|
||||||
QVector<LanguageDisplayPair> m_languages;
|
QVector<LanguageDisplayPair> m_languages;
|
||||||
ToolchainDetectionSettings m_detectionSettings;
|
ToolchainDetectionSettings m_detectionSettings;
|
||||||
bool m_loaded = false;
|
bool m_loaded = false;
|
||||||
@@ -83,6 +84,8 @@ using namespace Internal;
|
|||||||
|
|
||||||
const char DETECT_X64_AS_X32_KEY[] = "ProjectExplorer/Toolchains/DetectX64AsX32";
|
const char DETECT_X64_AS_X32_KEY[] = "ProjectExplorer/Toolchains/DetectX64AsX32";
|
||||||
|
|
||||||
|
static QString badToolchainsKey() { return {"BadToolChains"}; }
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// ToolChainManager
|
// ToolChainManager
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
@@ -104,6 +107,7 @@ ToolChainManager::ToolChainManager(QObject *parent) :
|
|||||||
QSettings * const s = Core::ICore::settings();
|
QSettings * const s = Core::ICore::settings();
|
||||||
d->m_detectionSettings.detectX64AsX32
|
d->m_detectionSettings.detectX64AsX32
|
||||||
= s->value(DETECT_X64_AS_X32_KEY, ToolchainDetectionSettings().detectX64AsX32).toBool();
|
= s->value(DETECT_X64_AS_X32_KEY, ToolchainDetectionSettings().detectX64AsX32).toBool();
|
||||||
|
d->m_badToolchains = BadToolchains::fromVariant(s->value(badToolchainsKey()));
|
||||||
}
|
}
|
||||||
|
|
||||||
ToolChainManager::~ToolChainManager()
|
ToolChainManager::~ToolChainManager()
|
||||||
@@ -139,6 +143,7 @@ void ToolChainManager::saveToolChains()
|
|||||||
s->setValueWithDefault(DETECT_X64_AS_X32_KEY,
|
s->setValueWithDefault(DETECT_X64_AS_X32_KEY,
|
||||||
d->m_detectionSettings.detectX64AsX32,
|
d->m_detectionSettings.detectX64AsX32,
|
||||||
ToolchainDetectionSettings().detectX64AsX32);
|
ToolchainDetectionSettings().detectX64AsX32);
|
||||||
|
s->setValue(badToolchainsKey(), d->m_badToolchains.toVariant());
|
||||||
}
|
}
|
||||||
|
|
||||||
const Toolchains &ToolChainManager::toolchains()
|
const Toolchains &ToolChainManager::toolchains()
|
||||||
@@ -278,4 +283,19 @@ void ToolChainManager::setDetectionSettings(const ToolchainDetectionSettings &se
|
|||||||
d->m_detectionSettings = settings;
|
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
|
} // namespace ProjectExplorer
|
||||||
|
@@ -83,6 +83,10 @@ public:
|
|||||||
static ToolchainDetectionSettings detectionSettings();
|
static ToolchainDetectionSettings detectionSettings();
|
||||||
static void setDetectionSettings(const ToolchainDetectionSettings &settings);
|
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();
|
void saveToolChains();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
@@ -412,6 +412,7 @@ void ToolChainOptionsWidget::redetectToolchains()
|
|||||||
});
|
});
|
||||||
Toolchains toAdd;
|
Toolchains toAdd;
|
||||||
QSet<ToolChain *> toDelete;
|
QSet<ToolChain *> toDelete;
|
||||||
|
ToolChainManager::resetBadToolchains();
|
||||||
for (ToolChainFactory *f : ToolChainFactory::allToolChainFactories()) {
|
for (ToolChainFactory *f : ToolChainFactory::allToolChainFactories()) {
|
||||||
const ToolchainDetector detector(knownTcs, {}); // FIXME: Pass device.
|
const ToolchainDetector detector(knownTcs, {}); // FIXME: Pass device.
|
||||||
for (ToolChain * const tc : f->autoDetect(detector)) {
|
for (ToolChain * const tc : f->autoDetect(detector)) {
|
||||||
|
Reference in New Issue
Block a user