diff options
Diffstat (limited to 'src/app/qbs-setup-toolchains/iarewprobe.cpp')
-rw-r--r-- | src/app/qbs-setup-toolchains/iarewprobe.cpp | 107 |
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); } |