diff --git a/src/plugins/ios/iosdebugsupport.cpp b/src/plugins/ios/iosdebugsupport.cpp index d698c9e438a196c2772cba661d7678ab4cc6327f..86e75d4f37e1aab4282236b4b89c739e4a5491b4 100644 --- a/src/plugins/ios/iosdebugsupport.cpp +++ b/src/plugins/ios/iosdebugsupport.cpp @@ -119,7 +119,9 @@ RunControl *IosDebugSupport::createDebugRunControl(IosRunConfiguration *runConfi Debugger::DebuggerRunConfigurationAspect *aspect = runConfig->extraAspect<Debugger::DebuggerRunConfigurationAspect>(); - if (aspect->useCppDebugger()) { + bool cppDebug = aspect->useCppDebugger(); + bool qmlDebug = aspect->useQmlDebugger(); + if (cppDebug) { params.languages |= CppLanguage; params.sysRoot = SysRootKitInformation::sysRoot(kit).toString(); params.debuggerCommand = DebuggerKitInformation::debuggerCommand(kit).toString(); @@ -128,42 +130,36 @@ RunControl *IosDebugSupport::createDebugRunControl(IosRunConfiguration *runConfi params.executable = runConfig->exePath().toString(); params.remoteChannel = QLatin1String("connect://localhost:0"); } - if (aspect->useQmlDebugger()) { + if (qmlDebug) { params.languages |= QmlLanguage; - QTcpServer server; - QTC_ASSERT(server.listen(QHostAddress::LocalHost) - || server.listen(QHostAddress::LocalHostIPv6), return 0); - params.qmlServerAddress = server.serverAddress().toString(); - params.remoteSetupNeeded = true; - //TODO: Not sure if these are the right paths. params.projectSourceDirectory = project->projectDirectory(); params.projectSourceFiles = project->files(QmakeProject::ExcludeGeneratedFiles); params.projectBuildDirectory = project->rootQmakeProjectNode()->buildDir(); + if (!cppDebug) + params.startMode = AttachToRemoteServer; } DebuggerRunControl * const debuggerRunControl = DebuggerPlugin::createDebugger(params, runConfig, errorMessage); if (debuggerRunControl) - new IosDebugSupport(runConfig, debuggerRunControl); + new IosDebugSupport(runConfig, debuggerRunControl, cppDebug, qmlDebug); return debuggerRunControl; } IosDebugSupport::IosDebugSupport(IosRunConfiguration *runConfig, - DebuggerRunControl *runControl) + DebuggerRunControl *runControl, bool cppDebug, bool qmlDebug) : QObject(runControl), m_runControl(runControl), - m_runner(new IosRunner(this, runConfig, true)), - m_qmlPort(0) + m_runner(new IosRunner(this, runConfig, cppDebug, qmlDebug)) { - connect(m_runControl->engine(), SIGNAL(requestRemoteSetup()), m_runner, SLOT(start())); connect(m_runControl, SIGNAL(finished()), m_runner, SLOT(stop())); - connect(m_runner, SIGNAL(gotGdbserverPort(int)), - SLOT(handleGdbServerPort(int))); - connect(m_runner, SIGNAL(gotInferiorPid(Q_PID)), - SLOT(handleGotInferiorPid(Q_PID))); + connect(m_runner, SIGNAL(gotServerPorts(int,int)), + SLOT(handleServerPorts(int,int))); + connect(m_runner, SIGNAL(gotInferiorPid(Q_PID, int)), + SLOT(handleGotInferiorPid(Q_PID, int))); connect(m_runner, SIGNAL(finished(bool)), SLOT(handleRemoteProcessFinished(bool))); @@ -177,22 +173,22 @@ IosDebugSupport::~IosDebugSupport() { } -void IosDebugSupport::handleGdbServerPort(int gdbServerPort) +void IosDebugSupport::handleServerPorts(int gdbServerPort, int qmlPort) { - if (gdbServerPort > 0) { - m_runControl->engine()->notifyEngineRemoteSetupDone(gdbServerPort, m_qmlPort); + if (gdbServerPort > 0 || (m_runner && !m_runner->cppDebug() && qmlPort > 0)) { + m_runControl->engine()->notifyEngineRemoteSetupDone(gdbServerPort, qmlPort); } else { m_runControl->engine()->notifyEngineRemoteSetupFailed( tr("Could not get debug server file descriptor.")); } } -void IosDebugSupport::handleGotInferiorPid(Q_PID pid) +void IosDebugSupport::handleGotInferiorPid(Q_PID pid, int qmlPort) { if (pid > 0) { //m_runControl->engine()->notifyInferiorPid(pid); #ifndef Q_OS_WIN // Q_PID might be 64 bit pointer... - m_runControl->engine()->notifyEngineRemoteSetupDone(int(pid), m_qmlPort); + m_runControl->engine()->notifyEngineRemoteSetupDone(int(pid), qmlPort); #endif } else { m_runControl->engine()->notifyEngineRemoteSetupFailed( diff --git a/src/plugins/ios/iosdebugsupport.h b/src/plugins/ios/iosdebugsupport.h index 020682557549bf33bb48066d90a2aee97e6b8023..8f038904ae356570431b9f3c599d183c087fa6af 100644 --- a/src/plugins/ios/iosdebugsupport.h +++ b/src/plugins/ios/iosdebugsupport.h @@ -50,12 +50,12 @@ public: QString *errorMessage); IosDebugSupport(IosRunConfiguration *runConfig, - Debugger::DebuggerRunControl *runControl); + Debugger::DebuggerRunControl *runControl, bool cppDebug, bool qmlDebug); ~IosDebugSupport(); private slots: - void handleGdbServerPort(int gdbServerFd); - void handleGotInferiorPid(Q_PID); + void handleServerPorts(int gdbServerFd, int qmlPort); + void handleGotInferiorPid(Q_PID, int qmlPort); void handleRemoteProcessFinished(bool cleanEnd); void handleRemoteOutput(const QString &output); @@ -65,8 +65,6 @@ private: Debugger::DebuggerRunControl *m_runControl; IosRunner * const m_runner; const QString m_dumperLib; - - int m_qmlPort; }; } // namespace Internal diff --git a/src/plugins/ios/iosruncontrol.cpp b/src/plugins/ios/iosruncontrol.cpp index 5a12772cd84c0d316026de9229402bf9c7d80f54..491707e18189e6b19855a867d4dff343c53af97e 100644 --- a/src/plugins/ios/iosruncontrol.cpp +++ b/src/plugins/ios/iosruncontrol.cpp @@ -42,7 +42,7 @@ namespace Internal { IosRunControl::IosRunControl(IosRunConfiguration *rc) : RunControl(rc, NormalRunMode) - , m_runner(new IosRunner(this, rc, false)) + , m_runner(new IosRunner(this, rc, false, false)) , m_running(false) { } diff --git a/src/plugins/ios/iosrunner.cpp b/src/plugins/ios/iosrunner.cpp index cb958259600e1af890aa5ee421e2e98fd4067ae4..11dec23ac8e8c54fa3d138f9e5134667d88cfe96 100644 --- a/src/plugins/ios/iosrunner.cpp +++ b/src/plugins/ios/iosrunner.cpp @@ -40,10 +40,12 @@ #include <projectexplorer/target.h> #include <projectexplorer/taskhub.h> #include <projectexplorer/projectexplorerconstants.h> +#include <debugger/debuggerrunconfigurationaspect.h> #include <QDir> #include <QTime> #include <QMessageBox> +#include <QRegExp> #include <signal.h> @@ -52,11 +54,12 @@ using namespace ProjectExplorer; namespace Ios { namespace Internal { -IosRunner::IosRunner(QObject *parent, IosRunConfiguration *runConfig, bool debuggingMode) +IosRunner::IosRunner(QObject *parent, IosRunConfiguration *runConfig, bool cppDebug, bool qmlDebug) : QObject(parent), m_toolHandler(0), m_bundleDir(runConfig->bundleDir().toString()), m_arguments(runConfig->commandLineArguments()), m_device(ProjectExplorer::DeviceKitInformation::device(runConfig->target()->kit())), - m_debuggingMode(debuggingMode), m_cleanExit(false), m_pid(0) + m_cppDebug(cppDebug), m_qmlDebug(qmlDebug), m_cleanExit(false), + m_qmlPort(0), m_pid(0) { } @@ -72,7 +75,10 @@ QString IosRunner::bundlePath() QStringList IosRunner::extraArgs() { - return m_arguments; + QStringList res = m_arguments; + if (m_qmlPort != 0) + res << QString::fromLatin1("-qmljsdebugger=port:%1,block").arg(m_qmlPort); + return res; } QString IosRunner::deviceId() @@ -85,11 +91,21 @@ QString IosRunner::deviceId() IosToolHandler::RunKind IosRunner::runType() { - if (m_debuggingMode) + if (m_cppDebug) return IosToolHandler::DebugRun; return IosToolHandler::NormalRun; } +bool IosRunner::cppDebug() const +{ + return m_cppDebug; +} + +bool IosRunner::qmlDebug() const +{ + return m_qmlDebug; +} + void IosRunner::start() { if (m_toolHandler) { @@ -97,15 +113,27 @@ void IosRunner::start() emit finished(m_cleanExit); } m_cleanExit = false; + m_qmlPort = 0; IosToolHandler::DeviceType devType = IosToolHandler::IosDeviceType; - if (m_device->type() != Ios::Constants::IOS_DEVICE_TYPE) { + if (m_device->type() == Ios::Constants::IOS_DEVICE_TYPE) { + IosDevice::ConstPtr iosDevice = m_device.dynamicCast<const IosDevice>(); + if (m_device.isNull()) { + emit finished(m_cleanExit); + return; + } + if (m_qmlDebug) + m_qmlPort = iosDevice->nextPort(); + } else { IosSimulator::ConstPtr sim = m_device.dynamicCast<const IosSimulator>(); if (sim.isNull()) { emit finished(m_cleanExit); return; } devType = IosToolHandler::IosSimulatedIphoneRetina4InchType; // store type in sim? + if (m_qmlDebug) + m_qmlPort = sim->nextPort(); } + m_toolHandler = new IosToolHandler(devType, this); connect(m_toolHandler, SIGNAL(appOutput(Ios::IosToolHandler*,QString)), SLOT(handleAppOutput(Ios::IosToolHandler*,QString))); @@ -114,8 +142,8 @@ void IosRunner::start() SLOT(handleDidStartApp(Ios::IosToolHandler*,QString,QString,Ios::IosToolHandler::OpStatus))); connect(m_toolHandler, SIGNAL(errorMsg(Ios::IosToolHandler*,QString)), SLOT(handleErrorMsg(Ios::IosToolHandler*,QString))); - connect(m_toolHandler, SIGNAL(gotGdbserverPort(Ios::IosToolHandler*,QString,QString,int)), - SLOT(handleGotGdbserverPort(Ios::IosToolHandler*,QString,QString,int))); + connect(m_toolHandler, SIGNAL(gotServerPorts(Ios::IosToolHandler*,QString,QString,int,int)), + SLOT(handleGotServerPorts(Ios::IosToolHandler*,QString,QString,int,int))); connect(m_toolHandler, SIGNAL(gotInferiorPid(Ios::IosToolHandler*,QString,QString,Q_PID)), SLOT(handleGotInferiorPid(Ios::IosToolHandler*,QString,QString,Q_PID))); connect(m_toolHandler, SIGNAL(toolExited(Ios::IosToolHandler*,int)), @@ -144,12 +172,13 @@ void IosRunner::handleDidStartApp(IosToolHandler *handler, const QString &bundle emit didStartApp(status); } -void IosRunner::handleGotGdbserverPort(IosToolHandler *handler, const QString &bundlePath, - const QString &deviceId, int gdbPort) +void IosRunner::handleGotServerPorts(IosToolHandler *handler, const QString &bundlePath, + const QString &deviceId, int gdbPort, int qmlPort) { Q_UNUSED(bundlePath); Q_UNUSED(deviceId); + m_qmlPort = qmlPort; if (m_toolHandler == handler) - emit gotGdbserverPort(gdbPort); + emit gotServerPorts(gdbPort, qmlPort); } void IosRunner::handleGotInferiorPid(IosToolHandler *handler, const QString &bundlePath, @@ -158,13 +187,18 @@ void IosRunner::handleGotInferiorPid(IosToolHandler *handler, const QString &bun Q_UNUSED(bundlePath); Q_UNUSED(deviceId); m_pid = pid; if (m_toolHandler == handler) - emit gotInferiorPid(pid); + emit gotInferiorPid(pid, m_qmlPort); } void IosRunner::handleAppOutput(IosToolHandler *handler, const QString &output) { Q_UNUSED(handler); - emit appOutput(output); + QRegExp qmlPortRe(QLatin1String("QML Debugger: Waiting for connection on port ([0-9]+)...")); + int index = qmlPortRe.indexIn(output); + QString res(output); + if (index != -1 && m_qmlPort) + res.replace(qmlPortRe.cap(1), QString::number(m_qmlPort)); + emit appOutput(res); } void IosRunner::handleErrorMsg(IosToolHandler *handler, const QString &msg) @@ -174,11 +208,16 @@ void IosRunner::handleErrorMsg(IosToolHandler *handler, const QString &msg) TaskHub::addTask(Task::Warning, tr("Run failed. The settings in the Organizer window of Xcode might be incorrect."), ProjectExplorer::Constants::TASK_CATEGORY_DEPLOYMENT); - else if (msg.contains(QLatin1String("Unexpected reply: ELocked (454c6f636b6564) vs OK (OK)"))) + else if (msg.contains(QLatin1String("Unexpected reply: ELocked (454c6f636b6564) vs OK (4f4b)"))) TaskHub::addTask(Task::Error, tr("The device is locked, please unlock."), ProjectExplorer::Constants::TASK_CATEGORY_DEPLOYMENT); - emit errorMsg(msg); + QRegExp qmlPortRe(QLatin1String("QML Debugger: Waiting for connection on port ([0-9]+)...")); + int index = qmlPortRe.indexIn(msg); + QString res(msg); + if (index != -1 && m_qmlPort) + res.replace(qmlPortRe.cap(1), QString::number(m_qmlPort)); + emit errorMsg(res); } void IosRunner::handleToolExited(IosToolHandler *handler, int code) diff --git a/src/plugins/ios/iosrunner.h b/src/plugins/ios/iosrunner.h index abf971c416dffbf8c71d0886fd9246b59593599b..21b1f9a7943db897fa860a79baa64669dab6493f 100644 --- a/src/plugins/ios/iosrunner.h +++ b/src/plugins/ios/iosrunner.h @@ -49,7 +49,7 @@ class IosRunner : public QObject Q_OBJECT public: - IosRunner(QObject *parent, IosRunConfiguration *m_runConfig, bool m_debuggingMode); + IosRunner(QObject *parent, IosRunConfiguration *runConfig, bool cppDebug, bool qmlDebug); ~IosRunner(); QString displayName() const; @@ -58,22 +58,24 @@ public: QStringList extraArgs(); QString deviceId(); IosToolHandler::RunKind runType(); + bool cppDebug() const; + bool qmlDebug() const; public slots: void start(); void stop(); signals: void didStartApp(Ios::IosToolHandler::OpStatus status); - void gotGdbserverPort(int gdbPort); - void gotInferiorPid(Q_PID pid); + void gotServerPorts(int gdbPort, int qmlPort); + void gotInferiorPid(Q_PID pid, int); void appOutput(const QString &output); void errorMsg(const QString &msg); void finished(bool cleanExit); private slots: void handleDidStartApp(Ios::IosToolHandler *handler, const QString &bundlePath, const QString &deviceId, Ios::IosToolHandler::OpStatus status); - void handleGotGdbserverPort(Ios::IosToolHandler *handler, const QString &bundlePath, - const QString &deviceId, int gdbPort); + void handleGotServerPorts(Ios::IosToolHandler *handler, const QString &bundlePath, + const QString &deviceId, int gdbPort, int qmlPort); void handleGotInferiorPid(Ios::IosToolHandler *handler, const QString &bundlePath, const QString &deviceId, Q_PID pid); void handleAppOutput(Ios::IosToolHandler *handler, const QString &output); @@ -85,8 +87,10 @@ private: QString m_bundleDir; QStringList m_arguments; ProjectExplorer::IDevice::ConstPtr m_device; - bool m_debuggingMode; + bool m_cppDebug; + bool m_qmlDebug; bool m_cleanExit; + quint16 m_qmlPort; Q_PID m_pid; }; diff --git a/src/plugins/ios/iostoolhandler.cpp b/src/plugins/ios/iostoolhandler.cpp index 26de448afbfd596b360c869c3698678803a354b2..6ceb6ede258829fdc0806884e5a638667b524c30 100644 --- a/src/plugins/ios/iostoolhandler.cpp +++ b/src/plugins/ios/iostoolhandler.cpp @@ -65,7 +65,7 @@ struct ParserState { ControlChar, AppStarted, InferiorPid, - GdbServerPort, + ServerPorts, Item, Status, AppTransfer, @@ -79,6 +79,7 @@ struct ParserState { QString value; QMap<QString,QString> info; int progress, maxProgress; + int gdbPort, qmlPort; bool collectChars() { switch (kind) { case Msg: @@ -87,9 +88,9 @@ struct ParserState { case Value: case Status: case InferiorPid: - case GdbServerPort: case AppOutput: return true; + case ServerPorts: case QueryResult: case ControlChar: case AppStarted: @@ -103,7 +104,7 @@ struct ParserState { } ParserState(Kind kind) : - kind(kind) { } + kind(kind), gdbPort(0), qmlPort(0) { } }; class IosToolHandlerPrivate @@ -142,7 +143,8 @@ public: IosToolHandler::OpStatus status); void didStartApp(const QString &bundlePath, const QString &deviceId, IosToolHandler::OpStatus status); - void gotGdbserverPort(const QString &bundlePath, const QString &deviceId, int gdbPort); + void gotServerPorts(const QString &bundlePath, const QString &deviceId, int gdbPort, + int qmlPort); void gotInferiorPid(const QString &bundlePath, const QString &deviceId, Q_PID pid); void deviceInfo(const QString &deviceId, const IosToolHandler::Dict &info); void appOutput(const QString &output); @@ -301,10 +303,10 @@ void IosToolHandlerPrivate::didStartApp(const QString &bundlePath, const QString emit q->didStartApp(q, bundlePath, deviceId, status); } -void IosToolHandlerPrivate::gotGdbserverPort(const QString &bundlePath, - const QString &deviceId, int gdbPort) +void IosToolHandlerPrivate::gotServerPorts(const QString &bundlePath, + const QString &deviceId, int gdbPort, int qmlPort) { - emit q->gotGdbserverPort(q, bundlePath, deviceId, gdbPort); + emit q->gotServerPorts(q, bundlePath, deviceId, gdbPort, qmlPort); } void IosToolHandlerPrivate::gotInferiorPid(const QString &bundlePath, const QString &deviceId, @@ -439,8 +441,12 @@ void IosToolHandlerPrivate::processXml() stack.append(ParserState(ParserState::DeviceInfo)); } else if (elName == QLatin1String("inferior_pid")) { stack.append(ParserState(ParserState::InferiorPid)); - } else if (elName == QLatin1String("gdb_server_port")) { - stack.append(ParserState(ParserState::GdbServerPort)); + } else if (elName == QLatin1String("server_ports")) { + stack.append(ParserState(ParserState::ServerPorts)); + QXmlStreamAttributes attributes = outputParser.attributes(); + int gdbServerPort = attributes.value(QLatin1String("gdb_server")).toString().toInt(); + int qmlServerPort = attributes.value(QLatin1String("qml_server")).toString().toInt(); + gotServerPorts(bundlePath, deviceId, gdbServerPort, qmlServerPort); } else { qDebug() << "unexpected element " << elName; } @@ -494,8 +500,7 @@ void IosToolHandlerPrivate::processXml() case ParserState::InferiorPid: gotInferiorPid(bundlePath, deviceId, Q_PID(p.chars.toInt())); break; - case ParserState::GdbServerPort: - gotGdbserverPort(bundlePath, deviceId, p.chars.toInt()); + case ParserState::ServerPorts: break; } break; diff --git a/src/plugins/ios/iostoolhandler.h b/src/plugins/ios/iostoolhandler.h index e8f4210a7f540082d60501a37b45731a4ada7940..8f163c02f63798b52d5d8aa0e7cceec60e030aa0 100644 --- a/src/plugins/ios/iostoolhandler.h +++ b/src/plugins/ios/iostoolhandler.h @@ -81,8 +81,8 @@ signals: const QString &deviceId, Ios::IosToolHandler::OpStatus status); void didStartApp(Ios::IosToolHandler *handler, const QString &bundlePath, const QString &deviceId, Ios::IosToolHandler::OpStatus status); - void gotGdbserverPort(Ios::IosToolHandler *handler, const QString &bundlePath, - const QString &deviceId, int gdbPort); + void gotServerPorts(Ios::IosToolHandler *handler, const QString &bundlePath, + const QString &deviceId, int gdbPort, int qmlPort); void gotInferiorPid(Ios::IosToolHandler *handler, const QString &bundlePath, const QString &deviceId, Q_PID pid); void deviceInfo(Ios::IosToolHandler *handler, const QString &deviceId,