BareMetal: Tune IAR compiler using 'platform codegen flags' feature

Previously we did a predefined macros generation for a some default
target CPU, which is hardcoded in a compiler.

Right now we have added the new text field in the IAR compiler settings
page, called "Platform codegen flags". In this field we can specify the
desired CPU or FPU target flags to generate an appropriate predefined
macros (e.g. such as --cpu=, --core= and so forth).

Change-Id: Ie38e077d8bac1851957085cde32661bcd189ddd2
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Denis Shienkov
2020-05-19 15:48:01 +03:00
parent 0c6386a548
commit fdfa68cc7a
2 changed files with 53 additions and 9 deletions

View File

@@ -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>
@@ -58,6 +59,7 @@ namespace Internal {
// Helpers: // Helpers:
static const char compilerCommandKeyC[] = "BareMetal.IarToolChain.CompilerPath"; static const char compilerCommandKeyC[] = "BareMetal.IarToolChain.CompilerPath";
static const char compilerPlatformCodeGenFlagsKeyC[] = "BareMetal.IarToolChain.PlatformCodeGenFlags";
static const char targetAbiKeyC[] = "BareMetal.IarToolChain.TargetAbi"; static const char targetAbiKeyC[] = "BareMetal.IarToolChain.TargetAbi";
static bool compilerExists(const FilePath &compilerPath) static bool compilerExists(const FilePath &compilerPath)
@@ -84,8 +86,8 @@ static QString cppLanguageOption(const FilePath &compiler)
return {}; return {};
} }
static Macros dumpPredefinedMacros(const FilePath &compiler, const Core::Id languageId, static Macros dumpPredefinedMacros(const FilePath &compiler, const QStringList &extraArgs,
const QStringList &env) const Core::Id languageId, const QStringList &env)
{ {
if (compiler.isEmpty() || !compiler.toFileInfo().isExecutable()) if (compiler.isEmpty() || !compiler.toFileInfo().isExecutable())
return {}; return {};
@@ -106,6 +108,7 @@ static Macros dumpPredefinedMacros(const FilePath &compiler, const Core::Id lang
CommandLine cmd(compiler, {fakeIn.fileName()}); CommandLine cmd(compiler, {fakeIn.fileName()});
if (languageId == ProjectExplorer::Constants::CXX_LANGUAGE_ID) if (languageId == ProjectExplorer::Constants::CXX_LANGUAGE_ID)
cmd.addArg(cppLanguageOption(compiler)); cmd.addArg(cppLanguageOption(compiler));
cmd.addArgs(extraArgs);
cmd.addArg("--predef_macros"); cmd.addArg("--predef_macros");
cmd.addArg(outpath); cmd.addArg(outpath);
@@ -307,16 +310,14 @@ ToolChain::MacroInspectionRunner IarToolChain::createMacroInspectionRunner() con
const Utils::FilePath compilerCommand = m_compilerCommand; const Utils::FilePath compilerCommand = m_compilerCommand;
const Core::Id languageId = language(); const Core::Id languageId = language();
const QStringList extraArgs = m_extraCodeModelFlags;
MacrosCache macrosCache = predefinedMacrosCache(); MacrosCache macrosCache = predefinedMacrosCache();
return [env, compilerCommand, return [env, compilerCommand, extraArgs, macrosCache, languageId]
macrosCache,
languageId]
(const QStringList &flags) { (const QStringList &flags) {
Q_UNUSED(flags) Q_UNUSED(flags)
Macros macros = dumpPredefinedMacros(compilerCommand, languageId, env.toStringList()); Macros macros = dumpPredefinedMacros(compilerCommand, extraArgs, languageId, env.toStringList());
macros.append({"__intrinsic", "", MacroType::Define}); macros.append({"__intrinsic", "", MacroType::Define});
macros.append({"__nounwind", "", MacroType::Define}); macros.append({"__nounwind", "", MacroType::Define});
macros.append({"__noreturn", "", MacroType::Define}); macros.append({"__noreturn", "", MacroType::Define});
@@ -396,6 +397,7 @@ QVariantMap IarToolChain::toMap() const
{ {
QVariantMap data = ToolChain::toMap(); QVariantMap data = ToolChain::toMap();
data.insert(compilerCommandKeyC, m_compilerCommand.toString()); data.insert(compilerCommandKeyC, m_compilerCommand.toString());
data.insert(compilerPlatformCodeGenFlagsKeyC, m_extraCodeModelFlags);
data.insert(targetAbiKeyC, m_targetAbi.toString()); data.insert(targetAbiKeyC, m_targetAbi.toString());
return data; return data;
} }
@@ -405,6 +407,7 @@ bool IarToolChain::fromMap(const QVariantMap &data)
if (!ToolChain::fromMap(data)) if (!ToolChain::fromMap(data))
return false; return false;
m_compilerCommand = FilePath::fromString(data.value(compilerCommandKeyC).toString()); m_compilerCommand = FilePath::fromString(data.value(compilerCommandKeyC).toString());
m_extraCodeModelFlags = data.value(compilerPlatformCodeGenFlagsKeyC).toStringList();
m_targetAbi = Abi::fromString(data.value(targetAbiKeyC).toString()); m_targetAbi = Abi::fromString(data.value(targetAbiKeyC).toString());
return true; return true;
} }
@@ -422,6 +425,7 @@ bool IarToolChain::operator==(const ToolChain &other) const
const auto customTc = static_cast<const IarToolChain *>(&other); const auto customTc = static_cast<const IarToolChain *>(&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
; ;
} }
@@ -438,6 +442,19 @@ FilePath IarToolChain::compilerCommand() const
return m_compilerCommand; return m_compilerCommand;
} }
void IarToolChain::setExtraCodeModelFlags(const QStringList &flags)
{
if (flags == m_extraCodeModelFlags)
return;
m_extraCodeModelFlags = flags;
toolChainUpdated();
}
QStringList IarToolChain::extraCodeModelFlags() const
{
return m_extraCodeModelFlags;
}
FilePath IarToolChain::makeCommand(const Environment &env) const FilePath IarToolChain::makeCommand(const Environment &env) const
{ {
Q_UNUSED(env) Q_UNUSED(env)
@@ -555,7 +572,7 @@ QList<ToolChain *> IarToolChainFactory::autoDetectToolchain(
const Candidate &candidate, Core::Id languageId) const const Candidate &candidate, Core::Id languageId) const
{ {
const auto env = Environment::systemEnvironment(); const auto env = Environment::systemEnvironment();
const Macros macros = dumpPredefinedMacros(candidate.compilerPath, languageId, const Macros macros = dumpPredefinedMacros(candidate.compilerPath, {}, languageId,
env.toStringList()); env.toStringList());
if (macros.isEmpty()) if (macros.isEmpty())
return {}; return {};
@@ -584,6 +601,9 @@ IarToolChainConfigWidget::IarToolChainConfigWidget(IarToolChain *tc) :
m_compilerCommand->setExpectedKind(PathChooser::ExistingCommand); m_compilerCommand->setExpectedKind(PathChooser::ExistingCommand);
m_compilerCommand->setHistoryCompleter("PE.IAREW.Command.History"); m_compilerCommand->setHistoryCompleter("PE.IAREW.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);
@@ -593,6 +613,8 @@ IarToolChainConfigWidget::IarToolChainConfigWidget(IarToolChain *tc) :
connect(m_compilerCommand, &PathChooser::rawPathChanged, connect(m_compilerCommand, &PathChooser::rawPathChanged,
this, &IarToolChainConfigWidget::handleCompilerCommandChange); this, &IarToolChainConfigWidget::handleCompilerCommandChange);
connect(m_platformCodeGenFlagsLineEdit, &QLineEdit::editingFinished,
this, &IarToolChainConfigWidget::handlePlatformCodeGenFlagsChange);
connect(m_abiWidget, &AbiWidget::abiChanged, connect(m_abiWidget, &AbiWidget::abiChanged,
this, &ToolChainConfigWidget::dirty); this, &ToolChainConfigWidget::dirty);
} }
@@ -605,6 +627,7 @@ void IarToolChainConfigWidget::applyImpl()
const auto tc = static_cast<IarToolChain *>(toolChain()); const auto tc = static_cast<IarToolChain *>(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);
@@ -621,6 +644,7 @@ bool IarToolChainConfigWidget::isDirtyImpl() const
{ {
const auto tc = static_cast<IarToolChain *>(toolChain()); const auto tc = static_cast<IarToolChain *>(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()
; ;
} }
@@ -628,6 +652,7 @@ bool IarToolChainConfigWidget::isDirtyImpl() const
void IarToolChainConfigWidget::makeReadOnlyImpl() void IarToolChainConfigWidget::makeReadOnlyImpl()
{ {
m_compilerCommand->setReadOnly(true); m_compilerCommand->setReadOnly(true);
m_platformCodeGenFlagsLineEdit->setEnabled(false);
m_abiWidget->setEnabled(false); m_abiWidget->setEnabled(false);
} }
@@ -636,6 +661,7 @@ void IarToolChainConfigWidget::setFromToolchain()
const QSignalBlocker blocker(this); const QSignalBlocker blocker(this);
const auto tc = static_cast<IarToolChain *>(toolChain()); const auto tc = static_cast<IarToolChain *>(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());
@@ -647,8 +673,9 @@ void IarToolChainConfigWidget::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();
const QStringList extraArgs = splitString(m_platformCodeGenFlagsLineEdit->text());
const auto languageId = toolChain()->language(); const auto languageId = toolChain()->language();
m_macros = dumpPredefinedMacros(compilerPath, languageId, m_macros = dumpPredefinedMacros(compilerPath, extraArgs, languageId,
env.toStringList()); env.toStringList());
const Abi guessed = guessAbi(m_macros); const Abi guessed = guessAbi(m_macros);
m_abiWidget->setAbis({}, guessed); m_abiWidget->setAbis({}, guessed);
@@ -658,5 +685,15 @@ void IarToolChainConfigWidget::handleCompilerCommandChange()
emit dirty(); emit dirty();
} }
void IarToolChainConfigWidget::handlePlatformCodeGenFlagsChange()
{
const QString str1 = m_platformCodeGenFlagsLineEdit->text();
const QString str2 = QtcProcess::joinArgs(splitString(str1));
if (str1 != str2)
m_platformCodeGenFlagsLineEdit->setText(str2);
else
handleCompilerCommandChange();
}
} // namespace Internal } // namespace Internal
} // namespace BareMetal } // namespace BareMetal

View File

@@ -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;
@@ -80,6 +81,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:
@@ -87,6 +91,7 @@ private:
ProjectExplorer::Abi m_targetAbi; ProjectExplorer::Abi m_targetAbi;
Utils::FilePath m_compilerCommand; Utils::FilePath m_compilerCommand;
QStringList m_extraCodeModelFlags;
friend class IarToolChainFactory; friend class IarToolChainFactory;
friend class IarToolChainConfigWidget; friend class IarToolChainConfigWidget;
@@ -126,9 +131,11 @@ private:
void setFromToolchain(); void setFromToolchain();
void handleCompilerCommandChange(); void handleCompilerCommandChange();
void handlePlatformCodeGenFlagsChange();
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;
}; };