diff --git a/src/plugins/projectexplorer/abstractmsvctoolchain.cpp b/src/plugins/projectexplorer/abstractmsvctoolchain.cpp new file mode 100644 index 0000000000000000000000000000000000000000..94b17e65cfb27461f53b5d9966e47f09c8aa0ce1 --- /dev/null +++ b/src/plugins/projectexplorer/abstractmsvctoolchain.cpp @@ -0,0 +1,269 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (info@qt.nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at info@qt.nokia.com. +** +**************************************************************************/ + +#include "abstractmsvctoolchain.h" + +#include "msvcparser.h" + +#include <projectexplorer/projectexplorer.h> +#include <projectexplorer/projectexplorersettings.h> + + +#include <utils/fileutils.h> +#include <utils/qtcprocess.h> +#include <utils/synchronousprocess.h> + +#include <QFileInfo> +#include <QDir> +#include <QTemporaryFile> + +enum { debug = 0 }; + +namespace ProjectExplorer { +namespace Internal { + + +AbstractMsvcToolChain::AbstractMsvcToolChain(const QString &id, + bool autodetect, + const Abi &abi, + const QString& vcvarsBat) : + ToolChain(id, autodetect), + m_lastEnvironment(Utils::Environment::systemEnvironment()), + m_abi(abi), + m_vcvarsBat(vcvarsBat) +{ + Q_ASSERT(abi.os() == Abi::WindowsOS); + Q_ASSERT(abi.binaryFormat() == Abi::PEFormat); + Q_ASSERT(abi.osFlavor() != Abi::WindowsMSysFlavor); + Q_ASSERT(!m_vcvarsBat.isEmpty()); +} + +AbstractMsvcToolChain::AbstractMsvcToolChain(const QString &id, bool autodetect) : + ToolChain(id, autodetect), + m_lastEnvironment(Utils::Environment::systemEnvironment()) +{ + +} + +Abi AbstractMsvcToolChain::targetAbi() const +{ + return m_abi; +} + +bool AbstractMsvcToolChain::isValid() const +{ + return !m_vcvarsBat.isEmpty(); +} + +QByteArray AbstractMsvcToolChain::predefinedMacros() const +{ + if (m_predefinedMacros.isEmpty()) { + Utils::Environment env(m_lastEnvironment); + addToEnvironment(env); + m_predefinedMacros = msvcPredefinedMacros(env); + } + return m_predefinedMacros; +} + +QList<HeaderPath> AbstractMsvcToolChain::systemHeaderPaths() const +{ + if (m_headerPaths.isEmpty()) { + Utils::Environment env(m_lastEnvironment); + addToEnvironment(env); + foreach (const QString &path, env.value("INCLUDE").split(QLatin1Char(';'))) + m_headerPaths.append(HeaderPath(path, HeaderPath::GlobalHeaderPath)); + } + return m_headerPaths; +} + +void AbstractMsvcToolChain::addToEnvironment(Utils::Environment &env) const +{ + // We cache the full environment (incoming + modifications by setup script). + if (!m_resultEnvironment.size() || env != m_lastEnvironment) { + if (debug) + qDebug() << "addToEnvironment: " << displayName(); + m_lastEnvironment = env; + m_resultEnvironment = readEnvironmentSetting(env); + } + env = m_resultEnvironment; +} + + +QString AbstractMsvcToolChain::makeCommand() const +{ + if (ProjectExplorerPlugin::instance()->projectExplorerSettings().useJom) { + // We want jom! Try to find it. + const QString jom = QLatin1String("jom.exe"); + const QFileInfo installedJom = QFileInfo(QCoreApplication::applicationDirPath() + + QLatin1Char('/') + jom); + if (installedJom.isFile() && installedJom.isExecutable()) { + return installedJom.absoluteFilePath(); + } else { + return jom; + } + } + return QLatin1String("nmake.exe"); +} + +void AbstractMsvcToolChain::setDebuggerCommand(const QString &d) +{ + if (m_debuggerCommand == d) + return; + m_debuggerCommand = d; + updateId(); + toolChainUpdated(); +} + +QString AbstractMsvcToolChain::debuggerCommand() const +{ + return m_debuggerCommand; +} + + +IOutputParser *AbstractMsvcToolChain::outputParser() const +{ + return new MsvcParser; +} + +bool AbstractMsvcToolChain::canClone() const +{ + return true; +} + +QByteArray AbstractMsvcToolChain::msvcPredefinedMacros(const Utils::Environment& env) const +{ + QByteArray predefinedMacros = "#define __MSVCRT__\n" + "#define __w64\n" + "#define __int64 long long\n" + "#define __int32 long\n" + "#define __int16 short\n" + "#define __int8 char\n" + "#define __ptr32\n" + "#define __ptr64\n"; + + return predefinedMacros; +} + + +bool AbstractMsvcToolChain::generateEnvironmentSettings(Utils::Environment &env, + const QString& batchFile, + const QString& batchArgs, + QMap<QString, QString>& envPairs) const +{ + // Create a temporary file name for the output. Use a temporary file here + // as I don't know another way to do this in Qt... + // Note, can't just use a QTemporaryFile all the way through as it remains open + // internally so it can't be streamed to later. + QString tempOutFile; + QTemporaryFile* pVarsTempFile = new QTemporaryFile(QDir::tempPath() + "/XXXXXX.txt"); + pVarsTempFile->setAutoRemove(false); + pVarsTempFile->open(); + pVarsTempFile->close(); + tempOutFile = pVarsTempFile->fileName(); + delete pVarsTempFile; + + // Create a batch file to create and save the env settings + Utils::TempFileSaver saver(QDir::tempPath() + "/XXXXXX.bat"); + + QByteArray call = "call "; + call += Utils::QtcProcess::quoteArg(batchFile).toLocal8Bit() + "\r\n"; + if (!batchArgs.isEmpty()) { + call += ' '; + call += batchArgs.toLocal8Bit(); + } + call += "\r\n"; + + saver.write(call); + const QByteArray redirect = "set > " + Utils::QtcProcess::quoteArg( + QDir::toNativeSeparators(tempOutFile)).toLocal8Bit() + "\r\n"; + saver.write(redirect); + if (!saver.finalize()) { + qWarning("%s: %s", Q_FUNC_INFO, qPrintable(saver.errorString())); + return false; + } + + Utils::QtcProcess run; + // As of WinSDK 7.1, there is logic preventing the path from being set + // correctly if "ORIGINALPATH" is already set. That can cause problems + // if Creator is launched within a session set up by setenv.cmd. + env.unset(QLatin1String("ORIGINALPATH")); + run.setEnvironment(env); + const QString cmdPath = QString::fromLocal8Bit(qgetenv("COMSPEC")); + // Windows SDK setup scripts require command line switches for environment expansion. + QString cmdArguments = QLatin1String(" /E:ON /V:ON /c \""); + cmdArguments += QDir::toNativeSeparators(saver.fileName()); + cmdArguments += QLatin1Char('"'); + run.setCommand(cmdPath, cmdArguments); + if (debug) + qDebug() << "readEnvironmentSetting: " << call << cmdPath << cmdArguments + << " Env: " << env.size(); + run.start(); + + if (!run.waitForStarted()) { + qWarning("%s: Unable to run '%s': %s", Q_FUNC_INFO, qPrintable(m_vcvarsBat), + qPrintable(run.errorString())); + return false; + } + if (!run.waitForFinished()) { + qWarning("%s: Timeout running '%s'", Q_FUNC_INFO, qPrintable(m_vcvarsBat)); + Utils::SynchronousProcess::stopProcess(run); + return false; + } + + // + // Now parse the file to get the environment settings + QFile varsFile(tempOutFile); + if (!varsFile.open(QIODevice::ReadOnly)) + return false; + + QRegExp regexp(QLatin1String("(\\w*)=(.*)")); + while (!varsFile.atEnd()) { + const QString line = QString::fromLocal8Bit(varsFile.readLine()).trimmed(); + if (regexp.exactMatch(line)) { + const QString varName = regexp.cap(1); + const QString varValue = regexp.cap(2); + + if (!varValue.isEmpty()) + envPairs.insert(varName, varValue); + } + } + + // Tidy up and remove the file + varsFile.close(); + varsFile.remove(); + + return true; +} + +} // namespace Internal +} // namespace ProjectExplorer + diff --git a/src/plugins/projectexplorer/abstractmsvctoolchain.h b/src/plugins/projectexplorer/abstractmsvctoolchain.h new file mode 100644 index 0000000000000000000000000000000000000000..1c346a13a6dab37808ea8b3d6a4e94b125457d0b --- /dev/null +++ b/src/plugins/projectexplorer/abstractmsvctoolchain.h @@ -0,0 +1,90 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (info@qt.nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at info@qt.nokia.com. +** +**************************************************************************/ + +#ifndef ABSTRACTMSVCTOOLCHAIN_H +#define ABSTRACTMSVCTOOLCHAIN_H + +#include "toolchain.h" +#include "abi.h" + +#include <utils/environment.h> + +namespace ProjectExplorer { +namespace Internal { + +class AbstractMsvcToolChain : public ToolChain +{ +public: + AbstractMsvcToolChain(const QString &id, bool autodetect, const Abi &abi, const QString& vcvarsBat); + AbstractMsvcToolChain(const QString &id, bool autodetect); + + Abi targetAbi() const; + + bool isValid() const; + QByteArray predefinedMacros() const; + + QList<HeaderPath> systemHeaderPaths() const; + + void addToEnvironment(Utils::Environment &env) const; + QString makeCommand() const; + void setDebuggerCommand(const QString &d); + + QString debuggerCommand() const; + IOutputParser *outputParser() const; + + bool canClone() const; + + QString varsBat() const { return m_vcvarsBat; } +protected: + virtual Utils::Environment readEnvironmentSetting(Utils::Environment& env) const = 0; + virtual QByteArray msvcPredefinedMacros(const Utils::Environment& env) const; + virtual void updateId() = 0; + + bool generateEnvironmentSettings(Utils::Environment &env, + const QString& batchFile, + const QString& batchArgs, + QMap<QString, QString>& envPairs) const; + + QString m_debuggerCommand; + mutable QByteArray m_predefinedMacros; + mutable Utils::Environment m_lastEnvironment; // Last checked 'incoming' environment. + mutable Utils::Environment m_resultEnvironment; // Resulting environment for VC + mutable QList<HeaderPath> m_headerPaths; + Abi m_abi; + + QString m_vcvarsBat; +}; + +} // namespace Internal +} // namespace ProjectExplorer + +#endif // ABSTRACTMSVCTOOLCHAIN_H diff --git a/src/plugins/projectexplorer/msvctoolchain.cpp b/src/plugins/projectexplorer/msvctoolchain.cpp index 9baa888e228423b8f29adccc50e3d11ce648a281..d7577b6a061919b5be10a356b3b9f648c0069ddd 100644 --- a/src/plugins/projectexplorer/msvctoolchain.cpp +++ b/src/plugins/projectexplorer/msvctoolchain.cpp @@ -40,18 +40,14 @@ #include <projectexplorer/projectexplorersettings.h> #include <utils/fileutils.h> -#include <utils/qtcprocess.h> -#include <utils/qtcassert.h> #include <utils/synchronousprocess.h> #include <utils/winutils.h> +#include <utils/qtcassert.h> -#include <QtCore/QCoreApplication> #include <QtCore/QDir> -#include <QtCore/QFileInfo> +#include <QtCore/QProcess> #include <QtCore/QSettings> #include <QtCore/QUrl> -#include <QtCore/QTemporaryFile> -#include <QtGui/QLabel> #include <QtGui/QFormLayout> #include <QtGui/QDesktopServices> @@ -170,16 +166,9 @@ static QByteArray msvcCompilationFile() } // Run MSVC 'cl' compiler to obtain #defines. -static QByteArray msvcPredefinedMacros(const Utils::Environment &env) +QByteArray MsvcToolChain::msvcPredefinedMacros(const Utils::Environment &env) const { - QByteArray predefinedMacros = "#define __MSVCRT__\n" - "#define __w64\n" - "#define __int64 long long\n" - "#define __int32 long\n" - "#define __int16 short\n" - "#define __int8 char\n" - "#define __ptr32\n" - "#define __ptr64\n"; + QByteArray predefinedMacros = AbstractMsvcToolChain::msvcPredefinedMacros(env); Utils::TempFileSaver saver(QDir::tempPath()+"/envtestXXXXXX.cpp"); saver.write(msvcCompilationFile()); @@ -258,77 +247,24 @@ static QString winExpandDelayedEnvReferences(QString in, const Utils::Environmen return in; } -static Utils::Environment msvcReadEnvironmentSetting(const QString &varsBat, - const QString &args, - Utils::Environment env) +Utils::Environment MsvcToolChain::readEnvironmentSetting(Utils::Environment& env) const { - // Run the setup script and extract the variables Utils::Environment result = env; - if (!QFileInfo(varsBat).exists()) + if (!QFileInfo(m_vcvarsBat).exists()) return result; - const QString tempOutputFileName = QDir::tempPath() + QLatin1String("\\qtcreator-msvc-environment.txt"); - Utils::TempFileSaver saver(QDir::tempPath() + "\\XXXXXX.bat"); - QByteArray call = "call "; - call += Utils::QtcProcess::quoteArg(varsBat).toLocal8Bit(); - if (!args.isEmpty()) { - call += ' '; - call += args.toLocal8Bit(); - } - call += "\r\n"; - saver.write(call); - const QByteArray redirect = "set > " + Utils::QtcProcess::quoteArg( - QDir::toNativeSeparators(tempOutputFileName)).toLocal8Bit() + "\r\n"; - saver.write(redirect); - if (!saver.finalize()) { - qWarning("%s: %s", Q_FUNC_INFO, qPrintable(saver.errorString())); + QMap<QString, QString> envPairs; + if (!generateEnvironmentSettings(env, m_vcvarsBat, m_varsBatArg, envPairs)) return result; - } - - Utils::QtcProcess run; - // As of WinSDK 7.1, there is logic preventing the path from being set - // correctly if "ORIGINALPATH" is already set. That can cause problems - // if Creator is launched within a session set up by setenv.cmd. - env.unset(QLatin1String("ORIGINALPATH")); - run.setEnvironment(env); - const QString cmdPath = QString::fromLocal8Bit(qgetenv("COMSPEC")); - // Windows SDK setup scripts require command line switches for environment expansion. - QString cmdArguments = QLatin1String(" /E:ON /V:ON /c \""); - cmdArguments += QDir::toNativeSeparators(saver.fileName()); - cmdArguments += QLatin1Char('"'); - run.setCommand(cmdPath, cmdArguments); - if (debug) - qDebug() << "msvcReadEnvironmentSetting: " << call << cmdPath << cmdArguments - << " Env: " << env.size(); - run.start(); - if (!run.waitForStarted()) { - qWarning("%s: Unable to run '%s': %s", Q_FUNC_INFO, qPrintable(varsBat), - qPrintable(run.errorString())); - return result; - } - if (!run.waitForFinished()) { - qWarning("%s: Timeout running '%s'", Q_FUNC_INFO, qPrintable(varsBat)); - Utils::SynchronousProcess::stopProcess(run); - return result; + // Now loop through and process them + QMap<QString,QString>::const_iterator envIter; + for (envIter = envPairs.begin(); envIter!=envPairs.end(); ++envIter) { + const QString expandedValue = winExpandDelayedEnvReferences(envIter.value(), env); + if (!expandedValue.isEmpty()) + result.set(envIter.key(), expandedValue); } - QFile varsFile(tempOutputFileName); - if (!varsFile.open(QIODevice::ReadOnly|QIODevice::Text)) - return result; - - QRegExp regexp(QLatin1String("(\\w*)=(.*)")); - while (!varsFile.atEnd()) { - const QString line = QString::fromLocal8Bit(varsFile.readLine()).trimmed(); - if (regexp.exactMatch(line)) { - const QString varName = regexp.cap(1); - const QString expandedValue = winExpandDelayedEnvReferences(regexp.cap(2), env); - if (!expandedValue.isEmpty()) - result.set(varName, expandedValue); - } - } - varsFile.close(); - varsFile.remove(); if (debug) { const QStringList newVars = result.toStringList(); const QStringList oldVars = env.toStringList(); @@ -347,26 +283,17 @@ static Utils::Environment msvcReadEnvironmentSetting(const QString &varsBat, MsvcToolChain::MsvcToolChain(const QString &name, const Abi &abi, const QString &varsBat, const QString &varsBatArg, bool autodetect) : - ToolChain(QLatin1String(Constants::MSVC_TOOLCHAIN_ID), autodetect), - m_varsBat(varsBat), - m_varsBatArg(varsBatArg), - m_lastEnvironment(Utils::Environment::systemEnvironment()), - m_abi(abi) + AbstractMsvcToolChain(QLatin1String(Constants::MSVC_TOOLCHAIN_ID), autodetect, abi, varsBat), + m_varsBatArg(varsBatArg) { Q_ASSERT(!name.isEmpty()); - Q_ASSERT(!m_varsBat.isEmpty()); - Q_ASSERT(QFileInfo(m_varsBat).exists()); - Q_ASSERT(abi.os() == Abi::WindowsOS); - Q_ASSERT(abi.binaryFormat() == Abi::PEFormat); - Q_ASSERT(abi.osFlavor() != Abi::WindowsMSysFlavor); updateId(); setDisplayName(name); } MsvcToolChain::MsvcToolChain() : - ToolChain(QLatin1String(Constants::MSVC_TOOLCHAIN_ID), false), - m_lastEnvironment(Utils::Environment::systemEnvironment()) + AbstractMsvcToolChain(QLatin1String(Constants::MSVC_TOOLCHAIN_ID), false) { } @@ -384,7 +311,7 @@ void MsvcToolChain::updateId() const QChar colon = QLatin1Char(':'); QString id = QLatin1String(Constants::MSVC_TOOLCHAIN_ID); id += colon; - id += m_varsBat; + id += m_vcvarsBat; id += colon; id += m_varsBatArg; id += colon; @@ -397,49 +324,6 @@ QString MsvcToolChain::typeName() const return MsvcToolChainFactory::tr("MSVC"); } -Abi MsvcToolChain::targetAbi() const -{ - return m_abi; -} - -bool MsvcToolChain::isValid() const -{ - return !m_varsBat.isEmpty(); -} - -QByteArray MsvcToolChain::predefinedMacros() const -{ - if (m_predefinedMacros.isEmpty()) { - Utils::Environment env(m_lastEnvironment); - addToEnvironment(env); - m_predefinedMacros = msvcPredefinedMacros(env); - } - return m_predefinedMacros; -} - -QList<HeaderPath> MsvcToolChain::systemHeaderPaths() const -{ - if (m_headerPaths.isEmpty()) { - Utils::Environment env(m_lastEnvironment); - addToEnvironment(env); - foreach (const QString &path, env.value("INCLUDE").split(QLatin1Char(';'))) - m_headerPaths.append(HeaderPath(path, HeaderPath::GlobalHeaderPath)); - } - return m_headerPaths; -} - -void MsvcToolChain::addToEnvironment(Utils::Environment &env) const -{ - // We cache the full environment (incoming + modifications by setup script). - if (!m_resultEnvironment.size() || env != m_lastEnvironment) { - if (debug) - qDebug() << "addToEnvironment: " << displayName(); - m_lastEnvironment = env; - m_resultEnvironment = msvcReadEnvironmentSetting(m_varsBat, m_varsBatArg, env); - } - env = m_resultEnvironment; -} - QString MsvcToolChain::mkspec() const { if (m_abi.osFlavor() == Abi::WindowsMsvc2005Flavor) @@ -451,42 +335,12 @@ QString MsvcToolChain::mkspec() const return QString(); } -QString MsvcToolChain::makeCommand() const -{ - if (ProjectExplorerPlugin::instance()->projectExplorerSettings().useJom) { - // We want jom! Try to find it. - const QString jom = QLatin1String("jom.exe"); - const QFileInfo installedJom = QFileInfo(QCoreApplication::applicationDirPath() - + QLatin1Char('/') + jom); - if (installedJom.isFile() && installedJom.isExecutable()) { - return installedJom.absoluteFilePath(); - } else { - return jom; - } - } - return QLatin1String("nmake.exe"); -} - -void MsvcToolChain::setDebuggerCommand(const QString &d) -{ - if (m_debuggerCommand == d) - return; - m_debuggerCommand = d; - updateId(); - toolChainUpdated(); -} - -QString MsvcToolChain::debuggerCommand() const -{ - return m_debuggerCommand; -} - QVariantMap MsvcToolChain::toMap() const { QVariantMap data = ToolChain::toMap(); if (!m_debuggerCommand.isEmpty()) data.insert(QLatin1String(debuggerCommandKeyC), m_debuggerCommand); - data.insert(QLatin1String(varsBatKeyC), m_varsBat); + data.insert(QLatin1String(varsBatKeyC), m_vcvarsBat); if (!m_varsBatArg.isEmpty()) data.insert(QLatin1String(varsBatArgKeyC), m_varsBatArg); data.insert(QLatin1String(supportedAbiKeyC), m_abi.toString()); @@ -497,30 +351,22 @@ bool MsvcToolChain::fromMap(const QVariantMap &data) { if (!ToolChain::fromMap(data)) return false; - m_varsBat = data.value(QLatin1String(varsBatKeyC)).toString(); + m_vcvarsBat = data.value(QLatin1String(varsBatKeyC)).toString(); m_varsBatArg = data.value(QLatin1String(varsBatArgKeyC)).toString(); m_debuggerCommand = data.value(QLatin1String(debuggerCommandKeyC)).toString(); const QString abiString = data.value(QLatin1String(supportedAbiKeyC)).toString(); m_abi = Abi(abiString); updateId(); - return !m_varsBat.isEmpty() && m_abi.isValid(); -} -IOutputParser *MsvcToolChain::outputParser() const -{ - return new MsvcParser; + return !m_vcvarsBat.isEmpty() && m_abi.isValid(); } + ToolChainConfigWidget *MsvcToolChain::configurationWidget() { return new MsvcToolChainConfigWidget(this); } -bool MsvcToolChain::canClone() const -{ - return true; -} - ToolChain *MsvcToolChain::clone() const { return new MsvcToolChain(*this); @@ -762,6 +608,7 @@ QList<ToolChain *> MsvcToolChainFactory::autoDetect() foreach (ToolChain *tc, results) static_cast<MsvcToolChain *>(tc)->setDebuggerCommand(tc->targetAbi().wordWidth() == 32 ? cdbDebugger.first : cdbDebugger.second); } + return results; } diff --git a/src/plugins/projectexplorer/msvctoolchain.h b/src/plugins/projectexplorer/msvctoolchain.h index 937154a9d91cefc72d00a66ef190d06fd1bd3100..fde8e1bb46c750a1f81d106642d650cfdb1da6e4 100644 --- a/src/plugins/projectexplorer/msvctoolchain.h +++ b/src/plugins/projectexplorer/msvctoolchain.h @@ -33,7 +33,7 @@ #ifndef MSVCTOOLCHAIN_H #define MSVCTOOLCHAIN_H -#include "toolchain.h" +#include "abstractmsvctoolchain.h" #include "abi.h" #include "toolchainconfigwidget.h" @@ -48,7 +48,7 @@ namespace Internal { // MsvcToolChain // -------------------------------------------------------------------------- -class MsvcToolChain : public ToolChain +class MsvcToolChain : public AbstractMsvcToolChain { public: enum Type { WindowsSDK, VS }; @@ -60,44 +60,29 @@ public: static MsvcToolChain *readFromMap(const QVariantMap &data); QString typeName() const; - Abi targetAbi() const; - bool isValid() const; - - QByteArray predefinedMacros() const; - QList<HeaderPath> systemHeaderPaths() const; - void addToEnvironment(Utils::Environment &env) const; QString mkspec() const; - QString makeCommand() const; - void setDebuggerCommand(const QString &d); - virtual QString debuggerCommand() const; - IOutputParser *outputParser() const; - virtual QVariantMap toMap() const; - virtual bool fromMap(const QVariantMap &data); + QVariantMap toMap() const; + bool fromMap(const QVariantMap &data); ToolChainConfigWidget *configurationWidget(); - bool canClone() const; ToolChain *clone() const; - QString varsBat() const { return m_varsBat; } QString varsBatArg() const { return m_varsBatArg; } static QPair<QString, QString> autoDetectCdbDebugger(); +protected: + Utils::Environment readEnvironmentSetting(Utils::Environment& env) const; + QByteArray msvcPredefinedMacros(const Utils::Environment &env) const; + private: MsvcToolChain(); void updateId(); - QString m_varsBat; // Script to setup environment QString m_varsBatArg; // Argument - QString m_debuggerCommand; - mutable QByteArray m_predefinedMacros; - mutable Utils::Environment m_lastEnvironment; // Last checked 'incoming' environment. - mutable Utils::Environment m_resultEnvironment; // Resulting environment for VC - mutable QList<HeaderPath> m_headerPaths; - Abi m_abi; }; // -------------------------------------------------------------------------- diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index cf380ace6afa4346076f77b5ac8acf1e6470a92d..6cbed896af0d79d87325ef1c049927eb2e102257 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -85,6 +85,7 @@ #ifdef Q_OS_WIN # include "windebuginterface.h" # include "msvctoolchain.h" +# include "wincetoolchain.h" #endif #include <extensionsystem/pluginspec.h> @@ -318,6 +319,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er addAutoReleasedObject(new Internal::MingwToolChainFactory); addAutoReleasedObject(new Internal::MsvcToolChainFactory); + addAutoReleasedObject(new Internal::WinCEToolChainFactory); #else addAutoReleasedObject(new Internal::GccToolChainFactory); addAutoReleasedObject(new Internal::LinuxIccToolChainFactory); diff --git a/src/plugins/projectexplorer/projectexplorer.pro b/src/plugins/projectexplorer/projectexplorer.pro index dd5f9abf2b22c841016c9b203769716704d5bd8f..b526d840fd7ad96e2faa98df4608b12175acc721 100644 --- a/src/plugins/projectexplorer/projectexplorer.pro +++ b/src/plugins/projectexplorer/projectexplorer.pro @@ -213,11 +213,15 @@ win32 { SOURCES += \ windebuginterface.cpp \ msvcparser.cpp \ - msvctoolchain.cpp + msvctoolchain.cpp \ + abstractmsvctoolchain.cpp \ + wincetoolchain.cpp HEADERS += \ windebuginterface.h \ msvcparser.h \ - msvctoolchain.h + msvctoolchain.h \ + abstractmsvctoolchain.h \ + wincetoolchain.h } else { macx:LIBS += -framework Carbon } diff --git a/src/plugins/projectexplorer/projectexplorerconstants.h b/src/plugins/projectexplorer/projectexplorerconstants.h index 8111e3fd24773b597aa3bb53093dd0c635d7f18f..a43c8756c41e3bf73c1272b29ffb9ede0aef6e45 100644 --- a/src/plugins/projectexplorer/projectexplorerconstants.h +++ b/src/plugins/projectexplorer/projectexplorerconstants.h @@ -215,6 +215,7 @@ const char GCC_TOOLCHAIN_ID[] = "ProjectExplorer.ToolChain.Gcc"; const char LINUXICC_TOOLCHAIN_ID[] = "ProjectExplorer.ToolChain.LinuxIcc"; const char MINGW_TOOLCHAIN_ID[] = "ProjectExplorer.ToolChain.Mingw"; const char MSVC_TOOLCHAIN_ID[] = "ProjectExplorer.ToolChain.Msvc"; +const char WINCE_TOOLCHAIN_ID[] = "ProjectExplorer.ToolChain.WinCE"; // Run Configuration defaults: const int QML_DEFAULT_DEBUG_SERVER_PORT = 3768; diff --git a/src/plugins/projectexplorer/wincetoolchain.cpp b/src/plugins/projectexplorer/wincetoolchain.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d3913524cf85cc4328f7d8b8553b076a73aa477c --- /dev/null +++ b/src/plugins/projectexplorer/wincetoolchain.cpp @@ -0,0 +1,488 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (info@qt.nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at info@qt.nokia.com. +** +**************************************************************************/ + +#include "wincetoolchain.h" + +#include "msvcparser.h" +#include "projectexplorerconstants.h" +#include "headerpath.h" + +#include <projectexplorer/projectexplorer.h> +#include <projectexplorer/projectexplorersettings.h> +#include <utils/qtcassert.h> + +#include <QtCore/QDir> +#include <QtCore/QFileInfo> +#include <QtCore/QSettings> + +#include <QtGui/QFormLayout> +#include <QtGui/QLabel> + +#include <QXmlStreamReader> + +#define KEY_ROOT "ProjectExplorer.WinCEToolChain." +static const char debuggerCommandKeyC[] = KEY_ROOT"Debugger"; +static const char msvcVerKeyC[] = KEY_ROOT"MSVCVer"; +static const char ceVerKeyC[] = KEY_ROOT"CEVer"; +static const char binPathKeyC[] = KEY_ROOT"BinPath"; +static const char includePathKeyC[] = KEY_ROOT"IncludePath"; +static const char libPathKeyC[] = KEY_ROOT"LibPath"; +static const char supportedAbiKeyC[] = KEY_ROOT"SupportedAbi"; +static const char vcVarsKeyC[] = KEY_ROOT"VCVars"; + +enum { debug = 0 }; + +namespace ProjectExplorer { +namespace Internal { + +// -------------------------------------------------------------------------- +// Helpers: +// -------------------------------------------------------------------------- + +// Just decodes from the integer version to the string used in Qt mkspecs +static QString findMsvcVer(int version) +{ + if (10 == version) + return QLatin1String("msvc2010"); + else if (9 == version) + return QLatin1String("msvc2008");; + + return QLatin1String("msvc2005"); +} + + +// Windows: Expand the delayed evaluation references returned by the +// SDK setup scripts: "PATH=$(Path);foo". Some values might expand +// to empty and should not be added +static QString winExpandDelayedEnvReferences(QString in, const Utils::Environment &env) +{ + const QString firstDelimit = QLatin1String("$("); + const QChar secondDelimit = QLatin1Char(')'); + for (int pos = 0; pos < in.size(); ) { + // Replace "$(REF)" by its value in process environment + pos = in.indexOf(firstDelimit, pos); + if (pos == -1) + break; + const int replaceStart = pos + firstDelimit.size(); + const int nextPos = in.indexOf(secondDelimit, replaceStart); + if (nextPos == -1) + break; + const QString var = in.mid(replaceStart, nextPos - replaceStart); + QString replacement = env.value(var.toUpper()); + if (replacement.isEmpty()) { + qWarning() << "No replacement for var: " << var; + pos = nextPos; + } + else { + // Not sure about this, but we need to account for the case where + // the end of the replacement doesn't have the directory seperator and + // neither does the start of the insert. This solution assumes: + // 1) Having \\ in a path is valid (it is on WinXP) + // 2) We're only replacing in paths. This will cause problems if there's + // a replace of a string + if (!replacement.endsWith('\\')) + replacement += '\\'; + + in.replace(pos, nextPos + 1 - pos, replacement); + pos += replacement.size(); + } + } + return in; +} + +// This is pretty much the same as the ReadEnvironmentSetting in the msvctoolchain.cpp, but +// this takes account of the library, binary and include paths to replace the vcvars versions +// with the ones for this toolchain. +Utils::Environment WinCEToolChain::readEnvironmentSetting(Utils::Environment& env) const +{ + Utils::Environment result = env; + if (!QFileInfo(m_vcvarsBat).exists()) + return result; + + // Get the env pairs + QMap<QString, QString> envPairs; + + if (!generateEnvironmentSettings(env, m_vcvarsBat, QString(), envPairs)) + return result; + + QMap<QString,QString>::const_iterator envPairIter; + for (envPairIter = envPairs.begin(); envPairIter!=envPairs.end(); ++envPairIter) { + // Replace the env values with those from the WinCE SDK + QString varValue = envPairIter.value(); + if ("PATH" == envPairIter.key()) + varValue = m_binPath + ";" + varValue; + else if ("INCLUDE" == envPairIter.key()) + varValue = m_includePath; + else if ("LIB" == envPairIter.key()) + varValue = m_libPath; + + if (!varValue.isEmpty()) + result.set(envPairIter.key(), varValue); + } + + + // Now loop round and do the delayed expansion + Utils::Environment::const_iterator envIter = result.constBegin(); + while (envIter != result.constEnd()) { + const QString key = result.key(envIter); + const QString unexpandedValue = result.value(envIter); + + const QString expandedValue = winExpandDelayedEnvReferences(unexpandedValue, result); + + result.set(key, expandedValue); + + ++envIter; + } + + if (debug) { + const QStringList newVars = result.toStringList(); + const QStringList oldVars = env.toStringList(); + QDebug nsp = qDebug().nospace(); + foreach (const QString &n, newVars) { + if (!oldVars.contains(n)) + nsp << n << '\n'; + } + } + return result; +} + +// Used to parse an SDK entry in the config file and extract information about this SDK +static bool parseSDK(QXmlStreamReader& theReader, + Abi::Architecture& sdkArch, + QString& sdkName, + QString& ceVer, + QString& binPath, + QString& includePath, + QString& libPath) +{ + sdkArch = Abi::UnknownArchitecture; + sdkName = ""; + + // Loop through until either the end of the file or until is gets to the next + // end element. + while (!theReader.atEnd()) { + theReader.readNext(); + + if (theReader.isEndElement()) { + // Got to the end element so return... + if (theReader.name() == "Platform") + return (sdkArch!=Abi::UnknownArchitecture && !sdkName.isEmpty()); + } else if (theReader.isStartElement()) { + const QStringRef elemName = theReader.name(); + if (elemName == "PlatformName") { + sdkName = theReader.readElementText(); + } else if (elemName == "Directories") { + // Populate the paths from this element. Note: we remove the + // $(PATH) from the binPath as this will be pre-pended in code + binPath = theReader.attributes().value("Path").toString(); + binPath.remove("$(PATH)"); + includePath = theReader.attributes().value("Include").toString(); + libPath = theReader.attributes().value("Library").toString(); + } else if (elemName == "OSMajorVersion") { + // Qt only supports CE5 and higher so drop out here if this version is + // invalid + ceVer = theReader.readElementText(); + if (ceVer.toInt() < 5) { + qDebug() << "Ignoring SDK as Qt only support CE 5 and higher."; + return false; + } + } else if (elemName == "Macro") { + // Pull out the architecture from the macro values. + if (theReader.attributes().value("Name") == "ARCHFAM") { + const QStringRef archFam = theReader.attributes().value("Value"); + + if (archFam == "ARM") + sdkArch = Abi::ArmArchitecture; + else if (archFam == "x86") + sdkArch = Abi::X86Architecture; + else if (archFam == "MIPS") + sdkArch = Abi::MipsArchitecture; + } + } + } + } + + // If we've got to here then the end of the file has been reached before the + // end of element tag, so return error. + return false; +} + +// -------------------------------------------------------------------------- +// WinCEToolChain +// -------------------------------------------------------------------------- + +WinCEToolChain::WinCEToolChain(const QString &name, + const Abi &abi, + const QString &vcvarsBat, + const QString &msvcVer, + const QString &ceVer, + const QString &binPath, + const QString &includePath, + const QString &libPath, + bool autodetect) : + AbstractMsvcToolChain(QLatin1String(Constants::WINCE_TOOLCHAIN_ID), autodetect, abi, vcvarsBat), + m_msvcVer(msvcVer), + m_ceVer(ceVer), + m_binPath(binPath), + m_includePath(includePath), + m_libPath(libPath) +{ + Q_ASSERT(!name.isEmpty()); + Q_ASSERT(!m_binPath.isEmpty()); + Q_ASSERT(!m_includePath.isEmpty()); + Q_ASSERT(!m_libPath.isEmpty()); + + updateId(); + setDisplayName(name); +} + +WinCEToolChain::WinCEToolChain() : + AbstractMsvcToolChain(QLatin1String(Constants::WINCE_TOOLCHAIN_ID), false) +{ +} + +WinCEToolChain *WinCEToolChain::readFromMap(const QVariantMap &data) +{ + WinCEToolChain *tc = new WinCEToolChain; + if (tc->fromMap(data)) + return tc; + delete tc; + return 0; +} + +void WinCEToolChain::updateId() +{ + const QChar colon = QLatin1Char(':'); + QString id = QLatin1String(Constants::WINCE_TOOLCHAIN_ID); + id += colon; + id += m_msvcVer; + id += colon; + id += m_binPath; + id += colon; + id += m_includePath; + id += colon; + id += m_libPath; + id += colon; + id += m_debuggerCommand; + setId(id); +} + +QString WinCEToolChain::typeName() const +{ + return WinCEToolChainFactory::tr("WinCE"); +} + +QString WinCEToolChain::mkspec() const +{ + const QChar specSeperator('-'); + + QString specString = QLatin1String("wince"); + + specString += m_ceVer; + specString += specSeperator; + specString += Abi::toString(m_abi.architecture()); + specString += specSeperator; + specString += m_msvcVer; + + return specString; +} + + +QString WinCEToolChain::ceVer() const +{ + return m_ceVer; +} + + +QVariantMap WinCEToolChain::toMap() const +{ + QVariantMap data = ToolChain::toMap(); + if (!m_debuggerCommand.isEmpty()) + data.insert(QLatin1String(debuggerCommandKeyC), m_debuggerCommand); + + data.insert(QLatin1String(msvcVerKeyC), m_msvcVer); + data.insert(QLatin1String(ceVerKeyC), m_ceVer); + data.insert(QLatin1String(binPathKeyC), m_binPath); + data.insert(QLatin1String(includePathKeyC), m_includePath); + data.insert(QLatin1String(libPathKeyC), m_libPath); + data.insert(QLatin1String(vcVarsKeyC), m_vcvarsBat); + + data.insert(QLatin1String(supportedAbiKeyC), m_abi.toString()); + return data; +} + +bool WinCEToolChain::fromMap(const QVariantMap &data) +{ + if (!ToolChain::fromMap(data)) + return false; + + m_msvcVer = data.value(QLatin1String(msvcVerKeyC)).toString(); + m_ceVer = data.value(QLatin1String(ceVerKeyC)).toString(); + m_binPath = data.value(QLatin1String(binPathKeyC)).toString(); + m_includePath = data.value(QLatin1String(includePathKeyC)).toString(); + m_libPath = data.value(QLatin1String(libPathKeyC)).toString(); + m_vcvarsBat = data.value(QLatin1String(vcVarsKeyC)).toString(); + + m_debuggerCommand = data.value(QLatin1String(debuggerCommandKeyC)).toString(); + const QString abiString = data.value(QLatin1String(supportedAbiKeyC)).toString(); + m_abi = Abi(abiString); + updateId(); + + return isValid(); +} + +ToolChainConfigWidget *WinCEToolChain::configurationWidget() +{ + return new WinCEToolChainConfigWidget(this); +} + +ToolChain *WinCEToolChain::clone() const +{ + return new WinCEToolChain(*this); +} + + + +// -------------------------------------------------------------------------- +// WinCEToolChainFactory +// -------------------------------------------------------------------------- + +QString WinCEToolChainFactory::displayName() const +{ + return tr("WinCE"); +} + +QString WinCEToolChainFactory::id() const +{ + return QLatin1String(Constants::WINCE_TOOLCHAIN_ID); +} + + +QList<ToolChain *> WinCEToolChainFactory::autoDetect() +{ + QList<ToolChain *> results; + + // 1) Installed WinCEs + const QSettings vsRegistry( +#ifdef Q_OS_WIN64 + QLatin1String("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\VisualStudio\\SxS\\VC7"), +#else + QLatin1String("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VC7"), +#endif + QSettings::NativeFormat); + + foreach (const QString &vsName, vsRegistry.allKeys()) { + // Scan for version major.minor + const int dotPos = vsName.indexOf(QLatin1Char('.')); + if (dotPos == -1) + continue; + + const QString path = QDir::fromNativeSeparators(vsRegistry.value(vsName).toString()); + const int version = vsName.left(dotPos).toInt(); + + // Check existence of various install scripts + const QString vcvars32bat = path + QLatin1String("bin/vcvars32.bat"); + QFile cePlatforms(path + "vcpackages/WCE.VCPlatform.config"); + + if (cePlatforms.exists()) { + const QString msvcVer = findMsvcVer(version); + cePlatforms.open(QIODevice::ReadOnly); + QXmlStreamReader platformReader(&cePlatforms); + + // Rip through the config file getting all of the installed platforms. + while (!platformReader.atEnd()) { + platformReader.readNext(); + if (platformReader.isStartElement()) { + if (platformReader.name() == "Platform") { + Abi::Architecture theArch; + QString thePlat; + QString binPath; + QString includePath; + QString libPath; + QString ceVer; + + if (parseSDK(platformReader, theArch, thePlat, ceVer, binPath, includePath, libPath)) { + WinCEToolChain *pChain = new WinCEToolChain(thePlat, + Abi(theArch, Abi::WindowsOS, Abi::WindowsCEFlavor, Abi::PEFormat, 32), + vcvars32bat, + msvcVer, + ceVer, + binPath, + includePath, + libPath, + true); + results.append(pChain); + } + } + } + } + } + } + + return results; +} + + +QString WinCEToolChain::autoDetectCdbDebugger(QStringList *checkedDirectories /* = 0 */) +{ + return QString(); +} + +bool WinCEToolChainFactory::canRestore(const QVariantMap &data) +{ + return idFromMap(data).startsWith(QLatin1String(Constants::WINCE_TOOLCHAIN_ID) + QLatin1Char(':')); +} + +ToolChain *WinCEToolChainFactory::restore(const QVariantMap &data) +{ + return WinCEToolChain::readFromMap(data); +} + +// -------------------------------------------------------------------------- +// WinCEToolChainConfigWidget +// -------------------------------------------------------------------------- + +WinCEToolChainConfigWidget::WinCEToolChainConfigWidget(ToolChain *tc) : + ToolChainConfigWidget(tc) +{ + WinCEToolChain *toolChain = static_cast<WinCEToolChain *>(tc); + QTC_ASSERT(tc, return); + + QFormLayout *formLayout = new QFormLayout(this); + formLayout->addRow(tr("SDK:"), new QLabel(toolChain->displayName())); + formLayout->addRow(tr("WinCE Version:"), new QLabel(toolChain->ceVer())); + formLayout->addRow(tr("ABI:"), new QLabel(toolChain->targetAbi().toString())); + addErrorLabel(formLayout); +} + +} // namespace Internal +} // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/wincetoolchain.h b/src/plugins/projectexplorer/wincetoolchain.h new file mode 100644 index 0000000000000000000000000000000000000000..2bc28932acc222c0204470cfb9dcb8fedea7ee24 --- /dev/null +++ b/src/plugins/projectexplorer/wincetoolchain.h @@ -0,0 +1,139 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (info@qt.nokia.com) +** +** +** GNU Lesser General Public License Usage +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at info@qt.nokia.com. +** +**************************************************************************/ + +#ifndef WINCETOOLCHAIN_H +#define WINCETOOLCHAIN_H + +#include "abstractmsvctoolchain.h" +#include "abi.h" +#include "toolchainconfigwidget.h" + +#include <utils/environment.h> + +#include <QtGui/QLabel> + +namespace ProjectExplorer { +namespace Internal { + +// -------------------------------------------------------------------------- +// WinCEToolChain +// -------------------------------------------------------------------------- + +class WinCEToolChain : public AbstractMsvcToolChain +{ +public: + + WinCEToolChain(const QString &name, + const Abi &abi, + const QString &vcvarsBat, + const QString &msvcVer, + const QString &ceVer, + const QString &binPath, + const QString &includePath, + const QString &libPath, + bool autodetect = false); + + static WinCEToolChain *readFromMap(const QVariantMap &data); + + QString typeName() const; + + QString mkspec() const; + + QString ceVer() const; + + QVariantMap toMap() const; + bool fromMap(const QVariantMap &data); + + ToolChainConfigWidget *configurationWidget(); + + ToolChain *clone() const; + + static QString autoDetectCdbDebugger(QStringList *checkedDirectories = 0); + +protected: + Utils::Environment readEnvironmentSetting(Utils::Environment& env) const; + +private: + WinCEToolChain(); + void updateId(); + + QString m_msvcVer; + QString m_ceVer; + QString m_binPath; + QString m_includePath; + QString m_libPath; +}; + +// -------------------------------------------------------------------------- +// WinCEToolChainConfigWidget +// -------------------------------------------------------------------------- +class WinCEToolChainConfigWidget : public ToolChainConfigWidget +{ + Q_OBJECT + +public: + WinCEToolChainConfigWidget(ToolChain *); + + void apply() {} + void discard() { } + bool isDirty() const {return false;} + +}; + +// -------------------------------------------------------------------------- +// WinCEToolChainFactory +// -------------------------------------------------------------------------- + +class WinCEToolChainFactory : public ToolChainFactory +{ + Q_OBJECT + +public: + QString displayName() const; + QString id() const; + + QList<ToolChain *> autoDetect(); + + bool canRestore(const QVariantMap &data); + ToolChain *restore(const QVariantMap &data); + + ToolChainConfigWidget *configurationWidget(ToolChain *); + +private: + QList<ToolChain *> detectCEToolKits(const QString& msvcPath, const QString& vcvarsbat); +}; + + +} // namespace Internal +} // namespace ProjectExplorer + +#endif // MSVCTOOLCHAIN_H diff --git a/src/plugins/qt4projectmanager/winceqtversion.cpp b/src/plugins/qt4projectmanager/winceqtversion.cpp index 44c8986e4de93289b82bfaa35cd09b1498544b2f..d0c99bb920c70f3438a62c256eebf9d957ed5de9 100644 --- a/src/plugins/qt4projectmanager/winceqtversion.cpp +++ b/src/plugins/qt4projectmanager/winceqtversion.cpp @@ -39,20 +39,22 @@ using namespace Qt4ProjectManager; using namespace Qt4ProjectManager::Internal; WinCeQtVersion::WinCeQtVersion() - : QtSupport::BaseQtVersion() + : QtSupport::BaseQtVersion(), + m_archType(ProjectExplorer::Abi::ArmArchitecture) { - } -WinCeQtVersion::WinCeQtVersion(const QString &path, bool isAutodetected, const QString &autodetectionSource) - : QtSupport::BaseQtVersion(path, isAutodetected, autodetectionSource) +WinCeQtVersion::WinCeQtVersion(const QString &path, const QString& archType, bool isAutodetected, const QString &autodetectionSource) + : QtSupport::BaseQtVersion(path, isAutodetected, autodetectionSource), m_archType(ProjectExplorer::Abi::ArmArchitecture) { - + if (0 == archType.compare("x86", Qt::CaseInsensitive)) + m_archType = ProjectExplorer::Abi::X86Architecture; + else if (0 == archType.compare("mipsii", Qt::CaseInsensitive)) + m_archType = ProjectExplorer::Abi::MipsArchitecture; } WinCeQtVersion::~WinCeQtVersion() { - } WinCeQtVersion *WinCeQtVersion::clone() const @@ -68,7 +70,7 @@ QString WinCeQtVersion::type() const QList<ProjectExplorer::Abi> WinCeQtVersion::detectQtAbis() const { return QList<ProjectExplorer::Abi>() - << ProjectExplorer::Abi(ProjectExplorer::Abi::ArmArchitecture, + << ProjectExplorer::Abi(m_archType, ProjectExplorer::Abi::WindowsOS, ProjectExplorer::Abi::WindowsCEFlavor, ProjectExplorer::Abi::PEFormat, @@ -89,3 +91,29 @@ QString WinCeQtVersion::description() const { return QCoreApplication::translate("QtVersion", "Qt for WinCE", "Qt Version is meant for WinCE"); } + +void WinCeQtVersion::fromMap(const QVariantMap &map) +{ + BaseQtVersion::fromMap(map); + + // Default to an ARM architecture, then use the makespec to see what + // the architecture is. This assumes that a WinCE makespec will be + // named <Description>-<Architecture>-<Compiler> with no other '-' characters. + m_archType = ProjectExplorer::Abi::ArmArchitecture; + + const QStringList splitSpec = mkspec().split("-"); + if (splitSpec.length() == 3) { + const QString archString = splitSpec.value(1); + if (archString.contains("x86", Qt::CaseInsensitive)) + m_archType = ProjectExplorer::Abi::X86Architecture; + else if (archString.contains("mips", Qt::CaseInsensitive)) + m_archType = ProjectExplorer::Abi::MipsArchitecture; + } +} + +QVariantMap WinCeQtVersion::toMap() const +{ + QVariantMap result = BaseQtVersion::toMap(); + + return result; +} diff --git a/src/plugins/qt4projectmanager/winceqtversion.h b/src/plugins/qt4projectmanager/winceqtversion.h index b94b8c339826c8deb1ba3ab84463ed6bfc55f89d..03d2ff8385cab1553700b766e73ade099cc1b2f7 100644 --- a/src/plugins/qt4projectmanager/winceqtversion.h +++ b/src/plugins/qt4projectmanager/winceqtversion.h @@ -42,7 +42,7 @@ class WinCeQtVersion : public QtSupport::BaseQtVersion { public: WinCeQtVersion(); - WinCeQtVersion(const QString &path, bool isAutodetected = false, const QString &autodetectionSource = QString()); + WinCeQtVersion(const QString &path, const QString& archType, bool isAutodetected = false, const QString &autodetectionSource = QString()); ~WinCeQtVersion(); WinCeQtVersion *clone() const; @@ -54,6 +54,12 @@ public: QSet<QString> supportedTargetIds() const; QString description() const; + + virtual QVariantMap toMap() const; + virtual void fromMap(const QVariantMap &data); + +private: + ProjectExplorer::Abi::Architecture m_archType; }; } diff --git a/src/plugins/qt4projectmanager/winceqtversionfactory.cpp b/src/plugins/qt4projectmanager/winceqtversionfactory.cpp index f6d9dbea5f979e40f70577838d13d6a11a423615..26a42fd5494e8c8c558787215646e14f71cd7163 100644 --- a/src/plugins/qt4projectmanager/winceqtversionfactory.cpp +++ b/src/plugins/qt4projectmanager/winceqtversionfactory.cpp @@ -79,7 +79,7 @@ QtSupport::BaseQtVersion *WinCeQtVersionFactory::create(const QString &qmakePath QString ce_arch = evaluator->value("CE_ARCH"); if (!ce_sdk.isEmpty() && !ce_arch.isEmpty()) - return new WinCeQtVersion(qmakePath, isAutoDetected, autoDetectionSource); + return new WinCeQtVersion(qmakePath, ce_arch, isAutoDetected, autoDetectionSource); return 0; }