forked from qt-creator/qt-creator
BareMetal: Tune Keil ARM compiler using 'platform codegen flags' feature
Previously, to generate macros, we always passed by default one target CPU as 'cortex-m0'. Right now we have added the new text field in the Keil compiler settings page, called "Platform codegen flags". In this field we can specify the desired CPU target flags. A new auto-or-manual created compiler still has the '--cpu=cortex-m0' flag as before. The user can modify this flag for a manually added compiler. Also, the deprecated '-cpu' syntax replaced with the actual '--cpu' syntax. Change-Id: I25fb3e28460606b98ea56f1f30fe8563306a8736 Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -37,6 +37,7 @@
|
|||||||
#include <utils/environment.h>
|
#include <utils/environment.h>
|
||||||
#include <utils/pathchooser.h>
|
#include <utils/pathchooser.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
#include <utils/qtcprocess.h>
|
||||||
#include <utils/synchronousprocess.h>
|
#include <utils/synchronousprocess.h>
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
@@ -276,13 +277,16 @@ static Macros dumpC166PredefinedMacros(const FilePath &compiler, const QStringLi
|
|||||||
return macros;
|
return macros;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Macros dumpArmPredefinedMacros(const FilePath &compiler, const QStringList &env)
|
static Macros dumpArmPredefinedMacros(const FilePath &compiler, const QStringList &extraArgs, const QStringList &env)
|
||||||
{
|
{
|
||||||
SynchronousProcess cpp;
|
SynchronousProcess cpp;
|
||||||
cpp.setEnvironment(env);
|
cpp.setEnvironment(env);
|
||||||
cpp.setTimeoutS(10);
|
cpp.setTimeoutS(10);
|
||||||
|
|
||||||
const CommandLine cmd(compiler, {"-E", "--list-macros", "-cpu=cortex-m0"});
|
QStringList args = extraArgs;
|
||||||
|
args.push_back("-E");
|
||||||
|
args.push_back("--list-macros");
|
||||||
|
const CommandLine cmd(compiler, args);
|
||||||
|
|
||||||
const SynchronousProcessResponse response = cpp.runBlocking(cmd);
|
const SynchronousProcessResponse response = cpp.runBlocking(cmd);
|
||||||
if (response.result != SynchronousProcessResponse::Finished
|
if (response.result != SynchronousProcessResponse::Finished
|
||||||
@@ -311,7 +315,7 @@ static bool isArmArchitecture(Abi::Architecture arch)
|
|||||||
return arch == Abi::Architecture::ArmArchitecture;
|
return arch == Abi::Architecture::ArmArchitecture;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Macros dumpPredefinedMacros(const FilePath &compiler, const QStringList &env)
|
static Macros dumpPredefinedMacros(const FilePath &compiler, const QStringList &args, const QStringList &env)
|
||||||
{
|
{
|
||||||
if (compiler.isEmpty() || !compiler.toFileInfo().isExecutable())
|
if (compiler.isEmpty() || !compiler.toFileInfo().isExecutable())
|
||||||
return {};
|
return {};
|
||||||
@@ -322,7 +326,7 @@ static Macros dumpPredefinedMacros(const FilePath &compiler, const QStringList &
|
|||||||
if (isC166Architecture(arch))
|
if (isC166Architecture(arch))
|
||||||
return dumpC166PredefinedMacros(compiler, env);
|
return dumpC166PredefinedMacros(compiler, env);
|
||||||
if (isArmArchitecture(arch))
|
if (isArmArchitecture(arch))
|
||||||
return dumpArmPredefinedMacros(compiler, env);
|
return dumpArmPredefinedMacros(compiler, args, env);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -408,6 +412,20 @@ static QString buildDisplayName(Abi::Architecture arch, Core::Id language,
|
|||||||
.arg(version, langName, archName);
|
.arg(version, langName, archName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void addDefaultCpuArgs(const FilePath &compiler, QStringList &extraArgs)
|
||||||
|
{
|
||||||
|
const Abi::Architecture arch = guessArchitecture(compiler);
|
||||||
|
if (!isArmArchitecture(arch))
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto extraArgsIt = std::find_if(std::begin(extraArgs), std::end(extraArgs),
|
||||||
|
[](const QString &extraArg) {
|
||||||
|
return extraArg.contains("-cpu") || extraArg.contains("--cpu");
|
||||||
|
});
|
||||||
|
if (extraArgsIt == std::end(extraArgs))
|
||||||
|
extraArgs.push_back("--cpu=cortex-m0");
|
||||||
|
}
|
||||||
|
|
||||||
// KeilToolchain
|
// KeilToolchain
|
||||||
|
|
||||||
KeilToolChain::KeilToolChain() :
|
KeilToolChain::KeilToolChain() :
|
||||||
@@ -443,12 +461,13 @@ ToolChain::MacroInspectionRunner KeilToolChain::createMacroInspectionRunner() co
|
|||||||
const Core::Id lang = language();
|
const Core::Id lang = language();
|
||||||
|
|
||||||
MacrosCache macroCache = predefinedMacrosCache();
|
MacrosCache macroCache = predefinedMacrosCache();
|
||||||
|
const QStringList extraArgs = m_extraCodeModelFlags;
|
||||||
|
|
||||||
return [env, compilerCommand, macroCache, lang]
|
return [env, compilerCommand, extraArgs, macroCache, lang]
|
||||||
(const QStringList &flags) {
|
(const QStringList &flags) {
|
||||||
Q_UNUSED(flags)
|
Q_UNUSED(flags)
|
||||||
|
|
||||||
const Macros macros = dumpPredefinedMacros(compilerCommand, env.toStringList());
|
const Macros macros = dumpPredefinedMacros(compilerCommand, extraArgs, env.toStringList());
|
||||||
const auto report = MacroInspectionReport{macros, languageVersion(lang, macros)};
|
const auto report = MacroInspectionReport{macros, languageVersion(lang, macros)};
|
||||||
macroCache->insert({}, report);
|
macroCache->insert({}, report);
|
||||||
|
|
||||||
@@ -541,6 +560,7 @@ bool KeilToolChain::operator ==(const ToolChain &other) const
|
|||||||
const auto customTc = static_cast<const KeilToolChain *>(&other);
|
const auto customTc = static_cast<const KeilToolChain *>(&other);
|
||||||
return m_compilerCommand == customTc->m_compilerCommand
|
return m_compilerCommand == customTc->m_compilerCommand
|
||||||
&& m_targetAbi == customTc->m_targetAbi
|
&& m_targetAbi == customTc->m_targetAbi
|
||||||
|
&& m_extraCodeModelFlags == customTc->m_extraCodeModelFlags
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -557,6 +577,19 @@ FilePath KeilToolChain::compilerCommand() const
|
|||||||
return m_compilerCommand;
|
return m_compilerCommand;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void KeilToolChain::setExtraCodeModelFlags(const QStringList &flags)
|
||||||
|
{
|
||||||
|
if (flags == m_extraCodeModelFlags)
|
||||||
|
return;
|
||||||
|
m_extraCodeModelFlags = flags;
|
||||||
|
toolChainUpdated();
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList KeilToolChain::extraCodeModelFlags() const
|
||||||
|
{
|
||||||
|
return m_extraCodeModelFlags;
|
||||||
|
}
|
||||||
|
|
||||||
FilePath KeilToolChain::makeCommand(const Environment &env) const
|
FilePath KeilToolChain::makeCommand(const Environment &env) const
|
||||||
{
|
{
|
||||||
Q_UNUSED(env)
|
Q_UNUSED(env)
|
||||||
@@ -701,7 +734,10 @@ QList<ToolChain *> KeilToolChainFactory::autoDetectToolchain(
|
|||||||
const Candidate &candidate, Core::Id language) const
|
const Candidate &candidate, Core::Id language) const
|
||||||
{
|
{
|
||||||
const auto env = Environment::systemEnvironment();
|
const auto env = Environment::systemEnvironment();
|
||||||
const Macros macros = dumpPredefinedMacros(candidate.compilerPath, env.toStringList());
|
|
||||||
|
QStringList extraArgs;
|
||||||
|
addDefaultCpuArgs(candidate.compilerPath, extraArgs);
|
||||||
|
const Macros macros = dumpPredefinedMacros(candidate.compilerPath, extraArgs, env.toStringList());
|
||||||
if (macros.isEmpty())
|
if (macros.isEmpty())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
@@ -717,6 +753,7 @@ QList<ToolChain *> KeilToolChainFactory::autoDetectToolchain(
|
|||||||
tc->setDetection(ToolChain::AutoDetection);
|
tc->setDetection(ToolChain::AutoDetection);
|
||||||
tc->setLanguage(language);
|
tc->setLanguage(language);
|
||||||
tc->setCompilerCommand(candidate.compilerPath);
|
tc->setCompilerCommand(candidate.compilerPath);
|
||||||
|
tc->setExtraCodeModelFlags(extraArgs);
|
||||||
tc->setTargetAbi(abi);
|
tc->setTargetAbi(abi);
|
||||||
tc->setDisplayName(buildDisplayName(abi.architecture(), language, candidate.compilerVersion));
|
tc->setDisplayName(buildDisplayName(abi.architecture(), language, candidate.compilerVersion));
|
||||||
|
|
||||||
@@ -735,6 +772,9 @@ KeilToolChainConfigWidget::KeilToolChainConfigWidget(KeilToolChain *tc) :
|
|||||||
m_compilerCommand->setExpectedKind(PathChooser::ExistingCommand);
|
m_compilerCommand->setExpectedKind(PathChooser::ExistingCommand);
|
||||||
m_compilerCommand->setHistoryCompleter("PE.KEIL.Command.History");
|
m_compilerCommand->setHistoryCompleter("PE.KEIL.Command.History");
|
||||||
m_mainLayout->addRow(tr("&Compiler path:"), m_compilerCommand);
|
m_mainLayout->addRow(tr("&Compiler path:"), m_compilerCommand);
|
||||||
|
m_platformCodeGenFlagsLineEdit = new QLineEdit(this);
|
||||||
|
m_platformCodeGenFlagsLineEdit->setText(QtcProcess::joinArgs(tc->extraCodeModelFlags()));
|
||||||
|
m_mainLayout->addRow(tr("Platform codegen flags:"), m_platformCodeGenFlagsLineEdit);
|
||||||
m_mainLayout->addRow(tr("&ABI:"), m_abiWidget);
|
m_mainLayout->addRow(tr("&ABI:"), m_abiWidget);
|
||||||
|
|
||||||
m_abiWidget->setEnabled(false);
|
m_abiWidget->setEnabled(false);
|
||||||
@@ -744,6 +784,8 @@ KeilToolChainConfigWidget::KeilToolChainConfigWidget(KeilToolChain *tc) :
|
|||||||
|
|
||||||
connect(m_compilerCommand, &PathChooser::rawPathChanged,
|
connect(m_compilerCommand, &PathChooser::rawPathChanged,
|
||||||
this, &KeilToolChainConfigWidget::handleCompilerCommandChange);
|
this, &KeilToolChainConfigWidget::handleCompilerCommandChange);
|
||||||
|
connect(m_platformCodeGenFlagsLineEdit, &QLineEdit::editingFinished,
|
||||||
|
this, &KeilToolChainConfigWidget::handlePlatformCodeGenFlagsChange);
|
||||||
connect(m_abiWidget, &AbiWidget::abiChanged,
|
connect(m_abiWidget, &AbiWidget::abiChanged,
|
||||||
this, &ToolChainConfigWidget::dirty);
|
this, &ToolChainConfigWidget::dirty);
|
||||||
}
|
}
|
||||||
@@ -756,6 +798,7 @@ void KeilToolChainConfigWidget::applyImpl()
|
|||||||
const auto tc = static_cast<KeilToolChain *>(toolChain());
|
const auto tc = static_cast<KeilToolChain *>(toolChain());
|
||||||
const QString displayName = tc->displayName();
|
const QString displayName = tc->displayName();
|
||||||
tc->setCompilerCommand(m_compilerCommand->filePath());
|
tc->setCompilerCommand(m_compilerCommand->filePath());
|
||||||
|
tc->setExtraCodeModelFlags(splitString(m_platformCodeGenFlagsLineEdit->text()));
|
||||||
tc->setTargetAbi(m_abiWidget->currentAbi());
|
tc->setTargetAbi(m_abiWidget->currentAbi());
|
||||||
tc->setDisplayName(displayName);
|
tc->setDisplayName(displayName);
|
||||||
|
|
||||||
@@ -772,6 +815,7 @@ bool KeilToolChainConfigWidget::isDirtyImpl() const
|
|||||||
{
|
{
|
||||||
const auto tc = static_cast<KeilToolChain *>(toolChain());
|
const auto tc = static_cast<KeilToolChain *>(toolChain());
|
||||||
return m_compilerCommand->filePath() != tc->compilerCommand()
|
return m_compilerCommand->filePath() != tc->compilerCommand()
|
||||||
|
|| m_platformCodeGenFlagsLineEdit->text() != QtcProcess::joinArgs(tc->extraCodeModelFlags())
|
||||||
|| m_abiWidget->currentAbi() != tc->targetAbi()
|
|| m_abiWidget->currentAbi() != tc->targetAbi()
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
@@ -779,6 +823,7 @@ bool KeilToolChainConfigWidget::isDirtyImpl() const
|
|||||||
void KeilToolChainConfigWidget::makeReadOnlyImpl()
|
void KeilToolChainConfigWidget::makeReadOnlyImpl()
|
||||||
{
|
{
|
||||||
m_compilerCommand->setReadOnly(true);
|
m_compilerCommand->setReadOnly(true);
|
||||||
|
m_platformCodeGenFlagsLineEdit->setEnabled(false);
|
||||||
m_abiWidget->setEnabled(false);
|
m_abiWidget->setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -787,6 +832,7 @@ void KeilToolChainConfigWidget::setFromToolChain()
|
|||||||
const QSignalBlocker blocker(this);
|
const QSignalBlocker blocker(this);
|
||||||
const auto tc = static_cast<KeilToolChain *>(toolChain());
|
const auto tc = static_cast<KeilToolChain *>(toolChain());
|
||||||
m_compilerCommand->setFilePath(tc->compilerCommand());
|
m_compilerCommand->setFilePath(tc->compilerCommand());
|
||||||
|
m_platformCodeGenFlagsLineEdit->setText(QtcProcess::joinArgs(tc->extraCodeModelFlags()));
|
||||||
m_abiWidget->setAbis({}, tc->targetAbi());
|
m_abiWidget->setAbis({}, tc->targetAbi());
|
||||||
const bool haveCompiler = compilerExists(m_compilerCommand->filePath());
|
const bool haveCompiler = compilerExists(m_compilerCommand->filePath());
|
||||||
m_abiWidget->setEnabled(haveCompiler && !tc->isAutoDetected());
|
m_abiWidget->setEnabled(haveCompiler && !tc->isAutoDetected());
|
||||||
@@ -798,7 +844,12 @@ void KeilToolChainConfigWidget::handleCompilerCommandChange()
|
|||||||
const bool haveCompiler = compilerExists(compilerPath);
|
const bool haveCompiler = compilerExists(compilerPath);
|
||||||
if (haveCompiler) {
|
if (haveCompiler) {
|
||||||
const auto env = Environment::systemEnvironment();
|
const auto env = Environment::systemEnvironment();
|
||||||
m_macros = dumpPredefinedMacros(compilerPath, env.toStringList());
|
const QStringList prevExtraArgs = splitString(m_platformCodeGenFlagsLineEdit->text());
|
||||||
|
QStringList newExtraArgs = prevExtraArgs;
|
||||||
|
addDefaultCpuArgs(compilerPath, newExtraArgs);
|
||||||
|
if (prevExtraArgs != newExtraArgs)
|
||||||
|
m_platformCodeGenFlagsLineEdit->setText(QtcProcess::joinArgs(newExtraArgs));
|
||||||
|
m_macros = dumpPredefinedMacros(compilerPath, newExtraArgs, env.toStringList());
|
||||||
const Abi guessed = guessAbi(m_macros);
|
const Abi guessed = guessAbi(m_macros);
|
||||||
m_abiWidget->setAbis({}, guessed);
|
m_abiWidget->setAbis({}, guessed);
|
||||||
}
|
}
|
||||||
@@ -807,5 +858,31 @@ void KeilToolChainConfigWidget::handleCompilerCommandChange()
|
|||||||
emit dirty();
|
emit dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void KeilToolChainConfigWidget::handlePlatformCodeGenFlagsChange()
|
||||||
|
{
|
||||||
|
const QString str1 = m_platformCodeGenFlagsLineEdit->text();
|
||||||
|
const QString str2 = QtcProcess::joinArgs(splitString(str1));
|
||||||
|
if (str1 != str2)
|
||||||
|
m_platformCodeGenFlagsLineEdit->setText(str2);
|
||||||
|
else
|
||||||
|
handleCompilerCommandChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList KeilToolChainConfigWidget::splitString(const QString &s) const
|
||||||
|
{
|
||||||
|
QtcProcess::SplitError splitError;
|
||||||
|
const OsType osType = HostOsInfo::hostOs();
|
||||||
|
QStringList res = QtcProcess::splitArgs(s, osType, false, &splitError);
|
||||||
|
if (splitError != QtcProcess::SplitOk){
|
||||||
|
res = QtcProcess::splitArgs(s + '\\', osType, false, &splitError);
|
||||||
|
if (splitError != QtcProcess::SplitOk){
|
||||||
|
res = QtcProcess::splitArgs(s + '"', osType, false, &splitError);
|
||||||
|
if (splitError != QtcProcess::SplitOk)
|
||||||
|
res = QtcProcess::splitArgs(s + '\'', osType, false, &splitError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace BareMetal
|
} // namespace BareMetal
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
#include <projectexplorer/toolchainconfigwidget.h>
|
#include <projectexplorer/toolchainconfigwidget.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QLineEdit;
|
||||||
class QPlainTextEdit;
|
class QPlainTextEdit;
|
||||||
class QPushButton;
|
class QPushButton;
|
||||||
class QTextEdit;
|
class QTextEdit;
|
||||||
@@ -81,6 +82,9 @@ public:
|
|||||||
void setCompilerCommand(const Utils::FilePath &file);
|
void setCompilerCommand(const Utils::FilePath &file);
|
||||||
Utils::FilePath compilerCommand() const final;
|
Utils::FilePath compilerCommand() const final;
|
||||||
|
|
||||||
|
void setExtraCodeModelFlags(const QStringList &flags);
|
||||||
|
QStringList extraCodeModelFlags() const final;
|
||||||
|
|
||||||
Utils::FilePath makeCommand(const Utils::Environment &env) const final;
|
Utils::FilePath makeCommand(const Utils::Environment &env) const final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -88,6 +92,7 @@ private:
|
|||||||
|
|
||||||
ProjectExplorer::Abi m_targetAbi;
|
ProjectExplorer::Abi m_targetAbi;
|
||||||
Utils::FilePath m_compilerCommand;
|
Utils::FilePath m_compilerCommand;
|
||||||
|
QStringList m_extraCodeModelFlags;
|
||||||
|
|
||||||
friend class KeilToolChainFactory;
|
friend class KeilToolChainFactory;
|
||||||
friend class KeilToolChainConfigWidget;
|
friend class KeilToolChainConfigWidget;
|
||||||
@@ -127,9 +132,12 @@ private:
|
|||||||
|
|
||||||
void setFromToolChain();
|
void setFromToolChain();
|
||||||
void handleCompilerCommandChange();
|
void handleCompilerCommandChange();
|
||||||
|
void handlePlatformCodeGenFlagsChange();
|
||||||
|
QStringList splitString(const QString &s) const;
|
||||||
|
|
||||||
Utils::PathChooser *m_compilerCommand = nullptr;
|
Utils::PathChooser *m_compilerCommand = nullptr;
|
||||||
ProjectExplorer::AbiWidget *m_abiWidget = nullptr;
|
ProjectExplorer::AbiWidget *m_abiWidget = nullptr;
|
||||||
|
QLineEdit *m_platformCodeGenFlagsLineEdit = nullptr;
|
||||||
ProjectExplorer::Macros m_macros;
|
ProjectExplorer::Macros m_macros;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user