diff options
author | David Schulz <david.schulz@digia.com> | 2014-04-25 09:20:57 +0200 |
---|---|---|
committer | hjk <hjk121@nokiamail.com> | 2014-05-16 11:21:33 +0200 |
commit | 751a61b2e4429f09209ad6f9d24c4e4eea84f2fe (patch) | |
tree | feb5c61de14c929439c749e49d042dd7adca5b7c /src/plugins/winrt | |
parent | 93e37b7e78156f2ff17d5d62645327c3eece839a (diff) | |
download | qt-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.pro | 8 | ||||
-rw-r--r-- | src/plugins/winrt/winrt.qbs | 7 | ||||
-rw-r--r-- | src/plugins/winrt/winrt_dependencies.pri | 1 | ||||
-rw-r--r-- | src/plugins/winrt/winrtdebugsupport.cpp | 141 | ||||
-rw-r--r-- | src/plugins/winrt/winrtdebugsupport.h | 65 | ||||
-rw-r--r-- | src/plugins/winrt/winrtdevice.cpp | 12 | ||||
-rw-r--r-- | src/plugins/winrt/winrtruncontrol.cpp | 125 | ||||
-rw-r--r-- | src/plugins/winrt/winrtruncontrol.h | 14 | ||||
-rw-r--r-- | src/plugins/winrt/winrtrunfactories.cpp | 35 | ||||
-rw-r--r-- | src/plugins/winrt/winrtrunnerhelper.cpp | 240 | ||||
-rw-r--r-- | src/plugins/winrt/winrtrunnerhelper.h | 99 |
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 |