diff options
author | Denis Shienkov <denis.shienkov@gmail.com> | 2019-07-02 21:35:43 +0300 |
---|---|---|
committer | Denis Shienkov <denis.shienkov@gmail.com> | 2019-07-03 14:03:06 +0000 |
commit | cfcae6d5927e1ffda42a7b367c89e201d61fc872 (patch) | |
tree | 3219f6ef16d11a93d8c090c3dfda5a78dc98d1ba /src/app | |
parent | b445b86dd30bc2a3e12525cdbafc60e24aeb200f (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>
Diffstat (limited to 'src/app')
-rw-r--r-- | src/app/qbs-setup-toolchains/iarewprobe.cpp | 59 | ||||
-rw-r--r-- | src/app/qbs-setup-toolchains/probe.cpp | 15 | ||||
-rw-r--r-- | src/app/qbs-setup-toolchains/probe.h | 6 |
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 ¯oDump, 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 ¯oDump, const QByteArray &keyToken); + #endif // Header guard |