From cfc7040ede907a7b05c0ed3cc717b2d2d1277de7 Mon Sep 17 00:00:00 2001
From: dt <qtc-committer@nokia.com>
Date: Thu, 22 Oct 2009 14:22:16 +0200
Subject: [PATCH] The qtversions's toolchain now depends on the actual compiler
 not mkspec

That is we actually parse the mkspec and evaluate QMAKE_CXX (and a few
other variables) to figure out the correct mkspec. This makes using
custom mkspecs easier and is also cleaner. I also changed mkspec() and
mkspecPath() to behave a little diffrent, essentialy mkspec() will
return only the name (the actual dir name) of the mkspec. That is in
general not sufficient for passing on to qmake. mkspecPath() only
returns the correct path to mkspecs/default.
Hopefully I haven't broken WinCE/Maemo/MinGW.
---
 .../cmakeprojectmanager/cmakeproject.cpp      |   2 +-
 src/plugins/debugger/debuggermanager.cpp      |   4 +-
 .../genericprojectmanager/genericproject.cpp  |   2 +-
 src/plugins/projectexplorer/cesdkhandler.cpp  |  47 ----
 src/plugins/projectexplorer/toolchain.cpp     |   4 +-
 src/plugins/projectexplorer/toolchain.h       |   2 +-
 .../qt4projectmanager/projectloadwizard.cpp   |  19 +-
 src/plugins/qt4projectmanager/qmakestep.cpp   |   4 -
 src/plugins/qt4projectmanager/qt4project.cpp  |  76 +-----
 src/plugins/qt4projectmanager/qt4project.h    |   4 +-
 .../qt4projectconfigwidget.cpp                |  11 -
 .../qt4projectmanager/qtversionmanager.cpp    | 245 ++++++++----------
 .../qt4projectmanager/qtversionmanager.h      |  25 +-
 13 files changed, 139 insertions(+), 306 deletions(-)

diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp
index acf75f5c61d..3fc55c3bad1 100644
--- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp
@@ -394,7 +394,7 @@ QString CMakeProject::buildParser(BuildConfiguration *configuration) const
     if (!m_toolChain)
         return QString::null;
     if (m_toolChain->type() == ProjectExplorer::ToolChain::GCC
-        || m_toolChain->type() == ProjectExplorer::ToolChain::LinuxICC
+        //|| m_toolChain->type() == ProjectExplorer::ToolChain::LinuxICC
         || m_toolChain->type() == ProjectExplorer::ToolChain::MinGW) {
         return ProjectExplorer::Constants::BUILD_PARSER_GCC;
     } else if (m_toolChain->type() == ProjectExplorer::ToolChain::MSVC
diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp
index c6d00f0112e..f4b4ed0385d 100644
--- a/src/plugins/debugger/debuggermanager.cpp
+++ b/src/plugins/debugger/debuggermanager.cpp
@@ -844,7 +844,7 @@ static IDebuggerEngine *debuggerEngineForToolChain(ProjectExplorer::ToolChain::T
 {
     IDebuggerEngine *rc = 0;
     switch (tc) {
-    case ProjectExplorer::ToolChain::LinuxICC:
+    //case ProjectExplorer::ToolChain::LinuxICC:
     case ProjectExplorer::ToolChain::MinGW:
     case ProjectExplorer::ToolChain::GCC:
         rc = gdbEngine;
@@ -1713,7 +1713,7 @@ bool DebuggerManager::checkDebugConfiguration(int toolChain,
     bool success = true;
     switch(toolChain) {
     case ProjectExplorer::ToolChain::GCC:
-    case ProjectExplorer::ToolChain::LinuxICC:
+    //case ProjectExplorer::ToolChain::LinuxICC:
     case ProjectExplorer::ToolChain::MinGW:
     case ProjectExplorer::ToolChain::WINCE: // S60
     case ProjectExplorer::ToolChain::WINSCW:
diff --git a/src/plugins/genericprojectmanager/genericproject.cpp b/src/plugins/genericprojectmanager/genericproject.cpp
index bc7c96138b1..d6d9d0a8c10 100644
--- a/src/plugins/genericprojectmanager/genericproject.cpp
+++ b/src/plugins/genericprojectmanager/genericproject.cpp
@@ -413,7 +413,7 @@ QString GenericProject::buildParser(BuildConfiguration *configuration) const
     if (m_toolChain) {
         switch (m_toolChain->type()) {
         case ProjectExplorer::ToolChain::GCC:
-        case ProjectExplorer::ToolChain::LinuxICC:
+        //case ProjectExplorer::ToolChain::LinuxICC:
         case ProjectExplorer::ToolChain::MinGW:
             return QLatin1String(ProjectExplorer::Constants::BUILD_PARSER_GCC);
 
diff --git a/src/plugins/projectexplorer/cesdkhandler.cpp b/src/plugins/projectexplorer/cesdkhandler.cpp
index 96c2b12df8d..d0ca7202d99 100644
--- a/src/plugins/projectexplorer/cesdkhandler.cpp
+++ b/src/plugins/projectexplorer/cesdkhandler.cpp
@@ -56,53 +56,6 @@ CeSdkHandler::CeSdkHandler()
 {
 }
 
-static void readMkSpec(const QString &qtpath, QString *ceSdk, QString *ceArch)
-{
-    QFile f(qtpath);
-    if (f.exists() && f.open(QIODevice::ReadOnly)) {
-        while (!f.atEnd()) {
-            QByteArray line = f.readLine();
-            if (line.startsWith("CE_SDK")) {
-                int index = line.indexOf('=');
-                if (index >= 0) {
-                    *ceSdk = line.mid(index + 1).trimmed();
-                }
-            } else if (line.startsWith("CE_ARCH")) {
-                int index = line.indexOf('=');
-                if (index >= 0) {
-                    *ceArch = line.mid(index + 1).trimmed();
-                }
-            } else if (line.startsWith("include(")) {
-                int startIndex = line.indexOf('(');
-                int endIndex = line.indexOf(')');
-                if (startIndex >= 0 && endIndex >= 0) {
-                    QString path = line.mid(startIndex + 1, endIndex - startIndex - 1).trimmed();
-
-                    int index = qtpath.lastIndexOf('/');
-                    if (index >= 0)
-                        readMkSpec(qtpath.left(index + 1) + path, ceSdk, ceArch);
-                    else
-                        readMkSpec(path, ceSdk, ceArch);
-                }
-            }
-        }
-    }
-}
-
-QString CeSdkHandler::platformName(const QString &qtpath)
-{
-    QString platformName;
-    QString CE_SDK;
-    QString CE_ARCH;
-
-    readMkSpec(qtpath, &CE_SDK, &CE_ARCH);
-
-    if (!CE_SDK.isEmpty() && !CE_ARCH.isEmpty())
-        platformName = CE_SDK + " (" + CE_ARCH + ")";
-
-    return platformName;
-}
-
 bool CeSdkHandler::parse(const QString &vsdir)
 {
     // look at the file at %VCInstallDir%/vcpackages/WCE.VCPlatform.config
diff --git a/src/plugins/projectexplorer/toolchain.cpp b/src/plugins/projectexplorer/toolchain.cpp
index 02608a6c293..eea09595cd6 100644
--- a/src/plugins/projectexplorer/toolchain.cpp
+++ b/src/plugins/projectexplorer/toolchain.cpp
@@ -111,8 +111,8 @@ QString ToolChain::toolChainName(ToolChainType tc)
     switch (tc) {
     case GCC:
         return QCoreApplication::translate("ToolChain", "GCC");
-    case LinuxICC:
-        return QCoreApplication::translate("ToolChain", "Intel C++ Compiler (Linux)");
+//    case LinuxICC:
+//        return QCoreApplication::translate("ToolChain", "Intel C++ Compiler (Linux)");
     case MinGW:
         return QCoreApplication::translate("ToolChain", "MinGW");
     case MSVC:
diff --git a/src/plugins/projectexplorer/toolchain.h b/src/plugins/projectexplorer/toolchain.h
index 26863c0245e..2492b5a417e 100644
--- a/src/plugins/projectexplorer/toolchain.h
+++ b/src/plugins/projectexplorer/toolchain.h
@@ -75,7 +75,7 @@ public:
     enum ToolChainType
     {
         GCC = 0,
-        LinuxICC = 1,
+        // LINUX_ICC = 1,
         MinGW = 2,
         MSVC = 3,
         WINCE = 4,
diff --git a/src/plugins/qt4projectmanager/projectloadwizard.cpp b/src/plugins/qt4projectmanager/projectloadwizard.cpp
index 29e518edc52..bebf7bc27a8 100644
--- a/src/plugins/qt4projectmanager/projectloadwizard.cpp
+++ b/src/plugins/qt4projectmanager/projectloadwizard.cpp
@@ -65,24 +65,7 @@ ProjectLoadWizard::ProjectLoadWizard(Qt4Project *project, QWidget *parent, Qt::W
         QPair<QtVersion::QmakeBuildConfig, QStringList> result =
                 QtVersionManager::scanMakeFile(directory, m_importVersion->defaultBuildConfig());
         m_importBuildConfig = result.first;
-        m_additionalArguments = result.second;
-
-        QString versionSpec = m_importVersion->sourcePath() + "/mkspecs/" + m_importVersion->mkspec();
-        QString parsedSpec = Qt4Project::extractSpecFromArgumentList(m_additionalArguments);
-
-        // Compare mkspecs and add to additional arguments
-        if (parsedSpec.isEmpty()) {
-            // using the default spec, don't modify additional arguments
-        } else {
-            QString parsedSpecOrginal = parsedSpec;
-            if (QFileInfo(parsedSpec).isRelative())
-                parsedSpec = QDir::cleanPath(directory + "/" + parsedSpec);
-            m_additionalArguments = Qt4Project::removeSpecFromArgumentList(m_additionalArguments);
-            if (parsedSpec != versionSpec) {
-                m_additionalArguments.prepend(parsedSpecOrginal);
-                m_additionalArguments.prepend("-spec");
-            }
-        }
+        m_additionalArguments = Qt4Project::removeSpecFromArgumentList(result.second);
     }
 
     // So now we have the version and the configuration for that version
diff --git a/src/plugins/qt4projectmanager/qmakestep.cpp b/src/plugins/qt4projectmanager/qmakestep.cpp
index 918f5cec767..613996b81d5 100644
--- a/src/plugins/qt4projectmanager/qmakestep.cpp
+++ b/src/plugins/qt4projectmanager/qmakestep.cpp
@@ -62,10 +62,6 @@ QStringList QMakeStep::arguments(const QString &buildConfiguration)
     ProjectExplorer::BuildConfiguration *bc = m_pro->buildConfiguration(buildConfiguration);
     QStringList arguments;
     arguments << project()->file()->fileName();
-    if (!additonalArguments.contains("-spec")) {
-        arguments << "-spec" << m_pro->qtVersion(bc)->mkspec();
-    }
-
     arguments << "-r";
 
 #ifdef Q_OS_WIN
diff --git a/src/plugins/qt4projectmanager/qt4project.cpp b/src/plugins/qt4projectmanager/qt4project.cpp
index 3d80b9c0f02..fbcbc531ceb 100644
--- a/src/plugins/qt4projectmanager/qt4project.cpp
+++ b/src/plugins/qt4projectmanager/qt4project.cpp
@@ -308,8 +308,7 @@ Qt4Project::Qt4Project(Qt4Manager *manager, const QString& fileName) :
     m_buildConfigurationFactory(new Qt4BuildConfigurationFactory(this)),
     m_fileInfo(new Qt4ProjectFile(this, fileName, this)),
     m_isApplication(true),
-    m_projectFiles(new Qt4ProjectFiles),
-    m_toolChain(0)
+    m_projectFiles(new Qt4ProjectFiles)
 {
     m_manager->registerProject(this);
 
@@ -322,7 +321,6 @@ Qt4Project::~Qt4Project()
 {
     m_manager->unregisterProject(this);
     delete m_projectFiles;
-    delete m_toolChain;
 }
 
 void Qt4Project::defaultQtVersionChanged()
@@ -496,17 +494,11 @@ void Qt4Project::scheduleUpdateCodeModel(Qt4ProjectManager::Internal::Qt4ProFile
 
 ProjectExplorer::ToolChain *Qt4Project::toolChain(BuildConfiguration *configuration) const
 {
-    ProjectExplorer::ToolChain *tempToolChain;
-    tempToolChain = qtVersion(configuration)->createToolChain(toolChainType(configuration));
-    if (!ProjectExplorer::ToolChain::equals(m_toolChain, tempToolChain)) {
-        if (m_toolChain)
-            delete m_toolChain;
-        m_toolChain = tempToolChain;
-    } else {
-        delete tempToolChain;
-    }
-
-    return m_toolChain;
+    ToolChain::ToolChainType tct = toolChainType(configuration);
+    foreach(ToolChain *tc, qtVersion(configuration)->toolChains())
+        if (tc->type() == tct)
+            return tc;
+    return 0;
 }
 
 QString Qt4Project::makeCommand(BuildConfiguration *configuration) const
@@ -1009,9 +1001,8 @@ void Qt4Project::updateActiveRunConfiguration()
 
 ProjectExplorer::ToolChain::ToolChainType Qt4Project::toolChainType(BuildConfiguration *configuration) const
 {
-    const ProjectExplorer::ToolChain::ToolChainType originalType =
-        (ProjectExplorer::ToolChain::ToolChainType)configuration->value("ToolChain").toInt();
-    ProjectExplorer::ToolChain::ToolChainType type = originalType;
+    ToolChain::ToolChainType originalType = ToolChain::ToolChainType(configuration->value("ToolChain").toInt());
+    ToolChain::ToolChainType type = originalType;
     const QtVersion *version = qtVersion(configuration);
     if (!version->possibleToolChainTypes().contains(type)) // use default tool chain
         type = version->defaultToolchainType();
@@ -1233,19 +1224,6 @@ QStringList Qt4Project::removeSpecFromArgumentList(const QStringList &old)
     return newList;
 }
 
-QString Qt4Project::extractSpecFromArgumentList(const QStringList &list)
-{
-    int index = list.indexOf("-spec");
-    if (index == -1)
-        index = list.indexOf("-platform");
-    if (index == -1)
-        return QString();
-    if (index + 1 < list.length())
-        return list.at(index +1);
-    else
-        return QString();
-}
-
 // returns true if both are equal
 bool Qt4Project::compareBuildConfigurationToImportFrom(BuildConfiguration *configuration, const QString &workingDirectory)
 {
@@ -1262,51 +1240,15 @@ bool Qt4Project::compareBuildConfigurationToImportFrom(BuildConfiguration *confi
                 // now compare arguments lists
                 // we have to compare without the spec/platform cmd argument
                 // and compare that on its own
-                QString actualSpec = extractSpecFromArgumentList(qs->value(configuration->name(), "qmakeArgs").toStringList());
-                if (actualSpec.isEmpty())
-                    actualSpec = version->mkspec();
-
-                // Now to convert the actualSpec to a absolute path, we go through a few hops
-                if (QFileInfo(actualSpec).isRelative()) {
-                    QString path = version->sourcePath() + "/mkspecs/" + actualSpec;
-                    if (QFileInfo(path).exists()) {
-                        actualSpec = QDir::cleanPath(path);
-                    } else {
-                        path = version->versionInfo().value("QMAKE_MKSPECS") + "/" + actualSpec;
-                        if (QFileInfo(path).exists()) {
-                            actualSpec = QDir::cleanPath(path);
-                        } else {
-                            path = workingDirectory + "/" + actualSpec;
-                            if (QFileInfo(path).exists())
-                                actualSpec = QDir::cleanPath(path);
-                        }
-                    }
-                }
-
-
-                QString parsedSpec = extractSpecFromArgumentList(result.second);
-                // if the MakeFile did not contain a mkspec, then it is the default for that qmake
-                if (parsedSpec.isEmpty())
-                    parsedSpec = version->sourcePath() + "/mkspecs/" + version->mkspec();
-                if (QFileInfo(parsedSpec).isRelative())
-                    parsedSpec = QDir::cleanPath(workingDirectory + "/" + parsedSpec);
 
                 QStringList actualArgs = removeSpecFromArgumentList(qs->value(configuration->name(), "qmakeArgs").toStringList());
                 QStringList parsedArgs = removeSpecFromArgumentList(result.second);
-
-#ifdef Q_OS_WIN
-                actualSpec = actualSpec.toLower();
-                parsedSpec = parsedSpec.toLower();
-#endif
-
                 if (debug) {
                     qDebug()<<"Actual args:"<<actualArgs;
                     qDebug()<<"Parsed args:"<<parsedArgs;
-                    qDebug()<<"Actual spec:"<<actualSpec;
-                    qDebug()<<"Parsed spec:"<<parsedSpec;
                 }
 
-                if (actualArgs == parsedArgs && actualSpec == parsedSpec)
+                if (actualArgs == parsedArgs)
                     return true;
             }
         }
diff --git a/src/plugins/qt4projectmanager/qt4project.h b/src/plugins/qt4projectmanager/qt4project.h
index 597a426247c..13c7f52fdaa 100644
--- a/src/plugins/qt4projectmanager/qt4project.h
+++ b/src/plugins/qt4projectmanager/qt4project.h
@@ -198,6 +198,7 @@ public:
     //returns the name of the qt version, might be QString::Null, which means default qt version
     // qtVersion is in general the better method to use
     QString qtVersionName(ProjectExplorer::BuildConfiguration *configuration) const;
+
     ProjectExplorer::ToolChain *toolChain(ProjectExplorer::BuildConfiguration *configuration) const;
     void setToolChainType(ProjectExplorer::BuildConfiguration *configuration, ProjectExplorer::ToolChain::ToolChainType type);
     ProjectExplorer::ToolChain::ToolChainType toolChainType(ProjectExplorer::BuildConfiguration *configuration) const;
@@ -234,7 +235,6 @@ public:
     bool compareBuildConfigurationToImportFrom(ProjectExplorer::BuildConfiguration *configuration, const QString &workingDirectory);
 
     static QStringList removeSpecFromArgumentList(const QStringList &old);
-    static QString extractSpecFromArgumentList(const QStringList &list);
 signals:
     void targetInformationChanged();
 
@@ -293,8 +293,6 @@ private:
     QList<Qt4ProjectManager::Internal::Qt4ProFileNode *> m_proFilesForCodeModelUpdate;
 
     QMap<QString, Internal::CodeModelInfo> m_codeModelInfo;
-    mutable ProjectExplorer::ToolChain *m_toolChain;
-
     friend class Qt4ProjectFile;
 };
 
diff --git a/src/plugins/qt4projectmanager/qt4projectconfigwidget.cpp b/src/plugins/qt4projectmanager/qt4projectconfigwidget.cpp
index 74f364880b2..cfe21ab420b 100644
--- a/src/plugins/qt4projectmanager/qt4projectconfigwidget.cpp
+++ b/src/plugins/qt4projectmanager/qt4projectconfigwidget.cpp
@@ -288,17 +288,6 @@ void Qt4ProjectConfigWidget::importLabelClicked()
             QtVersion::QmakeBuildConfig qmakeBuildConfig = result.first;
             QStringList additionalArguments = result.second;
 
-            QString versionSpec = version->sourcePath() + "/mkspecs/" + version->mkspec();
-            QString parsedSpec = Qt4Project::extractSpecFromArgumentList(additionalArguments);
-            QString parsedSpecOrginal = parsedSpec;
-            if (QFileInfo(parsedSpec).isRelative())
-                parsedSpec = QDir::cleanPath(directory + "/" + parsedSpec);
-            additionalArguments = Qt4Project::removeSpecFromArgumentList(additionalArguments);
-            if (parsedSpec != versionSpec) {
-                additionalArguments.prepend(parsedSpecOrginal);
-                additionalArguments.prepend("-spec");
-            }
-
             // So we got all the information now apply it...
             m_pro->setQtVersion(bc, version->uniqueId());
             // Combo box will be updated at the end
diff --git a/src/plugins/qt4projectmanager/qtversionmanager.cpp b/src/plugins/qt4projectmanager/qtversionmanager.cpp
index 3125fccddd2..51298b69f70 100644
--- a/src/plugins/qt4projectmanager/qtversionmanager.cpp
+++ b/src/plugins/qt4projectmanager/qtversionmanager.cpp
@@ -407,6 +407,7 @@ QtVersion::QtVersion(const QString &name, const QString &qmakeCommand, int id,
     m_autodetectionSource(autodetectionSource),
     m_hasDebuggingHelper(false),
     m_mkspecUpToDate(false),
+    m_toolChainUpToDate(false),
     m_versionInfoUpToDate(false),
     m_notInstalled(false),
     m_defaultConfigIsDebug(true),
@@ -429,6 +430,7 @@ QtVersion::QtVersion(const QString &name, const QString &qmakeCommand,
     m_autodetectionSource(autodetectionSource),
     m_hasDebuggingHelper(false),
     m_mkspecUpToDate(false),
+    m_toolChainUpToDate(false),
     m_versionInfoUpToDate(false),
     m_notInstalled(false),
     m_defaultConfigIsDebug(true),
@@ -447,6 +449,7 @@ QtVersion::QtVersion(const QString &qmakeCommand, bool isAutodetected, const QSt
     m_autodetectionSource(autodetectionSource),
     m_hasDebuggingHelper(false),
     m_mkspecUpToDate(false),
+    m_toolChainUpToDate(false),
     m_versionInfoUpToDate(false),
     m_notInstalled(false),
     m_defaultConfigIsDebug(true),
@@ -466,6 +469,7 @@ QtVersion::QtVersion()
     m_isAutodetected(false),
     m_hasDebuggingHelper(false),
     m_mkspecUpToDate(false),
+    m_toolChainUpToDate(false),
     m_versionInfoUpToDate(false),
     m_notInstalled(false),
     m_defaultConfigIsDebug(true),
@@ -480,7 +484,7 @@ QtVersion::QtVersion()
 
 QtVersion::~QtVersion()
 {
-
+    qDeleteAll(m_toolChains);
 }
 
 QString QtVersion::name() const
@@ -521,13 +525,6 @@ QHash<QString,QString> QtVersion::versionInfo() const
     return m_versionInfo;
 }
 
-QString QtVersion::qmakeCXX() const
-{
-    updateQMakeCXX();
-    return m_qmakeCXX;
-}
-
-
 void QtVersion::setName(const QString &name)
 {
     m_name = name;
@@ -541,8 +538,7 @@ void QtVersion::setQMakeCommand(const QString& qmakeCommand)
 #endif
     m_designerCommand = m_linguistCommand = m_uicCommand = QString::null;
     m_mkspecUpToDate = false;
-    m_qmakeCXX = QString::null;
-    m_qmakeCXXUpToDate = false;
+    m_toolChainUpToDate = false;
     // TODO do i need to optimize this?
     m_versionInfoUpToDate = false;
     m_hasDebuggingHelper = !debuggingHelperLibrary().isEmpty();
@@ -940,14 +936,14 @@ void QtVersion::updateMkSpec() const
 
     QString mkspec;
     // no .qmake.cache so look at the default mkspec
-    QString mkspecPath = versionInfo().value("QMAKE_MKSPECS");
-    if (mkspecPath.isEmpty())
-        mkspecPath = versionInfo().value("QT_INSTALL_DATA") + "/mkspecs/default";
+    m_mkspecFullPath = versionInfo().value("QMAKE_MKSPECS");
+    if (m_mkspecFullPath.isEmpty())
+        m_mkspecFullPath = versionInfo().value("QT_INSTALL_DATA") + "/mkspecs/default";
     else
-        mkspecPath = mkspecPath + "/default";
-//     qDebug() << "default mkspec is located at" << mkspecPath;
+        m_mkspecFullPath = m_mkspecFullPath + "/default";
+//     qDebug() << "default mkspec is located at" << m_mkspecFullPath;
 #ifdef Q_OS_WIN
-    QFile f2(mkspecPath + "/qmake.conf");
+    QFile f2(m_mkspecFullPath + "/qmake.conf");
     if (f2.exists() && f2.open(QIODevice::ReadOnly)) {
         while (!f2.atEnd()) {
             QByteArray line = f2.readLine();
@@ -962,7 +958,7 @@ void QtVersion::updateMkSpec() const
         f2.close();
     }
 #elif defined(Q_OS_MAC)
-    QFile f2(mkspecPath + "/qmake.conf");
+    QFile f2(m_mkspecFullPath + "/qmake.conf");
     if (f2.exists() && f2.open(QIODevice::ReadOnly)) {
         while (!f2.atEnd()) {
             QByteArray line = f2.readLine();
@@ -976,7 +972,7 @@ void QtVersion::updateMkSpec() const
                         mkspec = "macx-g++";
                     } else {
                         //resolve mkspec link
-                        QFileInfo f3(mkspecPath);
+                        QFileInfo f3(m_mkspecFullPath);
                         if (f3.isSymLink()) {
                             mkspec = f3.symLinkTarget();
                         }
@@ -988,18 +984,14 @@ void QtVersion::updateMkSpec() const
         f2.close();
     }
 #else
-    QFileInfo f2(mkspecPath);
+    QFileInfo f2(m_mkspecFullPath);
     if (f2.isSymLink()) {
         mkspec = f2.symLinkTarget();
     }
 #endif
 
-    m_mkspecFullPath = mkspec;
-    int index = mkspec.lastIndexOf('/');
-    if (index == -1)
-        index = mkspec.lastIndexOf('\\');
-    QString mkspecDir = QDir(versionInfo().value("QT_INSTALL_DATA") + "/mkspecs/").canonicalPath();
-    if (index >= 0 && QDir(mkspec.left(index)).canonicalPath() == mkspecDir)
+    int index = qMax(mkspec.lastIndexOf('/'), mkspec.lastIndexOf('\\'));
+    if (index >= 0)
         mkspec = mkspec.mid(index+1).trimmed();
 
     m_mkspec = mkspec;
@@ -1007,70 +999,6 @@ void QtVersion::updateMkSpec() const
 //    qDebug()<<"mkspec for "<<versionInfo().value("QT_INSTALL_DATA")<<" is "<<mkspec;
 }
 
-void QtVersion::updateQMakeCXX() const
-{
-    if (m_qmakeCXXUpToDate)
-        return;
-    ProFileReader *reader = new ProFileReader();
-    reader->setCumulative(false);
-    reader->setParsePreAndPostFiles(false);
-    reader->readProFile(mkspecPath() + "/qmake.conf");
-    m_qmakeCXX = reader->value("QMAKE_CXX");
-
-    delete reader;
-    m_qmakeCXXUpToDate = true;
-}
-
-ProjectExplorer::ToolChain *QtVersion::createToolChain(ProjectExplorer::ToolChain::ToolChainType type) const
-{
-    ProjectExplorer::ToolChain *tempToolchain = 0;
-    if (type == ProjectExplorer::ToolChain::MinGW) {
-        QString qmake_cxx = qmakeCXX();
-        ProjectExplorer::Environment env = ProjectExplorer::Environment::systemEnvironment();
-        //addToEnvironment(env);
-        env.prependOrSetPath(mingwDirectory()+"/bin");
-        qmake_cxx = env.searchInPath(qmake_cxx);
-        tempToolchain = ProjectExplorer::ToolChain::createMinGWToolChain(qmake_cxx, mingwDirectory());
-        //qDebug()<<"Mingw ToolChain";
-    } else if(type == ProjectExplorer::ToolChain::MSVC) {
-        tempToolchain = ProjectExplorer::ToolChain::createMSVCToolChain(msvcVersion(), isQt64Bit());
-        //qDebug()<<"MSVC ToolChain ("<<version->msvcVersion()<<")";
-    } else if(type == ProjectExplorer::ToolChain::WINCE) {
-        tempToolchain = ProjectExplorer::ToolChain::createWinCEToolChain(msvcVersion(), wincePlatform());
-        //qDebug()<<"WinCE ToolChain ("<<version->msvcVersion()<<","<<version->wincePlatform()<<")";
-    } else if(type == ProjectExplorer::ToolChain::GCC || type == ProjectExplorer::ToolChain::LinuxICC) {
-        QString qmake_cxx = qmakeCXX();
-        ProjectExplorer::Environment env = ProjectExplorer::Environment::systemEnvironment();
-        //addToEnvironment(env);
-        qmake_cxx = env.searchInPath(qmake_cxx);
-        if (qmake_cxx.isEmpty()) {
-            // macx-xcode mkspec resets the value of QMAKE_CXX.
-            // Unfortunately, we need a valid QMAKE_CXX to configure the parser.
-            qmake_cxx = QLatin1String("cc");
-        }
-        tempToolchain = ProjectExplorer::ToolChain::createGccToolChain(qmake_cxx);
-        //qDebug()<<"GCC ToolChain ("<<qmake_cxx<<")";
-#ifdef QTCREATOR_WITH_S60
-    } else if (type == ProjectExplorer::ToolChain::WINSCW) {
-        tempToolchain = S60Manager::instance()->createWINSCWToolChain(this);
-    } else if (type == ProjectExplorer::ToolChain::GCCE) {
-        tempToolchain = S60Manager::instance()->createGCCEToolChain(this);
-    } else if (type == ProjectExplorer::ToolChain::RVCT_ARMV5
-               || type == ProjectExplorer::ToolChain::RVCT_ARMV6) {
-        tempToolchain = S60Manager::instance()->createRVCTToolChain(this, type);
-#endif
-#ifdef QTCREATOR_WITH_MAEMO
-    } else if (type == ProjectExplorer::ToolChain::GCC_MAEMO) {
-        tempToolchain = MaemoManager::instance()->maemoToolChain(this);
-#endif
-    } else {
-        qDebug()<<"Could not create ToolChain for"<<mkspec();
-        qDebug()<<"Qt Creator doesn't know about the system includes, nor the systems defines.";
-    }
-    return tempToolchain;
-}
-
-
 QString QtVersion::findQtBinary(const QStringList &possibleCommands) const
 {
     const QString qtdirbin = versionInfo().value(QLatin1String("QT_INSTALL_BINS")) + QLatin1Char('/');
@@ -1134,58 +1062,98 @@ QString QtVersion::linguistCommand() const
     return m_linguistCommand;
 }
 
+QList<ProjectExplorer::ToolChain *> QtVersion::toolChains() const
+{
+    updateToolChain();
+    return m_toolChains;
+}
+
 QList<ProjectExplorer::ToolChain::ToolChainType> QtVersion::possibleToolChainTypes() const
 {
-    QList<ProjectExplorer::ToolChain::ToolChainType> toolChains;
-    if (!isValid())
-        return toolChains << ProjectExplorer::ToolChain::INVALID;
-    const QString &spec = mkspec();
-    if (spec.contains("win32-msvc")
-        || spec.contains(QLatin1String("win32-icc"))) {
-        toolChains << ProjectExplorer::ToolChain::MSVC;
-    } else if (spec.contains("win32-g++")) {
-        toolChains << ProjectExplorer::ToolChain::MinGW;
-    } else if (spec == QString::null) {
-        toolChains << ProjectExplorer::ToolChain::INVALID;
-    } else if (spec.contains("wince")) {
-        toolChains << ProjectExplorer::ToolChain::WINCE;
-    } else if (spec.contains("linux-icc")) {
-        toolChains << ProjectExplorer::ToolChain::LinuxICC;
+    QList<ProjectExplorer::ToolChain::ToolChainType> types;
+    foreach(ProjectExplorer::ToolChain *tc, toolChains())
+        types << tc->type();
+    return types;
+}
+
+ProjectExplorer::ToolChain::ToolChainType QtVersion::defaultToolchainType() const
+{
+    const QList<ProjectExplorer::ToolChain::ToolChainType> & list = possibleToolChainTypes();
+    if (list.isEmpty())
+        return ProjectExplorer::ToolChain::INVALID;
+    return list.first();
+}
+
+// if none, then it's INVALID everywhere this function is called
+void QtVersion::updateToolChain() const
+{
+    if (m_toolChainUpToDate)
+        return;
+
+    qDeleteAll(m_toolChains);
+
+    QString mkspecPath = versionInfo().value("QMAKE_MKSPECS");
+    if (mkspecPath.isEmpty())
+        mkspecPath = versionInfo().value("QT_INSTALL_DATA") + "/mkspecs/default";
+    else
+        mkspecPath = mkspecPath + "/default";
+
+    ProFileReader *reader = new ProFileReader();
+    reader->setCumulative(false);
+    reader->setParsePreAndPostFiles(false);
+    reader->readProFile(mkspecPath + "/qmake.conf");
+    QString qmakeCXX = reader->value("QMAKE_CXX");
+    QString makefileGenerator = reader->value("MAKEFILE_GENERATOR");
+    QString ce_sdk = reader->value("CE_SDK");
+    QString ce_arch = reader->value("CE_ARCH");
+    QString qt_arch = reader->value("QT_ARCH");
+    if (!ce_sdk.isEmpty() && !ce_arch.isEmpty()) {
+        QString wincePlatformName = ce_sdk + " (" + ce_arch + ")";
+        m_toolChains << ProjectExplorer::ToolChain::createWinCEToolChain(msvcVersion(), wincePlatformName);
+    } else if (makefileGenerator == "SYMBIAN_ABLD") {
 #ifdef QTCREATOR_WITH_S60
-    } else if (spec.contains("symbian-abld")) {
-        toolChains << ProjectExplorer::ToolChain::GCCE
-                << ProjectExplorer::ToolChain::RVCT_ARMV5
-                << ProjectExplorer::ToolChain::RVCT_ARMV6
-                << ProjectExplorer::ToolChain::WINSCW;
+        m_toolChains << S60Manager::instance()->createGCCEToolChain(this);
+        m_toolChains << S60Manager::instance()->createRVCTToolChain(this, ProjectExplorer::ToolChain::RVCT_ARMV5);
+        m_toolChains << S60Manager::instance()->createRVCTToolChain(this, ProjectExplorer::ToolChain::RVCT_ARMV6);
+        m_toolChains << S60Manager::instance()->createWINSCWToolChain(this);
 #endif
+    } else if (qt_arch == "arm") {
 #ifdef QTCREATOR_WITH_MAEMO
-    } else if (spec.contains("linux-g++-opengl")) {
-        bool maemo = false;
-        const QString baseDir = m_versionInfo.contains("QT_INSTALL_DATA") ?
-            m_versionInfo.value("QT_INSTALL_DATA") : QLatin1String("");
-        QFile qconfigpri(baseDir + QLatin1String("/mkspecs/qconfig.pri"));
-        if (qconfigpri.exists()) {
-            qconfigpri.open(QIODevice::ReadOnly | QIODevice::Text);
-            QTextStream stream(&qconfigpri);
-            while (!stream.atEnd()) {
-                QString line = stream.readLine().trimmed();
-                if (line.startsWith(QLatin1String("QT_ARCH"))
-                    && line.endsWith(QLatin1String("arm")))
-                    maemo = true;
-            }
-        }
-        toolChains << (maemo ? ProjectExplorer::ToolChain::GCC_MAEMO
-                       : ProjectExplorer::ToolChain::GCC);
+        m_toolChains << MaemoManager::instance()->maemoToolChain(this);
+
+        ProjectExplorer::Environment env = ProjectExplorer::Environment::systemEnvironment();
+        //addToEnvironment(env);
+        qmakeCXX = env.searchInPath(qmakeCXX);
+        m_toolChains << ProjectExplorer::ToolChain::createGccToolChain(qmakeCXX);
 #endif
-    } else {
-        toolChains << ProjectExplorer::ToolChain::GCC;
+    } else if (qmakeCXX == "cl" || qmakeCXX == "icl") {
+        // TODO proper support for intel cl
+        m_toolChains << ProjectExplorer::ToolChain::createMSVCToolChain(msvcVersion(), isQt64Bit());
+    } else if (qmakeCXX == "g++" && makefileGenerator == "MINGW") {
+        ProjectExplorer::Environment env = ProjectExplorer::Environment::systemEnvironment();
+        //addToEnvironment(env);
+        env.prependOrSetPath(mingwDirectory() + "/bin");
+        qmakeCXX = env.searchInPath(qmakeCXX);
+        m_toolChains << ProjectExplorer::ToolChain::createMinGWToolChain(qmakeCXX, mingwDirectory());
+    } else if (qmakeCXX == "g++" || qmakeCXX == "icc") {
+        ProjectExplorer::Environment env = ProjectExplorer::Environment::systemEnvironment();
+        //addToEnvironment(env);
+        qmakeCXX = env.searchInPath(qmakeCXX);
+        if (qmakeCXX.isEmpty()) {
+            // macx-xcode mkspec resets the value of QMAKE_CXX.
+            // Unfortunately, we need a valid QMAKE_CXX to configure the parser.
+            qmakeCXX = QLatin1String("cc");
+        }
+        m_toolChains << ProjectExplorer::ToolChain::createGccToolChain(qmakeCXX);
     }
-    return toolChains;
-}
 
-ProjectExplorer::ToolChain::ToolChainType QtVersion::defaultToolchainType() const
-{
-    return possibleToolChainTypes().at(0);
+    if (m_toolChains.isEmpty()) {
+        qDebug()<<"Could not create ToolChain for"<<mkspecPath<<qmakeCXX;
+        qDebug()<<"Qt Creator doesn't know about the system includes, nor the systems defines.";
+    }
+
+    delete reader;
+    m_toolChainUpToDate = true;
 }
 
 #ifdef QTCREATOR_WITH_S60
@@ -1208,6 +1176,7 @@ QString QtVersion::mingwDirectory() const
 void QtVersion::setMingwDirectory(const QString &directory)
 {
     m_mingwDirectory = directory;
+    m_toolChainUpToDate = false;
 }
 
 QString QtVersion::msvcVersion() const
@@ -1215,15 +1184,10 @@ QString QtVersion::msvcVersion() const
     return m_msvcVersion;
 }
 
-QString QtVersion::wincePlatform() const
-{
-//    qDebug()<<"QtVersion::wincePlatform returning"<<ProjectExplorer::CeSdkHandler::platformName(mkspecPath() + "/qmake.conf");
-    return ProjectExplorer::CeSdkHandler::platformName(mkspecPath() + "/qmake.conf");
-}
-
 void QtVersion::setMsvcVersion(const QString &version)
 {
     m_msvcVersion = version;
+    m_toolChainUpToDate = false;
 }
 
 void QtVersion::addToEnvironment(ProjectExplorer::Environment &env) const
@@ -1346,7 +1310,8 @@ QString QtVersion::buildDebuggingHelperLibrary()
     addToEnvironment(env);
 
     // TODO: the debugging helper doesn't comply to actual tool chain yet
-    ProjectExplorer::ToolChain *tc = createToolChain(defaultToolchainType());
+    QList<ProjectExplorer::ToolChain *> alltc = toolChains();
+    ProjectExplorer::ToolChain *tc = alltc.isEmpty() ? 0 : alltc.first();
     tc->addToEnvironment(env);
     QString output;
     QString directory = DebuggingHelperLibrary::copyDebuggingHelperLibrary(qtInstallData, &output);
diff --git a/src/plugins/qt4projectmanager/qtversionmanager.h b/src/plugins/qt4projectmanager/qtversionmanager.h
index d79809bffe9..93680f7ddcc 100644
--- a/src/plugins/qt4projectmanager/qtversionmanager.h
+++ b/src/plugins/qt4projectmanager/qtversionmanager.h
@@ -36,6 +36,10 @@
 #include <QtCore/QSharedPointer>
 #include <QtCore/QHash>
 
+namespace ProjectExplorer {
+    class ToolChain;
+}
+
 namespace Qt4ProjectManager {
 
 namespace Internal {
@@ -65,16 +69,21 @@ public:
 
     QString name() const;
     QString sourcePath() const;
-    QString mkspecPath() const;
     QString qmakeCommand() const;
     QString uicCommand() const;
     QString designerCommand() const;
     QString linguistCommand() const;
 
     QList<ProjectExplorer::ToolChain::ToolChainType> possibleToolChainTypes() const;
-    QString mkspec() const;
     ProjectExplorer::ToolChain::ToolChainType defaultToolchainType() const;
-    ProjectExplorer::ToolChain *createToolChain(ProjectExplorer::ToolChain::ToolChainType type) const;
+    QList<ProjectExplorer::ToolChain *> toolChains() const;
+
+    /// @returns the name of the mkspec, which is generally not enough
+    /// to pass to qmake.
+    QString mkspec() const;
+    /// @returns the full path to the default directory
+    /// specifally not the directory the symlink/ORIGINAL_QMAKESPEC points to
+    QString mkspecPath() const;
 
     void setName(const QString &name);
     void setQMakeCommand(const QString &path);
@@ -90,7 +99,6 @@ public:
     QString mingwDirectory() const;
     void setMingwDirectory(const QString &directory);
     QString msvcVersion() const;
-    QString wincePlatform() const;
     void setMsvcVersion(const QString &version);
     void addToEnvironment(ProjectExplorer::Environment &env) const;
 
@@ -128,9 +136,8 @@ private:
     void updateSourcePath();
     void updateMkSpec() const;
     void updateVersionInfo() const;
-    void updateQMakeCXX() const;
-    QString qmakeCXX() const;
     QString findQtBinary(const QStringList &possibleName) const;
+    void updateToolChain() const;
     QString m_name;
     QString m_sourcePath;
     QString m_mingwDirectory;
@@ -147,6 +154,9 @@ private:
     mutable QString m_mkspec; // updated lazily
     mutable QString m_mkspecFullPath;
 
+    mutable bool m_toolChainUpToDate;
+    mutable QList<ProjectExplorer::ToolChain *> m_toolChains;
+
     mutable bool m_versionInfoUpToDate;
     mutable QHash<QString,QString> m_versionInfo; // updated lazily
     mutable bool m_notInstalled;
@@ -161,9 +171,6 @@ private:
     mutable QString m_uicCommand;
     mutable QString m_designerCommand;
     mutable QString m_linguistCommand;
-
-    mutable bool m_qmakeCXXUpToDate;
-    mutable QString m_qmakeCXX;
 };
 
 struct QMakeAssignment
-- 
GitLab