aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/baremetal/keiltoolchain.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/baremetal/keiltoolchain.cpp')
-rw-r--r--src/plugins/baremetal/keiltoolchain.cpp432
1 files changed, 337 insertions, 95 deletions
diff --git a/src/plugins/baremetal/keiltoolchain.cpp b/src/plugins/baremetal/keiltoolchain.cpp
index 80ae51240e..96cef9a583 100644
--- a/src/plugins/baremetal/keiltoolchain.cpp
+++ b/src/plugins/baremetal/keiltoolchain.cpp
@@ -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>
@@ -60,6 +61,7 @@ namespace Internal {
// Helpers:
static const char compilerCommandKeyC[] = "BareMetal.KeilToolchain.CompilerPath";
+static const char compilerPlatformCodeGenFlagsKeyC[] = "BareMetal.KeilToolchain.PlatformCodeGenFlags";
static const char targetAbiKeyC[] = "BareMetal.KeilToolchain.TargetAbi";
static bool compilerExists(const FilePath &compilerPath)
@@ -74,28 +76,66 @@ static Abi::Architecture guessArchitecture(const FilePath &compilerPath)
const QString bn = fi.baseName().toLower();
if (bn == "c51" || bn == "cx51")
return Abi::Architecture::Mcs51Architecture;
+ if (bn == "c251")
+ return Abi::Architecture::Mcs251Architecture;
+ if (bn == "c166")
+ return Abi::Architecture::C166Architecture;
if (bn == "armcc")
return Abi::Architecture::ArmArchitecture;
return Abi::Architecture::UnknownArchitecture;
}
-// Note: The KEIL 8051 compiler does not support the predefined
-// macros dumping. So, we do it with following trick where we try
-// to compile a temporary file and to parse the console output.
-static Macros dumpC51PredefinedMacros(const FilePath &compiler, const QStringList &env)
+static Macros dumpMcsPredefinedMacros(const FilePath &compiler, const QStringList &env)
{
+ // Note: The KEIL C51 or C251 compiler does not support the predefined
+ // macros dumping. So, we do it with the following trick, where we try
+ // to create and compile a special temporary file and to parse the console
+ // output with the own magic pattern: (""|"key"|"value"|"").
+
QTemporaryFile fakeIn;
if (!fakeIn.open())
return {};
+
fakeIn.write("#define VALUE_TO_STRING(x) #x\n");
fakeIn.write("#define VALUE(x) VALUE_TO_STRING(x)\n");
- fakeIn.write("#define VAR_NAME_VALUE(var) \"\"\"|\"#var\"|\"VALUE(var)\n");
- fakeIn.write("#ifdef __C51__\n");
- fakeIn.write("#pragma message(VAR_NAME_VALUE(__C51__))\n");
+
+ // Prepare for C51 compiler.
+ fakeIn.write("#if defined(__C51__) || defined(__CX51__)\n");
+ fakeIn.write("# define VAR_NAME_VALUE(var) \"(\"\"\"\"|\"#var\"|\"VALUE(var)\"|\"\"\"\")\"\n");
+ fakeIn.write("# if defined (__C51__)\n");
+ fakeIn.write("# pragma message (VAR_NAME_VALUE(__C51__))\n");
+ fakeIn.write("# endif\n");
+ fakeIn.write("# if defined(__CX51__)\n");
+ fakeIn.write("# pragma message (VAR_NAME_VALUE(__CX51__))\n");
+ fakeIn.write("# endif\n");
+ fakeIn.write("# if defined(__MODEL__)\n");
+ fakeIn.write("# pragma message (VAR_NAME_VALUE(__MODEL__))\n");
+ fakeIn.write("# endif\n");
+ fakeIn.write("# if defined(__STDC__)\n");
+ fakeIn.write("# pragma message (VAR_NAME_VALUE(__STDC__))\n");
+ fakeIn.write("# endif\n");
fakeIn.write("#endif\n");
- fakeIn.write("#ifdef __CX51__\n");
- fakeIn.write("#pragma message(VAR_NAME_VALUE(__CX51__))\n");
+
+ // Prepare for C251 compiler.
+ fakeIn.write("#if defined(__C251__)\n");
+ fakeIn.write("# define VAR_NAME_VALUE(var) \"\"|#var|VALUE(var)|\"\"\n");
+ fakeIn.write("# if defined(__C251__)\n");
+ fakeIn.write("# warning (VAR_NAME_VALUE(__C251__))\n");
+ fakeIn.write("# endif\n");
+ fakeIn.write("# if defined(__MODEL__)\n");
+ fakeIn.write("# warning (VAR_NAME_VALUE(__MODEL__))\n");
+ fakeIn.write("# endif\n");
+ fakeIn.write("# if defined(__STDC__)\n");
+ fakeIn.write("# warning (VAR_NAME_VALUE(__STDC__))\n");
+ fakeIn.write("# endif\n");
+ fakeIn.write("# if defined(__FLOAT64__)\n");
+ fakeIn.write("# warning (VAR_NAME_VALUE(__FLOAT64__))\n");
+ fakeIn.write("# endif\n");
+ fakeIn.write("# if defined(__MODSRC__)\n");
+ fakeIn.write("# warning (VAR_NAME_VALUE(__MODSRC__))\n");
+ fakeIn.write("# endif\n");
fakeIn.write("#endif\n");
+
fakeIn.close();
SynchronousProcess cpp;
@@ -103,34 +143,151 @@ static Macros dumpC51PredefinedMacros(const FilePath &compiler, const QStringLis
cpp.setTimeoutS(10);
const CommandLine cmd(compiler, {fakeIn.fileName()});
-
const SynchronousProcessResponse response = cpp.runBlocking(cmd);
- if (response.result != SynchronousProcessResponse::Finished
- || response.exitCode != 0) {
- qWarning() << response.exitMessage(cmd.toUserOutput(), 10);
- return {};
- }
-
QString output = response.allOutput();
Macros macros;
QTextStream stream(&output);
QString line;
while (stream.readLineInto(&line)) {
+ enum { KEY_INDEX = 1, VALUE_INDEX = 2, ALL_PARTS = 4 };
const QStringList parts = line.split("\"|\"");
- if (parts.count() != 3)
+ if (parts.count() != ALL_PARTS)
continue;
- macros.push_back({parts.at(1).toUtf8(), parts.at(2).toUtf8()});
+ macros.push_back({parts.at(KEY_INDEX).toUtf8(), parts.at(VALUE_INDEX).toUtf8()});
}
return macros;
}
-static Macros dumpArmPredefinedMacros(const FilePath &compiler, const QStringList &env)
+static Macros dumpC166PredefinedMacros(const FilePath &compiler, const QStringList &env)
+{
+ // Note: The KEIL C166 compiler does not support the predefined
+ // macros dumping. Also, it does not support the '#pragma' and
+ // '#message|warning|error' directives properly (it is impossible
+ // to print to console the value of macro).
+ // So, we do it with the following trick, where we try
+ // to create and compile a special temporary file and to parse the console
+ // output with the own magic pattern, e.g:
+ //
+ // *** WARNING C320 IN LINE 41 OF c51.c: __C166__
+ // *** WARNING C2 IN LINE 42 OF c51.c: '757': unknown #pragma/control, line ignored
+ //
+ // where the '__C166__' is a key, and the '757' is a value.
+
+ QTemporaryFile fakeIn;
+ if (!fakeIn.open())
+ return {};
+
+ // Prepare for C166 compiler.
+ fakeIn.write("#if defined(__C166__)\n");
+ fakeIn.write("# if defined(__C166__)\n");
+ fakeIn.write("# warning __C166__\n");
+ fakeIn.write("# pragma __C166__\n");
+ fakeIn.write("# endif\n");
+ fakeIn.write("# if defined(__DUS__)\n");
+ fakeIn.write("# warning __DUS__\n");
+ fakeIn.write("# pragma __DUS__\n");
+ fakeIn.write("# endif\n");
+ fakeIn.write("# if defined(__MAC__)\n");
+ fakeIn.write("# warning __MAC__\n");
+ fakeIn.write("# pragma __MAC__\n");
+ fakeIn.write("# endif\n");
+ fakeIn.write("# if defined(__MOD167__)\n");
+ fakeIn.write("# warning __MOD167__\n");
+ fakeIn.write("# pragma __MOD167__\n");
+ fakeIn.write("# endif\n");
+ fakeIn.write("# if defined(__MODEL__)\n");
+ fakeIn.write("# warning __MODEL__\n");
+ fakeIn.write("# pragma __MODEL__\n");
+ fakeIn.write("# endif\n");
+ fakeIn.write("# if defined(__MODV2__)\n");
+ fakeIn.write("# warning __MODV2__\n");
+ fakeIn.write("# pragma __MODV2__\n");
+ fakeIn.write("# endif\n");
+ fakeIn.write("# if defined(__SAVEMAC__)\n");
+ fakeIn.write("# warning __SAVEMAC__\n");
+ fakeIn.write("# pragma __SAVEMAC__\n");
+ fakeIn.write("# endif\n");
+ fakeIn.write("# if defined(__STDC__)\n");
+ fakeIn.write("# warning __STDC__\n");
+ fakeIn.write("# pragma __STDC__\n");
+ fakeIn.write("# endif\n");
+ fakeIn.write("#endif\n");
+
+ fakeIn.close();
+
+ SynchronousProcess cpp;
+ cpp.setEnvironment(env);
+ cpp.setTimeoutS(10);
+
+ Macros macros;
+ auto extractMacros = [&macros](const QString &output) {
+ const QStringList lines = output.split('\n');
+ for (auto it = lines.cbegin(); it != lines.cend();) {
+ if (!it->startsWith("***")) {
+ ++it;
+ continue;
+ }
+
+ // Search for the key at a first line.
+ QByteArray key;
+ if (it->endsWith("__C166__"))
+ key = "__C166__";
+ else if (it->endsWith("__DUS__"))
+ key = "__DUS__";
+ else if (it->endsWith("__MAC__"))
+ key = "__MAC__";
+ else if (it->endsWith("__MOD167__"))
+ key = "__MOD167__";
+ else if (it->endsWith("__MODEL__"))
+ key = "__MODEL__";
+ else if (it->endsWith("__MODV2__"))
+ key = "__MODV2__";
+ else if (it->endsWith("__SAVEMAC__"))
+ key = "__SAVEMAC__";
+ else if (it->endsWith("__STDC__"))
+ key = "__STDC__";
+
+ if (key.isEmpty()) {
+ ++it;
+ continue;
+ }
+
+ ++it;
+ if (it == lines.cend() || !it->startsWith("***"))
+ break;
+
+ // Search for the value at a second line.
+ const int startIndex = it->indexOf('\'');
+ if (startIndex == -1)
+ break;
+ const int stopIndex = it->indexOf('\'', startIndex + 1);
+ if (stopIndex == -1)
+ break;
+ const QByteArray value = it->mid(startIndex + 1, stopIndex - startIndex - 1).toLatin1();
+
+ macros.append(Macro{key, value});
+
+ ++it;
+ }
+ };
+
+ const CommandLine cmd(compiler, {fakeIn.fileName()});
+ const SynchronousProcessResponse response = cpp.runBlocking(cmd);
+ const QString output = response.allOutput();
+ extractMacros(output);
+ return macros;
+}
+
+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"});
+ 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
@@ -143,20 +300,35 @@ static Macros dumpArmPredefinedMacros(const FilePath &compiler, const QStringLis
return Macro::toMacros(output);
}
-static Macros dumpPredefinedMacros(const FilePath &compiler, const QStringList &env)
+static bool isMcsArchitecture(Abi::Architecture arch)
+{
+ return arch == Abi::Architecture::Mcs51Architecture
+ || arch == Abi::Architecture::Mcs251Architecture;
+}
+
+static bool isC166Architecture(Abi::Architecture arch)
+{
+ return arch == Abi::Architecture::C166Architecture;
+}
+
+static bool isArmArchitecture(Abi::Architecture arch)
+{
+ return arch == Abi::Architecture::ArmArchitecture;
+}
+
+static Macros dumpPredefinedMacros(const FilePath &compiler, const QStringList &args, const QStringList &env)
{
if (compiler.isEmpty() || !compiler.toFileInfo().isExecutable())
return {};
const Abi::Architecture arch = guessArchitecture(compiler);
- switch (arch) {
- case Abi::Architecture::Mcs51Architecture:
- return dumpC51PredefinedMacros(compiler, env);
- case Abi::Architecture::ArmArchitecture:
- return dumpArmPredefinedMacros(compiler, env);
- default:
- return {};
- }
+ if (isMcsArchitecture(arch))
+ return dumpMcsPredefinedMacros(compiler, env);
+ if (isC166Architecture(arch))
+ return dumpC166PredefinedMacros(compiler, env);
+ if (isArmArchitecture(arch))
+ return dumpArmPredefinedMacros(compiler, args, env);
+ return {};
}
static HeaderPaths dumpHeaderPaths(const FilePath &compiler)
@@ -171,11 +343,11 @@ static HeaderPaths dumpHeaderPaths(const FilePath &compiler)
HeaderPaths headerPaths;
const Abi::Architecture arch = guessArchitecture(compiler);
- if (arch == Abi::Architecture::Mcs51Architecture) {
+ if (isMcsArchitecture(arch) || isC166Architecture(arch)) {
QDir includeDir(toolkitDir);
if (includeDir.cd("inc"))
headerPaths.push_back({includeDir.canonicalPath(), HeaderPathType::BuiltIn});
- } else if (arch == Abi::Architecture::ArmArchitecture) {
+ } else if (isArmArchitecture(arch)) {
QDir includeDir(toolkitDir);
if (includeDir.cd("include"))
headerPaths.push_back({includeDir.canonicalPath(), HeaderPathType::BuiltIn});
@@ -191,15 +363,22 @@ static Abi::Architecture guessArchitecture(const Macros &macros)
return Abi::Architecture::ArmArchitecture;
if (macro.key == "__C51__" || macro.key == "__CX51__")
return Abi::Architecture::Mcs51Architecture;
+ if (macro.key == "__C251__")
+ return Abi::Architecture::Mcs251Architecture;
+ if (macro.key == "__C166__")
+ return Abi::Architecture::C166Architecture;
}
return Abi::Architecture::UnknownArchitecture;
}
static unsigned char guessWordWidth(const Macros &macros, Abi::Architecture arch)
{
- // Check for C51 compiler first.
- if (arch == Abi::Architecture::Mcs51Architecture)
- return 16; // C51 always have 16-bit word width.
+ // Check for C51 or C251 compiler first, which are always have 16-bit word width:
+ // * http://www.keil.com/support/man/docs/c51/c51_le_datatypes.htm
+ // * http://www.keil.com/support/man/docs/c251/c251_le_datatypes.htm
+ // * http://www.keil.com/support/man/docs/c166/c166_le_datatypes.htm
+ if (isMcsArchitecture(arch) || isC166Architecture(arch))
+ return 16;
const Macro sizeMacro = Utils::findOrDefault(macros, [](const Macro &m) {
return m.key == "__sizeof_int";
@@ -211,9 +390,9 @@ static unsigned char guessWordWidth(const Macros &macros, Abi::Architecture arch
static Abi::BinaryFormat guessFormat(Abi::Architecture arch)
{
- if (arch == Abi::Architecture::ArmArchitecture)
+ if (isArmArchitecture(arch))
return Abi::BinaryFormat::ElfFormat;
- if (arch == Abi::Architecture::Mcs51Architecture)
+ if (isMcsArchitecture(arch) || isC166Architecture(arch))
return Abi::BinaryFormat::OmfFormat;
return Abi::BinaryFormat::UnknownFormat;
}
@@ -225,24 +404,38 @@ static Abi guessAbi(const Macros &macros)
guessFormat(arch), guessWordWidth(macros, arch)};
}
-static QString buildDisplayName(Abi::Architecture arch, Core::Id language,
+static QString buildDisplayName(Abi::Architecture arch, Utils::Id language,
const QString &version)
{
const auto archName = Abi::toString(arch);
const auto langName = ToolChainManager::displayNameOfLanguageId(language);
- return KeilToolchain::tr("KEIL %1 (%2, %3)")
+ return KeilToolChain::tr("KEIL %1 (%2, %3)")
.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() :
ToolChain(Constants::KEIL_TOOLCHAIN_TYPEID)
{
- setTypeDisplayName(Internal::KeilToolchainFactory::tr("KEIL"));
+ setTypeDisplayName(tr("KEIL"));
}
-void KeilToolchain::setTargetAbi(const Abi &abi)
+void KeilToolChain::setTargetAbi(const Abi &abi)
{
if (abi == m_targetAbi)
return;
@@ -250,31 +443,32 @@ void KeilToolchain::setTargetAbi(const Abi &abi)
toolChainUpdated();
}
-Abi KeilToolchain::targetAbi() const
+Abi KeilToolChain::targetAbi() const
{
return m_targetAbi;
}
-bool KeilToolchain::isValid() const
+bool KeilToolChain::isValid() const
{
return true;
}
-ToolChain::MacroInspectionRunner KeilToolchain::createMacroInspectionRunner() const
+ToolChain::MacroInspectionRunner KeilToolChain::createMacroInspectionRunner() const
{
Environment env = Environment::systemEnvironment();
addToEnvironment(env);
const Utils::FilePath compilerCommand = m_compilerCommand;
- const Core::Id lang = language();
+ const Utils::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);
@@ -282,23 +476,23 @@ ToolChain::MacroInspectionRunner KeilToolchain::createMacroInspectionRunner() co
};
}
-Macros KeilToolchain::predefinedMacros(const QStringList &cxxflags) const
+Macros KeilToolChain::predefinedMacros(const QStringList &cxxflags) const
{
return createMacroInspectionRunner()(cxxflags).macros;
}
-Utils::LanguageExtensions KeilToolchain::languageExtensions(const QStringList &) const
+Utils::LanguageExtensions KeilToolChain::languageExtensions(const QStringList &) const
{
return LanguageExtension::None;
}
-WarningFlags KeilToolchain::warningFlags(const QStringList &cxxflags) const
+WarningFlags KeilToolChain::warningFlags(const QStringList &cxxflags) const
{
Q_UNUSED(cxxflags)
return WarningFlags::Default;
}
-ToolChain::BuiltInHeaderPathsRunner KeilToolchain::createBuiltInHeaderPathsRunner(
+ToolChain::BuiltInHeaderPathsRunner KeilToolChain::createBuiltInHeaderPathsRunner(
const Environment &) const
{
const Utils::FilePath compilerCommand = m_compilerCommand;
@@ -317,14 +511,14 @@ ToolChain::BuiltInHeaderPathsRunner KeilToolchain::createBuiltInHeaderPathsRunne
};
}
-HeaderPaths KeilToolchain::builtInHeaderPaths(const QStringList &cxxFlags,
+HeaderPaths KeilToolChain::builtInHeaderPaths(const QStringList &cxxFlags,
const FilePath &fileName,
const Environment &env) const
{
return createBuiltInHeaderPathsRunner(env)(cxxFlags, fileName.toString(), "");
}
-void KeilToolchain::addToEnvironment(Environment &env) const
+void KeilToolChain::addToEnvironment(Environment &env) const
{
if (!m_compilerCommand.isEmpty()) {
const FilePath path = m_compilerCommand.parentDir();
@@ -332,45 +526,48 @@ void KeilToolchain::addToEnvironment(Environment &env) const
}
}
-IOutputParser *KeilToolchain::outputParser() const
+QList<OutputLineParser *> KeilToolChain::createOutputParsers() const
{
- return new KeilParser;
+ return {new KeilParser};
}
-QVariantMap KeilToolchain::toMap() const
+QVariantMap KeilToolChain::toMap() const
{
QVariantMap data = ToolChain::toMap();
data.insert(compilerCommandKeyC, m_compilerCommand.toString());
+ data.insert(compilerPlatformCodeGenFlagsKeyC, m_extraCodeModelFlags);
data.insert(targetAbiKeyC, m_targetAbi.toString());
return data;
}
-bool KeilToolchain::fromMap(const QVariantMap &data)
+bool KeilToolChain::fromMap(const QVariantMap &data)
{
if (!ToolChain::fromMap(data))
return false;
m_compilerCommand = FilePath::fromString(data.value(compilerCommandKeyC).toString());
+ m_extraCodeModelFlags = data.value(compilerPlatformCodeGenFlagsKeyC).toStringList();
m_targetAbi = Abi::fromString(data.value(targetAbiKeyC).toString());
return true;
}
-std::unique_ptr<ToolChainConfigWidget> KeilToolchain::createConfigurationWidget()
+std::unique_ptr<ToolChainConfigWidget> KeilToolChain::createConfigurationWidget()
{
- return std::make_unique<KeilToolchainConfigWidget>(this);
+ return std::make_unique<KeilToolChainConfigWidget>(this);
}
-bool KeilToolchain::operator ==(const ToolChain &other) const
+bool KeilToolChain::operator ==(const ToolChain &other) const
{
if (!ToolChain::operator ==(other))
return false;
- const auto customTc = static_cast<const KeilToolchain *>(&other);
+ const auto customTc = static_cast<const KeilToolChain *>(&other);
return m_compilerCommand == customTc->m_compilerCommand
&& m_targetAbi == customTc->m_targetAbi
+ && m_extraCodeModelFlags == customTc->m_extraCodeModelFlags
;
}
-void KeilToolchain::setCompilerCommand(const FilePath &file)
+void KeilToolChain::setCompilerCommand(const FilePath &file)
{
if (file == m_compilerCommand)
return;
@@ -378,12 +575,25 @@ void KeilToolchain::setCompilerCommand(const FilePath &file)
toolChainUpdated();
}
-FilePath KeilToolchain::compilerCommand() const
+FilePath KeilToolChain::compilerCommand() const
{
return m_compilerCommand;
}
-FilePath KeilToolchain::makeCommand(const Environment &env) const
+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)
return {};
@@ -391,13 +601,13 @@ FilePath KeilToolchain::makeCommand(const Environment &env) const
// KeilToolchainFactory
-KeilToolchainFactory::KeilToolchainFactory()
+KeilToolChainFactory::KeilToolChainFactory()
{
- setDisplayName(tr("KEIL"));
+ setDisplayName(KeilToolChain::tr("KEIL"));
setSupportedToolChainType(Constants::KEIL_TOOLCHAIN_TYPEID);
setSupportedLanguages({ProjectExplorer::Constants::C_LANGUAGE_ID,
ProjectExplorer::Constants::CXX_LANGUAGE_ID});
- setToolchainConstructor([] { return new KeilToolchain; });
+ setToolchainConstructor([] { return new KeilToolChain; });
setUserCreatable(true);
}
@@ -445,7 +655,7 @@ static QString extractVersion(const QString &toolsFile, const QString &section)
return {};
}
-QList<ToolChain *> KeilToolchainFactory::autoDetect(const QList<ToolChain *> &alreadyKnown)
+QList<ToolChain *> KeilToolChainFactory::autoDetect(const QList<ToolChain *> &alreadyKnown)
{
#ifdef Q_OS_WIN64
static const char kRegistryNode[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Microsoft\\" \
@@ -468,9 +678,13 @@ QList<ToolChain *> KeilToolchainFactory::autoDetect(const QList<ToolChain *> &al
// Fetch the toolchain executable path.
FilePath compilerPath;
if (productPath.endsWith("ARM"))
- compilerPath = productPath.pathAppended("\\ARMCC\\bin\\armcc.exe");
+ compilerPath = productPath.pathAppended("ARMCC/bin/armcc.exe");
else if (productPath.endsWith("C51"))
- compilerPath = productPath.pathAppended("\\BIN\\c51.exe");
+ compilerPath = productPath.pathAppended("BIN/c51.exe");
+ else if (productPath.endsWith("C251"))
+ compilerPath = productPath.pathAppended("BIN/c251.exe");
+ else if (productPath.endsWith("C166"))
+ compilerPath = productPath.pathAppended("BIN/c166.exe");
if (compilerPath.exists()) {
// Fetch the toolchain version.
@@ -492,7 +706,7 @@ QList<ToolChain *> KeilToolchainFactory::autoDetect(const QList<ToolChain *> &al
return autoDetectToolchains(candidates, alreadyKnown);
}
-QList<ToolChain *> KeilToolchainFactory::autoDetectToolchains(
+QList<ToolChain *> KeilToolChainFactory::autoDetectToolchains(
const Candidates &candidates, const QList<ToolChain *> &alreadyKnown) const
{
QList<ToolChain *> result;
@@ -519,26 +733,30 @@ QList<ToolChain *> KeilToolchainFactory::autoDetectToolchains(
return result;
}
-QList<ToolChain *> KeilToolchainFactory::autoDetectToolchain(
- const Candidate &candidate, Core::Id language) const
+QList<ToolChain *> KeilToolChainFactory::autoDetectToolchain(
+ const Candidate &candidate, Utils::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 {};
const Abi abi = guessAbi(macros);
const Abi::Architecture arch = abi.architecture();
- if (arch == Abi::Architecture::Mcs51Architecture
+ if ((isMcsArchitecture(arch) || isC166Architecture(arch))
&& language == ProjectExplorer::Constants::CXX_LANGUAGE_ID) {
- // KEIL C51 compiler does not support C++ language.
+ // KEIL C51/C251/C166 compilers does not support C++ language.
return {};
}
- const auto tc = new KeilToolchain;
+ const auto tc = new KeilToolChain;
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));
@@ -549,7 +767,7 @@ QList<ToolChain *> KeilToolchainFactory::autoDetectToolchain(
// KeilToolchainConfigWidget
-KeilToolchainConfigWidget::KeilToolchainConfigWidget(KeilToolchain *tc) :
+KeilToolChainConfigWidget::KeilToolChainConfigWidget(KeilToolChain *tc) :
ToolChainConfigWidget(tc),
m_compilerCommand(new PathChooser),
m_abiWidget(new AbiWidget)
@@ -557,27 +775,33 @@ 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);
addErrorLabel();
- setFromToolchain();
+ setFromToolChain();
connect(m_compilerCommand, &PathChooser::rawPathChanged,
- this, &KeilToolchainConfigWidget::handleCompilerCommandChange);
+ this, &KeilToolChainConfigWidget::handleCompilerCommandChange);
+ connect(m_platformCodeGenFlagsLineEdit, &QLineEdit::editingFinished,
+ this, &KeilToolChainConfigWidget::handlePlatformCodeGenFlagsChange);
connect(m_abiWidget, &AbiWidget::abiChanged,
this, &ToolChainConfigWidget::dirty);
}
-void KeilToolchainConfigWidget::applyImpl()
+void KeilToolChainConfigWidget::applyImpl()
{
if (toolChain()->isAutoDetected())
return;
- const auto tc = static_cast<KeilToolchain *>(toolChain());
+ const auto tc = static_cast<KeilToolChain *>(toolChain());
const QString displayName = tc->displayName();
- tc->setCompilerCommand(m_compilerCommand->fileName());
+ tc->setCompilerCommand(m_compilerCommand->filePath());
+ tc->setExtraCodeModelFlags(splitString(m_platformCodeGenFlagsLineEdit->text()));
tc->setTargetAbi(m_abiWidget->currentAbi());
tc->setDisplayName(displayName);
@@ -587,40 +811,48 @@ void KeilToolchainConfigWidget::applyImpl()
const auto languageVersion = ToolChain::languageVersion(tc->language(), m_macros);
tc->predefinedMacrosCache()->insert({}, {m_macros, languageVersion});
- setFromToolchain();
+ setFromToolChain();
}
-bool KeilToolchainConfigWidget::isDirtyImpl() const
+bool KeilToolChainConfigWidget::isDirtyImpl() const
{
- const auto tc = static_cast<KeilToolchain *>(toolChain());
- return m_compilerCommand->fileName() != tc->compilerCommand()
+ 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()
;
}
-void KeilToolchainConfigWidget::makeReadOnlyImpl()
+void KeilToolChainConfigWidget::makeReadOnlyImpl()
{
m_compilerCommand->setReadOnly(true);
+ m_platformCodeGenFlagsLineEdit->setEnabled(false);
m_abiWidget->setEnabled(false);
}
-void KeilToolchainConfigWidget::setFromToolchain()
+void KeilToolChainConfigWidget::setFromToolChain()
{
const QSignalBlocker blocker(this);
- const auto tc = static_cast<KeilToolchain *>(toolChain());
- m_compilerCommand->setFileName(tc->compilerCommand());
+ 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->fileName());
+ const bool haveCompiler = compilerExists(m_compilerCommand->filePath());
m_abiWidget->setEnabled(haveCompiler && !tc->isAutoDetected());
}
-void KeilToolchainConfigWidget::handleCompilerCommandChange()
+void KeilToolChainConfigWidget::handleCompilerCommandChange()
{
- const FilePath compilerPath = m_compilerCommand->fileName();
+ const FilePath compilerPath = m_compilerCommand->filePath();
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);
}
@@ -629,5 +861,15 @@ 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();
+}
+
} // namespace Internal
} // namespace BareMetal