forked from qt-creator/qt-creator
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:
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user