forked from qt-creator/qt-creator
ProjectExplorer: Fix Clang toolchain setup on Windows
Clang toolchain in gcc mode requires mingw sysroot and target in order to be used properly on Windows. Requires Qt >= 5.12 to work properly (it has the required mkspec). Change-Id: I4e5a734c699ac98740c0d50560aa7b69751ae58c Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
@@ -40,6 +40,7 @@
|
|||||||
#include <projectexplorer/buildmanager.h>
|
#include <projectexplorer/buildmanager.h>
|
||||||
#include <projectexplorer/buildsteplist.h>
|
#include <projectexplorer/buildsteplist.h>
|
||||||
#include <projectexplorer/kit.h>
|
#include <projectexplorer/kit.h>
|
||||||
|
#include <projectexplorer/kitinformation.h>
|
||||||
#include <projectexplorer/projectexplorer.h>
|
#include <projectexplorer/projectexplorer.h>
|
||||||
#include <projectexplorer/projectexplorerconstants.h>
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
#include <projectexplorer/projectmacroexpander.h>
|
#include <projectexplorer/projectmacroexpander.h>
|
||||||
@@ -500,6 +501,18 @@ CMakeBuildInfo *CMakeBuildConfigurationFactory::createBuildInfo(const ProjectExp
|
|||||||
if (!buildTypeItem.isNull())
|
if (!buildTypeItem.isNull())
|
||||||
info->configuration.append(buildTypeItem);
|
info->configuration.append(buildTypeItem);
|
||||||
|
|
||||||
|
const QString sysRoot = SysRootKitInformation::sysRoot(k).toString();
|
||||||
|
if (!sysRoot.isEmpty()) {
|
||||||
|
info->configuration.append(CMakeConfigItem("CMAKE_SYSROOT", sysRoot.toUtf8()));
|
||||||
|
ProjectExplorer::ToolChain *tc = ProjectExplorer::ToolChainKitInformation::toolChain(
|
||||||
|
k, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
|
||||||
|
if (tc) {
|
||||||
|
const QByteArray targetTriple = tc->originalTargetTriple().toUtf8();
|
||||||
|
info->configuration.append(CMakeConfigItem("CMAKE_C_COMPILER_TARGET", targetTriple));
|
||||||
|
info->configuration.append(CMakeConfigItem("CMAKE_CXX_COMPILER_TARGET ", targetTriple));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
#include <utils/synchronousprocess.h>
|
#include <utils/synchronousprocess.h>
|
||||||
|
|
||||||
#include <QBuffer>
|
#include <QBuffer>
|
||||||
|
#include <QComboBox>
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
@@ -74,6 +75,7 @@ static const char compilerPlatformLinkerFlagsKeyC[] = "ProjectExplorer.GccToolCh
|
|||||||
static const char targetAbiKeyC[] = "ProjectExplorer.GccToolChain.TargetAbi";
|
static const char targetAbiKeyC[] = "ProjectExplorer.GccToolChain.TargetAbi";
|
||||||
static const char originalTargetTripleKeyC[] = "ProjectExplorer.GccToolChain.OriginalTargetTriple";
|
static const char originalTargetTripleKeyC[] = "ProjectExplorer.GccToolChain.OriginalTargetTriple";
|
||||||
static const char supportedAbisKeyC[] = "ProjectExplorer.GccToolChain.SupportedAbis";
|
static const char supportedAbisKeyC[] = "ProjectExplorer.GccToolChain.SupportedAbis";
|
||||||
|
static const char parentToolChainIdKeyC[] = "ProjectExplorer.ClangToolChain.ParentToolChainId";
|
||||||
static const char binaryRegexp[] = "(?:^|-|\\b)(?:gcc|g\\+\\+|clang(?:\\+\\+)?)(?:-([\\d.]+))?$";
|
static const char binaryRegexp[] = "(?:^|-|\\b)(?:gcc|g\\+\\+|clang(?:\\+\\+)?)(?:-([\\d.]+))?$";
|
||||||
|
|
||||||
static QByteArray runGcc(const FileName &gcc, const QStringList &arguments, const QStringList &env)
|
static QByteArray runGcc(const FileName &gcc, const QStringList &arguments, const QStringList &env)
|
||||||
@@ -1042,8 +1044,8 @@ QList<ToolChain *> GccToolChainFactory::autoDetectToolChain(const FileName &comp
|
|||||||
|
|
||||||
GccToolChainConfigWidget::GccToolChainConfigWidget(GccToolChain *tc) :
|
GccToolChainConfigWidget::GccToolChainConfigWidget(GccToolChain *tc) :
|
||||||
ToolChainConfigWidget(tc),
|
ToolChainConfigWidget(tc),
|
||||||
m_compilerCommand(new PathChooser),
|
m_abiWidget(new AbiWidget),
|
||||||
m_abiWidget(new AbiWidget)
|
m_compilerCommand(new PathChooser)
|
||||||
{
|
{
|
||||||
Q_ASSERT(tc);
|
Q_ASSERT(tc);
|
||||||
|
|
||||||
@@ -1083,8 +1085,10 @@ void GccToolChainConfigWidget::applyImpl()
|
|||||||
Q_ASSERT(tc);
|
Q_ASSERT(tc);
|
||||||
QString displayName = tc->displayName();
|
QString displayName = tc->displayName();
|
||||||
tc->setCompilerCommand(m_compilerCommand->fileName());
|
tc->setCompilerCommand(m_compilerCommand->fileName());
|
||||||
|
if (m_abiWidget) {
|
||||||
tc->setSupportedAbis(m_abiWidget->supportedAbis());
|
tc->setSupportedAbis(m_abiWidget->supportedAbis());
|
||||||
tc->setTargetAbi(m_abiWidget->currentAbi());
|
tc->setTargetAbi(m_abiWidget->currentAbi());
|
||||||
|
}
|
||||||
tc->setOriginalTargetTriple(tc->detectSupportedAbis().originalTargetTriple);
|
tc->setOriginalTargetTriple(tc->detectSupportedAbis().originalTargetTriple);
|
||||||
tc->setDisplayName(displayName); // reset display name
|
tc->setDisplayName(displayName); // reset display name
|
||||||
tc->setPlatformCodeGenFlags(splitString(m_platformCodeGenFlagsLineEdit->text()));
|
tc->setPlatformCodeGenFlags(splitString(m_platformCodeGenFlagsLineEdit->text()));
|
||||||
@@ -1108,9 +1112,11 @@ void GccToolChainConfigWidget::setFromToolchain()
|
|||||||
m_compilerCommand->setFileName(tc->compilerCommand());
|
m_compilerCommand->setFileName(tc->compilerCommand());
|
||||||
m_platformCodeGenFlagsLineEdit->setText(QtcProcess::joinArgs(tc->platformCodeGenFlags()));
|
m_platformCodeGenFlagsLineEdit->setText(QtcProcess::joinArgs(tc->platformCodeGenFlags()));
|
||||||
m_platformLinkerFlagsLineEdit->setText(QtcProcess::joinArgs(tc->platformLinkerFlags()));
|
m_platformLinkerFlagsLineEdit->setText(QtcProcess::joinArgs(tc->platformLinkerFlags()));
|
||||||
|
if (m_abiWidget) {
|
||||||
m_abiWidget->setAbis(tc->supportedAbis(), tc->targetAbi());
|
m_abiWidget->setAbis(tc->supportedAbis(), tc->targetAbi());
|
||||||
if (!m_isReadOnly && !m_compilerCommand->path().isEmpty())
|
if (!m_isReadOnly && !m_compilerCommand->path().isEmpty())
|
||||||
m_abiWidget->setEnabled(true);
|
m_abiWidget->setEnabled(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GccToolChainConfigWidget::isDirtyImpl() const
|
bool GccToolChainConfigWidget::isDirtyImpl() const
|
||||||
@@ -1118,14 +1124,17 @@ bool GccToolChainConfigWidget::isDirtyImpl() const
|
|||||||
auto tc = static_cast<GccToolChain *>(toolChain());
|
auto tc = static_cast<GccToolChain *>(toolChain());
|
||||||
Q_ASSERT(tc);
|
Q_ASSERT(tc);
|
||||||
return m_compilerCommand->fileName() != tc->compilerCommand()
|
return m_compilerCommand->fileName() != tc->compilerCommand()
|
||||||
|| m_platformCodeGenFlagsLineEdit->text() != QtcProcess::joinArgs(tc->platformCodeGenFlags())
|
|| m_platformCodeGenFlagsLineEdit->text()
|
||||||
|| m_platformLinkerFlagsLineEdit->text() != QtcProcess::joinArgs(tc->platformLinkerFlags())
|
!= QtcProcess::joinArgs(tc->platformCodeGenFlags())
|
||||||
|| m_abiWidget->currentAbi() != tc->targetAbi();
|
|| m_platformLinkerFlagsLineEdit->text()
|
||||||
|
!= QtcProcess::joinArgs(tc->platformLinkerFlags())
|
||||||
|
|| (m_abiWidget && m_abiWidget->currentAbi() != tc->targetAbi());
|
||||||
}
|
}
|
||||||
|
|
||||||
void GccToolChainConfigWidget::makeReadOnlyImpl()
|
void GccToolChainConfigWidget::makeReadOnlyImpl()
|
||||||
{
|
{
|
||||||
m_compilerCommand->setReadOnly(true);
|
m_compilerCommand->setReadOnly(true);
|
||||||
|
if (m_abiWidget)
|
||||||
m_abiWidget->setEnabled(false);
|
m_abiWidget->setEnabled(false);
|
||||||
m_platformCodeGenFlagsLineEdit->setEnabled(false);
|
m_platformCodeGenFlagsLineEdit->setEnabled(false);
|
||||||
m_platformLinkerFlagsLineEdit->setEnabled(false);
|
m_platformLinkerFlagsLineEdit->setEnabled(false);
|
||||||
@@ -1150,6 +1159,9 @@ QStringList GccToolChainConfigWidget::splitString(const QString &s)
|
|||||||
|
|
||||||
void GccToolChainConfigWidget::handleCompilerCommandChange()
|
void GccToolChainConfigWidget::handleCompilerCommandChange()
|
||||||
{
|
{
|
||||||
|
if (!m_abiWidget)
|
||||||
|
return;
|
||||||
|
|
||||||
bool haveCompiler = false;
|
bool haveCompiler = false;
|
||||||
Abi currentAbi = m_abiWidget->currentAbi();
|
Abi currentAbi = m_abiWidget->currentAbi();
|
||||||
bool customAbi = m_abiWidget->isCustomAbi() && m_abiWidget->isEnabled();
|
bool customAbi = m_abiWidget->isCustomAbi() && m_abiWidget->isEnabled();
|
||||||
@@ -1207,13 +1219,76 @@ void GccToolChainConfigWidget::handlePlatformLinkerFlagsChange()
|
|||||||
// ClangToolChain
|
// ClangToolChain
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
static QList<ToolChain *> mingwToolChains()
|
||||||
|
{
|
||||||
|
return ToolChainManager::toolChains([](const ToolChain *tc) -> bool {
|
||||||
|
return tc->typeId() == Constants::MINGW_TOOLCHAIN_TYPEID;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static const MingwToolChain *mingwToolChainFromId(const QByteArray &id)
|
||||||
|
{
|
||||||
|
if (id.isEmpty())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
for (const ToolChain *tc : mingwToolChains()) {
|
||||||
|
if (tc->id() == id)
|
||||||
|
return static_cast<const MingwToolChain *>(tc);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClangToolChain::syncAutodetectedWithParentToolchains()
|
||||||
|
{
|
||||||
|
if (!HostOsInfo::isWindowsHost() || !isAutoDetected())
|
||||||
|
return;
|
||||||
|
|
||||||
|
QObject::disconnect(m_thisToolchainRemovedConnection);
|
||||||
|
QObject::disconnect(m_mingwToolchainAddedConnection);
|
||||||
|
|
||||||
|
if (!mingwToolChainFromId(m_parentToolChainId)) {
|
||||||
|
const QList<ToolChain *> mingwTCs = mingwToolChains();
|
||||||
|
m_parentToolChainId = mingwTCs.isEmpty() ? "" : mingwTCs.front()->id();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subscribe only autodetected toolchains.
|
||||||
|
ToolChainManager *tcManager = ToolChainManager::instance();
|
||||||
|
m_mingwToolchainAddedConnection
|
||||||
|
= QObject::connect(tcManager, &ToolChainManager::toolChainAdded, [this](ToolChain *tc) {
|
||||||
|
if (tc->typeId() == Constants::MINGW_TOOLCHAIN_TYPEID
|
||||||
|
&& !mingwToolChainFromId(m_parentToolChainId)) {
|
||||||
|
m_parentToolChainId = tc->id();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
m_thisToolchainRemovedConnection
|
||||||
|
= QObject::connect(tcManager, &ToolChainManager::toolChainRemoved, [this](ToolChain *tc) {
|
||||||
|
if (tc == this) {
|
||||||
|
QObject::disconnect(m_thisToolchainRemovedConnection);
|
||||||
|
QObject::disconnect(m_mingwToolchainAddedConnection);
|
||||||
|
} else if (m_parentToolChainId == tc->id()) {
|
||||||
|
const QList<ToolChain *> mingwTCs = mingwToolChains();
|
||||||
|
m_parentToolChainId = mingwTCs.isEmpty() ? "" : mingwTCs.front()->id();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
ClangToolChain::ClangToolChain(Detection d) :
|
ClangToolChain::ClangToolChain(Detection d) :
|
||||||
GccToolChain(Constants::CLANG_TOOLCHAIN_TYPEID, d)
|
GccToolChain(Constants::CLANG_TOOLCHAIN_TYPEID, d)
|
||||||
{ }
|
{
|
||||||
|
syncAutodetectedWithParentToolchains();
|
||||||
|
}
|
||||||
|
|
||||||
ClangToolChain::ClangToolChain(Core::Id typeId, ToolChain::Detection d) :
|
ClangToolChain::ClangToolChain(Core::Id typeId, ToolChain::Detection d) :
|
||||||
GccToolChain(typeId, d)
|
GccToolChain(typeId, d)
|
||||||
{ }
|
{
|
||||||
|
syncAutodetectedWithParentToolchains();
|
||||||
|
}
|
||||||
|
|
||||||
|
ClangToolChain::ClangToolChain(const ClangToolChain &other)
|
||||||
|
: GccToolChain(other)
|
||||||
|
, m_parentToolChainId(other.m_parentToolChainId)
|
||||||
|
{}
|
||||||
|
|
||||||
QString ClangToolChain::typeDisplayName() const
|
QString ClangToolChain::typeDisplayName() const
|
||||||
{
|
{
|
||||||
@@ -1261,22 +1336,30 @@ WarningFlags ClangToolChain::warningFlags(const QStringList &cflags) const
|
|||||||
FileNameList ClangToolChain::suggestedMkspecList() const
|
FileNameList ClangToolChain::suggestedMkspecList() const
|
||||||
{
|
{
|
||||||
Abi abi = targetAbi();
|
Abi abi = targetAbi();
|
||||||
if (abi.os() == Abi::DarwinOS)
|
if (abi.os() == Abi::DarwinOS) {
|
||||||
return FileNameList()
|
return FileNameList()
|
||||||
<< FileName::fromLatin1("macx-clang")
|
<< FileName::fromLatin1("macx-clang")
|
||||||
<< FileName::fromLatin1("macx-clang-32")
|
<< FileName::fromLatin1("macx-clang-32")
|
||||||
<< FileName::fromLatin1("unsupported/macx-clang")
|
<< FileName::fromLatin1("unsupported/macx-clang")
|
||||||
<< FileName::fromLatin1("macx-ios-clang");
|
<< FileName::fromLatin1("macx-ios-clang");
|
||||||
else if (abi.os() == Abi::LinuxOS)
|
} else if (abi.os() == Abi::LinuxOS) {
|
||||||
return FileNameList()
|
return FileNameList()
|
||||||
<< FileName::fromLatin1("linux-clang")
|
<< FileName::fromLatin1("linux-clang")
|
||||||
<< FileName::fromLatin1("unsupported/linux-clang");
|
<< FileName::fromLatin1("unsupported/linux-clang");
|
||||||
|
} else if (abi.os() == Abi::WindowsOS) {
|
||||||
|
return FileNameList() << FileName::fromLatin1("win32-clang-g++");
|
||||||
|
}
|
||||||
return FileNameList(); // Note: Not supported by Qt yet, so default to the mkspec the Qt was build with
|
return FileNameList(); // Note: Not supported by Qt yet, so default to the mkspec the Qt was build with
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClangToolChain::addToEnvironment(Environment &env) const
|
void ClangToolChain::addToEnvironment(Environment &env) const
|
||||||
{
|
{
|
||||||
GccToolChain::addToEnvironment(env);
|
GccToolChain::addToEnvironment(env);
|
||||||
|
|
||||||
|
const QString sysroot = sysRoot();
|
||||||
|
if (!sysroot.isEmpty())
|
||||||
|
env.prependOrSetPath(sysroot + "/bin");
|
||||||
|
|
||||||
// Clang takes PWD as basis for debug info, if set.
|
// Clang takes PWD as basis for debug info, if set.
|
||||||
// When running Qt Creator from a shell, PWD is initially set to an "arbitrary" value.
|
// When running Qt Creator from a shell, PWD is initially set to an "arbitrary" value.
|
||||||
// Since the tools are not called through a shell, PWD is never changed to the actual cwd,
|
// Since the tools are not called through a shell, PWD is never changed to the actual cwd,
|
||||||
@@ -1284,6 +1367,47 @@ void ClangToolChain::addToEnvironment(Environment &env) const
|
|||||||
env.unset("PWD");
|
env.unset("PWD");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString ClangToolChain::originalTargetTriple() const
|
||||||
|
{
|
||||||
|
const MingwToolChain *parentTC = mingwToolChainFromId(m_parentToolChainId);
|
||||||
|
if (parentTC)
|
||||||
|
return parentTC->originalTargetTriple();
|
||||||
|
|
||||||
|
return GccToolChain::originalTargetTriple();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ClangToolChain::sysRoot() const
|
||||||
|
{
|
||||||
|
const MingwToolChain *parentTC = mingwToolChainFromId(m_parentToolChainId);
|
||||||
|
if (!parentTC)
|
||||||
|
return QString();
|
||||||
|
|
||||||
|
const FileName mingwCompiler = parentTC->compilerCommand();
|
||||||
|
return mingwCompiler.parentDir().parentDir().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<ToolChainConfigWidget> ClangToolChain::createConfigurationWidget()
|
||||||
|
{
|
||||||
|
return std::make_unique<ClangToolChainConfigWidget>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap ClangToolChain::toMap() const
|
||||||
|
{
|
||||||
|
QVariantMap data = GccToolChain::toMap();
|
||||||
|
data.insert(parentToolChainIdKeyC, m_parentToolChainId);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClangToolChain::fromMap(const QVariantMap &data)
|
||||||
|
{
|
||||||
|
if (!GccToolChain::fromMap(data))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
m_parentToolChainId = data.value(parentToolChainIdKeyC).toByteArray();
|
||||||
|
syncAutodetectedWithParentToolchains();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
LanguageExtensions ClangToolChain::defaultLanguageExtensions() const
|
LanguageExtensions ClangToolChain::defaultLanguageExtensions() const
|
||||||
{
|
{
|
||||||
return LanguageExtension::Gnu;
|
return LanguageExtension::Gnu;
|
||||||
@@ -1341,6 +1465,7 @@ QList<ToolChain *> ClangToolChainFactory::autoDetect(const QList<ToolChain *> &a
|
|||||||
hostAbi, Constants::C_LANGUAGE_ID,
|
hostAbi, Constants::C_LANGUAGE_ID,
|
||||||
Constants::CLANG_TOOLCHAIN_TYPEID, alreadyKnown));
|
Constants::CLANG_TOOLCHAIN_TYPEID, alreadyKnown));
|
||||||
}
|
}
|
||||||
|
|
||||||
return tcs;
|
return tcs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1363,6 +1488,118 @@ GccToolChain *ClangToolChainFactory::createToolChain(bool autoDetect)
|
|||||||
return new ClangToolChain(autoDetect ? ToolChain::AutoDetection : ToolChain::ManualDetection);
|
return new ClangToolChain(autoDetect ? ToolChain::AutoDetection : ToolChain::ManualDetection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ClangToolChainConfigWidget::ClangToolChainConfigWidget(ClangToolChain *tc) :
|
||||||
|
GccToolChainConfigWidget(tc)
|
||||||
|
{
|
||||||
|
if (!HostOsInfo::isWindowsHost())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Remove m_abiWidget row because the parent toolchain abi is going to be used.
|
||||||
|
m_mainLayout->removeRow(m_mainLayout->rowCount() - 2);
|
||||||
|
m_abiWidget = nullptr;
|
||||||
|
|
||||||
|
m_parentToolchainCombo = new QComboBox(this);
|
||||||
|
m_mainLayout->insertRow(m_mainLayout->rowCount() - 1,
|
||||||
|
tr("Parent Toolchain:"),
|
||||||
|
m_parentToolchainCombo);
|
||||||
|
|
||||||
|
ToolChainManager *tcManager = ToolChainManager::instance();
|
||||||
|
m_parentToolChainConnections.append(
|
||||||
|
connect(tcManager, &ToolChainManager::toolChainUpdated, this, [this](ToolChain *tc) {
|
||||||
|
if (tc->typeId() == Constants::MINGW_TOOLCHAIN_TYPEID)
|
||||||
|
updateParentToolChainComboBox();
|
||||||
|
}));
|
||||||
|
m_parentToolChainConnections.append(
|
||||||
|
connect(tcManager, &ToolChainManager::toolChainAdded, this, [this](ToolChain *tc) {
|
||||||
|
if (tc->typeId() == Constants::MINGW_TOOLCHAIN_TYPEID)
|
||||||
|
updateParentToolChainComboBox();
|
||||||
|
}));
|
||||||
|
m_parentToolChainConnections.append(
|
||||||
|
connect(tcManager, &ToolChainManager::toolChainRemoved, this, [this](ToolChain *tc) {
|
||||||
|
if (tc->id() == toolChain()->id()) {
|
||||||
|
for (QMetaObject::Connection &connection : m_parentToolChainConnections)
|
||||||
|
QObject::disconnect(connection);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (tc->typeId() == Constants::MINGW_TOOLCHAIN_TYPEID)
|
||||||
|
updateParentToolChainComboBox();
|
||||||
|
}));
|
||||||
|
|
||||||
|
setFromClangToolchain();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClangToolChainConfigWidget::updateParentToolChainComboBox()
|
||||||
|
{
|
||||||
|
auto *tc = static_cast<ClangToolChain *>(toolChain());
|
||||||
|
QByteArray parentId = m_parentToolchainCombo->currentData().toByteArray();
|
||||||
|
if (tc->isAutoDetected() || m_parentToolchainCombo->count() == 0)
|
||||||
|
parentId = tc->m_parentToolChainId;
|
||||||
|
|
||||||
|
const MingwToolChain *parentTC = mingwToolChainFromId(parentId);
|
||||||
|
|
||||||
|
m_parentToolchainCombo->clear();
|
||||||
|
m_parentToolchainCombo->addItem(parentTC ? parentTC->displayName() : "",
|
||||||
|
parentTC ? parentId : "");
|
||||||
|
|
||||||
|
if (tc->isAutoDetected())
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (const ToolChain *mingwTC : mingwToolChains()) {
|
||||||
|
if (parentId != mingwTC->id())
|
||||||
|
m_parentToolchainCombo->addItem(mingwTC->displayName(), mingwTC->id());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClangToolChainConfigWidget::setFromClangToolchain()
|
||||||
|
{
|
||||||
|
GccToolChainConfigWidget::setFromToolchain();
|
||||||
|
|
||||||
|
if (m_parentToolchainCombo)
|
||||||
|
updateParentToolChainComboBox();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClangToolChainConfigWidget::applyImpl()
|
||||||
|
{
|
||||||
|
GccToolChainConfigWidget::applyImpl();
|
||||||
|
if (!m_parentToolchainCombo)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto *tc = static_cast<ClangToolChain *>(toolChain());
|
||||||
|
tc->m_parentToolChainId.clear();
|
||||||
|
|
||||||
|
const QByteArray parentId = m_parentToolchainCombo->currentData().toByteArray();
|
||||||
|
if (!parentId.isEmpty()) {
|
||||||
|
for (const ToolChain *mingwTC : mingwToolChains()) {
|
||||||
|
if (parentId == mingwTC->id()) {
|
||||||
|
tc->m_parentToolChainId = mingwTC->id();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClangToolChainConfigWidget::isDirtyImpl() const
|
||||||
|
{
|
||||||
|
if (GccToolChainConfigWidget::isDirtyImpl())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (!m_parentToolchainCombo)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto tc = static_cast<ClangToolChain *>(toolChain());
|
||||||
|
Q_ASSERT(tc);
|
||||||
|
const MingwToolChain *parentTC = mingwToolChainFromId(tc->m_parentToolChainId);
|
||||||
|
const QByteArray parentId = parentTC ? parentTC->id() : "";
|
||||||
|
return parentId != m_parentToolchainCombo->currentData();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClangToolChainConfigWidget::makeReadOnlyImpl()
|
||||||
|
{
|
||||||
|
GccToolChainConfigWidget::makeReadOnlyImpl();
|
||||||
|
if (m_parentToolchainCombo)
|
||||||
|
m_parentToolchainCombo->setEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// MingwToolChain
|
// MingwToolChain
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ namespace ProjectExplorer {
|
|||||||
|
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
class ClangToolChainFactory;
|
class ClangToolChainFactory;
|
||||||
|
class ClangToolChainConfigWidget;
|
||||||
class GccToolChainConfigWidget;
|
class GccToolChainConfigWidget;
|
||||||
class GccToolChainFactory;
|
class GccToolChainFactory;
|
||||||
class MingwToolChainFactory;
|
class MingwToolChainFactory;
|
||||||
@@ -208,6 +209,7 @@ class PROJECTEXPLORER_EXPORT ClangToolChain : public GccToolChain
|
|||||||
public:
|
public:
|
||||||
explicit ClangToolChain(Detection d);
|
explicit ClangToolChain(Detection d);
|
||||||
ClangToolChain(Core::Id typeId, Detection d);
|
ClangToolChain(Core::Id typeId, Detection d);
|
||||||
|
ClangToolChain(const ClangToolChain &other);
|
||||||
QString typeDisplayName() const override;
|
QString typeDisplayName() const override;
|
||||||
QString makeCommand(const Utils::Environment &environment) const override;
|
QString makeCommand(const Utils::Environment &environment) const override;
|
||||||
|
|
||||||
@@ -221,11 +223,25 @@ public:
|
|||||||
Utils::FileNameList suggestedMkspecList() const override;
|
Utils::FileNameList suggestedMkspecList() const override;
|
||||||
void addToEnvironment(Utils::Environment &env) const override;
|
void addToEnvironment(Utils::Environment &env) const override;
|
||||||
|
|
||||||
|
QString originalTargetTriple() const override;
|
||||||
|
QString sysRoot() const override;
|
||||||
|
|
||||||
|
std::unique_ptr<ToolChainConfigWidget> createConfigurationWidget() override;
|
||||||
|
|
||||||
|
QVariantMap toMap() const override;
|
||||||
|
bool fromMap(const QVariantMap &data) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Utils::LanguageExtensions defaultLanguageExtensions() const override;
|
Utils::LanguageExtensions defaultLanguageExtensions() const override;
|
||||||
|
void syncAutodetectedWithParentToolchains();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
QByteArray m_parentToolChainId;
|
||||||
|
QMetaObject::Connection m_mingwToolchainAddedConnection;
|
||||||
|
QMetaObject::Connection m_thisToolchainRemovedConnection;
|
||||||
|
|
||||||
friend class Internal::ClangToolChainFactory;
|
friend class Internal::ClangToolChainFactory;
|
||||||
|
friend class Internal::ClangToolChainConfigWidget;
|
||||||
friend class ToolChainFactory;
|
friend class ToolChainFactory;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ QT_END_NAMESPACE
|
|||||||
namespace Utils { class PathChooser; }
|
namespace Utils { class PathChooser; }
|
||||||
|
|
||||||
namespace ProjectExplorer {
|
namespace ProjectExplorer {
|
||||||
|
class ClangToolChain;
|
||||||
class GccToolChain;
|
class GccToolChain;
|
||||||
|
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
@@ -91,7 +92,7 @@ public:
|
|||||||
explicit GccToolChainConfigWidget(GccToolChain *tc);
|
explicit GccToolChainConfigWidget(GccToolChain *tc);
|
||||||
static QStringList splitString(const QString &s);
|
static QStringList splitString(const QString &s);
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
void handleCompilerCommandChange();
|
void handleCompilerCommandChange();
|
||||||
void handlePlatformCodeGenFlagsChange();
|
void handlePlatformCodeGenFlagsChange();
|
||||||
void handlePlatformLinkerFlagsChange();
|
void handlePlatformLinkerFlagsChange();
|
||||||
@@ -103,15 +104,39 @@ private:
|
|||||||
|
|
||||||
void setFromToolchain();
|
void setFromToolchain();
|
||||||
|
|
||||||
|
AbiWidget *m_abiWidget;
|
||||||
|
|
||||||
|
private:
|
||||||
Utils::PathChooser *m_compilerCommand;
|
Utils::PathChooser *m_compilerCommand;
|
||||||
QLineEdit *m_platformCodeGenFlagsLineEdit;
|
QLineEdit *m_platformCodeGenFlagsLineEdit;
|
||||||
QLineEdit *m_platformLinkerFlagsLineEdit;
|
QLineEdit *m_platformLinkerFlagsLineEdit;
|
||||||
AbiWidget *m_abiWidget;
|
|
||||||
|
|
||||||
bool m_isReadOnly = false;
|
bool m_isReadOnly = false;
|
||||||
ProjectExplorer::Macros m_macros;
|
ProjectExplorer::Macros m_macros;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
// ClangToolChainConfigWidget
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class ClangToolChainConfigWidget : public GccToolChainConfigWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit ClangToolChainConfigWidget(ClangToolChain *tc);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void applyImpl() override;
|
||||||
|
void discardImpl() override { setFromClangToolchain(); }
|
||||||
|
bool isDirtyImpl() const override;
|
||||||
|
void makeReadOnlyImpl() override;
|
||||||
|
|
||||||
|
void setFromClangToolchain();
|
||||||
|
void updateParentToolChainComboBox();
|
||||||
|
QList<QMetaObject::Connection> m_parentToolChainConnections;
|
||||||
|
QComboBox *m_parentToolchainCombo = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// ClangToolChainFactory
|
// ClangToolChainFactory
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -121,12 +121,33 @@ Utils::FileName SysRootKitInformation::sysRoot(const Kit *k)
|
|||||||
{
|
{
|
||||||
if (!k)
|
if (!k)
|
||||||
return Utils::FileName();
|
return Utils::FileName();
|
||||||
|
|
||||||
|
if (!k->value(SysRootKitInformation::id()).toString().isEmpty())
|
||||||
return Utils::FileName::fromString(k->value(SysRootKitInformation::id()).toString());
|
return Utils::FileName::fromString(k->value(SysRootKitInformation::id()).toString());
|
||||||
|
|
||||||
|
for (ToolChain *tc : ToolChainKitInformation::toolChains(k)) {
|
||||||
|
if (!tc->sysRoot().isEmpty())
|
||||||
|
return Utils::FileName::fromString(tc->sysRoot());
|
||||||
|
}
|
||||||
|
|
||||||
|
return Utils::FileName();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SysRootKitInformation::setSysRoot(Kit *k, const Utils::FileName &v)
|
void SysRootKitInformation::setSysRoot(Kit *k, const Utils::FileName &v)
|
||||||
{
|
{
|
||||||
if (k)
|
if (!k)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (ToolChain *tc : ToolChainKitInformation::toolChains(k)) {
|
||||||
|
if (!tc->sysRoot().isEmpty()) {
|
||||||
|
// It's the sysroot from toolchain, don't set it.
|
||||||
|
if (tc->sysRoot() == v.toString())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// We've changed the default toolchain sysroot, set it.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
k->setValue(SysRootKitInformation::id(), v.toString());
|
k->setValue(SysRootKitInformation::id(), v.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -362,6 +362,11 @@ QList<Task> ToolChain::validateKit(const Kit *) const
|
|||||||
return QList<Task>();
|
return QList<Task>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString ToolChain::sysRoot() const
|
||||||
|
{
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\class ProjectExplorer::ToolChainFactory
|
\class ProjectExplorer::ToolChainFactory
|
||||||
\brief The ToolChainFactory class creates tool chains from settings or
|
\brief The ToolChainFactory class creates tool chains from settings or
|
||||||
|
|||||||
@@ -110,6 +110,7 @@ public:
|
|||||||
|
|
||||||
virtual Utils::LanguageExtensions languageExtensions(const QStringList &cxxflags) const = 0;
|
virtual Utils::LanguageExtensions languageExtensions(const QStringList &cxxflags) const = 0;
|
||||||
virtual WarningFlags warningFlags(const QStringList &cflags) const = 0;
|
virtual WarningFlags warningFlags(const QStringList &cflags) const = 0;
|
||||||
|
virtual QString sysRoot() const;
|
||||||
|
|
||||||
class MacroInspectionReport
|
class MacroInspectionReport
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -145,8 +145,14 @@ QMakeStepConfig QMakeStep::deducedArguments() const
|
|||||||
ProjectExplorer::ToolChain *tc
|
ProjectExplorer::ToolChain *tc
|
||||||
= ProjectExplorer::ToolChainKitInformation::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
|
= ProjectExplorer::ToolChainKitInformation::toolChain(kit, ProjectExplorer::Constants::CXX_LANGUAGE_ID);
|
||||||
ProjectExplorer::Abi targetAbi;
|
ProjectExplorer::Abi targetAbi;
|
||||||
if (tc)
|
if (tc) {
|
||||||
targetAbi = tc->targetAbi();
|
targetAbi = tc->targetAbi();
|
||||||
|
if (HostOsInfo::isWindowsHost()
|
||||||
|
&& tc->typeId() == ProjectExplorer::Constants::CLANG_TOOLCHAIN_TYPEID) {
|
||||||
|
config.sysRoot = ProjectExplorer::SysRootKitInformation::sysRoot(kit).toString();
|
||||||
|
config.targetTriple = tc->originalTargetTriple();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BaseQtVersion *version = QtKitInformation::qtVersion(target()->kit());
|
BaseQtVersion *version = QtKitInformation::qtVersion(target()->kit());
|
||||||
|
|
||||||
@@ -902,5 +908,16 @@ QStringList QMakeStepConfig::toArguments() const
|
|||||||
if (separateDebugInfo)
|
if (separateDebugInfo)
|
||||||
arguments << "CONFIG+=force_debug_info" << "CONFIG+=separate_debug_info";
|
arguments << "CONFIG+=force_debug_info" << "CONFIG+=separate_debug_info";
|
||||||
|
|
||||||
|
if (!sysRoot.isEmpty()) {
|
||||||
|
arguments << ("QMAKE_CFLAGS+=--sysroot=\"" + sysRoot + "\"");
|
||||||
|
arguments << ("QMAKE_CXXFLAGS+=--sysroot=\"" + sysRoot + "\"");
|
||||||
|
arguments << ("QMAKE_LFLAGS+=--sysroot=\"" + sysRoot + "\"");
|
||||||
|
if (!targetTriple.isEmpty()) {
|
||||||
|
arguments << ("QMAKE_CFLAGS+=--target=" + targetTriple);
|
||||||
|
arguments << ("QMAKE_CXXFLAGS+=--target=" + targetTriple);
|
||||||
|
arguments << ("QMAKE_LFLAGS+=--target=" + targetTriple);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return arguments;
|
return arguments;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,6 +76,8 @@ public:
|
|||||||
QStringList toArguments() const;
|
QStringList toArguments() const;
|
||||||
|
|
||||||
// Actual data
|
// Actual data
|
||||||
|
QString sysRoot;
|
||||||
|
QString targetTriple;
|
||||||
TargetArchConfig archConfig = NoArch;
|
TargetArchConfig archConfig = NoArch;
|
||||||
OsType osType = NoOsType;
|
OsType osType = NoOsType;
|
||||||
bool linkQmlDebuggingQQ2 = false;
|
bool linkQmlDebuggingQQ2 = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user