summaryrefslogtreecommitdiff
path: root/src/plugins/winrt
diff options
context:
space:
mode:
authorDavid Schulz <david.schulz@digia.com>2014-04-25 09:20:57 +0200
committerhjk <hjk121@nokiamail.com>2014-05-16 11:21:33 +0200
commit751a61b2e4429f09209ad6f9d24c4e4eea84f2fe (patch)
treefeb5c61de14c929439c749e49d042dd7adca5b7c /src/plugins/winrt
parent93e37b7e78156f2ff17d5d62645327c3eece839a (diff)
downloadqt-creator-751a61b2e4429f09209ad6f9d24c4e4eea84f2fe.tar.gz
WinRT: Enable debugging for local packages.
Change-Id: Ic04f1a471f951caf7a79c69cceecb0ebd5d09919 Reviewed-by: hjk <hjk121@nokiamail.com>
Diffstat (limited to 'src/plugins/winrt')
-rw-r--r--src/plugins/winrt/winrt.pro8
-rw-r--r--src/plugins/winrt/winrt.qbs7
-rw-r--r--src/plugins/winrt/winrt_dependencies.pri1
-rw-r--r--src/plugins/winrt/winrtdebugsupport.cpp141
-rw-r--r--src/plugins/winrt/winrtdebugsupport.h65
-rw-r--r--src/plugins/winrt/winrtdevice.cpp12
-rw-r--r--src/plugins/winrt/winrtruncontrol.cpp125
-rw-r--r--src/plugins/winrt/winrtruncontrol.h14
-rw-r--r--src/plugins/winrt/winrtrunfactories.cpp35
-rw-r--r--src/plugins/winrt/winrtrunnerhelper.cpp240
-rw-r--r--src/plugins/winrt/winrtrunnerhelper.h99
11 files changed, 622 insertions, 125 deletions
diff --git a/src/plugins/winrt/winrt.pro b/src/plugins/winrt/winrt.pro
index f86adb8fcd..3d21060488 100644
--- a/src/plugins/winrt/winrt.pro
+++ b/src/plugins/winrt/winrt.pro
@@ -2,6 +2,7 @@ include(../../qtcreatorplugin.pri)
HEADERS += \
winrtconstants.h \
+ winrtdebugsupport.h \
winrtdeployconfiguration.h \
winrtdevice.h \
winrtdevicefactory.h \
@@ -14,9 +15,11 @@ HEADERS += \
winrtrunconfiguration.h \
winrtrunconfigurationwidget.h \
winrtruncontrol.h \
- winrtrunfactories.h
+ winrtrunfactories.h \
+ winrtrunnerhelper.h
SOURCES += \
+ winrtdebugsupport.cpp \
winrtdeployconfiguration.cpp \
winrtdevice.cpp \
winrtdevicefactory.cpp \
@@ -29,7 +32,8 @@ SOURCES += \
winrtrunconfiguration.cpp \
winrtrunconfigurationwidget.cpp \
winrtruncontrol.cpp \
- winrtrunfactories.cpp
+ winrtrunfactories.cpp \
+ winrtrunnerhelper.cpp
DEFINES += WINRT_LIBRARY
diff --git a/src/plugins/winrt/winrt.qbs b/src/plugins/winrt/winrt.qbs
index 45f3e3acee..c3168b2b2b 100644
--- a/src/plugins/winrt/winrt.qbs
+++ b/src/plugins/winrt/winrt.qbs
@@ -7,12 +7,15 @@ QtcPlugin {
minimumQtVersion: "5.0"
Depends { name: "Core" }
+ Depends { name: "Debugger" }
Depends { name: "ProjectExplorer" }
Depends { name: "QtSupport" }
Depends { name: "Qt.gui" }
files: [
"winrtconstants.h",
+ "winrtdebugsupport.cpp",
+ "winrtdebugsupport.h",
"winrtdeployconfiguration.cpp",
"winrtdeployconfiguration.h",
"winrtdevice.cpp",
@@ -40,6 +43,8 @@ QtcPlugin {
"winrtruncontrol.cpp",
"winrtruncontrol.h",
"winrtrunfactories.cpp",
- "winrtrunfactories.h"
+ "winrtrunfactories.h",
+ "winrtrunnerhelper.cpp",
+ "winrtrunnerhelper.h"
]
}
diff --git a/src/plugins/winrt/winrt_dependencies.pri b/src/plugins/winrt/winrt_dependencies.pri
index 43e33249af..8ba3491bc2 100644
--- a/src/plugins/winrt/winrt_dependencies.pri
+++ b/src/plugins/winrt/winrt_dependencies.pri
@@ -1,5 +1,6 @@
QTC_PLUGIN_NAME = WinRt
QTC_PLUGIN_DEPENDS += \
coreplugin \
+ debugger \
projectexplorer \
qtsupport
diff --git a/src/plugins/winrt/winrtdebugsupport.cpp b/src/plugins/winrt/winrtdebugsupport.cpp
new file mode 100644
index 0000000000..bb6bd4a373
--- /dev/null
+++ b/src/plugins/winrt/winrtdebugsupport.cpp
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "winrtdebugsupport.h"
+#include "winrtrunconfiguration.h"
+#include "winrtrunnerhelper.h"
+
+#include <debugger/debuggerengine.h>
+#include <debugger/debuggerkitinformation.h>
+#include <debugger/debuggerplugin.h>
+#include <debugger/debuggerrunner.h>
+#include <debugger/debuggerstartparameters.h>
+#include <projectexplorer/target.h>
+#include <projectexplorer/toolchain.h>
+
+#include <QFileInfo>
+#include <QLocalServer>
+#include <QLocalSocket>
+
+#include <utils/qtcprocess.h>
+
+namespace WinRt {
+namespace Internal {
+
+using namespace ProjectExplorer;
+
+WinRtDebugSupport::WinRtDebugSupport(RunControl *runControl, WinRtRunnerHelper *runner)
+ : QObject(runControl)
+ , m_debugRunControl(runControl)
+ , m_runner(runner)
+{
+ connect(m_debugRunControl, SIGNAL(finished()), this, SLOT(finish()));
+}
+
+void WinRtDebugSupport::finish()
+{
+ m_runner->stop();
+}
+
+RunControl *WinRtDebugSupport::createDebugRunControl(WinRtRunConfiguration *runConfig,
+ RunMode mode,
+ QString *errorMessage)
+{
+ // FIXME: This is just working for local debugging;
+ using namespace Debugger;
+ DebuggerStartParameters params;
+ params.startMode = AttachExternal;
+ params.languages |= CppLanguage;
+ params.breakOnMain = mode == DebugRunModeWithBreakOnMain;
+ // The first Thread needs to be resumed manually.
+ params.commandsAfterConnect = "~0 m";
+ Kit *kit = runConfig->target()->kit();
+ params.debuggerCommand = DebuggerKitInformation::debuggerCommand(kit).toString();
+ if (ToolChain *tc = ToolChainKitInformation::toolChain(kit))
+ params.toolChainAbi = tc->targetAbi();
+
+ QFileInfo debuggerHelper(QCoreApplication::applicationDirPath()
+ + QLatin1String("/winrtdebughelper.exe"));
+ if (!debuggerHelper.isExecutable()) {
+ *errorMessage = tr("The WinRT debugging helper is missing from your Qt Creator "
+ "installation. It was assumed to be located at").arg(
+ debuggerHelper.absoluteFilePath());
+ return 0;
+ }
+
+ WinRtRunnerHelper *runner = new WinRtRunnerHelper(runConfig, errorMessage);
+ if (!errorMessage->isEmpty())
+ return 0;
+
+ runner->debug(debuggerHelper.absoluteFilePath());
+ if (!runner->waitForStarted()) {
+ *errorMessage = tr("Cannot start the WinRT Runner Tool.");
+ return 0;
+ }
+
+ QLocalServer server;
+ server.listen(QLatin1String("QtCreatorWinRtDebugPIDPipe"));
+ if (!server.waitForNewConnection(10000)) {
+ *errorMessage = tr("Cannot establish connection to the WinRT debugging helper.");
+ return 0;
+ }
+
+ while (server.hasPendingConnections()) {
+ QLocalSocket *connection = server.nextPendingConnection();
+ if (connection->waitForReadyRead(1000)) {
+ const QByteArray &output = connection->readAll();
+ QList<QByteArray> arg = output.split(':');
+ if (arg.first() == "PID") {
+ bool ok =false;
+ params.attachPID = arg.last().toInt(&ok);
+ if (!ok) {
+ *errorMessage = tr("Cannot extract the PID from the WinRT debugging helper. "
+ "(output: %1)").arg(QString::fromLocal8Bit(output));
+ return 0;
+ }
+ server.close();
+ Debugger::DebuggerRunControl *debugRunControl
+ = DebuggerPlugin::createDebugger(params, runConfig, errorMessage);
+ runner->setRunControl(debugRunControl);
+ new WinRtDebugSupport(debugRunControl, runner);
+ return debugRunControl;
+ }
+ }
+ }
+
+ server.close();
+
+ *errorMessage = tr("Cannot create an appropriate run control for "
+ "the current run configuration.");
+
+ return 0;
+}
+
+} // namespace Internal
+} // namespace WinRt
diff --git a/src/plugins/winrt/winrtdebugsupport.h b/src/plugins/winrt/winrtdebugsupport.h
new file mode 100644
index 0000000000..3eece409e4
--- /dev/null
+++ b/src/plugins/winrt/winrtdebugsupport.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+
+#ifndef WINRT_INTERNAL_WINRTDEBUGSUPPORT_H
+#define WINRT_INTERNAL_WINRTDEBUGSUPPORT_H
+
+#include <projectexplorer/runconfiguration.h>
+
+#include <QObject>
+
+namespace WinRt {
+namespace Internal {
+
+class WinRtRunConfiguration;
+class WinRtRunnerHelper;
+
+class WinRtDebugSupport : public QObject
+{
+ Q_OBJECT
+public:
+ static ProjectExplorer::RunControl *createDebugRunControl(WinRtRunConfiguration *runConfig,
+ ProjectExplorer::RunMode mode,
+ QString *errorMessage);
+
+private:
+ WinRtDebugSupport(ProjectExplorer::RunControl *runControl, WinRtRunnerHelper *runner);
+
+ ProjectExplorer::RunControl *m_debugRunControl;
+ WinRtRunnerHelper *m_runner;
+
+private slots:
+ void finish();
+};
+
+} // namespace Internal
+} // namespace WinRt
+
+#endif // WINRT_INTERNAL_WINRTDEBUGSUPPORT_H
diff --git a/src/plugins/winrt/winrtdevice.cpp b/src/plugins/winrt/winrtdevice.cpp
index b919c18102..b9c42db938 100644
--- a/src/plugins/winrt/winrtdevice.cpp
+++ b/src/plugins/winrt/winrtdevice.cpp
@@ -30,6 +30,7 @@
#include "winrtdevice.h"
#include "winrtconstants.h"
+#include <projectexplorer/devicesupport/desktopprocesssignaloperation.h>
#include <projectexplorer/devicesupport/devicemanager.h>
#include <projectexplorer/devicesupport/deviceprocesslist.h>
#include <utils/qtcassert.h>
@@ -84,9 +85,16 @@ void WinRtDevice::executeAction(Core::Id actionId, QWidget *parent)
Q_UNUSED(parent);
}
-ProjectExplorer::DeviceProcessSignalOperation::Ptr WinRtDevice::signalOperation() const
+DeviceProcessSignalOperation::Ptr WinRtDevice::signalOperation() const
{
- return DeviceProcessSignalOperation::Ptr();
+ class WinRtDesktopSignalOperation : public ProjectExplorer::DesktopProcessSignalOperation
+ {
+ public:
+ WinRtDesktopSignalOperation() {}
+ ~WinRtDesktopSignalOperation() {}
+ };
+
+ return DeviceProcessSignalOperation::Ptr(new WinRtDesktopSignalOperation());
}
void WinRtDevice::fromMap(const QVariantMap &map)
diff --git a/src/plugins/winrt/winrtruncontrol.cpp b/src/plugins/winrt/winrtruncontrol.cpp
index 830ba5c27b..92598c34e6 100644
--- a/src/plugins/winrt/winrtruncontrol.cpp
+++ b/src/plugins/winrt/winrtruncontrol.cpp
@@ -28,9 +28,10 @@
****************************************************************************/
#include "winrtruncontrol.h"
-#include "winrtrunconfiguration.h"
-#include "winrtconstants.h"
+
#include "winrtdevice.h"
+#include "winrtrunconfiguration.h"
+#include "winrtrunnerhelper.h"
#include <coreplugin/idocument.h>
#include <extensionsystem/pluginmanager.h>
@@ -41,7 +42,8 @@
#include <projectexplorer/kitinformation.h>
#include <qtsupport/qtkitinformation.h>
-using ProjectExplorer::BuildConfiguration;
+#include <QTimer>
+
using ProjectExplorer::DeviceKitInformation;
using ProjectExplorer::IDevice;
using ProjectExplorer::RunControl;
@@ -54,39 +56,10 @@ namespace Internal {
WinRtRunControl::WinRtRunControl(WinRtRunConfiguration *runConfiguration, RunMode mode)
: RunControl(runConfiguration, mode)
+ , m_runConfiguration(runConfiguration)
, m_state(StoppedState)
- , m_process(0)
+ , m_runner(0)
{
- Target *target = runConfiguration->target();
- IDevice::ConstPtr device = DeviceKitInformation::device(target->kit());
- m_device = device.dynamicCast<const WinRtDevice>();
-
- const QtSupport::BaseQtVersion *qt = QtSupport::QtKitInformation::qtVersion(target->kit());
- if (!qt) {
- appendMessage(tr("The current kit has no Qt version."),
- Utils::ErrorMessageFormat);
- return;
- }
-
- m_isWinPhone = (qt->type() == QLatin1String(Constants::WINRT_WINPHONEQT));
- m_runnerFilePath = qt->binPath().toString() + QStringLiteral("/winrtrunner.exe");
- if (!QFile::exists(m_runnerFilePath)) {
- appendMessage(tr("Cannot find winrtrunner.exe in \"%1\".").arg(
- QDir::toNativeSeparators(qt->binPath().toString())),
- Utils::ErrorMessageFormat);
- return;
- }
-
- const Utils::FileName proFile = Utils::FileName::fromString(
- target->project()->document()->filePath());
- m_executableFilePath = target->applicationTargets().targetForProject(proFile).toString()
- + QStringLiteral(".exe"); // ### we should not need to append ".exe" here.
-
- m_arguments = runConfiguration->arguments();
- m_uninstallAfterStop = runConfiguration->uninstallAfterStop();
-
- if (BuildConfiguration *bc = target->activeBuildConfiguration())
- m_environment = bc->environment();
}
void WinRtRunControl::start()
@@ -99,13 +72,10 @@ void WinRtRunControl::start()
RunControl::StopResult WinRtRunControl::stop()
{
- if (m_state != StartedState) {
- m_state = StoppedState;
+ if (m_state == StoppedState)
return StoppedSynchronously;
- }
- QTC_ASSERT(m_process, return StoppedSynchronously);
- m_process->interrupt();
+ m_runner->stop();
return AsynchronousStop;
}
@@ -126,84 +96,31 @@ void WinRtRunControl::onProcessStarted()
emit started();
}
-void WinRtRunControl::onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus)
+void WinRtRunControl::onProcessFinished()
{
- QTC_ASSERT(m_process, return);
QTC_CHECK(m_state == StartedState);
-
- if (exitStatus == QProcess::CrashExit) {
- appendMessage(tr("winrtrunner crashed.") + QLatin1Char('\n'), Utils::ErrorMessageFormat);
- } else if (exitCode != 0) {
- appendMessage(tr("winrtrunner returned with exit code %1.").arg(exitCode)
- + QLatin1Char('\n'), Utils::ErrorMessageFormat);
- } else {
- appendMessage(tr("winrtrunner finished successfully.")
- + QLatin1Char('\n'), Utils::NormalMessageFormat);
- }
-
- m_process->disconnect();
- m_process->deleteLater();
- m_process = 0;
- m_state = StoppedState;
- emit finished();
+ onProcessError();
}
void WinRtRunControl::onProcessError()
{
- QTC_ASSERT(m_process, return);
- appendMessage(tr("Error while executing winrtrunner: %1\n").arg(m_process->errorString()),
- Utils::ErrorMessageFormat);
- m_process->disconnect();
- m_process->deleteLater();
- m_process = 0;
+ QTC_ASSERT(m_runner, return);
+ m_runner->disconnect();
+ m_runner->deleteLater();
+ m_runner = 0;
m_state = StoppedState;
emit finished();
}
-void WinRtRunControl::onProcessReadyReadStdOut()
-{
- QTC_ASSERT(m_process, return);
- appendMessage(QString::fromLocal8Bit(m_process->readAllStandardOutput()), Utils::StdOutFormat);
-}
-
-void WinRtRunControl::onProcessReadyReadStdErr()
-{
- QTC_ASSERT(m_process, return);
- appendMessage(QString::fromLocal8Bit(m_process->readAllStandardError()), Utils::StdErrFormat);
-}
-
bool WinRtRunControl::startWinRtRunner()
{
- QString runnerArgs;
- QtcProcess::addArg(&runnerArgs, QStringLiteral("--profile"));
- QtcProcess::addArg(&runnerArgs, m_isWinPhone ? QStringLiteral("xap") : QStringLiteral("appx"));
- if (m_device) {
- QtcProcess::addArg(&runnerArgs, QStringLiteral("--device"));
- QtcProcess::addArg(&runnerArgs, QString::number(m_device->deviceId()));
- }
- QtcProcess::addArgs(&runnerArgs, QStringLiteral("--install --start --stop --wait 0"));
- QtcProcess::addArg(&runnerArgs, m_executableFilePath);
- if (!m_arguments.isEmpty())
- QtcProcess::addArgs(&runnerArgs, m_arguments);
-
- appendMessage(QStringLiteral("winrtrunner ") + runnerArgs + QLatin1Char('\n'),
- Utils::NormalMessageFormat);
-
- QTC_ASSERT(!m_process, m_process->deleteLater());
- m_process = new QtcProcess(this);
- connect(m_process, SIGNAL(started()), SLOT(onProcessStarted()));
- connect(m_process, SIGNAL(finished(int,QProcess::ExitStatus)),
- SLOT(onProcessFinished(int,QProcess::ExitStatus)));
- connect(m_process, SIGNAL(error(QProcess::ProcessError)), SLOT(onProcessError()));
- connect(m_process, SIGNAL(readyReadStandardOutput()), SLOT(onProcessReadyReadStdOut()));
- connect(m_process, SIGNAL(readyReadStandardError()), SLOT(onProcessReadyReadStdErr()));
-
+ QTC_ASSERT(!m_runner, return false);
+ m_runner = new WinRtRunnerHelper(this);
+ connect(m_runner, SIGNAL(started()), SLOT(onProcessStarted()));
+ connect(m_runner, SIGNAL(finished(int,QProcess::ExitStatus)), SLOT(onProcessFinished()));
+ connect(m_runner, SIGNAL(error(QProcess::ProcessError)), SLOT(onProcessError()));
m_state = StartingState;
- m_process->setUseCtrlCStub(true);
- m_process->setCommand(m_runnerFilePath, runnerArgs);
- m_process->setEnvironment(m_environment);
- m_process->setWorkingDirectory(QFileInfo(m_executableFilePath).absolutePath());
- m_process->start();
+ m_runner->start();
return true;
}
diff --git a/src/plugins/winrt/winrtruncontrol.h b/src/plugins/winrt/winrtruncontrol.h
index 8fb84c789d..1779894c5c 100644
--- a/src/plugins/winrt/winrtruncontrol.h
+++ b/src/plugins/winrt/winrtruncontrol.h
@@ -47,6 +47,7 @@ namespace WinRt {
namespace Internal {
class WinRtRunConfiguration;
+class WinRtRunnerHelper;
class WinRtRunControl : public ProjectExplorer::RunControl
{
@@ -61,24 +62,17 @@ public:
private slots:
void onProcessStarted();
- void onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
+ void onProcessFinished();
void onProcessError();
- void onProcessReadyReadStdOut();
- void onProcessReadyReadStdErr();
private:
enum State { StartingState, StartedState, StoppedState };
bool startWinRtRunner();
+ WinRtRunConfiguration *m_runConfiguration;
State m_state;
- WinRtDevice::ConstPtr m_device;
- QString m_runnerFilePath;
- QString m_executableFilePath;
- QString m_arguments;
- bool m_uninstallAfterStop;
- bool m_isWinPhone;
Utils::QtcProcess *m_process;
- Utils::Environment m_environment;
+ WinRtRunnerHelper *m_runner;
};
} // namespace Internal
diff --git a/src/plugins/winrt/winrtrunfactories.cpp b/src/plugins/winrt/winrtrunfactories.cpp
index 99c5fe77b2..48a896dfd1 100644
--- a/src/plugins/winrt/winrtrunfactories.cpp
+++ b/src/plugins/winrt/winrtrunfactories.cpp
@@ -31,16 +31,24 @@
#include "winrtrunconfiguration.h"
#include "winrtruncontrol.h"
#include "winrtconstants.h"
+#include "winrtdebugsupport.h"
-#include <projectexplorer/target.h>
-#include <projectexplorer/project.h>
#include <projectexplorer/kit.h>
#include <projectexplorer/kitinformation.h>
+#include <projectexplorer/project.h>
+#include <projectexplorer/target.h>
+#include <projectexplorer/toolchain.h>
+#include <debugger/debuggerkitinformation.h>
+#include <debugger/debuggerplugin.h>
#include <debugger/debuggerrunner.h>
+#include <debugger/debuggerstartparameters.h>
#include <utils/qtcassert.h>
+#include <QLocalServer>
+#include <QLocalSocket>
+
using namespace ProjectExplorer;
namespace WinRt {
@@ -80,7 +88,6 @@ QString WinRtRunConfigurationFactory::displayNameForId(const Core::Id id) const
bool WinRtRunConfigurationFactory::canCreate(Target *parent, const Core::Id id) const
{
- Q_UNUSED(parent);
return id == winrtConfigurationIdC && isKitCompatible(parent->kit());
}
@@ -91,7 +98,6 @@ RunConfiguration *WinRtRunConfigurationFactory::doCreate(Target *parent, const C
bool WinRtRunConfigurationFactory::canRestore(Target *parent, const QVariantMap &map) const
{
- Q_UNUSED(parent);
return ProjectExplorer::idFromMap(map) == winrtConfigurationIdC && isKitCompatible(parent->kit());
}
@@ -123,9 +129,23 @@ WinRtRunControlFactory::WinRtRunControlFactory()
bool WinRtRunControlFactory::canRun(ProjectExplorer::RunConfiguration *runConfiguration,
ProjectExplorer::RunMode mode) const
{
- if (mode != NormalRunMode)
+ if (!runConfiguration)
return false;
- return qobject_cast<WinRtRunConfiguration *>(runConfiguration);
+ IDevice::ConstPtr device = DeviceKitInformation::device(runConfiguration->target()->kit());
+ if (!device)
+ return false;
+
+ switch (mode) {
+ case DebugRunMode:
+ case DebugRunModeWithBreakOnMain:
+ if (device->type() != Constants::WINRT_DEVICE_TYPE_LOCAL)
+ return false;
+ // fall through
+ case NormalRunMode:
+ return qobject_cast<WinRtRunConfiguration *>(runConfiguration);
+ default:
+ return false;
+ }
}
ProjectExplorer::RunControl *WinRtRunControlFactory::create(
@@ -137,6 +157,9 @@ ProjectExplorer::RunControl *WinRtRunControlFactory::create(
switch (mode) {
case NormalRunMode:
return new WinRtRunControl(rc, mode);
+ case DebugRunMode:
+ case DebugRunModeWithBreakOnMain:
+ return WinRtDebugSupport::createDebugRunControl(rc, mode, errorMessage);
default:
break;
}
diff --git a/src/plugins/winrt/winrtrunnerhelper.cpp b/src/plugins/winrt/winrtrunnerhelper.cpp
new file mode 100644
index 0000000000..119bcbc8e3
--- /dev/null
+++ b/src/plugins/winrt/winrtrunnerhelper.cpp
@@ -0,0 +1,240 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+
+#include "winrtrunnerhelper.h"
+
+#include "winrtconstants.h"
+#include "winrtrunconfiguration.h"
+
+#include <coreplugin/idocument.h>
+#include <projectexplorer/buildtargetinfo.h>
+#include <projectexplorer/devicesupport/idevice.h>
+#include <projectexplorer/buildconfiguration.h>
+#include <projectexplorer/kitinformation.h>
+#include <projectexplorer/project.h>
+#include <projectexplorer/runconfiguration.h>
+#include <projectexplorer/target.h>
+#include <qtsupport/baseqtversion.h>
+#include <qtsupport/qtkitinformation.h>
+#include <utils/qtcprocess.h>
+
+#include <QDir>
+
+using namespace WinRt;
+using namespace WinRt::Internal;
+
+WinRtRunnerHelper::WinRtRunnerHelper(WinRtRunConfiguration *runConfiguration, QString *errormessage)
+ : QObject(runConfiguration)
+ , m_messenger(0)
+ , m_runConfiguration(runConfiguration)
+ , m_process(0)
+{
+ init(runConfiguration, errormessage);
+}
+
+WinRtRunnerHelper::WinRtRunnerHelper(ProjectExplorer::RunControl *runControl)
+ : QObject(runControl)
+ , m_messenger(runControl)
+ , m_runConfiguration(0)
+ , m_process(0)
+{
+ m_runConfiguration = qobject_cast<WinRtRunConfiguration *>(runControl->runConfiguration());
+ QString errorMessage;
+ if (!init(m_runConfiguration, &errorMessage))
+ runControl->appendMessage(errorMessage, Utils::ErrorMessageFormat);
+}
+
+bool WinRtRunnerHelper::init(WinRtRunConfiguration *runConfiguration, QString *errorMessage)
+{
+ ProjectExplorer::Target *target = runConfiguration->target();
+ m_device = ProjectExplorer::DeviceKitInformation::device(
+ target->kit()).dynamicCast<const WinRtDevice>();
+
+ const QtSupport::BaseQtVersion *qt = QtSupport::QtKitInformation::qtVersion(target->kit());
+ if (!qt) {
+ *errorMessage = tr("The current kit has no Qt version.");
+ return false;
+ }
+
+ m_isWinPhone = (qt->type() == QLatin1String(Constants::WINRT_WINPHONEQT));
+ m_runnerFilePath = qt->binPath().toString() + QStringLiteral("/winrtrunner.exe");
+ if (!QFile::exists(m_runnerFilePath)) {
+ *errorMessage = tr("Cannot find winrtrunner.exe in \"%1\".").arg(
+ QDir::toNativeSeparators(qt->binPath().toString()));
+ return false;
+ }
+
+ const Utils::FileName proFile = Utils::FileName::fromString(
+ target->project()->document()->filePath());
+ m_executableFilePath = target->applicationTargets().targetForProject(proFile).toString()
+ + QStringLiteral(".exe"); // ### we should not need to append ".exe" here.
+
+ m_arguments = runConfiguration->arguments();
+ m_uninstallAfterStop = runConfiguration->uninstallAfterStop();
+
+ if (ProjectExplorer::BuildConfiguration *bc = target->activeBuildConfiguration())
+ m_environment = bc->environment();
+
+ return true;
+}
+
+void WinRtRunnerHelper::debug(const QString &debuggerExecutable, const QString &debuggerArguments)
+{
+ m_debuggerExecutable = debuggerExecutable;
+ m_debuggerArguments = debuggerArguments;
+ startWinRtRunner(Debug);
+}
+
+void WinRtRunnerHelper::start()
+{
+ startWinRtRunner(Start);
+}
+
+void WinRtRunnerHelper::stop()
+{
+ if (m_process)
+ m_process->interrupt();
+ else
+ startWinRtRunner(Stop);
+}
+
+bool WinRtRunnerHelper::waitForStarted(int msecs)
+{
+ QTC_ASSERT(m_process, return false);
+ return m_process->waitForStarted(msecs);
+}
+
+void WinRtRunnerHelper::setRunControl(ProjectExplorer::RunControl *runControl)
+{
+ m_messenger = runControl;
+}
+
+void WinRtRunnerHelper::onProcessReadyReadStdOut()
+{
+ QTC_ASSERT(m_process, return);
+ if (m_messenger) {
+ m_messenger->appendMessage(QString::fromLocal8Bit(
+ m_process->readAllStandardOutput()), Utils::StdOutFormat);
+ }
+}
+
+void WinRtRunnerHelper::onProcessReadyReadStdErr()
+{
+ QTC_ASSERT(m_process, return);
+ if (m_messenger) {
+ m_messenger->appendMessage(QString::fromLocal8Bit(
+ m_process->readAllStandardError()), Utils::StdErrFormat);
+ }
+}
+
+void WinRtRunnerHelper::onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus)
+{
+ QTC_ASSERT(m_process, return);
+ m_process->disconnect();
+ m_process->deleteLater();
+ m_process = 0;
+ emit finished(exitCode, exitStatus);
+}
+
+void WinRtRunnerHelper::onProcessError(QProcess::ProcessError processError)
+{
+ QTC_ASSERT(m_process, return);
+ if (m_messenger) {
+ m_messenger->appendMessage(tr("Error while executing the WinRT Runner Tool: %1\n").arg(
+ m_process->errorString()),
+ Utils::ErrorMessageFormat);
+ }
+ m_process->disconnect();
+ m_process->deleteLater();
+ m_process = 0;
+ emit error(processError);
+}
+
+void WinRtRunnerHelper::startWinRtRunner(const RunConf &conf)
+{
+ using namespace Utils;
+ QString runnerArgs;
+ QtcProcess::addArg(&runnerArgs, QStringLiteral("--profile"));
+ QtcProcess::addArg(&runnerArgs, m_isWinPhone ? QStringLiteral("xap") : QStringLiteral("appx"));
+ if (m_device) {
+ QtcProcess::addArg(&runnerArgs, QStringLiteral("--device"));
+ QtcProcess::addArg(&runnerArgs, QString::number(m_device->deviceId()));
+ }
+
+ Utils::QtcProcess *process = 0;
+ bool connectProcess = false;
+
+ switch (conf) {
+ case Debug:
+ Utils::QtcProcess::addArg(&runnerArgs, QStringLiteral("--debug"));
+ Utils::QtcProcess::addArg(&runnerArgs, m_debuggerExecutable);
+ if (!m_debuggerArguments.isEmpty()) {
+ Utils::QtcProcess::addArg(&runnerArgs, QStringLiteral("--debugger-arguments"));
+ Utils::QtcProcess::addArg(&runnerArgs, m_debuggerArguments);
+ }
+ // fall through
+ case Start:
+ QtcProcess::addArgs(&runnerArgs, QStringLiteral("--start --stop --install --wait 0"));
+ connectProcess = true;
+ QTC_ASSERT(!m_process, m_process->deleteLater());
+ m_process = new QtcProcess(this);
+ process = m_process;
+ break;
+ case Stop:
+ Utils::QtcProcess::addArgs(&runnerArgs, QStringLiteral("--stop"));
+ process = new QtcProcess(this);
+ break;
+ }
+
+ QtcProcess::addArg(&runnerArgs, m_executableFilePath);
+ if (!m_arguments.isEmpty())
+ QtcProcess::addArgs(&runnerArgs, m_arguments);
+
+ if (m_messenger) {
+ m_messenger->appendMessage(QStringLiteral("winrtrunner ") + runnerArgs + QLatin1Char('\n'),
+ Utils::NormalMessageFormat);
+ }
+
+ if (connectProcess) {
+ connect(process, SIGNAL(started()), SIGNAL(started()));
+ connect(process, SIGNAL(finished(int, QProcess::ExitStatus)),
+ SLOT(onProcessFinished(int, QProcess::ExitStatus)));
+ connect(process, SIGNAL(error(QProcess::ProcessError)),
+ SLOT(onProcessError(QProcess::ProcessError)));
+ connect(process, SIGNAL(readyReadStandardOutput()), SLOT(onProcessReadyReadStdOut()));
+ connect(process, SIGNAL(readyReadStandardError()), SLOT(onProcessReadyReadStdErr()));
+ }
+
+ process->setUseCtrlCStub(true);
+ process->setCommand(m_runnerFilePath, runnerArgs);
+ process->setEnvironment(m_environment);
+ process->setWorkingDirectory(QFileInfo(m_executableFilePath).absolutePath());
+ process->start();
+}
diff --git a/src/plugins/winrt/winrtrunnerhelper.h b/src/plugins/winrt/winrtrunnerhelper.h
new file mode 100644
index 0000000000..06e7d36389
--- /dev/null
+++ b/src/plugins/winrt/winrtrunnerhelper.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of Qt Creator.
+**
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+
+#ifndef WINRTRUNNERHELPER_H
+#define WINRTRUNNERHELPER_H
+
+#include "winrtdevice.h"
+
+#include <utils/environment.h>
+#include <utils/outputformat.h>
+
+#include <QObject>
+#include <QProcess>
+
+
+namespace Utils { class QtcProcess; }
+namespace ProjectExplorer { class RunControl; }
+
+namespace WinRt {
+namespace Internal {
+
+class WinRtRunConfiguration;
+
+class WinRtRunnerHelper : public QObject
+{
+ Q_OBJECT
+public:
+ WinRtRunnerHelper(ProjectExplorer::RunControl *runControl);
+ WinRtRunnerHelper(WinRtRunConfiguration *runConfiguration, QString *errormessage);
+
+ void debug(const QString &debuggerExecutable, const QString &debuggerArguments = QString());
+ void start();
+
+ void stop();
+
+ bool waitForStarted(int msecs = 10000);
+ void setRunControl(ProjectExplorer::RunControl *runControl);
+
+signals:
+ void started();
+ void finished(int exitCode, QProcess::ExitStatus exitStatus);
+ void error(QProcess::ProcessError error);
+
+private slots:
+ void onProcessReadyReadStdOut();
+ void onProcessReadyReadStdErr();
+ void onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
+ void onProcessError(QProcess::ProcessError processError);
+
+private:
+ enum RunConf { Start, Stop, Debug };
+ void startWinRtRunner(const RunConf &conf);
+ bool init(WinRtRunConfiguration *runConfiguration, QString *errorMessage);
+
+ ProjectExplorer::RunControl *m_messenger;
+ WinRtRunConfiguration *m_runConfiguration;
+ WinRtDevice::ConstPtr m_device;
+ Utils::Environment m_environment;
+ QString m_runnerFilePath;
+ QString m_executableFilePath;
+ QString m_debuggerExecutable;
+ QString m_debuggerArguments;
+ QString m_arguments;
+ bool m_uninstallAfterStop;
+ bool m_isWinPhone;
+ Utils::QtcProcess *m_process;
+};
+
+} // namespace WinRt
+} // namespace Internal
+
+#endif // WINRTRUNNERHELPER_H