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:
Denis Shienkov
2020-05-18 19:03:55 +03:00
parent d54c61b4bd
commit 071f99875e
2 changed files with 93 additions and 8 deletions

View File

@@ -37,6 +37,7 @@
#include <utils/environment.h>
#include <utils/pathchooser.h>
#include <utils/qtcassert.h>
#include <utils/qtcprocess.h>
#include <utils/synchronousprocess.h>
#include <QDebug>
@@ -276,13 +277,16 @@ static Macros dumpC166PredefinedMacros(const FilePath &compiler, const QStringLi
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;
cpp.setEnvironment(env);
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);
if (response.result != SynchronousProcessResponse::Finished
@@ -311,7 +315,7 @@ static bool isArmArchitecture(Abi::Architecture arch)
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())
return {};
@@ -322,7 +326,7 @@ static Macros dumpPredefinedMacros(const FilePath &compiler, const QStringList &
if (isC166Architecture(arch))
return dumpC166PredefinedMacros(compiler, env);
if (isArmArchitecture(arch))
return dumpArmPredefinedMacros(compiler, env);
return dumpArmPredefinedMacros(compiler, args, env);
return {};
}
@@ -408,6 +412,20 @@ static QString buildDisplayName(Abi::Architecture arch, Core::Id language,
.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() :
@@ -443,12 +461,13 @@ ToolChain::MacroInspectionRunner KeilToolChain::createMacroInspectionRunner() co
const Core::Id lang = language();
MacrosCache macroCache = predefinedMacrosCache();
const QStringList extraArgs = m_extraCodeModelFlags;
return [env, compilerCommand, macroCache, lang]
return [env, compilerCommand, extraArgs, macroCache, lang]
(const QStringList &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)};
macroCache->insert({}, report);
@@ -541,6 +560,7 @@ bool KeilToolChain::operator ==(const ToolChain &other) const
const auto customTc = static_cast<const KeilToolChain *>(&other);
return m_compilerCommand == customTc->m_compilerCommand
&& m_targetAbi == customTc->m_targetAbi
&& m_extraCodeModelFlags == customTc->m_extraCodeModelFlags
;
}
@@ -557,6 +577,19 @@ FilePath KeilToolChain::compilerCommand() const
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
{
Q_UNUSED(env)
@@ -701,7 +734,10 @@ QList<ToolChain *> KeilToolChainFactory::autoDetectToolchain(
const Candidate &candidate, Core::Id language) const
{
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())
return {};
@@ -717,6 +753,7 @@ QList<ToolChain *> KeilToolChainFactory::autoDetectToolchain(
tc->setDetection(ToolChain::AutoDetection);
tc->setLanguage(language);
tc->setCompilerCommand(candidate.compilerPath);
tc->setExtraCodeModelFlags(extraArgs);
tc->setTargetAbi(abi);
tc->setDisplayName(buildDisplayName(abi.architecture(), language, candidate.compilerVersion));
@@ -735,6 +772,9 @@ KeilToolChainConfigWidget::KeilToolChainConfigWidget(KeilToolChain *tc) :
m_compilerCommand->setExpectedKind(PathChooser::ExistingCommand);
m_compilerCommand->setHistoryCompleter("PE.KEIL.Command.History");
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_abiWidget->setEnabled(false);
@@ -744,6 +784,8 @@ KeilToolChainConfigWidget::KeilToolChainConfigWidget(KeilToolChain *tc) :
connect(m_compilerCommand, &PathChooser::rawPathChanged,
this, &KeilToolChainConfigWidget::handleCompilerCommandChange);
connect(m_platformCodeGenFlagsLineEdit, &QLineEdit::editingFinished,
this, &KeilToolChainConfigWidget::handlePlatformCodeGenFlagsChange);
connect(m_abiWidget, &AbiWidget::abiChanged,
this, &ToolChainConfigWidget::dirty);
}
@@ -756,6 +798,7 @@ void KeilToolChainConfigWidget::applyImpl()
const auto tc = static_cast<KeilToolChain *>(toolChain());
const QString displayName = tc->displayName();
tc->setCompilerCommand(m_compilerCommand->filePath());
tc->setExtraCodeModelFlags(splitString(m_platformCodeGenFlagsLineEdit->text()));
tc->setTargetAbi(m_abiWidget->currentAbi());
tc->setDisplayName(displayName);
@@ -772,6 +815,7 @@ bool KeilToolChainConfigWidget::isDirtyImpl() const
{
const auto tc = static_cast<KeilToolChain *>(toolChain());
return m_compilerCommand->filePath() != tc->compilerCommand()
|| m_platformCodeGenFlagsLineEdit->text() != QtcProcess::joinArgs(tc->extraCodeModelFlags())
|| m_abiWidget->currentAbi() != tc->targetAbi()
;
}
@@ -779,6 +823,7 @@ bool KeilToolChainConfigWidget::isDirtyImpl() const
void KeilToolChainConfigWidget::makeReadOnlyImpl()
{
m_compilerCommand->setReadOnly(true);
m_platformCodeGenFlagsLineEdit->setEnabled(false);
m_abiWidget->setEnabled(false);
}
@@ -787,6 +832,7 @@ void KeilToolChainConfigWidget::setFromToolChain()
const QSignalBlocker blocker(this);
const auto tc = static_cast<KeilToolChain *>(toolChain());
m_compilerCommand->setFilePath(tc->compilerCommand());
m_platformCodeGenFlagsLineEdit->setText(QtcProcess::joinArgs(tc->extraCodeModelFlags()));
m_abiWidget->setAbis({}, tc->targetAbi());
const bool haveCompiler = compilerExists(m_compilerCommand->filePath());
m_abiWidget->setEnabled(haveCompiler && !tc->isAutoDetected());
@@ -798,7 +844,12 @@ void KeilToolChainConfigWidget::handleCompilerCommandChange()
const bool haveCompiler = compilerExists(compilerPath);
if (haveCompiler) {
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);
m_abiWidget->setAbis({}, guessed);
}
@@ -807,5 +858,31 @@ void KeilToolChainConfigWidget::handleCompilerCommandChange()
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 BareMetal

View File

@@ -30,6 +30,7 @@
#include <projectexplorer/toolchainconfigwidget.h>
QT_BEGIN_NAMESPACE
class QLineEdit;
class QPlainTextEdit;
class QPushButton;
class QTextEdit;
@@ -81,6 +82,9 @@ public:
void setCompilerCommand(const Utils::FilePath &file);
Utils::FilePath compilerCommand() const final;
void setExtraCodeModelFlags(const QStringList &flags);
QStringList extraCodeModelFlags() const final;
Utils::FilePath makeCommand(const Utils::Environment &env) const final;
private:
@@ -88,6 +92,7 @@ private:
ProjectExplorer::Abi m_targetAbi;
Utils::FilePath m_compilerCommand;
QStringList m_extraCodeModelFlags;
friend class KeilToolChainFactory;
friend class KeilToolChainConfigWidget;
@@ -127,9 +132,12 @@ private:
void setFromToolChain();
void handleCompilerCommandChange();
void handlePlatformCodeGenFlagsChange();
QStringList splitString(const QString &s) const;
Utils::PathChooser *m_compilerCommand = nullptr;
ProjectExplorer::AbiWidget *m_abiWidget = nullptr;
QLineEdit *m_platformCodeGenFlagsLineEdit = nullptr;
ProjectExplorer::Macros m_macros;
};