aboutsummaryrefslogtreecommitdiffstats
path: root/src/app/qbs-setup-toolchains/iarewprobe.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/app/qbs-setup-toolchains/iarewprobe.cpp')
-rw-r--r--src/app/qbs-setup-toolchains/iarewprobe.cpp107
1 files changed, 89 insertions, 18 deletions
diff --git a/src/app/qbs-setup-toolchains/iarewprobe.cpp b/src/app/qbs-setup-toolchains/iarewprobe.cpp
index 5d3785759..47592b9c0 100644
--- a/src/app/qbs-setup-toolchains/iarewprobe.cpp
+++ b/src/app/qbs-setup-toolchains/iarewprobe.cpp
@@ -47,9 +47,9 @@
#include <tools/hostosinfo.h>
#include <tools/profile.h>
-#include <QtCore/qfileinfo.h>
-#include <QtCore/qlist.h>
+#include <QtCore/qprocess.h>
#include <QtCore/qsettings.h>
+#include <QtCore/qstandardpaths.h>
using namespace qbs;
using Internal::Tr;
@@ -57,7 +57,9 @@ using Internal::HostOsInfo;
static QStringList knownIarCompilerNames()
{
- return {QStringLiteral("icc8051"), QStringLiteral("iccarm"), QStringLiteral("iccavr")};
+ return {QStringLiteral("icc8051"), QStringLiteral("iccarm"),
+ QStringLiteral("iccavr"), QStringLiteral("iccstm8"),
+ QStringLiteral("icc430")};
}
static QString guessIarArchitecture(const QFileInfo &compiler)
@@ -69,17 +71,31 @@ static QString guessIarArchitecture(const QFileInfo &compiler)
return QStringLiteral("arm");
if (baseName == QLatin1String("iccavr"))
return QStringLiteral("avr");
+ if (baseName == QLatin1String("iccstm8"))
+ return QStringLiteral("stm8");
+ if (baseName == QLatin1String("icc430"))
+ return QStringLiteral("msp430");
return {};
}
-static Profile createIarProfileHelper(const QFileInfo &compiler, Settings *settings,
+static Profile createIarProfileHelper(const ToolchainInstallInfo &info,
+ Settings *settings,
QString profileName = QString())
{
+ const QFileInfo compiler = info.compilerPath;
const QString architecture = guessIarArchitecture(compiler);
// In case the profile is auto-detected.
- if (profileName.isEmpty())
- profileName = QLatin1String("iar-") + architecture;
+ if (profileName.isEmpty()) {
+ if (!info.compilerVersion.isValid()) {
+ profileName = QStringLiteral("iar-unknown-%1").arg(architecture);
+ } else {
+ const QString version = info.compilerVersion.toString(QLatin1Char('_'),
+ QLatin1Char('_'));
+ profileName = QStringLiteral("iar-%1-%2").arg(
+ version, architecture);
+ }
+ }
Profile profile(profileName, settings);
profile.setValue(QLatin1String("cpp.toolchainInstallPath"), compiler.absolutePath());
@@ -92,9 +108,53 @@ static Profile createIarProfileHelper(const QFileInfo &compiler, Settings *setti
return profile;
}
-static std::vector<IarInstallInfo> installedIarsFromPath()
+static Version dumpIarCompilerVersion(const QFileInfo &compiler)
+{
+ const QString outFilePath = QStandardPaths::writableLocation(QStandardPaths::TempLocation)
+ + QLatin1String("/macros.dump");
+ const QStringList args = {QStringLiteral("."),
+ QStringLiteral("--predef_macros"),
+ outFilePath};
+ QProcess p;
+ p.start(compiler.absoluteFilePath(), args);
+ p.waitForFinished(3000);
+ const auto es = p.exitStatus();
+ if (es != QProcess::NormalExit) {
+ const QByteArray out = p.readAll();
+ qbsWarning() << Tr::tr("Compiler dumping failed:\n%1")
+ .arg(QString::fromUtf8(out));
+ return Version{};
+ }
+
+ QByteArray dump;
+ QFile out(outFilePath);
+ if (out.open(QIODevice::ReadOnly))
+ dump = out.readAll();
+ out.remove();
+
+ const int verCode = extractVersion(dump, "__VER__ ");
+ if (verCode < 0) {
+ qbsWarning() << Tr::tr("No '__VER__' token was found in a compiler dump:\n%1")
+ .arg(QString::fromUtf8(dump));
+ return Version{};
+ }
+
+ const QString arch = guessIarArchitecture(compiler);
+ if (arch == QLatin1String("arm")) {
+ return Version{verCode / 1000000, (verCode / 1000) % 1000, verCode % 1000};
+ } else if (arch == QLatin1String("avr")
+ || arch == QLatin1String("mcs51")
+ || arch == QLatin1String("stm8")
+ || arch == QLatin1String("msp430")) {
+ return Version{verCode / 100, verCode % 100};
+ }
+
+ return Version{};
+}
+
+static std::vector<ToolchainInstallInfo> installedIarsFromPath()
{
- std::vector<IarInstallInfo> infos;
+ std::vector<ToolchainInstallInfo> infos;
const auto compilerNames = knownIarCompilerNames();
for (const QString &compilerName : compilerNames) {
const QFileInfo iarPath(
@@ -102,14 +162,16 @@ static std::vector<IarInstallInfo> installedIarsFromPath()
HostOsInfo::appendExecutableSuffix(compilerName)));
if (!iarPath.exists())
continue;
- infos.push_back({iarPath.absoluteFilePath(), {}});
+ const Version version = dumpIarCompilerVersion(iarPath);
+ infos.push_back({iarPath, version});
}
+ std::sort(infos.begin(), infos.end());
return infos;
}
-static std::vector<IarInstallInfo> installedIarsFromRegistry()
+static std::vector<ToolchainInstallInfo> installedIarsFromRegistry()
{
- std::vector<IarInstallInfo> infos;
+ std::vector<ToolchainInstallInfo> infos;
if (HostOsInfo::isWindowsHost()) {
@@ -127,6 +189,8 @@ static std::vector<IarInstallInfo> installedIarsFromRegistry()
{QStringLiteral("EWARM"), QStringLiteral("\\arm\\bin\\iccarm.exe")},
{QStringLiteral("EWAVR"), QStringLiteral("\\avr\\bin\\iccavr.exe")},
{QStringLiteral("EW8051"), QStringLiteral("\\8051\\bin\\icc8051.exe")},
+ {QStringLiteral("EWSTM8"), QStringLiteral("\\stm8\\bin\\iccstm8.exe")},
+ {QStringLiteral("EW430"), QStringLiteral("\\430\\bin\\icc430.exe")},
};
QSettings registry(QLatin1String(kRegistryNode), QSettings::NativeFormat);
@@ -148,7 +212,7 @@ static std::vector<IarInstallInfo> installedIarsFromRegistry()
if (iarPath.exists()) {
// Note: threeLevelKey is a guessed toolchain version.
const QString version = threeLevelKey;
- infos.push_back({iarPath.absoluteFilePath(), version});
+ infos.push_back({iarPath, Version::fromString(version)});
}
}
registry.endGroup();
@@ -161,6 +225,7 @@ static std::vector<IarInstallInfo> installedIarsFromRegistry()
}
+ std::sort(infos.begin(), infos.end());
return infos;
}
@@ -175,19 +240,25 @@ bool isIarCompiler(const QString &compilerName)
void createIarProfile(const QFileInfo &compiler, Settings *settings,
QString profileName)
{
- createIarProfileHelper(compiler, settings, profileName);
+ const ToolchainInstallInfo info = {compiler, Version{}};
+ createIarProfileHelper(info, settings, profileName);
}
void iarProbe(Settings *settings, QList<Profile> &profiles)
{
qbsInfo() << Tr::tr("Trying to detect IAR toolchains...");
- std::vector<IarInstallInfo> allInfos = installedIarsFromRegistry();
- const std::vector<IarInstallInfo> pathInfos = installedIarsFromPath();
- allInfos.insert(std::end(allInfos), std::begin(pathInfos), std::end(pathInfos));
+ // Make sure that a returned infos are sorted before using the std::set_union!
+ const std::vector<ToolchainInstallInfo> regInfos = installedIarsFromRegistry();
+ const std::vector<ToolchainInstallInfo> pathInfos = installedIarsFromPath();
+ std::vector<ToolchainInstallInfo> allInfos;
+ allInfos.reserve(regInfos.size() + pathInfos.size());
+ std::set_union(regInfos.cbegin(), regInfos.cend(),
+ pathInfos.cbegin(), pathInfos.cend(),
+ std::back_inserter(allInfos));
- for (const IarInstallInfo &info : allInfos) {
- const auto profile = createIarProfileHelper(info.compilerPath, settings);
+ for (const ToolchainInstallInfo &info : allInfos) {
+ const auto profile = createIarProfileHelper(info, settings);
profiles.push_back(profile);
}