Commit 2c732970 authored by Frantisek Vacek's avatar Frantisek Vacek Committed by Fanda Vacek
Browse files

Qnx: Add support for qml profiler in BlackBerry/Qnx



We cannot set -qmljsdebugger arg in bar-descriptor.xml file since
it can be done in DeployStep only. QTC architecture do not allows this.

Current approach modifies already deployed MANIFEST.MF on the device.

This patch has nothing to do with QML analyzer for pure QNX,
it's purely for BlackBerry.

Task-number: QTCREATORBUG-10520
Change-Id: I89e83c6ff70a7a35344ff7e3fe573fc19e797ccb
Reviewed-by: default avatarTobias Hunger <tobias.hunger@digia.com>
parent 1910fe91
......@@ -240,8 +240,6 @@ void QmlProfilerClientManager::connectToClient()
if (!d->connection || d->connection->state() != QAbstractSocket::UnconnectedState)
return;
QmlProfilerTool::logStatus(QString::fromLatin1("QML Profiler: Connecting to %1:%2 ...")
.arg(d->tcpHost, QString::number(d->tcpPort)));
d->connection->connectToHost(d->tcpHost, d->tcpPort);
}
......@@ -309,14 +307,17 @@ void QmlProfilerClientManager::connectionStateChanged()
case QAbstractSocket::ConnectingState: {
if (QmlProfilerPlugin::debugOutput)
qWarning("QML Profiler: Connecting to debug server ...");
QmlProfilerTool::logStatus(tr("QML Profiler: Connecting to %1:%2 ...")
.arg(d->tcpHost, QString::number(d->tcpPort)));
break;
}
case QAbstractSocket::ConnectedState:
{
if (QmlProfilerPlugin::debugOutput)
qWarning("QML Profiler: connected and running");
// notify the client recording status
clientRecordingChanged();
// notify the client recording status
clientRecordingChanged();
QmlProfilerTool::logStatus(tr("QML Profiler: connected and running"));
break;
}
case QAbstractSocket::ClosingState:
......
......@@ -42,14 +42,18 @@
#include <projectexplorer/kit.h>
#include <projectexplorer/target.h>
#include <qmakeprojectmanager/qmakebuildconfiguration.h>
#include <debugger/debuggerrunconfigurationaspect.h>
#include <ssh/sshremoteprocessrunner.h>
#include <utils/qtcassert.h>
#include <QMessageBox>
#include <QTimer>
#include <QDir>
#include <QTemporaryFile>
namespace {
enum { debugCheckQmlJSArgs = 0 };
bool parseRunningState(const QString &line)
{
QTC_ASSERT(line.startsWith(QLatin1String("result::")), return false);
......@@ -61,9 +65,9 @@ using namespace ProjectExplorer;
using namespace Qnx;
using namespace Qnx::Internal;
BlackBerryApplicationRunner::BlackBerryApplicationRunner(bool cppDebugMode, BlackBerryRunConfiguration *runConfiguration, QObject *parent)
BlackBerryApplicationRunner::BlackBerryApplicationRunner(const BlackBerryApplicationRunner::LaunchFlags &launchFlags, BlackBerryRunConfiguration *runConfiguration, QObject *parent)
: QObject(parent)
, m_cppDebugMode(cppDebugMode)
, m_launchFlags(launchFlags)
, m_pid(-1)
, m_appId(QString())
, m_running(false)
......@@ -74,6 +78,8 @@ BlackBerryApplicationRunner::BlackBerryApplicationRunner(bool cppDebugMode, Blac
, m_logProcessRunner(0)
, m_runningStateTimer(new QTimer(this))
, m_runningStateProcess(0)
, m_qmlDebugServerPort(0)
, m_checkQmlJsDebugArgumentsProcess(0)
{
QTC_ASSERT(runConfiguration, return);
......@@ -92,6 +98,11 @@ BlackBerryApplicationRunner::BlackBerryApplicationRunner(bool cppDebugMode, Blac
m_sshParams = m_device->sshParameters();
m_sshParams.authenticationType = QSsh::SshConnectionParameters::AuthenticationTypePublicKey;
Debugger::DebuggerRunConfigurationAspect *aspect =
runConfiguration->extraAspect<Debugger::DebuggerRunConfigurationAspect>();
if (aspect)
m_qmlDebugServerPort = aspect->qmlDebugServerPort();
m_runningStateTimer->setInterval(3000);
m_runningStateTimer->setSingleShot(true);
connect(m_runningStateTimer, SIGNAL(timeout()), this, SLOT(determineRunningState()));
......@@ -148,7 +159,7 @@ void BlackBerryApplicationRunner::checkDeviceRuntimeVersion(int status)
if (m_bbApiLevelVersion.isEmpty()) {
emit output(tr("Cannot determine API level version."), Utils::StdErrFormat);
launchApplication();
checkQmlJsDebugArguments();
return;
}
......@@ -170,7 +181,7 @@ void BlackBerryApplicationRunner::checkDeviceRuntimeVersion(int status)
}
}
launchApplication();
checkQmlJsDebugArguments();
}
void BlackBerryApplicationRunner::queryDeviceInformation()
......@@ -273,7 +284,7 @@ void BlackBerryApplicationRunner::disconnectFromDeviceSignals(Core::Id deviceId)
{
if (m_device->id() == deviceId) {
disconnect(BlackBerryDeviceConnectionManager::instance(), SIGNAL(deviceConnected()),
this, SLOT(launchApplication()));
this, SLOT(checkDeployMode()));
disconnect(BlackBerryDeviceConnectionManager::instance(), SIGNAL(deviceDisconnected(Core::Id)),
this, SLOT(disconnectFromDeviceSignals(Core::Id)));
disconnect(BlackBerryDeviceConnectionManager::instance(), SIGNAL(connectionOutput(Core::Id,QString)),
......@@ -291,6 +302,105 @@ void BlackBerryApplicationRunner::setApplicationId(const QString &applicationId)
m_appId = applicationId;
}
void BlackBerryApplicationRunner::checkQmlJsDebugArguments()
{
if (!m_launchFlags.testFlag(QmlDebugLaunch)) {
// no need to change anytning in app manifest for this kind of run
launchApplication();
}
emit output(tr("Checking qmljsdebugger command line argument."), Utils::StdOutFormat);
QString nativePackagerCmd = m_environment.searchInPath(QLatin1String("blackberry-nativepackager"));
if (nativePackagerCmd.isEmpty()) {
emit output(tr("Cannot find Native Packager executable."), Utils::StdErrFormat);
return;
}
m_checkQmlJsDebugArgumentsProcess = new QProcess(this);
connect(m_checkQmlJsDebugArgumentsProcess, SIGNAL(error(QProcess::ProcessError)), this, SLOT(checkQmlJsDebugArgumentsManifestLoaded()));
connect(m_checkQmlJsDebugArgumentsProcess, SIGNAL(finished(int)), this, SLOT(checkQmlJsDebugArgumentsManifestLoaded()));
QStringList args;
args << QLatin1String("-listManifest") << QDir::toNativeSeparators(m_barPackage);
if (debugCheckQmlJSArgs)
qDebug() << "get manifest:" << nativePackagerCmd << args.join(QLatin1Char(' '));
m_checkQmlJsDebugArgumentsProcess->start(nativePackagerCmd, args);
}
void BlackBerryApplicationRunner::checkQmlJsDebugArgumentsManifestLoaded()
{
m_checkQmlJsDebugArgumentsProcess->deleteLater();
if (m_checkQmlJsDebugArgumentsProcess->exitStatus() != QProcess::NormalExit) {
emit output(tr("Cannot read bar package manifest."), Utils::StdErrFormat);
qWarning() << "Cannot read bar package manifest:" << m_checkQmlJsDebugArgumentsProcess->errorString();
qWarning() << m_checkQmlJsDebugArgumentsProcess->readAllStandardError();
return;
}
QString manifestContent = QString::fromUtf8(m_checkQmlJsDebugArgumentsProcess->readAllStandardOutput());
QRegExp rxEoln(QLatin1String("(\\r\\n|\\n|\\r)"));
QStringList manifestLines = manifestContent.split(rxEoln);
QMutableListIterator<QString> it(manifestLines);
QLatin1String entryPoint("Entry-Point: ");
while (it.hasNext()) {
it.next();
if (it.value().startsWith(entryPoint)) {
while (it.hasNext() && it.peekNext().startsWith(QLatin1Char(' ')))
it.next();
QString qmljsdbgArg = QString::fromLatin1("-qmljsdebugger=port:%1%2")
.arg(m_qmlDebugServerPort)
.arg(m_launchFlags.testFlag(QmlDebugLaunchBlocking)? QLatin1String(",block"): QLatin1String(""));
it.insert(QLatin1String(" ") + qmljsdbgArg);
manifestContent = manifestLines.join(QLatin1String("\n"));
break;
}
}
m_checkQmlJsDebugArgumentsProcess = new QProcess(this);
connect(m_checkQmlJsDebugArgumentsProcess, SIGNAL(error(QProcess::ProcessError)), this, SLOT(checkQmlJsDebugArgumentsManifestSaved()));
connect(m_checkQmlJsDebugArgumentsProcess, SIGNAL(finished(int)), this, SLOT(checkQmlJsDebugArgumentsManifestSaved()));
QTemporaryFile *manifestFile = new QTemporaryFile(m_checkQmlJsDebugArgumentsProcess);
if (!manifestFile->open()) {
emit output(tr("Internal error: Cannot create temporary manifest file '%1'")
.arg(manifestFile->fileName()), Utils::StdErrFormat);
delete manifestFile;
return;
}
manifestFile->write(manifestContent.toUtf8());
manifestFile->flush();
QStringList args;
args << QLatin1String("-device") << m_sshParams.host;
if (!m_sshParams.password.isEmpty())
args << QLatin1String("-password") << m_sshParams.password;
args << QLatin1String("-package") << QDir::toNativeSeparators(m_barPackage);
args << QLatin1String("-putFile");
args << manifestFile->fileName();
args << QLatin1String("app/META-INF/MANIFEST.MF");
if (debugCheckQmlJSArgs)
qDebug() << "set manifest:" << m_deployCmd << args.join(QLatin1Char(' '));
m_checkQmlJsDebugArgumentsProcess->start(m_deployCmd, args);
}
void BlackBerryApplicationRunner::checkQmlJsDebugArgumentsManifestSaved()
{
m_checkQmlJsDebugArgumentsProcess->deleteLater();
if (m_checkQmlJsDebugArgumentsProcess->exitStatus() != QProcess::NormalExit) {
emit output(tr("Cannot set command line arguments."), Utils::StdErrFormat);
qWarning() << "Cannot set command line arguments:" << m_checkQmlJsDebugArgumentsProcess->errorString();
qWarning() << m_checkQmlJsDebugArgumentsProcess->readAllStandardError();
return;
}
launchApplication();
}
void BlackBerryApplicationRunner::launchApplication()
{
// If original device connection fails before launching, this method maybe triggered
......@@ -300,12 +410,12 @@ void BlackBerryApplicationRunner::launchApplication()
QStringList args;
args << QLatin1String("-launchApp");
if (m_cppDebugMode)
if (m_launchFlags.testFlag(CppDebugLaunch))
args << QLatin1String("-debugNative");
args << QLatin1String("-device") << m_sshParams.host;
if (!m_sshParams.password.isEmpty())
args << QLatin1String("-password") << m_sshParams.password;
args << QDir::toNativeSeparators(m_barPackage);
args << QLatin1String("-package") << QDir::toNativeSeparators(m_barPackage);
if (!m_launchProcess) {
m_launchProcess = new QProcess(this);
......@@ -316,7 +426,8 @@ void BlackBerryApplicationRunner::launchApplication()
m_launchProcess->setEnvironment(m_environment.toStringList());
}
if (debugCheckQmlJSArgs)
qDebug() << "launch:" << m_deployCmd << args.join(QLatin1Char(' '));
m_launchProcess->start(m_deployCmd, args);
m_runningStateTimer->start();
m_running = true;
......@@ -329,10 +440,10 @@ void BlackBerryApplicationRunner::checkDeployMode()
if (!BlackBerryDeviceConnectionManager::instance()->isConnected(m_device->id()))
return;
if (m_cppDebugMode)
if (m_launchFlags.testFlag(CppDebugLaunch))
queryDeviceInformation(); // check API version vs Runtime version
else
launchApplication();
checkQmlJsDebugArguments();
}
void BlackBerryApplicationRunner::startRunningStateTimer()
......
......@@ -58,15 +58,24 @@ class BlackBerryApplicationRunner : public QObject
{
Q_OBJECT
public:
explicit BlackBerryApplicationRunner(bool cppDebugMode, BlackBerryRunConfiguration *runConfiguration, QObject *parent = 0);
enum LaunchFlag
{
CppDebugLaunch = 0x1,
QmlDebugLaunch = 0x2,
QmlDebugLaunchBlocking = 0x4,
QmlProfilerLaunch = 0x8
};
Q_DECLARE_FLAGS(LaunchFlags, LaunchFlag)
public:
explicit BlackBerryApplicationRunner(const LaunchFlags &launchFlags, BlackBerryRunConfiguration *runConfiguration, QObject *parent = 0);
bool isRunning() const;
qint64 pid() const;
ProjectExplorer::RunControl::StopResult stop();
public slots:
void start();
ProjectExplorer::RunControl::StopResult stop();
signals:
void output(const QString &msg, Utils::OutputFormat format);
......@@ -97,11 +106,15 @@ private slots:
void displayConnectionOutput(Core::Id deviceId, const QString &output);
void checkDeviceRuntimeVersion(int status);
void checkQmlJsDebugArguments();
void checkQmlJsDebugArgumentsManifestLoaded();
void checkQmlJsDebugArgumentsManifestSaved();
private:
void reset();
void queryDeviceInformation();
bool m_cppDebugMode;
LaunchFlags m_launchFlags;
qint64 m_pid;
QString m_appId;
......@@ -126,6 +139,9 @@ private:
QProcess *m_runningStateProcess;
BlackBerryVersionNumber m_bbApiLevelVersion;
int m_qmlDebugServerPort;
QProcess *m_checkQmlJsDebugArgumentsProcess;
};
} // namespace Internal
......
......@@ -306,20 +306,6 @@ bool BlackBerryCreatePackageStep::prepareAppDescriptorFile(const QString &appDes
QDir::toNativeSeparators(target()->project()->projectDirectory());
doc.expandPlaceHolders(placeHoldersHash);
// Add parameter for QML debugging (if enabled)
Debugger::DebuggerRunConfigurationAspect *aspect
= target()->activeRunConfiguration()->extraAspect<Debugger::DebuggerRunConfigurationAspect>();
if (aspect->useQmlDebugger()) {
const QString qmlDebuggerArg = QString::fromLatin1("-qmljsdebugger=port:%1")
.arg(aspect->qmlDebugServerPort());
QStringList args = doc.value(BarDescriptorDocument::arg).toStringList();
if (!args.contains(qmlDebuggerArg))
args.append(qmlDebuggerArg);
doc.setValue(BarDescriptorDocument::arg, args);
}
// Set up correct environment depending on using bundled/pre-installed Qt
QList<Utils::EnvironmentItem> envItems =
doc.value(BarDescriptorDocument::env).value<QList<Utils::EnvironmentItem> >();
......
......@@ -44,8 +44,12 @@ BlackBerryDebugSupport::BlackBerryDebugSupport(BlackBerryRunConfiguration *runCo
: QObject(runControl->engine())
, m_engine(runControl->engine())
{
const bool cppDebugMode = m_engine->startParameters().languages & Debugger::CppLanguage;
m_runner = new BlackBerryApplicationRunner(cppDebugMode, runConfig, this);
BlackBerryApplicationRunner::LaunchFlags launchFlags;
if (m_engine->startParameters().languages & Debugger::CppLanguage)
launchFlags |= BlackBerryApplicationRunner::CppDebugLaunch;
if (m_engine->startParameters().languages & Debugger::QmlLanguage)
launchFlags |= BlackBerryApplicationRunner::QmlDebugLaunch;
m_runner = new BlackBerryApplicationRunner(launchFlags, runConfig, this);
connect(m_engine, SIGNAL(requestRemoteSetup()), this, SLOT(launchRemoteApplication()));
connect(m_engine, SIGNAL(stateChanged(Debugger::DebuggerState)),
......
......@@ -43,7 +43,7 @@ using namespace Qnx::Internal;
BlackBerryRunControl::BlackBerryRunControl(BlackBerryRunConfiguration *runConfiguration)
: ProjectExplorer::RunControl(runConfiguration, ProjectExplorer::NormalRunMode)
{
m_runner = new BlackBerryApplicationRunner(false, runConfiguration, this);
m_runner = new BlackBerryApplicationRunner(BlackBerryApplicationRunner::LaunchFlags(), runConfiguration, this);
connect(m_runner, SIGNAL(started()), this, SIGNAL(started()));
connect(m_runner, SIGNAL(finished()), this, SIGNAL(finished()));
......
......@@ -36,6 +36,7 @@
#include "blackberrydebugsupport.h"
#include "blackberryqtversion.h"
#include "blackberrydeviceconnectionmanager.h"
#include "blackberryapplicationrunner.h"
#include "qnxutils.h"
#include <debugger/debuggerplugin.h>
......@@ -48,6 +49,10 @@
#include <projectexplorer/toolchain.h>
#include <qmakeprojectmanager/qmakebuildconfiguration.h>
#include <qtsupport/qtkitinformation.h>
#include <analyzerbase/analyzerstartparameters.h>
#include <analyzerbase/analyzermanager.h>
#include <analyzerbase/analyzerruncontrol.h>
#include <coreplugin/messagemanager.h>
using namespace Qnx;
using namespace Qnx::Internal;
......@@ -86,6 +91,28 @@ bool BlackBerryRunControlFactory::canRun(ProjectExplorer::RunConfiguration *runC
return activeDeployConf != 0;
}
static void createAnalyzerStartParameters(Analyzer::AnalyzerStartParameters *pStartParameters, BlackBerryRunConfiguration* runConfiguration, ProjectExplorer::RunMode mode)
{
QTC_ASSERT(pStartParameters, return);
pStartParameters->runMode = mode;
if (mode == ProjectExplorer::QmlProfilerRunMode)
pStartParameters->startMode = Analyzer::StartLocal;
ProjectExplorer::Target *target = runConfiguration->target();
ProjectExplorer::Kit *kit = target->kit();
ProjectExplorer::IDevice::ConstPtr device = ProjectExplorer::DeviceKitInformation::device(kit);
if (device) {
pStartParameters->connParams = device->sshParameters();
pStartParameters->analyzerHost = device->qmlProfilerHost();
}
pStartParameters->sysroot = ProjectExplorer::SysRootKitInformation::sysRoot(kit).toString();
Debugger::DebuggerRunConfigurationAspect *aspect = runConfiguration->extraAspect<Debugger::DebuggerRunConfigurationAspect>();
if (aspect)
pStartParameters->analyzerPort = aspect->qmlDebugServerPort();
}
ProjectExplorer::RunControl *BlackBerryRunControlFactory::create(ProjectExplorer::RunConfiguration *runConfiguration,
ProjectExplorer::RunMode mode, QString *errorMessage)
{
......@@ -106,7 +133,32 @@ ProjectExplorer::RunControl *BlackBerryRunControlFactory::create(ProjectExplorer
m_activeRunControls[rc->key()] = runControl;
return runControl;
}
if (mode == ProjectExplorer::QmlProfilerRunMode) {
QtSupport::BaseQtVersion *qtVer = QtSupport::QtKitInformation::qtVersion(rc->target()->kit());
if (qtVer && qtVer->qtVersion() <= QtSupport::QtVersionNumber(4, 8, 6))
Core::MessageManager::write(tr("Target Qt version (%1) might not support QML profiling. "
"Cascades applications are not affected and should work as expected. "
"For more info see http://qt-project.org/wiki/Qt-Creator-with-BlackBerry-10")
.arg(qtVer->qtVersionString()), Core::MessageManager::Flash
);
Analyzer::AnalyzerStartParameters params;
createAnalyzerStartParameters(&params, rc, mode);
Analyzer::AnalyzerRunControl *runControl = Analyzer::AnalyzerManager::createRunControl(params, runConfiguration);
BlackBerryApplicationRunner::LaunchFlags launchFlags(BlackBerryApplicationRunner::QmlDebugLaunch
| BlackBerryApplicationRunner::QmlDebugLaunchBlocking
| BlackBerryApplicationRunner::QmlProfilerLaunch);
BlackBerryApplicationRunner *runner = new BlackBerryApplicationRunner(launchFlags, rc, runControl);
connect(runner, SIGNAL(finished()), runControl, SLOT(notifyRemoteFinished()));
connect(runner, SIGNAL(output(QString, Utils::OutputFormat)),
runControl, SLOT(logApplicationMessage(QString, Utils::OutputFormat)));
connect(runControl, SIGNAL(starting(const Analyzer::AnalyzerRunControl*)),
runner, SLOT(start()));
connect(runControl, SIGNAL(finished()), runner, SLOT(stop()));
return runControl;
}
Debugger::DebuggerRunControl * const runControl =
Debugger::DebuggerPlugin::createDebugger(startParameters(rc), runConfiguration, errorMessage);
if (!runControl)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment