From d33e66c895a7eb682abb936e14db9cc2583c8ae1 Mon Sep 17 00:00:00 2001
From: David Schulz <david.schulz@digia.com>
Date: Tue, 8 Apr 2014 13:31:57 +0200
Subject: [PATCH] ProjectExplorer: Detect all msvc toolchains.

The host system will not be taken into account, so the cross build
toolchains are also detected.

Task-number: QTCREATORBUG-10998
Change-Id: I04a410bbf368898b70d9560d2c2a4a6c60ed0b61
Reviewed-by: Daniel Teske <daniel.teske@digia.com>
---
 src/plugins/projectexplorer/msvctoolchain.cpp | 118 +++++++++---------
 src/plugins/projectexplorer/msvctoolchain.h   |   7 +-
 .../projectexplorer/toolchainmanager.cpp      |   2 +-
 src/plugins/qtsupport/qtoptionspage.cpp       |  18 ++-
 4 files changed, 75 insertions(+), 70 deletions(-)

diff --git a/src/plugins/projectexplorer/msvctoolchain.cpp b/src/plugins/projectexplorer/msvctoolchain.cpp
index 80613b7d1f0..265532887a8 100644
--- a/src/plugins/projectexplorer/msvctoolchain.cpp
+++ b/src/plugins/projectexplorer/msvctoolchain.cpp
@@ -63,17 +63,44 @@ static QString platformName(MsvcToolChain::Platform t)
 {
     switch (t) {
     case MsvcToolChain::x86:
-        return QLatin1String(" (x86)");
+        return QLatin1String("x86");
     case MsvcToolChain::amd64:
-        return QLatin1String(" (amd64)");
+        return QLatin1String("amd64");
+    case MsvcToolChain::x86_amd64:
+        return QLatin1String("x86_amd64");
     case MsvcToolChain::ia64:
-        return QLatin1String(" (ia64)");
+        return QLatin1String("ia64");
+    case MsvcToolChain::x86_ia64:
+        return QLatin1String("x86_ia64");
     case MsvcToolChain::arm:
-        return QLatin1String(" (arm)");
+        return QLatin1String("arm");
+    case MsvcToolChain::x86_arm:
+        return QLatin1String("x86_arm");
+    case MsvcToolChain::amd64_arm:
+        return QLatin1String("amd64_arm");
     }
     return QString();
 }
 
+static bool hostSupportsPlatform(MsvcToolChain::Platform platform)
+{
+    switch (Utils::HostOsInfo::hostArchitecture()) {
+    case Utils::HostOsInfo::HostArchitectureAMD64:
+        if (platform == MsvcToolChain::amd64 || platform == MsvcToolChain::amd64_arm)
+            return true;
+        // fall through (all x86 toolchains are also working on an amd64 host)
+    case Utils::HostOsInfo::HostArchitectureX86:
+        return platform == MsvcToolChain::x86 || platform == MsvcToolChain::x86_amd64
+                || platform == MsvcToolChain::x86_ia64 || platform == MsvcToolChain::x86_arm;
+    case Utils::HostOsInfo::HostArchitectureArm:
+        return platform == MsvcToolChain::arm;
+    case Utils::HostOsInfo::HostArchitectureItanium:
+        return platform == MsvcToolChain::ia64;
+    default:
+        return false;
+    }
+}
+
 static Abi findAbiOfMsvc(MsvcToolChain::Type type, MsvcToolChain::Platform platform, const QString &version)
 {
     Abi::Architecture arch = Abi::X86Architecture;
@@ -86,11 +113,15 @@ static Abi findAbiOfMsvc(MsvcToolChain::Type type, MsvcToolChain::Platform platf
         wordWidth = 32;
         break;
     case ProjectExplorer::Internal::MsvcToolChain::ia64:
+    case ProjectExplorer::Internal::MsvcToolChain::x86_ia64:
         arch = Abi::ItaniumArchitecture;
         break;
     case ProjectExplorer::Internal::MsvcToolChain::amd64:
+    case ProjectExplorer::Internal::MsvcToolChain::x86_amd64:
         break;
     case ProjectExplorer::Internal::MsvcToolChain::arm:
+    case ProjectExplorer::Internal::MsvcToolChain::x86_arm:
+    case ProjectExplorer::Internal::MsvcToolChain::amd64_arm:
         arch = Abi::ArmArchitecture;
         wordWidth = 32;
         break;
@@ -126,13 +157,13 @@ static QString generateDisplayName(const QString &name,
 {
     if (t == MsvcToolChain::WindowsSDK) {
         QString sdkName = name;
-        sdkName += platformName(p);
+        sdkName += QString::fromLatin1(" (%1)").arg(platformName(p));
         return sdkName;
     }
     // Comes as "9.0" from the registry
     QString vcName = QLatin1String("Microsoft Visual C++ Compiler ");
     vcName += name;
-    vcName += platformName(p);
+    vcName += QString::fromLatin1(" (%1)").arg(platformName(p));
     return vcName;
 }
 
@@ -482,6 +513,11 @@ QString MsvcToolChainFactory::vcVarsBatFor(const QString &basePath, const QStrin
     return QString();
 }
 
+QString MsvcToolChainFactory::vcVarsBatFor(const QString &basePath, MsvcToolChain::Platform platform)
+{
+    return vcVarsBatFor(basePath, platformName(platform));
+}
+
 QList<ToolChain *> MsvcToolChainFactory::autoDetect()
 {
     QList<ToolChain *> results;
@@ -545,64 +581,22 @@ QList<ToolChain *> MsvcToolChainFactory::autoDetect()
         const int version = vsName.left(dotPos).toInt();
         const QString vcvarsAllbat = path + QLatin1String("/vcvarsall.bat");
         if (QFileInfo(vcvarsAllbat).isFile()) {
-            Utils::HostOsInfo::HostArchitecture arch = Utils::HostOsInfo::hostArchitecture();
-            if (QFileInfo(vcVarsBatFor(path, QLatin1String("x86"))).isFile())
-                results.append(new MsvcToolChain(generateDisplayName(vsName, MsvcToolChain::VS, MsvcToolChain::x86),
-                                                 findAbiOfMsvc(MsvcToolChain::VS, MsvcToolChain::x86, vsName),
-                                                 vcvarsAllbat, QLatin1String("x86"), ToolChain::AutoDetection));
-
-            if (arch == Utils::HostOsInfo::HostArchitectureX86) {
-                if (QFileInfo(vcVarsBatFor(path, QLatin1String("x86_amd64"))).isFile())
-                    results.append(new MsvcToolChain(generateDisplayName(vsName, MsvcToolChain::VS, MsvcToolChain::amd64),
-                                                     findAbiOfMsvc(MsvcToolChain::VS, MsvcToolChain::amd64, vsName),
-                                                     vcvarsAllbat, QLatin1String("x86_amd64"), ToolChain::AutoDetection));
-            } else if (arch == Utils::HostOsInfo::HostArchitectureAMD64) {
-                if (QFileInfo(vcVarsBatFor(path, QLatin1String("amd64"))).isFile()) {
-                    results.append(new MsvcToolChain(generateDisplayName(vsName, MsvcToolChain::VS, MsvcToolChain::amd64),
-                                                     findAbiOfMsvc(MsvcToolChain::VS, MsvcToolChain::amd64, vsName),
-                                                     vcvarsAllbat, QLatin1String("amd64"), ToolChain::AutoDetection));
-                } else if (QFileInfo(vcVarsBatFor(path, QLatin1String("x86_amd64"))).isFile()) {
-                    // Fall back to 32 bit to 4 bit
-                    results.append(new MsvcToolChain(generateDisplayName(vsName, MsvcToolChain::VS, MsvcToolChain::amd64),
-                                                     findAbiOfMsvc(MsvcToolChain::VS, MsvcToolChain::amd64, vsName),
-                                                     vcvarsAllbat, QLatin1String("x86_amd64"), ToolChain::AutoDetection));
+            QList<MsvcToolChain::Platform> platforms; // prioritized list
+            platforms << MsvcToolChain::x86
+                      << MsvcToolChain::amd64 << MsvcToolChain::x86_amd64
+                      << MsvcToolChain::arm << MsvcToolChain::amd64_arm << MsvcToolChain::x86_arm
+                      << MsvcToolChain::ia64 << MsvcToolChain::x86_ia64;
+            foreach (const MsvcToolChain::Platform &platform, platforms) {
+                if (hostSupportsPlatform(platform)
+                        && QFileInfo(vcVarsBatFor(path, platform)).isFile()) {
+                    results.append(new MsvcToolChain(
+                                       generateDisplayName(vsName, MsvcToolChain::VS, platform),
+                                       findAbiOfMsvc(MsvcToolChain::VS, platform, vsName),
+                                       vcvarsAllbat,
+                                       platformName(platform),
+                                       ToolChain::AutoDetection));
                 }
             }
-
-            if (arch == Utils::HostOsInfo::HostArchitectureX86) {
-                if (QFileInfo(vcVarsBatFor(path, QLatin1String("x86_arm"))).isFile())
-                    results.append(new MsvcToolChain(generateDisplayName(vsName, MsvcToolChain::VS, MsvcToolChain::arm),
-                                                     findAbiOfMsvc(MsvcToolChain::VS, MsvcToolChain::arm, vsName),
-                                                     vcvarsAllbat, QLatin1String("x86_arm"), ToolChain::AutoDetection));
-            } else if (arch == Utils::HostOsInfo::HostArchitectureAMD64) {
-                if (QFileInfo(vcVarsBatFor(path, QLatin1String("amd64_arm"))).isFile()) {
-                    results.append(new MsvcToolChain(generateDisplayName(vsName, MsvcToolChain::VS, MsvcToolChain::arm),
-                                                     findAbiOfMsvc(MsvcToolChain::VS, MsvcToolChain::arm, vsName),
-                                                     vcvarsAllbat, QLatin1String("amd64_arm"), ToolChain::AutoDetection));
-                } else if (QFileInfo(vcVarsBatFor(path, QLatin1String("x86_arm"))).isFile()) {
-                    results.append(new MsvcToolChain(generateDisplayName(vsName, MsvcToolChain::VS, MsvcToolChain::arm),
-                                                     findAbiOfMsvc(MsvcToolChain::VS, MsvcToolChain::arm, vsName),
-                                                     vcvarsAllbat, QLatin1String("x86_arm"), ToolChain::AutoDetection));
-                }
-            } else if (arch == Utils::HostOsInfo::HostArchitectureArm) {
-                if (QFileInfo(vcVarsBatFor(path, QLatin1String("arm"))).isFile())
-                    results.append(new MsvcToolChain(generateDisplayName(vsName, MsvcToolChain::VS, MsvcToolChain::arm),
-                                                     findAbiOfMsvc(MsvcToolChain::VS, MsvcToolChain::arm, vsName),
-                                                     vcvarsAllbat, QLatin1String("arm"), ToolChain::AutoDetection));
-            }
-
-            if (arch == Utils::HostOsInfo::HostArchitectureItanium) {
-                if (QFileInfo(vcVarsBatFor(path, QLatin1String("ia64"))).isFile())
-                    results.append(new MsvcToolChain(generateDisplayName(vsName, MsvcToolChain::VS, MsvcToolChain::ia64),
-                                                     findAbiOfMsvc(MsvcToolChain::VS, MsvcToolChain::ia64, vsName),
-                                                     vcvarsAllbat, QLatin1String("ia64"), ToolChain::AutoDetection));
-            } else if (arch == Utils::HostOsInfo::HostArchitectureX86
-                       || arch == Utils::HostOsInfo::HostArchitectureAMD64) {
-                if (QFileInfo(vcVarsBatFor(path, QLatin1String("x86_ia64"))).isFile())
-                    results.append(new MsvcToolChain(generateDisplayName(vsName, MsvcToolChain::VS, MsvcToolChain::ia64),
-                                                     findAbiOfMsvc(MsvcToolChain::VS, MsvcToolChain::ia64, vsName),
-                                                     vcvarsAllbat, QLatin1String("x86_ia64"), ToolChain::AutoDetection));
-            }
         } else {
             qWarning("Unable to find MSVC setup script %s in version %d", qPrintable(vcvarsAllbat), version);
         }
diff --git a/src/plugins/projectexplorer/msvctoolchain.h b/src/plugins/projectexplorer/msvctoolchain.h
index f65b2c806d4..8a642aceee9 100644
--- a/src/plugins/projectexplorer/msvctoolchain.h
+++ b/src/plugins/projectexplorer/msvctoolchain.h
@@ -49,8 +49,12 @@ public:
     enum Type { WindowsSDK, VS };
     enum Platform { x86,
                     amd64,
+                    x86_amd64,
                     ia64,
-                    arm
+                    x86_ia64,
+                    arm,
+                    x86_arm,
+                    amd64_arm
                   };
 
     MsvcToolChain(const QString &name, const Abi &abi,
@@ -104,6 +108,7 @@ public:
 
     ToolChainConfigWidget *configurationWidget(ToolChain *);
     static QString vcVarsBatFor(const QString &basePath, const QString &toolchainName);
+    static QString vcVarsBatFor(const QString &basePath, MsvcToolChain::Platform platform);
 private:
     static bool checkForVisualStudioInstallation(const QString &vsName);
 };
diff --git a/src/plugins/projectexplorer/toolchainmanager.cpp b/src/plugins/projectexplorer/toolchainmanager.cpp
index 461ae042689..aeb04af22cf 100644
--- a/src/plugins/projectexplorer/toolchainmanager.cpp
+++ b/src/plugins/projectexplorer/toolchainmanager.cpp
@@ -77,7 +77,7 @@ public:
     QMap<QString, FileName> m_abiToDebugger;
     PersistentSettingsWriter *m_writer;
 
-    QList<ToolChain *> m_toolChains;
+    QList<ToolChain *> m_toolChains; // prioritized List
 };
 
 ToolChainManagerPrivate::~ToolChainManagerPrivate()
diff --git a/src/plugins/qtsupport/qtoptionspage.cpp b/src/plugins/qtsupport/qtoptionspage.cpp
index 6c6477469cb..935f405cfb8 100644
--- a/src/plugins/qtsupport/qtoptionspage.cpp
+++ b/src/plugins/qtsupport/qtoptionspage.cpp
@@ -386,15 +386,21 @@ QtOptionsPageWidget::ValidityInfo QtOptionsPageWidget::validInformation(const Ba
 
 QList<ToolChain*> QtOptionsPageWidget::toolChains(const BaseQtVersion *version)
 {
-    QHash<QString,ToolChain*> toolChains;
+    QList<ToolChain*> toolChains;
     if (!version)
-        return toolChains.values();
+        return toolChains;
 
-    foreach (const Abi &a, version->qtAbis())
-        foreach (ToolChain *tc, ToolChainManager::findToolChains(a))
-            toolChains.insert(tc->id(), tc);
+    QSet<QString> ids;
+    foreach (const Abi &a, version->qtAbis()) {
+        foreach (ToolChain *tc, ToolChainManager::findToolChains(a)) {
+            if (ids.contains(tc->id()))
+                continue;
+            ids.insert(tc->id());
+            toolChains.append(tc);
+        }
+    }
 
-    return toolChains.values();
+    return toolChains;
 }
 
 QString QtOptionsPageWidget::defaultToolChainId(const BaseQtVersion *version)
-- 
GitLab