aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/app/qbs-setup-toolchains/iarewprobe.cpp95
-rw-r--r--src/app/qbs-setup-toolchains/iarewprobe.h6
-rw-r--r--src/app/qbs-setup-toolchains/keilprobe.cpp40
-rw-r--r--src/app/qbs-setup-toolchains/keilprobe.h6
-rw-r--r--src/app/qbs-setup-toolchains/probe.cpp15
-rw-r--r--src/app/qbs-setup-toolchains/probe.h16
-rw-r--r--src/app/qbs-setup-toolchains/sdccprobe.cpp40
-rw-r--r--src/app/qbs-setup-toolchains/sdccprobe.h6
-rw-r--r--src/lib/corelib/tools/version.cpp12
-rw-r--r--src/lib/corelib/tools/version.h4
10 files changed, 169 insertions, 71 deletions
diff --git a/src/app/qbs-setup-toolchains/iarewprobe.cpp b/src/app/qbs-setup-toolchains/iarewprobe.cpp
index 5d3785759..7ac786b98 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;
@@ -72,14 +72,24 @@ static QString guessIarArchitecture(const QFileInfo &compiler)
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 +102,51 @@ 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")) {
+ 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 +154,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()) {
@@ -148,7 +202,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 +215,7 @@ static std::vector<IarInstallInfo> installedIarsFromRegistry()
}
+ std::sort(infos.begin(), infos.end());
return infos;
}
@@ -175,19 +230,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);
}
diff --git a/src/app/qbs-setup-toolchains/iarewprobe.h b/src/app/qbs-setup-toolchains/iarewprobe.h
index f5caf61ed..b21049314 100644
--- a/src/app/qbs-setup-toolchains/iarewprobe.h
+++ b/src/app/qbs-setup-toolchains/iarewprobe.h
@@ -51,12 +51,6 @@ class Profile;
class Settings;
}
-struct IarInstallInfo
-{
- QString compilerPath;
- QString version;
-};
-
bool isIarCompiler(const QString &compilerName);
void createIarProfile(const QFileInfo &compiler, qbs::Settings *settings,
diff --git a/src/app/qbs-setup-toolchains/keilprobe.cpp b/src/app/qbs-setup-toolchains/keilprobe.cpp
index dc327d2ee..51657e520 100644
--- a/src/app/qbs-setup-toolchains/keilprobe.cpp
+++ b/src/app/qbs-setup-toolchains/keilprobe.cpp
@@ -47,7 +47,6 @@
#include <tools/hostosinfo.h>
#include <tools/profile.h>
-#include <QtCore/qfileinfo.h>
#include <QtCore/qlist.h>
#include <QtCore/qsettings.h>
@@ -70,14 +69,24 @@ static QString guessKeilArchitecture(const QFileInfo &compiler)
return {};
}
-static Profile createKeilProfileHelper(const QFileInfo &compiler, Settings *settings,
+static Profile createKeilProfileHelper(const ToolchainInstallInfo &info,
+ Settings *settings,
QString profileName = QString())
{
+ const QFileInfo compiler = info.compilerPath;
const QString architecture = guessKeilArchitecture(compiler);
// In case the profile is auto-detected.
- if (profileName.isEmpty())
- profileName = QLatin1String("keil-") + architecture;
+ if (profileName.isEmpty()) {
+ if (!info.compilerVersion.isValid()) {
+ profileName = QStringLiteral("keil-unknown-%1").arg(architecture);
+ } else {
+ const QString version = info.compilerVersion.toString(QLatin1Char('_'),
+ QLatin1Char('_'));
+ profileName = QStringLiteral("keil-%1-%2").arg(
+ version, architecture);
+ }
+ }
Profile profile(profileName, settings);
profile.setValue(QStringLiteral("cpp.toolchainInstallPath"), compiler.absolutePath());
@@ -90,9 +99,9 @@ static Profile createKeilProfileHelper(const QFileInfo &compiler, Settings *sett
return profile;
}
-static std::vector<KeilInstallInfo> installedKeilsFromPath()
+static std::vector<ToolchainInstallInfo> installedKeilsFromPath()
{
- std::vector<KeilInstallInfo> infos;
+ std::vector<ToolchainInstallInfo> infos;
const auto compilerNames = knownKeilCompilerNames();
for (const QString &compilerName : compilerNames) {
const QFileInfo keilPath(
@@ -100,14 +109,14 @@ static std::vector<KeilInstallInfo> installedKeilsFromPath()
HostOsInfo::appendExecutableSuffix(compilerName)));
if (!keilPath.exists())
continue;
- infos.push_back({keilPath.absoluteFilePath(), {}});
+ infos.push_back({keilPath, Version{}});
}
return infos;
}
-static std::vector<KeilInstallInfo> installedKeilsFromRegistry()
+static std::vector<ToolchainInstallInfo> installedKeilsFromRegistry()
{
- std::vector<KeilInstallInfo> infos;
+ std::vector<ToolchainInstallInfo> infos;
if (HostOsInfo::isWindowsHost()) {
@@ -148,7 +157,7 @@ static std::vector<KeilInstallInfo> installedKeilsFromRegistry()
.toString();
if (version.startsWith(QLatin1Char('V')))
version.remove(0, 1);
- infos.push_back({keilPath.absoluteFilePath(), version});
+ infos.push_back({keilPath, Version::fromString(version)});
}
}
registry.endGroup();
@@ -170,19 +179,20 @@ bool isKeilCompiler(const QString &compilerName)
void createKeilProfile(const QFileInfo &compiler, Settings *settings,
QString profileName)
{
- createKeilProfileHelper(compiler, settings, profileName);
+ const ToolchainInstallInfo info = {compiler, Version{}};
+ createKeilProfileHelper(info, settings, profileName);
}
void keilProbe(Settings *settings, QList<Profile> &profiles)
{
qbsInfo() << Tr::tr("Trying to detect KEIL toolchains...");
- std::vector<KeilInstallInfo> allInfos = installedKeilsFromRegistry();
- const std::vector<KeilInstallInfo> pathInfos = installedKeilsFromPath();
+ std::vector<ToolchainInstallInfo> allInfos = installedKeilsFromRegistry();
+ const std::vector<ToolchainInstallInfo> pathInfos = installedKeilsFromPath();
allInfos.insert(std::end(allInfos), std::begin(pathInfos), std::end(pathInfos));
- for (const KeilInstallInfo &info : allInfos) {
- const auto profile = createKeilProfileHelper(info.compilerPath, settings);
+ for (const ToolchainInstallInfo &info : allInfos) {
+ const auto profile = createKeilProfileHelper(info, settings);
profiles.push_back(profile);
}
diff --git a/src/app/qbs-setup-toolchains/keilprobe.h b/src/app/qbs-setup-toolchains/keilprobe.h
index 6a897b84b..321909bda 100644
--- a/src/app/qbs-setup-toolchains/keilprobe.h
+++ b/src/app/qbs-setup-toolchains/keilprobe.h
@@ -51,12 +51,6 @@ class Profile;
class Settings;
}
-struct KeilInstallInfo
-{
- QString compilerPath;
- QString version;
-};
-
bool isKeilCompiler(const QString &compilerName);
void createKeilProfile(const QFileInfo &compiler, qbs::Settings *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 510747ef7..5e0ccc33c 100644
--- a/src/app/qbs-setup-toolchains/probe.h
+++ b/src/app/qbs-setup-toolchains/probe.h
@@ -39,7 +39,9 @@
#ifndef QBS_PROBE_H
#define QBS_PROBE_H
-#include <QtCore/qglobal.h>
+#include <tools/version.h>
+
+#include <QtCore/qfileinfo.h>
QT_BEGIN_NAMESPACE
class QString;
@@ -55,4 +57,16 @@ void createProfile(const QString &profileName, const QString &toolchainType,
void probe(qbs::Settings *settings);
+struct ToolchainInstallInfo
+{
+ QFileInfo compilerPath;
+ 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
diff --git a/src/app/qbs-setup-toolchains/sdccprobe.cpp b/src/app/qbs-setup-toolchains/sdccprobe.cpp
index 751e872ee..41bd45e2a 100644
--- a/src/app/qbs-setup-toolchains/sdccprobe.cpp
+++ b/src/app/qbs-setup-toolchains/sdccprobe.cpp
@@ -47,7 +47,6 @@
#include <tools/hostosinfo.h>
#include <tools/profile.h>
-#include <QtCore/qfileinfo.h>
#include <QtCore/qlist.h>
#include <QtCore/qsettings.h>
@@ -68,14 +67,24 @@ static QString guessSdccArchitecture(const QFileInfo &compiler)
return {};
}
-static Profile createSdccProfileHelper(const QFileInfo &compiler, Settings *settings,
+static Profile createSdccProfileHelper(const ToolchainInstallInfo &info,
+ Settings *settings,
QString profileName = QString())
{
+ const QFileInfo compiler = info.compilerPath;
const QString architecture = guessSdccArchitecture(compiler);
// In case the profile is auto-detected.
- if (profileName.isEmpty())
- profileName = QLatin1String("sdcc-") + architecture;
+ if (profileName.isEmpty()) {
+ if (!info.compilerVersion.isValid()) {
+ profileName = QStringLiteral("sdcc-unknown-%1").arg(architecture);
+ } else {
+ const QString version = info.compilerVersion.toString(QLatin1Char('_'),
+ QLatin1Char('_'));
+ profileName = QStringLiteral("sdcc-%1-%2").arg(
+ version, architecture);
+ }
+ }
Profile profile(profileName, settings);
profile.setValue(QStringLiteral("cpp.toolchainInstallPath"), compiler.absolutePath());
@@ -88,9 +97,9 @@ static Profile createSdccProfileHelper(const QFileInfo &compiler, Settings *sett
return profile;
}
-static std::vector<SdccInstallInfo> installedSdccsFromPath()
+static std::vector<ToolchainInstallInfo> installedSdccsFromPath()
{
- std::vector<SdccInstallInfo> infos;
+ std::vector<ToolchainInstallInfo> infos;
const auto compilerNames = knownSdccCompilerNames();
for (const QString &compilerName : compilerNames) {
const QFileInfo sdccPath(
@@ -98,14 +107,14 @@ static std::vector<SdccInstallInfo> installedSdccsFromPath()
HostOsInfo::appendExecutableSuffix(compilerName)));
if (!sdccPath.exists())
continue;
- infos.push_back({sdccPath.absoluteFilePath(), {}});
+ infos.push_back({sdccPath, Version{}});
}
return infos;
}
-static std::vector<SdccInstallInfo> installedSdccsFromRegistry()
+static std::vector<ToolchainInstallInfo> installedSdccsFromRegistry()
{
- std::vector<SdccInstallInfo> infos;
+ std::vector<ToolchainInstallInfo> infos;
if (HostOsInfo::isWindowsHost()) {
@@ -126,7 +135,7 @@ static std::vector<SdccInstallInfo> installedSdccsFromRegistry()
registry.value(QStringLiteral("VersionMajor")).toString(),
registry.value(QStringLiteral("VersionMinor")).toString(),
registry.value(QStringLiteral("VersionRevision")).toString());
- infos.push_back({sdccPath.absoluteFilePath(), version});
+ infos.push_back({sdccPath, Version::fromString(version)});
}
}
}
@@ -145,19 +154,20 @@ bool isSdccCompiler(const QString &compilerName)
void createSdccProfile(const QFileInfo &compiler, Settings *settings,
QString profileName)
{
- createSdccProfileHelper(compiler, settings, profileName);
+ const ToolchainInstallInfo info = {compiler, Version{}};
+ createSdccProfileHelper(info, settings, profileName);
}
void sdccProbe(Settings *settings, QList<Profile> &profiles)
{
qbsInfo() << Tr::tr("Trying to detect SDCC toolchains...");
- std::vector<SdccInstallInfo> allInfos = installedSdccsFromRegistry();
- const std::vector<SdccInstallInfo> pathInfos = installedSdccsFromPath();
+ std::vector<ToolchainInstallInfo> allInfos = installedSdccsFromRegistry();
+ const std::vector<ToolchainInstallInfo> pathInfos = installedSdccsFromPath();
allInfos.insert(std::end(allInfos), std::begin(pathInfos), std::end(pathInfos));
- for (const SdccInstallInfo &info : allInfos) {
- const auto profile = createSdccProfileHelper(info.compilerPath, settings);
+ for (const ToolchainInstallInfo &info : allInfos) {
+ const auto profile = createSdccProfileHelper(info, settings);
profiles.push_back(profile);
}
diff --git a/src/app/qbs-setup-toolchains/sdccprobe.h b/src/app/qbs-setup-toolchains/sdccprobe.h
index 7f4219b5a..4fe5ca407 100644
--- a/src/app/qbs-setup-toolchains/sdccprobe.h
+++ b/src/app/qbs-setup-toolchains/sdccprobe.h
@@ -51,12 +51,6 @@ class Profile;
class Settings;
}
-struct SdccInstallInfo
-{
- QString compilerPath;
- QString version;
-};
-
bool isSdccCompiler(const QString &compilerName);
void createSdccProfile(const QFileInfo &compiler, qbs::Settings *settings,
diff --git a/src/lib/corelib/tools/version.cpp b/src/lib/corelib/tools/version.cpp
index d2b337d3a..dfb7f49b7 100644
--- a/src/lib/corelib/tools/version.cpp
+++ b/src/lib/corelib/tools/version.cpp
@@ -105,13 +105,17 @@ Version Version::fromString(const QString &versionString, bool buildNumberAllowe
return Version{majorNr, minorNr, patchNr, buildNr};
}
-QString Version::toString() const
+QString Version::toString(const QChar &separator, const QChar &buildSeparator) const
{
if (m_build) {
- return QString(QStringLiteral("%1.%2.%3-%4"))
- .arg(m_major).arg(m_minor).arg(m_patch).arg(m_build);
+ return QStringLiteral("%1%5%2%5%3%6%4")
+ .arg(QString::number(m_major), QString::number(m_minor),
+ QString::number(m_patch), QString::number(m_build),
+ separator, buildSeparator);
}
- return QString(QStringLiteral("%1.%2.%3")).arg(m_major).arg(m_minor).arg(m_patch);
+ return QStringLiteral("%1%4%2%4%3")
+ .arg(QString::number(m_major), QString::number(m_minor),
+ QString::number(m_patch), separator);
}
int compare(const Version &lhs, const Version &rhs)
diff --git a/src/lib/corelib/tools/version.h b/src/lib/corelib/tools/version.h
index 4f5e46500..a0239a6e4 100644
--- a/src/lib/corelib/tools/version.h
+++ b/src/lib/corelib/tools/version.h
@@ -42,6 +42,7 @@
#include "qbs_export.h"
+#include <QtCore/qchar.h>
#include <QtCore/qglobal.h>
QT_BEGIN_NAMESPACE
@@ -71,7 +72,8 @@ public:
void setBuildNumber(int nr);
static Version fromString(const QString &versionString, bool buildNumberAllowed = false);
- QString toString() const;
+ QString toString(const QChar &separator = QLatin1Char('.'),
+ const QChar &buildSeparator = QLatin1Char('-')) const;
private:
int m_major;