summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Shienkov <denis.shienkov@gmail.com>2020-01-24 18:04:19 +0300
committerDenis Shienkov <denis.shienkov@gmail.com>2020-01-27 12:48:00 +0000
commitde2fc39aa11aba1f94646f055b71bf42ad711f0b (patch)
tree8e8381c4d1e1b490e7100b514d302a77e4d15394
parent5f1fd0caeea9a78a521ecc88d5315f2829da28d8 (diff)
downloadqt-creator-de2fc39aa11aba1f94646f055b71bf42ad711f0b.tar.gz
BareMetal: Fix Keil toolchains detection on Windows
A problem is that a latest installed toolchain overrides a previous installed toolchain. In this case a previous toolchain will be skipped from the search. We need to fetch an information from the 'uninstall' registry entry, which describes all installed toolchains. Change-Id: I662e2696900909607d5ce618a728804e3683c856 Reviewed-by: hjk <hjk@qt.io> Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
-rw-r--r--src/plugins/baremetal/keiltoolchain.cpp99
1 files changed, 70 insertions, 29 deletions
diff --git a/src/plugins/baremetal/keiltoolchain.cpp b/src/plugins/baremetal/keiltoolchain.cpp
index eb6afe8e0e..ce3da730a1 100644
--- a/src/plugins/baremetal/keiltoolchain.cpp
+++ b/src/plugins/baremetal/keiltoolchain.cpp
@@ -401,48 +401,89 @@ KeilToolchainFactory::KeilToolchainFactory()
setUserCreatable(true);
}
+// Parse the 'tools.ini' file to fetch a toolchain version.
+// Note: We can't use QSettings here!
+static QString extractVersion(const QString &toolsFile, const QString &section)
+{
+ QFile f(toolsFile);
+ if (!f.open(QIODevice::ReadOnly))
+ return {};
+ QTextStream in(&f);
+ enum State { Enter, Lookup, Exit } state = Enter;
+ while (!in.atEnd()) {
+ const QString line = in.readLine().trimmed();
+ // Search for section.
+ const int firstBracket = line.indexOf('[');
+ const int lastBracket = line.lastIndexOf(']');
+ const bool hasSection = (firstBracket == 0 && lastBracket != -1
+ && (lastBracket + 1) == line.size());
+ switch (state) {
+ case Enter:
+ if (hasSection) {
+ const auto content = line.midRef(firstBracket + 1,
+ lastBracket - firstBracket - 1);
+ if (content == section)
+ state = Lookup;
+ }
+ break;
+ case Lookup: {
+ if (hasSection)
+ return {}; // Next section found.
+ const int versionIndex = line.indexOf("VERSION=");
+ if (versionIndex < 0)
+ continue;
+ QString version = line.mid(8);
+ if (version.startsWith('V'))
+ version.remove(0, 1);
+ return version;
+ }
+ break;
+ default:
+ return {};
+ }
+ }
+ return {};
+}
+
QList<ToolChain *> KeilToolchainFactory::autoDetect(const QList<ToolChain *> &alreadyKnown)
{
#ifdef Q_OS_WIN64
- static const char kRegistryNode[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Keil\\Products";
+ static const char kRegistryNode[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Microsoft\\" \
+ "Windows\\CurrentVersion\\Uninstall\\Keil µVision4"
#else
- static const char kRegistryNode[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Keil\\Products";
+ static const char kRegistryNode[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\" \
+ "Windows\\CurrentVersion\\Uninstall\\Keil µVision4";
#endif
- struct Entry {
- QString productKey;
- QString subExePath;
- };
-
- // Dictionary for know toolchains.
- static const std::array<Entry, 2> knowToolchains = {{
- {QString("MDK"), QString("\\ARMCC\\bin\\armcc.exe")},
- {QString("C51"), QString("\\BIN\\c51.exe")},
- }};
-
Candidates candidates;
QSettings registry(kRegistryNode, QSettings::NativeFormat);
const auto productGroups = registry.childGroups();
for (const QString &productKey : productGroups) {
- const Entry entry = Utils::findOrDefault(knowToolchains,
- [productKey](const Entry &entry) {
- return entry.productKey == productKey; });
-
- if (entry.productKey.isEmpty())
+ if (!productKey.startsWith("App"))
continue;
-
registry.beginGroup(productKey);
- QString compilerPath = registry.value("Path").toString();
- if (!compilerPath.isEmpty()) {
- // Build full compiler path.
- compilerPath += entry.subExePath;
- const FilePath fn = FilePath::fromString(compilerPath);
- if (compilerExists(fn)) {
- QString version = registry.value("Version").toString();
- if (version.startsWith('V'))
- version.remove(0, 1);
- candidates.push_back({fn, version});
+ const FilePath productPath(FilePath::fromString(registry.value("ProductDir")
+ .toString()));
+ // Fetch the toolchain executable path.
+ FilePath compilerPath;
+ if (productPath.endsWith("ARM"))
+ compilerPath = productPath.pathAppended("\\ARMCC\\bin\\armcc.exe");
+ else if (productPath.endsWith("C51"))
+ compilerPath = productPath.pathAppended("\\BIN\\c51.exe");
+
+ if (compilerPath.exists()) {
+ // Fetch the toolchain version.
+ const QDir rootDir(registry.value("Directory").toString());
+ const QString toolsFilePath = rootDir.absoluteFilePath("tools.ini");
+ for (auto index = 1; index <= 2; ++index) {
+ const QString section = registry.value(
+ QStringLiteral("Section %1").arg(index)).toString();
+ const QString version = extractVersion(toolsFilePath, section);
+ if (!version.isEmpty()) {
+ candidates.push_back({compilerPath, version});
+ break;
+ }
}
}
registry.endGroup();