summaryrefslogtreecommitdiff
path: root/src/plugins/projectexplorer/wincetoolchain.cpp
diff options
context:
space:
mode:
authorSteveKing <steve_king_1974@yahoo.co.uk>2011-11-16 21:15:48 +0000
committerhjk <qthjk@ovi.com>2011-11-24 14:47:43 +0100
commitff14295b47a63c66e11498e74f807a6660bc979e (patch)
tree47a73ec6a3c5044a7a64df7ec944c1409132712b /src/plugins/projectexplorer/wincetoolchain.cpp
parent756c734e221f946f9bb69cf8c28134e07c784726 (diff)
downloadqt-creator-ff14295b47a63c66e11498e74f807a6660bc979e.tar.gz
Fix the support for WinCE.
Change-Id: Id08dab3128b9ff943c68b442e8cadf14caaee204 Reviewed-by: hjk <qthjk@ovi.com>
Diffstat (limited to 'src/plugins/projectexplorer/wincetoolchain.cpp')
-rw-r--r--src/plugins/projectexplorer/wincetoolchain.cpp488
1 files changed, 488 insertions, 0 deletions
diff --git a/src/plugins/projectexplorer/wincetoolchain.cpp b/src/plugins/projectexplorer/wincetoolchain.cpp
new file mode 100644
index 0000000000..d3913524cf
--- /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