diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/app/qbs-setup-toolchains/iarewprobe.cpp | 95 | ||||
-rw-r--r-- | src/app/qbs-setup-toolchains/iarewprobe.h | 6 | ||||
-rw-r--r-- | src/app/qbs-setup-toolchains/keilprobe.cpp | 40 | ||||
-rw-r--r-- | src/app/qbs-setup-toolchains/keilprobe.h | 6 | ||||
-rw-r--r-- | src/app/qbs-setup-toolchains/probe.cpp | 15 | ||||
-rw-r--r-- | src/app/qbs-setup-toolchains/probe.h | 16 | ||||
-rw-r--r-- | src/app/qbs-setup-toolchains/sdccprobe.cpp | 40 | ||||
-rw-r--r-- | src/app/qbs-setup-toolchains/sdccprobe.h | 6 | ||||
-rw-r--r-- | src/lib/corelib/tools/version.cpp | 12 | ||||
-rw-r--r-- | src/lib/corelib/tools/version.h | 4 |
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 ¯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 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 ¯oDump, 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; |