aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDenis Shienkov <denis.shienkov@gmail.com>2019-07-02 21:35:43 +0300
committerDenis Shienkov <denis.shienkov@gmail.com>2019-07-03 14:03:06 +0000
commitcfcae6d5927e1ffda42a7b367c89e201d61fc872 (patch)
tree3219f6ef16d11a93d8c090c3dfda5a78dc98d1ba
parentb445b86dd30bc2a3e12525cdbafc60e24aeb200f (diff)
baremetal: Detect IAREW compiler version if it is found in a path
Previously we have only the IAR toolchain version detection from the Windows registry. This patch adds a compiler version detection in case the compiler path specified in a PATH environment variable. Change-Id: I61578723e15f109542aba1e231753aec611439eb Reviewed-by: Ivan Komissarov <ABBAPOH@gmail.com> Reviewed-by: Qbs CI Bot <travis-bot@weickelt.de> Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
-rw-r--r--src/app/qbs-setup-toolchains/iarewprobe.cpp59
-rw-r--r--src/app/qbs-setup-toolchains/probe.cpp15
-rw-r--r--src/app/qbs-setup-toolchains/probe.h6
3 files changed, 76 insertions, 4 deletions
diff --git a/src/app/qbs-setup-toolchains/iarewprobe.cpp b/src/app/qbs-setup-toolchains/iarewprobe.cpp
index cc55575df..7ac786b98 100644
--- a/src/app/qbs-setup-toolchains/iarewprobe.cpp
+++ b/src/app/qbs-setup-toolchains/iarewprobe.cpp
@@ -47,8 +47,9 @@
#include <tools/hostosinfo.h>
#include <tools/profile.h>
-#include <QtCore/qlist.h>
+#include <QtCore/qprocess.h>
#include <QtCore/qsettings.h>
+#include <QtCore/qstandardpaths.h>
using namespace qbs;
using Internal::Tr;
@@ -101,6 +102,48 @@ static Profile createIarProfileHelper(const ToolchainInstallInfo &info,
return profile;
}
+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")) {
+ return Version{verCode / 100, verCode % 100};
+ }
+
+ return Version{};
+}
+
static std::vector<ToolchainInstallInfo> installedIarsFromPath()
{
std::vector<ToolchainInstallInfo> infos;
@@ -111,8 +154,10 @@ static std::vector<ToolchainInstallInfo> installedIarsFromPath()
HostOsInfo::appendExecutableSuffix(compilerName)));
if (!iarPath.exists())
continue;
- infos.push_back({iarPath, Version{}});
+ const Version version = dumpIarCompilerVersion(iarPath);
+ infos.push_back({iarPath, version});
}
+ std::sort(infos.begin(), infos.end());
return infos;
}
@@ -170,6 +215,7 @@ static std::vector<ToolchainInstallInfo> installedIarsFromRegistry()
}
+ std::sort(infos.begin(), infos.end());
return infos;
}
@@ -192,9 +238,14 @@ void iarProbe(Settings *settings, QList<Profile> &profiles)
{
qbsInfo() << Tr::tr("Trying to detect IAR toolchains...");
- std::vector<ToolchainInstallInfo> allInfos = installedIarsFromRegistry();
+ // 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();
- allInfos.insert(std::end(allInfos), std::begin(pathInfos), std::end(pathInfos));
+ 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 ToolchainInstallInfo &info : allInfos) {
const auto profile = createIarProfileHelper(info, settings);
diff --git a/src/app/qbs-setup-toolchains/probe.cpp b/src/app/qbs-setup-toolchains/probe.cpp
index 3fae20a6e..852c053b2 100644
--- a/src/app/qbs-setup-toolchains/probe.cpp
+++ b/src/app/qbs-setup-toolchains/probe.cpp
@@ -348,3 +348,18 @@ void createProfile(const QString &profileName, const QString &toolchainType,
else
throw qbs::ErrorInfo(Tr::tr("Cannot create profile: Unknown toolchain type."));
}
+
+int extractVersion(const QByteArray &macroDump, const QByteArray &keyToken)
+{
+ const int startIndex = macroDump.indexOf(keyToken);
+ if (startIndex == -1)
+ return -1;
+ const int endIndex = macroDump.indexOf('\n', startIndex);
+ if (endIndex == -1)
+ return -1;
+ const auto keyLength = keyToken.length();
+ const int version = macroDump.mid(startIndex + keyLength,
+ endIndex - startIndex - keyLength)
+ .toInt();
+ return version;
+}
diff --git a/src/app/qbs-setup-toolchains/probe.h b/src/app/qbs-setup-toolchains/probe.h
index dab48a340..5e0ccc33c 100644
--- a/src/app/qbs-setup-toolchains/probe.h
+++ b/src/app/qbs-setup-toolchains/probe.h
@@ -63,4 +63,10 @@ struct ToolchainInstallInfo
qbs::Version compilerVersion;
};
+inline bool operator<(const ToolchainInstallInfo &lhs, const ToolchainInstallInfo &rhs)
+{ return lhs.compilerPath.absoluteFilePath() < rhs.compilerPath.absoluteFilePath()
+ || lhs.compilerVersion < rhs.compilerVersion; }
+
+int extractVersion(const QByteArray &macroDump, const QByteArray &keyToken);
+
#endif // Header guard