ProjectExplorer: Make manual setup of clang-cl compiler easier

Automatically pick the proper available MSVC script if possible.

Change-Id: I39b0744983f5aa51c3c962afc2622ab21313f30e
Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
This commit is contained in:
Ivan Donchevskii
2018-07-09 12:30:02 +02:00
parent 391c68cddc
commit c4bc55975b
5 changed files with 245 additions and 134 deletions

View File

@@ -53,10 +53,6 @@ AbstractMsvcToolChain::AbstractMsvcToolChain(Core::Id typeId, Core::Id l, Detect
m_abi(abi), m_abi(abi),
m_vcvarsBat(vcvarsBat) m_vcvarsBat(vcvarsBat)
{ {
Q_ASSERT(abi.os() == Abi::WindowsOS);
Q_ASSERT(abi.binaryFormat() == Abi::PEFormat);
Q_ASSERT(abi.osFlavor() != Abi::WindowsMSysFlavor);
Q_ASSERT(!m_vcvarsBat.isEmpty());
setLanguage(l); setLanguage(l);
} }

View File

@@ -36,6 +36,7 @@
#include <utils/synchronousprocess.h> #include <utils/synchronousprocess.h>
#include <utils/runextensions.h> #include <utils/runextensions.h>
#include <utils/temporarydirectory.h> #include <utils/temporarydirectory.h>
#include <utils/pathchooser.h>
#include <utils/winutils.h> #include <utils/winutils.h>
#include <QDir> #include <QDir>
@@ -84,6 +85,8 @@ const MsvcPlatform platforms[] =
{MsvcToolChain::amd64_x86, "amd64_x86", "/bin/amd64_x86", "vcvarsamd64_x86.bat"} {MsvcToolChain::amd64_x86, "amd64_x86", "/bin/amd64_x86", "vcvarsamd64_x86.bat"}
}; };
static QList<const MsvcToolChain *> g_availableMsvcToolchains;
static const MsvcPlatform *platformEntry(MsvcToolChain::Platform t) static const MsvcPlatform *platformEntry(MsvcToolChain::Platform t)
{ {
for (const MsvcPlatform &p : platforms) { for (const MsvcPlatform &p : platforms) {
@@ -776,20 +779,138 @@ MsvcToolChainConfigWidget::MsvcToolChainConfigWidget(ToolChain *tc) :
ClangClToolChainConfigWidget::ClangClToolChainConfigWidget(ToolChain *tc) ClangClToolChainConfigWidget::ClangClToolChainConfigWidget(ToolChain *tc)
: MsvcBasedToolChainConfigWidget(tc) : MsvcBasedToolChainConfigWidget(tc)
, m_llvmDirLabel(new QLabel(this))
{ {
if (tc->isAutoDetected()) {
m_llvmDirLabel = new QLabel(this);
m_llvmDirLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); m_llvmDirLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
m_mainLayout->addRow(tr("LLVM:"), m_llvmDirLabel); m_mainLayout->addRow(tr("&Compiler path:"), m_llvmDirLabel);
} else {
const QStringList gnuVersionArgs = QStringList("--version");
m_compilerCommand = new Utils::PathChooser(this);
m_compilerCommand->setExpectedKind(Utils::PathChooser::ExistingCommand);
m_compilerCommand->setCommandVersionArguments(gnuVersionArgs);
m_compilerCommand->setHistoryCompleter("PE.Clang.Command.History");
m_mainLayout->addRow(tr("&Compiler path:"), m_compilerCommand);
}
addErrorLabel(); addErrorLabel();
setFromClangClToolChain(); setFromClangClToolChain();
if (m_compilerCommand) {
connect(m_compilerCommand, &Utils::PathChooser::rawPathChanged,
this, &ClangClToolChainConfigWidget::dirty);
}
} }
void ClangClToolChainConfigWidget::setFromClangClToolChain() void ClangClToolChainConfigWidget::setFromClangClToolChain()
{ {
setFromMsvcToolChain(); setFromMsvcToolChain();
const ClangClToolChain *tc = static_cast<const ClangClToolChain *>(toolChain()); const auto *clangClToolChain = static_cast<const ClangClToolChain *>(toolChain());
QTC_ASSERT(tc, return); if (clangClToolChain->isAutoDetected())
m_llvmDirLabel->setText(QDir::toNativeSeparators(tc-> llvmDir())); m_llvmDirLabel->setText(QDir::toNativeSeparators(clangClToolChain->clangPath()));
else
m_compilerCommand->setFileName(Utils::FileName::fromString(clangClToolChain->clangPath()));
}
static const MsvcToolChain *findMsvcToolChain(unsigned char wordWidth, Abi::OSFlavor flavor)
{
return Utils::findOrDefault(g_availableMsvcToolchains,
[wordWidth, flavor] (const MsvcToolChain *tc)
{ const Abi abi = tc->targetAbi();
return abi.osFlavor() == flavor
&& wordWidth == abi.wordWidth();} );
}
static QVersionNumber clangClVersion(const QString& clangClPath)
{
Utils::SynchronousProcess clangClProcess;
const Utils::SynchronousProcessResponse response = clangClProcess.runBlocking(
clangClPath, {QStringLiteral("--version")});
if (response.result != Utils::SynchronousProcessResponse::Finished || response.exitCode != 0)
return {};
const QRegularExpressionMatch match = QRegularExpression(
QStringLiteral("clang version (\\d+(\\.\\d+)+)")).match(response.stdOut());
if (!match.hasMatch())
return {};
return QVersionNumber::fromString(match.captured(1));
}
static const MsvcToolChain *selectMsvcToolChain(const QString &clangClPath,
unsigned char wordWidth)
{
const MsvcToolChain *toolChain = nullptr;
const QVersionNumber version = clangClVersion(clangClPath);
if (version.majorVersion() >= 6)
toolChain = findMsvcToolChain(wordWidth, Abi::WindowsMsvc2017Flavor);
if (!toolChain) {
toolChain = findMsvcToolChain(wordWidth, Abi::WindowsMsvc2015Flavor);
if (!toolChain)
toolChain = findMsvcToolChain(wordWidth, Abi::WindowsMsvc2013Flavor);
}
return toolChain;
}
static void detectClangClToolChainInPath(const QString &clangClPath,
QList<ToolChain *> &list)
{
const unsigned char wordWidth = Utils::is64BitWindowsBinary(clangClPath) ? 64 : 32;
const MsvcToolChain *toolChain = selectMsvcToolChain(clangClPath, wordWidth);
if (!toolChain) {
qWarning("Unable to find a suitable MSVC version for \"%s\".",
qPrintable(QDir::toNativeSeparators(clangClPath)));
return;
}
const Abi targetAbi = toolChain->targetAbi();
const QString name = QStringLiteral("LLVM ") + QString::number(wordWidth)
+ QStringLiteral("bit based on ")
+ Abi::toString(targetAbi.osFlavor()).toUpper();
for (auto language: {Constants::C_LANGUAGE_ID, Constants::CXX_LANGUAGE_ID}) {
auto *clangClToolChain = new ClangClToolChain(name, clangClPath,
language, ToolChain::AutoDetection);
clangClToolChain->resetMsvcToolChain(toolChain);
list.append(clangClToolChain);
}
}
static QString compilerFromPath(const QString &path)
{
return path + "/bin/clang-cl.exe";
}
void ClangClToolChainConfigWidget::applyImpl()
{
Utils::FileName clangClPath = m_compilerCommand->fileName();
auto clangClToolChain = static_cast<ClangClToolChain *>(toolChain());
clangClToolChain->setClangPath(clangClPath.toString());
if (clangClPath.fileName() != "clang-cl.exe") {
clangClToolChain->resetMsvcToolChain();
setFromClangClToolChain();
return;
}
QList<ToolChain *> results;
detectClangClToolChainInPath(clangClPath.toString(), results);
if (results.isEmpty()) {
clangClToolChain->resetMsvcToolChain();
} else {
for (const ToolChain *toolchain : results) {
if (toolchain->language() == clangClToolChain->language()) {
clangClToolChain->resetMsvcToolChain(static_cast<const MsvcToolChain *>(toolchain));
break;
}
}
qDeleteAll(results);
}
setFromClangClToolChain();
}
void ClangClToolChainConfigWidget::discardImpl()
{
setFromClangClToolChain();
} }
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
@@ -797,36 +918,33 @@ void ClangClToolChainConfigWidget::setFromClangClToolChain()
// clang-cl.exe as a [to some extent] compatible drop-in replacement for cl. // clang-cl.exe as a [to some extent] compatible drop-in replacement for cl.
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
static QString compilerFromPath(const QString &path) ClangClToolChain::ClangClToolChain(const QString &name, const QString &clangPath,
{ Core::Id language,
return path + "/bin/clang-cl.exe";
}
ClangClToolChain::ClangClToolChain(const QString &name, const QString &llvmDir,
const Abi &abi,
const QString &varsBat, const QString &varsBatArg, Core::Id language,
Detection d) Detection d)
: MsvcToolChain(Constants::CLANG_CL_TOOLCHAIN_TYPEID, name, abi, varsBat, varsBatArg, language, d) : MsvcToolChain(Constants::CLANG_CL_TOOLCHAIN_TYPEID, name, Abi(), "", "", language, d)
, m_llvmDir(llvmDir) , m_clangPath(clangPath)
{ } {
}
ClangClToolChain::ClangClToolChain() : MsvcToolChain(Constants::CLANG_CL_TOOLCHAIN_TYPEID) ClangClToolChain::ClangClToolChain() : MsvcToolChain(Constants::CLANG_CL_TOOLCHAIN_TYPEID)
{ } { }
bool ClangClToolChain::isValid() const bool ClangClToolChain::isValid() const
{ {
return MsvcToolChain::isValid() && compilerCommand().exists(); return MsvcToolChain::isValid() && compilerCommand().exists()
&& compilerCommand().fileName() == "clang-cl.exe";
} }
void ClangClToolChain::addToEnvironment(Utils::Environment &env) const void ClangClToolChain::addToEnvironment(Utils::Environment &env) const
{ {
MsvcToolChain::addToEnvironment(env); MsvcToolChain::addToEnvironment(env);
env.prependOrSetPath(m_llvmDir + QStringLiteral("/bin")); QDir path = QFileInfo(m_clangPath).absoluteDir(); // bin folder
env.prependOrSetPath(path.canonicalPath());
} }
Utils::FileName ClangClToolChain::compilerCommand() const Utils::FileName ClangClToolChain::compilerCommand() const
{ {
return Utils::FileName::fromString(compilerFromPath(m_llvmDir)); return Utils::FileName::fromString(m_clangPath);
} }
QString ClangClToolChain::typeDisplayName() const QString ClangClToolChain::typeDisplayName() const
@@ -856,7 +974,7 @@ static inline QString llvmDirKey() { return QStringLiteral("ProjectExplorer.Clan
QVariantMap ClangClToolChain::toMap() const QVariantMap ClangClToolChain::toMap() const
{ {
QVariantMap result = MsvcToolChain::toMap(); QVariantMap result = MsvcToolChain::toMap();
result.insert(llvmDirKey(), m_llvmDir); result.insert(llvmDirKey(), m_clangPath);
return result; return result;
} }
@@ -864,10 +982,11 @@ bool ClangClToolChain::fromMap(const QVariantMap &data)
{ {
if (!MsvcToolChain::fromMap(data)) if (!MsvcToolChain::fromMap(data))
return false; return false;
const QString llvmDir = data.value(llvmDirKey()).toString(); const QString clangPath = data.value(llvmDirKey()).toString();
if (llvmDir.isEmpty()) if (clangPath.isEmpty())
return false; return false;
m_llvmDir = llvmDir; m_clangPath = clangPath;
return true; return true;
} }
@@ -876,6 +995,19 @@ ToolChainConfigWidget *ClangClToolChain::configurationWidget()
return new ClangClToolChainConfigWidget(this); return new ClangClToolChainConfigWidget(this);
} }
void ClangClToolChain::resetMsvcToolChain(const MsvcToolChain *base)
{
if (!base) {
m_abi = Abi();
m_vcvarsBat.clear();
setVarsBatArg("");
return;
}
m_abi = base->targetAbi();
m_vcvarsBat = base->varsBat();
setVarsBatArg(base->varsBatArg());
}
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
// MsvcToolChainFactory // MsvcToolChainFactory
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
@@ -969,96 +1101,6 @@ static void detectCppBuildTools2015(QList<ToolChain *> *list)
} }
} }
static ToolChain *findMsvcToolChain(const QList<ToolChain *> &list,
unsigned char wordWidth, Abi::OSFlavor flavor)
{
return Utils::findOrDefault(list, [wordWidth, flavor] (const ToolChain *tc)
{ const Abi abi = tc->targetAbi();
return abi.osFlavor() == flavor
&& wordWidth == abi.wordWidth();} );
}
static QVersionNumber clangClVersion(const QString& clangClPath)
{
Utils::SynchronousProcess clangClProcess;
const Utils::SynchronousProcessResponse response = clangClProcess.runBlocking(
clangClPath, {QStringLiteral("--version")});
if (response.result != Utils::SynchronousProcessResponse::Finished || response.exitCode != 0)
return {};
const QRegularExpressionMatch match = QRegularExpression(
QStringLiteral("clang version (\\d+(\\.\\d+)+)")).match(response.stdOut());
if (!match.hasMatch())
return {};
return QVersionNumber::fromString(match.captured(1));
}
static const ToolChain *selectMsvcToolChain(const QString &clangClPath,
const QList<ToolChain *> &list,
unsigned char wordWidth)
{
const ToolChain *toolChain = nullptr;
const QVersionNumber version = clangClVersion(clangClPath);
if (version.majorVersion() >= 6)
toolChain = findMsvcToolChain(list, wordWidth, Abi::WindowsMsvc2017Flavor);
if (!toolChain) {
toolChain = findMsvcToolChain(list, wordWidth, Abi::WindowsMsvc2015Flavor);
if (!toolChain)
toolChain = findMsvcToolChain(list, wordWidth, Abi::WindowsMsvc2013Flavor);
}
return toolChain;
}
static void detectClangClToolChainInPath(const QString &clangClPath, QList<ToolChain *> *list)
{
const unsigned char wordWidth = Utils::is64BitWindowsBinary(clangClPath) ? 64 : 32;
const ToolChain *toolChain = selectMsvcToolChain(clangClPath, *list, wordWidth);
QDir path = QFileInfo(clangClPath).absoluteDir(); // bin folder
path.cdUp(); // cd to LLVM root
const QString rootPath = path.canonicalPath();
if (!toolChain) {
qWarning("Unable to find a suitable MSVC version for \"%s\".",
qPrintable(QDir::toNativeSeparators(rootPath)));
return;
}
const MsvcToolChain *msvcToolChain = static_cast<const MsvcToolChain *>(toolChain);
const Abi targetAbi = msvcToolChain->targetAbi();
const QString name = QStringLiteral("LLVM ") + QString::number(wordWidth)
+ QStringLiteral("bit based on ")
+ Abi::toString(targetAbi.osFlavor()).toUpper();
for (auto language: {Constants::C_LANGUAGE_ID, Constants::CXX_LANGUAGE_ID}) {
list->append(new ClangClToolChain(name, rootPath, targetAbi,
msvcToolChain->varsBat(), msvcToolChain->varsBatArg(),
language, ToolChain::AutoDetection));
}
}
// Detect Clang-cl on top of MSVC2017, MSVC2015 or MSVC2013.
static void detectClangClToolChain(QList<ToolChain *> *list)
{
#ifdef Q_OS_WIN64
const char registryNode[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\LLVM\\LLVM";
#else
const char registryNode[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\LLVM\\LLVM";
#endif
const QSettings registry(QLatin1String(registryNode), QSettings::NativeFormat);
if (registry.status() == QSettings::NoError) {
const QString path = QDir::cleanPath(registry.value(QStringLiteral(".")).toString());
const QString clangClPath = compilerFromPath(path);
if (!path.isEmpty()) {
detectClangClToolChainInPath(path, list);
return;
}
}
const Utils::Environment systemEnvironment = Utils::Environment::systemEnvironment();
const Utils::FileName clangClPath = systemEnvironment.searchInPath("clang-cl");
if (!clangClPath.isEmpty())
detectClangClToolChainInPath(clangClPath.toString(), list);
}
QList<ToolChain *> MsvcToolChainFactory::autoDetect(const QList<ToolChain *> &alreadyKnown) QList<ToolChain *> MsvcToolChainFactory::autoDetect(const QList<ToolChain *> &alreadyKnown)
{ {
QList<ToolChain *> results; QList<ToolChain *> results;
@@ -1131,11 +1173,53 @@ QList<ToolChain *> MsvcToolChainFactory::autoDetect(const QList<ToolChain *> &al
detectCppBuildTools2015(&results); detectCppBuildTools2015(&results);
detectClangClToolChain(&results); for (const ToolChain *toolchain : results)
g_availableMsvcToolchains.append(static_cast<const MsvcToolChain *>(toolchain));
return results; return results;
} }
ClangClToolChainFactory::ClangClToolChainFactory()
{
setDisplayName(tr("clang-cl"));
}
bool ClangClToolChainFactory::canCreate()
{
return !g_availableMsvcToolchains.isEmpty();
}
QList<ToolChain *> ClangClToolChainFactory::autoDetect(const QList<ToolChain *> &alreadyKnown)
{
#ifdef Q_OS_WIN64
const char registryNode[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\LLVM\\LLVM";
#else
const char registryNode[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\LLVM\\LLVM";
#endif
QList<ToolChain *> results;
const QSettings registry(QLatin1String(registryNode), QSettings::NativeFormat);
if (registry.status() == QSettings::NoError) {
const QString path = QDir::cleanPath(registry.value(QStringLiteral(".")).toString());
const QString clangClPath = compilerFromPath(path);
if (!path.isEmpty()) {
detectClangClToolChainInPath(clangClPath, results);
return results;
}
}
const Utils::Environment systemEnvironment = Utils::Environment::systemEnvironment();
const Utils::FileName clangClPath = systemEnvironment.searchInPath("clang-cl");
if (!clangClPath.isEmpty())
detectClangClToolChainInPath(clangClPath.toString(), results);
return results;
}
ToolChain *ClangClToolChainFactory::create(Core::Id l)
{
return new ClangClToolChain("clang-cl", "", l, ToolChain::ManualDetection);
}
bool MsvcToolChain::operator ==(const ToolChain &other) const bool MsvcToolChain::operator ==(const ToolChain &other) const
{ {
if (!AbstractMsvcToolChain::operator ==(other)) if (!AbstractMsvcToolChain::operator ==(other))
@@ -1147,7 +1231,7 @@ bool MsvcToolChain::operator ==(const ToolChain &other) const
bool MsvcToolChainFactory::canRestore(const QVariantMap &data) bool MsvcToolChainFactory::canRestore(const QVariantMap &data)
{ {
const Core::Id id = typeIdFromMap(data); const Core::Id id = typeIdFromMap(data);
return id == Constants::MSVC_TOOLCHAIN_TYPEID || id == Constants::CLANG_CL_TOOLCHAIN_TYPEID; return id == Constants::MSVC_TOOLCHAIN_TYPEID;
} }
template <class ToolChainType> template <class ToolChainType>
@@ -1162,11 +1246,19 @@ ToolChainType *readFromMap(const QVariantMap &data)
ToolChain *MsvcToolChainFactory::restore(const QVariantMap &data) ToolChain *MsvcToolChainFactory::restore(const QVariantMap &data)
{ {
const Core::Id id = typeIdFromMap(data);
if (id == Constants::CLANG_CL_TOOLCHAIN_TYPEID)
return readFromMap<ClangClToolChain>(data);
return readFromMap<MsvcToolChain>(data); return readFromMap<MsvcToolChain>(data);
} }
bool ClangClToolChainFactory::canRestore(const QVariantMap &data)
{
const Core::Id id = typeIdFromMap(data);
return id == Constants::CLANG_CL_TOOLCHAIN_TYPEID;
}
ToolChain *ClangClToolChainFactory::restore(const QVariantMap &data)
{
return readFromMap<ClangClToolChain>(data);
}
} // namespace Internal } // namespace Internal
} // namespace ProjectExplorer } // namespace ProjectExplorer

View File

@@ -34,6 +34,8 @@
QT_FORWARD_DECLARE_CLASS(QLabel) QT_FORWARD_DECLARE_CLASS(QLabel)
QT_FORWARD_DECLARE_CLASS(QVersionNumber) QT_FORWARD_DECLARE_CLASS(QVersionNumber)
namespace Utils { class PathChooser; }
namespace ProjectExplorer { namespace ProjectExplorer {
namespace Internal { namespace Internal {
@@ -74,6 +76,7 @@ public:
ToolChain *clone() const override; ToolChain *clone() const override;
QString varsBatArg() const { return m_varsBatArg; } QString varsBatArg() const { return m_varsBatArg; }
void setVarsBatArg(const QString &varsBA) { m_varsBatArg = varsBA; }
bool operator == (const ToolChain &) const override; bool operator == (const ToolChain &) const override;
@@ -103,11 +106,9 @@ private:
class ClangClToolChain : public MsvcToolChain class ClangClToolChain : public MsvcToolChain
{ {
public: public:
explicit ClangClToolChain(const QString &name, const QString &llvmDir, ClangClToolChain(const QString &name, const QString &llvmDir,
const Abi &abi,
const QString &varsBat, const QString &varsBatArg,
Core::Id language, Core::Id language,
Detection d = ManualDetection); Detection d);
ClangClToolChain(); ClangClToolChain();
bool isValid() const override; bool isValid() const override;
@@ -121,10 +122,13 @@ public:
bool fromMap(const QVariantMap &data) override; bool fromMap(const QVariantMap &data) override;
ToolChainConfigWidget *configurationWidget() override; ToolChainConfigWidget *configurationWidget() override;
QString llvmDir() const { return m_llvmDir; } const QList<MsvcToolChain *> &msvcToolchains() const;
QString clangPath() const { return m_clangPath; }
void setClangPath(const QString &path) { m_clangPath = path; }
void resetMsvcToolChain(const MsvcToolChain *base = nullptr);
private: private:
QString m_llvmDir; QString m_clangPath;
}; };
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
@@ -144,11 +148,27 @@ public:
bool canRestore(const QVariantMap &data) override; bool canRestore(const QVariantMap &data) override;
ToolChain *restore(const QVariantMap &data) override; ToolChain *restore(const QVariantMap &data) override;
ToolChainConfigWidget *configurationWidget(ToolChain *);
static QString vcVarsBatFor(const QString &basePath, MsvcToolChain::Platform platform, static QString vcVarsBatFor(const QString &basePath, MsvcToolChain::Platform platform,
const QVersionNumber &v); const QVersionNumber &v);
}; };
class ClangClToolChainFactory : public MsvcToolChainFactory
{
Q_OBJECT
public:
ClangClToolChainFactory();
QList<ToolChain *> autoDetect(const QList<ToolChain *> &alreadyKnown) override;
bool canRestore(const QVariantMap &data) override;
ToolChain *restore(const QVariantMap &data) override;
bool canCreate() override;
ToolChain *create(Core::Id l) override;
};
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
// MsvcBasedToolChainConfigWidget // MsvcBasedToolChainConfigWidget
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
@@ -197,12 +217,14 @@ public:
explicit ClangClToolChainConfigWidget(ToolChain *); explicit ClangClToolChainConfigWidget(ToolChain *);
protected: protected:
void discardImpl() override { setFromClangClToolChain(); } void applyImpl() override;
void discardImpl() override;
private: private:
void setFromClangClToolChain(); void setFromClangClToolChain();
QLabel *m_llvmDirLabel; QLabel *m_llvmDirLabel = nullptr;
Utils::PathChooser *m_compilerCommand = nullptr;
}; };
} // namespace Internal } // namespace Internal

View File

@@ -447,6 +447,7 @@ public:
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
WinDebugInterface m_winDebugInterface; WinDebugInterface m_winDebugInterface;
MsvcToolChainFactory m_mscvToolChainFactory; MsvcToolChainFactory m_mscvToolChainFactory;
ClangClToolChainFactory m_clangClToolChainFactory;
#else #else
LinuxIccToolChainFactory m_linuxToolChainFactory; LinuxIccToolChainFactory m_linuxToolChainFactory;
#endif #endif