forked from qt-creator/qt-creator
Android: Add QML debugging support
Change-Id: I2fb2c75001569385e417ea44ae90d34e92a22449 Reviewed-by: BogDan Vatra <bog_dan_ro@yahoo.com> Reviewed-by: Tobias Hunger <tobias.hunger@nokia.com>
This commit is contained in:
committed by
Tobias Hunger
parent
70ce95b44f
commit
fcd01af143
@@ -70,30 +70,40 @@ static Qt4Project *project(AndroidRunConfiguration *rc)
|
|||||||
RunControl *AndroidDebugSupport::createDebugRunControl(AndroidRunConfiguration *runConfig)
|
RunControl *AndroidDebugSupport::createDebugRunControl(AndroidRunConfiguration *runConfig)
|
||||||
{
|
{
|
||||||
DebuggerStartParameters params;
|
DebuggerStartParameters params;
|
||||||
Profile *profile = runConfig->target()->profile();
|
|
||||||
params.sysRoot = SysRootProfileInformation::sysRoot(profile).toString();
|
|
||||||
params.debuggerCommand = DebuggerProfileInformation::debuggerCommand(profile).toString();
|
|
||||||
if (ToolChain *tc = ToolChainProfileInformation::toolChain(profile))
|
|
||||||
params.toolChainAbi = tc->targetAbi();
|
|
||||||
params.dumperLibrary = runConfig->dumperLib();
|
|
||||||
params.startMode = AttachToRemoteServer;
|
params.startMode = AttachToRemoteServer;
|
||||||
params.executable = project(runConfig)->rootQt4ProjectNode()->buildDir() + QLatin1String("/app_process");
|
|
||||||
params.remoteChannel = runConfig->remoteChannel();
|
|
||||||
params.displayName = AndroidManager::packageName(runConfig->target());
|
params.displayName = AndroidManager::packageName(runConfig->target());
|
||||||
|
|
||||||
params.solibSearchPath.clear();
|
|
||||||
|
|
||||||
QList<Qt4ProFileNode *> nodes = project(runConfig)->allProFiles();
|
|
||||||
foreach (Qt4ProFileNode *node, nodes)
|
|
||||||
if (node->projectType() == ApplicationTemplate)
|
|
||||||
params.solibSearchPath.append(node->targetInformation().buildDir);
|
|
||||||
|
|
||||||
QtSupport::BaseQtVersion *version = QtSupport::QtProfileInformation::qtVersion(runConfig->target()->profile());
|
|
||||||
params.solibSearchPath.append(qtSoPaths(version));
|
|
||||||
|
|
||||||
params.useServerStartScript = true;
|
|
||||||
params.remoteSetupNeeded = true;
|
params.remoteSetupNeeded = true;
|
||||||
params.remoteArchitecture = QLatin1String("arm");
|
|
||||||
|
if (runConfig->debuggerAspect()->useCppDebugger()) {
|
||||||
|
params.languages |= CppLanguage;
|
||||||
|
Profile *profile = runConfig->target()->profile();
|
||||||
|
params.sysRoot = SysRootProfileInformation::sysRoot(profile).toString();
|
||||||
|
params.debuggerCommand = DebuggerProfileInformation::debuggerCommand(profile).toString();
|
||||||
|
if (ToolChain *tc = ToolChainProfileInformation::toolChain(profile))
|
||||||
|
params.toolChainAbi = tc->targetAbi();
|
||||||
|
params.dumperLibrary = runConfig->dumperLib();
|
||||||
|
params.executable = project(runConfig)->rootQt4ProjectNode()->buildDir() + QLatin1String("/app_process");
|
||||||
|
params.remoteChannel = runConfig->remoteChannel();
|
||||||
|
params.remoteArchitecture = QLatin1String("arm");
|
||||||
|
params.useServerStartScript = true;
|
||||||
|
|
||||||
|
params.solibSearchPath.clear();
|
||||||
|
QList<Qt4ProFileNode *> nodes = project(runConfig)->allProFiles();
|
||||||
|
foreach (Qt4ProFileNode *node, nodes)
|
||||||
|
if (node->projectType() == ApplicationTemplate)
|
||||||
|
params.solibSearchPath.append(node->targetInformation().buildDir);
|
||||||
|
QtSupport::BaseQtVersion *version = QtSupport::QtProfileInformation::qtVersion(runConfig->target()->profile());
|
||||||
|
params.solibSearchPath.append(qtSoPaths(version));
|
||||||
|
}
|
||||||
|
if (runConfig->debuggerAspect()->useQmlDebugger()) {
|
||||||
|
params.languages |= QmlLanguage;
|
||||||
|
params.qmlServerAddress = QLatin1String("localhost");
|
||||||
|
params.qmlServerPort = runConfig->debuggerAspect()->qmlDebugServerPort();
|
||||||
|
//TODO: Not sure if these are the right paths.
|
||||||
|
params.projectSourceDirectory = project(runConfig)->projectDirectory();
|
||||||
|
params.projectSourceFiles = project(runConfig)->files(Qt4Project::ExcludeGeneratedFiles);
|
||||||
|
params.projectBuildDirectory = project(runConfig)->rootQt4ProjectNode()->buildDir();
|
||||||
|
}
|
||||||
|
|
||||||
DebuggerRunControl * const debuggerRunControl
|
DebuggerRunControl * const debuggerRunControl
|
||||||
= DebuggerPlugin::createDebugger(params, runConfig);
|
= DebuggerPlugin::createDebugger(params, runConfig);
|
||||||
@@ -106,8 +116,10 @@ AndroidDebugSupport::AndroidDebugSupport(AndroidRunConfiguration *runConfig,
|
|||||||
: QObject(runControl), m_runControl(runControl),
|
: QObject(runControl), m_runControl(runControl),
|
||||||
m_runner(new AndroidRunner(this, runConfig, true)),
|
m_runner(new AndroidRunner(this, runConfig, true)),
|
||||||
m_debuggingType(runConfig->debuggingType()),
|
m_debuggingType(runConfig->debuggingType()),
|
||||||
m_gdbServerPort(5039), m_qmlPort(-1)
|
m_gdbServerPort(5039), m_qmlPort(runConfig->debuggerAspect()->qmlDebugServerPort())
|
||||||
{
|
{
|
||||||
|
Q_ASSERT(runConfig->debuggerAspect()->useCppDebugger() || runConfig->debuggerAspect()->useQmlDebugger());
|
||||||
|
|
||||||
connect(m_runControl->engine(), SIGNAL(requestRemoteSetup()),
|
connect(m_runControl->engine(), SIGNAL(requestRemoteSetup()),
|
||||||
m_runner, SLOT(start()));
|
m_runner, SLOT(start()));
|
||||||
connect(m_runControl, SIGNAL(finished()),
|
connect(m_runControl, SIGNAL(finished()),
|
||||||
@@ -144,14 +156,22 @@ void AndroidDebugSupport::handleRemoteProcessFinished(const QString &errorMsg)
|
|||||||
|
|
||||||
void AndroidDebugSupport::handleRemoteOutput(const QByteArray &output)
|
void AndroidDebugSupport::handleRemoteOutput(const QByteArray &output)
|
||||||
{
|
{
|
||||||
if (m_runControl)
|
if (m_runControl) {
|
||||||
m_runControl->showMessage(QString::fromUtf8(output), AppOutput);
|
if (m_runControl->engine())
|
||||||
|
m_runControl->engine()->showMessage(QString::fromUtf8(output), AppOutput);
|
||||||
|
else
|
||||||
|
m_runControl->showMessage(QString::fromUtf8(output), AppOutput);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidDebugSupport::handleRemoteErrorOutput(const QByteArray &output)
|
void AndroidDebugSupport::handleRemoteErrorOutput(const QByteArray &output)
|
||||||
{
|
{
|
||||||
if (m_runControl)
|
if (m_runControl) {
|
||||||
m_runControl->showMessage(QString::fromUtf8(output), AppError);
|
if (m_runControl->engine())
|
||||||
|
m_runControl->engine()->showMessage(QString::fromUtf8(output), AppError);
|
||||||
|
else
|
||||||
|
m_runControl->showMessage(QString::fromUtf8(output), AppError);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList AndroidDebugSupport::qtSoPaths(QtSupport::BaseQtVersion *qtVersion)
|
QStringList AndroidDebugSupport::qtSoPaths(QtSupport::BaseQtVersion *qtVersion)
|
||||||
|
|||||||
@@ -142,7 +142,12 @@ QString AndroidRunConfiguration::proFilePath() const
|
|||||||
|
|
||||||
AndroidRunConfiguration::DebuggingType AndroidRunConfiguration::debuggingType() const
|
AndroidRunConfiguration::DebuggingType AndroidRunConfiguration::debuggingType() const
|
||||||
{
|
{
|
||||||
return DebugCppAndQml;
|
if (debuggerAspect()->useCppDebugger()) {
|
||||||
|
if (debuggerAspect()->useQmlDebugger())
|
||||||
|
return DebugCppAndQml;
|
||||||
|
return DebugCppOnly;
|
||||||
|
}
|
||||||
|
return DebugQmlOnly;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
|||||||
@@ -38,7 +38,6 @@
|
|||||||
#include "androidrunner.h"
|
#include "androidrunner.h"
|
||||||
|
|
||||||
#include <projectexplorer/projectexplorerconstants.h>
|
#include <projectexplorer/projectexplorerconstants.h>
|
||||||
#include <utils/qtcassert.h>
|
|
||||||
|
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
|
|
||||||
|
|||||||
@@ -46,11 +46,13 @@
|
|||||||
namespace Android {
|
namespace Android {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
AndroidRunner::AndroidRunner(QObject *parent,
|
AndroidRunner::AndroidRunner(QObject *parent, AndroidRunConfiguration *runConfig, bool debuggingMode)
|
||||||
AndroidRunConfiguration *runConfig, bool debugging)
|
|
||||||
: QThread(parent)
|
: QThread(parent)
|
||||||
{
|
{
|
||||||
m_remoteChannel = runConfig->remoteChannel();
|
m_useCppDebugger = debuggingMode && runConfig->debuggerAspect()->useCppDebugger();
|
||||||
|
m_useQmlDebugger = debuggingMode && runConfig->debuggerAspect()->useQmlDebugger();
|
||||||
|
m_remoteGdbChannel = runConfig->remoteChannel();
|
||||||
|
m_qmlPort = runConfig->debuggerAspect()->qmlDebugServerPort();
|
||||||
ProjectExplorer::Target *target = runConfig->target();
|
ProjectExplorer::Target *target = runConfig->target();
|
||||||
AndroidDeployStep *ds = runConfig->deployStep();
|
AndroidDeployStep *ds = runConfig->deployStep();
|
||||||
if ((m_useLocalQtLibs = ds->useLocalQtLibs())) {
|
if ((m_useLocalQtLibs = ds->useLocalQtLibs())) {
|
||||||
@@ -58,7 +60,6 @@ AndroidRunner::AndroidRunner(QObject *parent,
|
|||||||
m_localJars = AndroidManager::loadLocalJars(target, ds->deviceAPILevel());
|
m_localJars = AndroidManager::loadLocalJars(target, ds->deviceAPILevel());
|
||||||
}
|
}
|
||||||
m_intentName = AndroidManager::intentName(target);
|
m_intentName = AndroidManager::intentName(target);
|
||||||
m_debugingMode = debugging;
|
|
||||||
m_packageName = m_intentName.left(m_intentName.indexOf(QLatin1Char('/')));
|
m_packageName = m_intentName.left(m_intentName.indexOf(QLatin1Char('/')));
|
||||||
m_deviceSerialNumber = ds->deviceSerialNumber();
|
m_deviceSerialNumber = ds->deviceSerialNumber();
|
||||||
m_processPID = -1;
|
m_processPID = -1;
|
||||||
@@ -101,9 +102,9 @@ void AndroidRunner::checkPID()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_processPID = pid;
|
m_processPID = pid;
|
||||||
if (!m_debugingMode)
|
|
||||||
return;
|
|
||||||
|
|
||||||
|
if (!m_useCppDebugger)
|
||||||
|
return;
|
||||||
m_gdbserverPID = -1;
|
m_gdbserverPID = -1;
|
||||||
foreach (const QByteArray &proc, procs) {
|
foreach (const QByteArray &proc, procs) {
|
||||||
if (proc.trimmed().endsWith("gdbserver")) {
|
if (proc.trimmed().endsWith("gdbserver")) {
|
||||||
@@ -145,22 +146,39 @@ void AndroidRunner::asyncStart()
|
|||||||
killPID(); // kill any process with this name
|
killPID(); // kill any process with this name
|
||||||
QString extraParams;
|
QString extraParams;
|
||||||
QProcess adbStarProc;
|
QProcess adbStarProc;
|
||||||
if (m_debugingMode) {
|
if (m_useCppDebugger) {
|
||||||
QStringList arguments;
|
QStringList arguments;
|
||||||
arguments << QLatin1String("-s") << m_deviceSerialNumber
|
arguments << QLatin1String("-s") << m_deviceSerialNumber
|
||||||
<< QLatin1String("forward") << QString::fromLatin1("tcp%1").arg(m_remoteChannel)
|
<< QLatin1String("forward") << QString::fromLatin1("tcp%1").arg(m_remoteGdbChannel)
|
||||||
<< QString::fromLatin1("localfilesystem:/data/data/%1/debug-socket").arg(m_packageName);
|
<< QString::fromLatin1("localfilesystem:/data/data/%1/debug-socket").arg(m_packageName);
|
||||||
adbStarProc.start(AndroidConfigurations::instance().adbToolPath().toString(), arguments);
|
adbStarProc.start(AndroidConfigurations::instance().adbToolPath().toString(), arguments);
|
||||||
if (!adbStarProc.waitForStarted()) {
|
if (!adbStarProc.waitForStarted()) {
|
||||||
emit remoteProcessFinished(tr("Failed to forward debugging ports. Reason: $1").arg(adbStarProc.errorString()));
|
emit remoteProcessFinished(tr("Failed to forward C++ debugging ports. Reason: %1").arg(adbStarProc.errorString()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!adbStarProc.waitForFinished(-1)) {
|
if (!adbStarProc.waitForFinished(-1)) {
|
||||||
emit remoteProcessFinished(tr("Failed to forward debugging ports"));
|
emit remoteProcessFinished(tr("Failed to forward C++ debugging ports"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
extraParams = QLatin1String("-e native_debug true -e gdbserver_socket +debug-socket");
|
extraParams = QLatin1String("-e native_debug true -e gdbserver_socket +debug-socket");
|
||||||
}
|
}
|
||||||
|
if (m_useQmlDebugger) {
|
||||||
|
QStringList arguments;
|
||||||
|
QString port = QString::fromLatin1("tcp:%1").arg(m_qmlPort);
|
||||||
|
arguments << QLatin1String("-s") << m_deviceSerialNumber
|
||||||
|
<< QLatin1String("forward") << port << port; // currently forward to same port on device and host
|
||||||
|
adbStarProc.start(AndroidConfigurations::instance().adbToolPath().toString(), arguments);
|
||||||
|
if (!adbStarProc.waitForStarted()) {
|
||||||
|
emit remoteProcessFinished(tr("Failed to forward QML debugging ports. Reason: %1").arg(adbStarProc.errorString()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!adbStarProc.waitForFinished(-1)) {
|
||||||
|
emit remoteProcessFinished(tr("Failed to forward QML debugging ports"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
extraParams+=QString::fromLatin1(" -e qml_debug true -e qmljsdebugger port:%1")
|
||||||
|
.arg(m_qmlPort);
|
||||||
|
}
|
||||||
|
|
||||||
if (m_useLocalQtLibs) {
|
if (m_useLocalQtLibs) {
|
||||||
extraParams += QLatin1String(" -e use_local_qt_libs true");
|
extraParams += QLatin1String(" -e use_local_qt_libs true");
|
||||||
@@ -197,7 +215,7 @@ void AndroidRunner::asyncStart()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_debugingMode) {
|
if (m_useCppDebugger) {
|
||||||
startTime = QTime::currentTime();
|
startTime = QTime::currentTime();
|
||||||
while (m_gdbserverPID == -1 && startTime.secsTo(QTime::currentTime()) < 25) { // wait up to 25 seconds to connect
|
while (m_gdbserverPID == -1 && startTime.secsTo(QTime::currentTime()) < 25) { // wait up to 25 seconds to connect
|
||||||
checkPID();
|
checkPID();
|
||||||
@@ -247,6 +265,9 @@ void AndroidRunner::logcatReadStandardOutput()
|
|||||||
foreach (line, m_logcat.split('\n')) {
|
foreach (line, m_logcat.split('\n')) {
|
||||||
if (!line.contains(pid))
|
if (!line.contains(pid))
|
||||||
continue;
|
continue;
|
||||||
|
if (line.endsWith('\r'))
|
||||||
|
line.chop(1);
|
||||||
|
line.append('\n');
|
||||||
if (line.startsWith("E/"))
|
if (line.startsWith("E/"))
|
||||||
emit remoteErrorOutput(line);
|
emit remoteErrorOutput(line);
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -52,8 +52,7 @@ class AndroidRunner : public QThread
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AndroidRunner(QObject *parent, AndroidRunConfiguration *runConfig,
|
AndroidRunner(QObject *parent, AndroidRunConfiguration *runConfig, bool debuggingMode);
|
||||||
bool debugging);
|
|
||||||
~AndroidRunner();
|
~AndroidRunner();
|
||||||
|
|
||||||
QString displayName() const;
|
QString displayName() const;
|
||||||
@@ -82,7 +81,6 @@ private:
|
|||||||
void adbKill(qint64 pid, const QString &device, int timeout = 2000, const QString &runAsPackageName = QString());
|
void adbKill(qint64 pid, const QString &device, int timeout = 2000, const QString &runAsPackageName = QString());
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_debugingMode;
|
|
||||||
QProcess m_adbLogcatProcess;
|
QProcess m_adbLogcatProcess;
|
||||||
QByteArray m_logcat;
|
QByteArray m_logcat;
|
||||||
QString m_intentName;
|
QString m_intentName;
|
||||||
@@ -91,7 +89,10 @@ private:
|
|||||||
qint64 m_processPID;
|
qint64 m_processPID;
|
||||||
qint64 m_gdbserverPID;
|
qint64 m_gdbserverPID;
|
||||||
QTimer m_checkPIDTimer;
|
QTimer m_checkPIDTimer;
|
||||||
QString m_remoteChannel;
|
bool m_useCppDebugger;
|
||||||
|
bool m_useQmlDebugger;
|
||||||
|
QString m_remoteGdbChannel;
|
||||||
|
uint m_qmlPort;
|
||||||
bool m_useLocalQtLibs;
|
bool m_useLocalQtLibs;
|
||||||
QString m_localLibs;
|
QString m_localLibs;
|
||||||
QString m_localJars;
|
QString m_localJars;
|
||||||
|
|||||||
Reference in New Issue
Block a user