ProjectExplorer: Merge GccToolChainFactories further

This replaces the four classes from the GccToolChainFactories
hierarchy by a single (parametrized) GccToolChainFactory, but
makes the "RealGcc" one responsible for all autodetection.

This is a hack to move closer to a "scan only once" setup, and
temporarily necessary as there is currently one factory creates
one type of toolchain, so we need four factories for the current
four gcc-ish toolchain types.

Change-Id: Icbecb1be6e89cf5efad76baf92ef38ac63be074f
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
hjk
2023-09-26 10:25:16 +02:00
parent 61048fa737
commit 4d2f3e8b01
4 changed files with 190 additions and 210 deletions

View File

@@ -1198,182 +1198,228 @@ static Utils::FilePaths renesasRl78SearchPathsFromRegistry()
return searchPaths; return searchPaths;
} }
GccToolChainFactory::GccToolChainFactory() static ToolChain *constructRealGccToolchain()
{ {
setDisplayName(Tr::tr("GCC")); return new GccToolChain(Constants::GCC_TOOLCHAIN_TYPEID, GccToolChain::RealGcc);
setSupportedToolChainType(Constants::GCC_TOOLCHAIN_TYPEID); }
static ToolChain *constructClangToolchain()
{
return new GccToolChain(Constants::CLANG_TOOLCHAIN_TYPEID, GccToolChain::Clang);
}
static ToolChain *constructMinGWToolchain()
{
return new GccToolChain(Constants::MINGW_TOOLCHAIN_TYPEID, GccToolChain::MinGW);
}
static ToolChain *constructLinuxIccToolchain()
{
return new GccToolChain(Constants::LINUXICC_TOOLCHAIN_TYPEID, GccToolChain::LinuxIcc);
}
GccToolChainFactory::GccToolChainFactory(GccToolChain::SubType subType)
: m_autoDetecting(subType == GccToolChain::RealGcc)
{
switch (subType) {
case GccToolChain::RealGcc:
setDisplayName(Tr::tr("GCC"));
setSupportedToolChainType(Constants::GCC_TOOLCHAIN_TYPEID);
setToolchainConstructor(&constructRealGccToolchain);
break;
case GccToolChain::Clang:
setDisplayName(Tr::tr("Clang"));
setSupportedToolChainType(Constants::CLANG_TOOLCHAIN_TYPEID);
setToolchainConstructor(&constructClangToolchain);
break;
case GccToolChain::MinGW:
setDisplayName(Tr::tr("MinGW"));
setSupportedToolChainType(Constants::MINGW_TOOLCHAIN_TYPEID);
setToolchainConstructor(&constructMinGWToolchain);
break;
case GccToolChain::LinuxIcc:
setDisplayName(Tr::tr("ICC"));
setSupportedToolChainType(Constants::LINUXICC_TOOLCHAIN_TYPEID);
setToolchainConstructor(&constructLinuxIccToolchain);
break;
}
setSupportedLanguages({Constants::C_LANGUAGE_ID, Constants::CXX_LANGUAGE_ID}); setSupportedLanguages({Constants::C_LANGUAGE_ID, Constants::CXX_LANGUAGE_ID});
setToolchainConstructor([] { return new GccToolChain(Constants::GCC_TOOLCHAIN_TYPEID); });
setUserCreatable(true); setUserCreatable(true);
} }
Toolchains GccToolChainFactory::autoDetect(const ToolchainDetector &detector) const Toolchains GccToolChainFactory::autoDetect(const ToolchainDetector &detector) const
{ {
if (m_subType == GccToolChain::LinuxIcc) { Toolchains result;
Toolchains result = autoDetectToolchains("icpc",
DetectVariants::No, // Do all autodetection in th 'RealGcc' case, and none in the others.
Constants::CXX_LANGUAGE_ID, if (!m_autoDetecting)
Constants::LINUXICC_TOOLCHAIN_TYPEID,
detector,
toolchainConstructor());
result += autoDetectToolchains("icc",
DetectVariants::Yes,
Constants::C_LANGUAGE_ID,
Constants::LINUXICC_TOOLCHAIN_TYPEID,
detector,
toolchainConstructor());
return result; return result;
}
if (m_subType == GccToolChain::MinGW) { // Linux ICC
static const auto tcChecker = [](const ToolChain *tc) {
return tc->targetAbi().osFlavor() == Abi::WindowsMSysFlavor;
};
Toolchains result = autoDetectToolchains("g++",
DetectVariants::Yes,
Constants::CXX_LANGUAGE_ID,
Constants::MINGW_TOOLCHAIN_TYPEID,
detector,
toolchainConstructor(),
tcChecker);
result += autoDetectToolchains("gcc",
DetectVariants::Yes,
Constants::C_LANGUAGE_ID,
Constants::MINGW_TOOLCHAIN_TYPEID,
detector,
toolchainConstructor(),
tcChecker);
return result;
}
if (m_subType == GccToolChain::Clang) { result += autoDetectToolchains("icpc",
Toolchains tcs; DetectVariants::No,
Toolchains known = detector.alreadyKnown; Constants::CXX_LANGUAGE_ID,
Constants::LINUXICC_TOOLCHAIN_TYPEID,
detector,
&constructLinuxIccToolchain);
result += autoDetectToolchains("icc",
DetectVariants::Yes,
Constants::C_LANGUAGE_ID,
Constants::LINUXICC_TOOLCHAIN_TYPEID,
detector,
&constructLinuxIccToolchain);
tcs.append(autoDetectToolchains("clang++", // MinGW
DetectVariants::Yes,
Constants::CXX_LANGUAGE_ID,
Constants::CLANG_TOOLCHAIN_TYPEID,
detector,
toolchainConstructor()));
tcs.append(autoDetectToolchains("clang",
DetectVariants::Yes,
Constants::C_LANGUAGE_ID,
Constants::CLANG_TOOLCHAIN_TYPEID,
detector,
toolchainConstructor()));
known.append(tcs);
const FilePath compilerPath = Core::ICore::clangExecutable(CLANG_BINDIR); static const auto tcChecker = [](const ToolChain *tc) {
if (!compilerPath.isEmpty()) { return tc->targetAbi().osFlavor() == Abi::WindowsMSysFlavor;
const FilePath clang = compilerPath.parentDir().pathAppended("clang").withExecutableSuffix(); };
tcs.append( result += autoDetectToolchains("g++",
autoDetectToolchains(clang.toString(), DetectVariants::Yes,
DetectVariants::No, Constants::CXX_LANGUAGE_ID,
Constants::C_LANGUAGE_ID, Constants::MINGW_TOOLCHAIN_TYPEID,
Constants::CLANG_TOOLCHAIN_TYPEID, detector,
ToolchainDetector(known, detector.device, detector.searchPaths), &constructMinGWToolchain,
toolchainConstructor())); tcChecker);
} result += autoDetectToolchains("gcc",
DetectVariants::Yes,
Constants::C_LANGUAGE_ID,
Constants::MINGW_TOOLCHAIN_TYPEID,
detector,
&constructMinGWToolchain,
tcChecker);
return tcs; // Clang
}
// GCC is almost never what you want on macOS, but it is by default found in /usr/bin
if (HostOsInfo::isMacHost() && detector.device->type() == Constants::DESKTOP_DEVICE_TYPE)
return {};
Toolchains tcs; Toolchains tcs;
static const auto tcChecker = [](const ToolChain *tc) { Toolchains known = detector.alreadyKnown;
return tc->targetAbi().osFlavor() != Abi::WindowsMSysFlavor
&& tc->compilerCommand().fileName() != "c89-gcc" tcs.append(autoDetectToolchains("clang++",
&& tc->compilerCommand().fileName() != "c99-gcc";
};
tcs.append(autoDetectToolchains("g++",
DetectVariants::Yes, DetectVariants::Yes,
Constants::CXX_LANGUAGE_ID, Constants::CXX_LANGUAGE_ID,
Constants::GCC_TOOLCHAIN_TYPEID, Constants::CLANG_TOOLCHAIN_TYPEID,
detector, detector,
toolchainConstructor(), &constructClangToolchain));
tcChecker)); tcs.append(autoDetectToolchains("clang",
tcs.append(autoDetectToolchains("gcc",
DetectVariants::Yes, DetectVariants::Yes,
Constants::C_LANGUAGE_ID, Constants::C_LANGUAGE_ID,
Constants::GCC_TOOLCHAIN_TYPEID, Constants::CLANG_TOOLCHAIN_TYPEID,
detector, detector,
toolchainConstructor(), &constructClangToolchain));
tcChecker)); known.append(tcs);
return tcs;
const FilePath compilerPath = Core::ICore::clangExecutable(CLANG_BINDIR);
if (!compilerPath.isEmpty()) {
const FilePath clang = compilerPath.parentDir().pathAppended("clang").withExecutableSuffix();
tcs.append(
autoDetectToolchains(clang.toString(),
DetectVariants::No,
Constants::C_LANGUAGE_ID,
Constants::CLANG_TOOLCHAIN_TYPEID,
ToolchainDetector(known, detector.device, detector.searchPaths),
&constructClangToolchain));
}
result += tcs;
// GCC
// Gcc is almost never what you want on macOS, but it is by default found in /usr/bin
if (!HostOsInfo::isMacHost() || detector.device->type() != Constants::DESKTOP_DEVICE_TYPE) {
Toolchains tcs;
static const auto tcChecker = [](const ToolChain *tc) {
return tc->targetAbi().osFlavor() != Abi::WindowsMSysFlavor
&& tc->compilerCommand().fileName() != "c89-gcc"
&& tc->compilerCommand().fileName() != "c99-gcc";
};
tcs.append(autoDetectToolchains("g++",
DetectVariants::Yes,
Constants::CXX_LANGUAGE_ID,
Constants::GCC_TOOLCHAIN_TYPEID,
detector,
&constructRealGccToolchain,
tcChecker));
tcs.append(autoDetectToolchains("gcc",
DetectVariants::Yes,
Constants::C_LANGUAGE_ID,
Constants::GCC_TOOLCHAIN_TYPEID,
detector,
&constructRealGccToolchain,
tcChecker));
result += tcs;
}
return result;
} }
Toolchains GccToolChainFactory::detectForImport(const ToolChainDescription &tcd) const Toolchains GccToolChainFactory::detectForImport(const ToolChainDescription &tcd) const
{ {
if (m_subType == GccToolChain::LinuxIcc) { Toolchains result;
const QString fileName = tcd.compilerPath.completeBaseName();
if ((tcd.language == Constants::CXX_LANGUAGE_ID && fileName.startsWith("icpc")) ||
(tcd.language == Constants::C_LANGUAGE_ID && fileName.startsWith("icc"))) {
return autoDetectToolChain(tcd, toolchainConstructor());
}
return {};
}
if (m_subType == GccToolChain::MinGW) { // Do all autodetection in th 'RealGcc' case, and none in the others.
const QString fileName = tcd.compilerPath.completeBaseName(); if (!m_autoDetecting)
return result;
const bool cCompiler = tcd.language == Constants::C_LANGUAGE_ID
&& ((fileName.startsWith("gcc") || fileName.endsWith("gcc"))
|| fileName == "cc");
const bool cxxCompiler = tcd.language == Constants::CXX_LANGUAGE_ID
&& ((fileName.startsWith("g++") || fileName.endsWith("g++"))
|| (fileName.startsWith("c++") || fileName.endsWith("c++")));
if (cCompiler || cxxCompiler) {
return autoDetectToolChain(tcd, toolchainConstructor(), [](const ToolChain *tc) {
return tc->targetAbi().osFlavor() == Abi::WindowsMSysFlavor;
});
}
return {};
}
if (m_subType == GccToolChain::Clang) {
const QString fileName = tcd.compilerPath.completeBaseName();
const QString resolvedSymlinksFileName = tcd.compilerPath.resolveSymlinks().completeBaseName();
const bool isCCompiler = tcd.language == Constants::C_LANGUAGE_ID
&& ((fileName.startsWith("clang") && !fileName.startsWith("clang++"))
|| (fileName == "cc" && resolvedSymlinksFileName.contains("clang")));
const bool isCxxCompiler = tcd.language == Constants::CXX_LANGUAGE_ID
&& (fileName.startsWith("clang++")
|| (fileName == "c++" && resolvedSymlinksFileName.contains("clang")));
if (isCCompiler || isCxxCompiler)
return autoDetectToolChain(tcd, toolchainConstructor());
return {};
}
const QString fileName = tcd.compilerPath.completeBaseName(); const QString fileName = tcd.compilerPath.completeBaseName();
const QString resolvedSymlinksFileName = tcd.compilerPath.resolveSymlinks().completeBaseName(); const QString resolvedSymlinksFileName = tcd.compilerPath.resolveSymlinks().completeBaseName();
const bool isCCompiler = tcd.language == Constants::C_LANGUAGE_ID // Linux ICC
if ((tcd.language == Constants::CXX_LANGUAGE_ID && fileName.startsWith("icpc")) ||
(tcd.language == Constants::C_LANGUAGE_ID && fileName.startsWith("icc"))) {
result += autoDetectToolChain(tcd, &constructLinuxIccToolchain);
}
// MingW
const bool cCompiler = tcd.language == Constants::C_LANGUAGE_ID
&& ((fileName.startsWith("gcc") || fileName.endsWith("gcc"))
|| fileName == "cc");
const bool cxxCompiler = tcd.language == Constants::CXX_LANGUAGE_ID
&& ((fileName.startsWith("g++") || fileName.endsWith("g++"))
|| (fileName.startsWith("c++") || fileName.endsWith("c++")));
if (cCompiler || cxxCompiler) {
result += autoDetectToolChain(tcd, &constructMinGWToolchain, [](const ToolChain *tc) {
return tc->targetAbi().osFlavor() == Abi::WindowsMSysFlavor;
});
}
// Clang
bool isCCompiler = tcd.language == Constants::C_LANGUAGE_ID
&& ((fileName.startsWith("clang") && !fileName.startsWith("clang++"))
|| (fileName == "cc" && resolvedSymlinksFileName.contains("clang")));
bool isCxxCompiler = tcd.language == Constants::CXX_LANGUAGE_ID
&& (fileName.startsWith("clang++")
|| (fileName == "c++" && resolvedSymlinksFileName.contains("clang")));
if (isCCompiler || isCxxCompiler)
result += autoDetectToolChain(tcd, &constructClangToolchain);
// GCC
isCCompiler = tcd.language == Constants::C_LANGUAGE_ID
&& (fileName.startsWith("gcc") && (fileName.startsWith("gcc")
|| fileName.endsWith("gcc") || fileName.endsWith("gcc")
|| (fileName == "cc" && !resolvedSymlinksFileName.contains("clang"))); || (fileName == "cc" && !resolvedSymlinksFileName.contains("clang")));
const bool isCxxCompiler = tcd.language == Constants::CXX_LANGUAGE_ID isCxxCompiler = tcd.language == Constants::CXX_LANGUAGE_ID
&& (fileName.startsWith("g++") && (fileName.startsWith("g++")
|| fileName.endsWith("g++") || fileName.endsWith("g++")
|| (fileName == "c++" && !resolvedSymlinksFileName.contains("clang"))); || (fileName == "c++" && !resolvedSymlinksFileName.contains("clang")));
if (isCCompiler || isCxxCompiler) { if (isCCompiler || isCxxCompiler) {
return autoDetectToolChain(tcd, toolchainConstructor(), [](const ToolChain *tc) { result += autoDetectToolChain(tcd, &constructRealGccToolchain, [](const ToolChain *tc) {
return tc->targetAbi().osFlavor() != Abi::WindowsMSysFlavor; return tc->targetAbi().osFlavor() != Abi::WindowsMSysFlavor;
}); });
} }
return {};
return result;
} }
static FilePaths findCompilerCandidates(const ToolchainDetector &detector, static FilePaths findCompilerCandidates(const ToolchainDetector &detector,
@@ -1910,22 +1956,6 @@ QString GccToolChain::sysRoot() const
return {}; return {};
} }
// --------------------------------------------------------------------------
// ClangToolChainFactory
// --------------------------------------------------------------------------
ClangToolChainFactory::ClangToolChainFactory()
{
m_subType = GccToolChain::Clang;
setDisplayName(Tr::tr("Clang"));
setSupportedToolChainType(Constants::CLANG_TOOLCHAIN_TYPEID);
setSupportedLanguages({Constants::CXX_LANGUAGE_ID, Constants::C_LANGUAGE_ID});
setToolchainConstructor([] {
return new GccToolChain(Constants::CLANG_TOOLCHAIN_TYPEID, GccToolChain::Clang);
});
}
void GccToolChainConfigWidget::updateParentToolChainComboBox() void GccToolChainConfigWidget::updateParentToolChainComboBox()
{ {
QTC_ASSERT(m_parentToolchainCombo, return); QTC_ASSERT(m_parentToolchainCombo, return);
@@ -1953,36 +1983,6 @@ void GccToolChainConfigWidget::updateParentToolChainComboBox()
} }
} }
// --------------------------------------------------------------------------
// MingwToolChainFactory
// --------------------------------------------------------------------------
MingwToolChainFactory::MingwToolChainFactory()
{
m_subType = GccToolChain::MinGW;
setDisplayName(Tr::tr("MinGW"));
setSupportedToolChainType(Constants::MINGW_TOOLCHAIN_TYPEID);
setSupportedLanguages({Constants::CXX_LANGUAGE_ID, Constants::C_LANGUAGE_ID});
setToolchainConstructor([] {
return new GccToolChain(Constants::MINGW_TOOLCHAIN_TYPEID, GccToolChain::MinGW);
});
}
// --------------------------------------------------------------------------
// LinuxIccToolChainFactory
// --------------------------------------------------------------------------
LinuxIccToolChainFactory::LinuxIccToolChainFactory()
{
m_subType = GccToolChain::LinuxIcc;
setDisplayName(Tr::tr("ICC"));
setSupportedToolChainType(Constants::LINUXICC_TOOLCHAIN_TYPEID);
setSupportedLanguages({Constants::CXX_LANGUAGE_ID, Constants::C_LANGUAGE_ID});
setToolchainConstructor([] {
return new GccToolChain(Constants::LINUXICC_TOOLCHAIN_TYPEID, GccToolChain::LinuxIcc);
});
}
GccToolChain::WarningFlagAdder::WarningFlagAdder(const QString &flag, WarningFlags &flags) : GccToolChain::WarningFlagAdder::WarningFlagAdder(const QString &flag, WarningFlags &flags) :
m_flags(flags) m_flags(flags)
{ {

View File

@@ -180,22 +180,18 @@ private:
QMetaObject::Connection m_thisToolchainRemovedConnection; QMetaObject::Connection m_thisToolchainRemovedConnection;
}; };
// --------------------------------------------------------------------------
// Factories
// --------------------------------------------------------------------------
namespace Internal { namespace Internal {
class GccToolChainFactory : public ToolChainFactory class GccToolChainFactory : public ToolChainFactory
{ {
public: public:
GccToolChainFactory(); explicit GccToolChainFactory(GccToolChain::SubType subType);
Toolchains autoDetect(const ToolchainDetector &detector) const final; Toolchains autoDetect(const ToolchainDetector &detector) const final;
Toolchains detectForImport(const ToolChainDescription &tcd) const final; Toolchains detectForImport(const ToolChainDescription &tcd) const final;
protected: private:
GccToolChain::SubType m_subType = GccToolChain::RealGcc;
enum class DetectVariants { Yes, No }; enum class DetectVariants { Yes, No };
using ToolchainChecker = std::function<bool(const ToolChain *)>; using ToolchainChecker = std::function<bool(const ToolChain *)>;
static Toolchains autoDetectToolchains(const QString &compilerName, static Toolchains autoDetectToolchains(const QString &compilerName,
@@ -208,24 +204,8 @@ protected:
static Toolchains autoDetectToolChain(const ToolChainDescription &tcd, static Toolchains autoDetectToolChain(const ToolChainDescription &tcd,
const ToolChainConstructor &constructor, const ToolChainConstructor &constructor,
const ToolchainChecker &checker = {}); const ToolchainChecker &checker = {});
};
class ClangToolChainFactory : public GccToolChainFactory const bool m_autoDetecting;
{
public:
ClangToolChainFactory();
};
class MingwToolChainFactory : public GccToolChainFactory
{
public:
MingwToolChainFactory();
};
class LinuxIccToolChainFactory : public GccToolChainFactory
{
public:
LinuxIccToolChainFactory();
}; };
} // namespace Internal } // namespace Internal

View File

@@ -626,15 +626,16 @@ public:
MsvcToolChainFactory m_mscvToolChainFactory; MsvcToolChainFactory m_mscvToolChainFactory;
ClangClToolChainFactory m_clangClToolChainFactory; ClangClToolChainFactory m_clangClToolChainFactory;
#else #else
LinuxIccToolChainFactory m_linuxToolChainFactory; GccToolChainFactory m_linuxToolChainFactory{GccToolChain::LinuxIcc};
#endif #endif
#ifndef Q_OS_MACOS #ifndef Q_OS_MACOS
MingwToolChainFactory m_mingwToolChainFactory; // Mingw offers cross-compiling to windows // Mingw offers cross-compiling to windows
GccToolChainFactory m_mingwToolChainFactory{GccToolChain::MinGW};
#endif #endif
GccToolChainFactory m_gccToolChainFactory; GccToolChainFactory m_gccToolChainFactory{GccToolChain::RealGcc};
ClangToolChainFactory m_clangToolChainFactory; GccToolChainFactory m_clangToolChainFactory{GccToolChain::Clang};
CustomToolChainFactory m_customToolChainFactory; CustomToolChainFactory m_customToolChainFactory;
DesktopDeviceFactory m_desktopDeviceFactory; DesktopDeviceFactory m_desktopDeviceFactory;

View File

@@ -671,8 +671,7 @@ void ToolChainFactory::setSupportsAllLanguages(bool supportsAllLanguages)
m_supportsAllLanguages = supportsAllLanguages; m_supportsAllLanguages = supportsAllLanguages;
} }
void ToolChainFactory::setToolchainConstructor void ToolChainFactory::setToolchainConstructor(const ToolChainConstructor &toolchainContructor)
(const ToolChainConstructor &toolchainContructor)
{ {
m_toolchainConstructor = toolchainContructor; m_toolchainConstructor = toolchainContructor;
} }