forked from qt-creator/qt-creator
QmlProfiler: Support local connections on Qt >= 5.6
This removes the need to receive messages from the application via stderr. The "Connecting to socket" is still parsed, but only for diagnostic purposes. If it doesn't arrive, the profiling will still work. Change-Id: I022691293da2a1e671ba1263bc76e4044bf1a5b7 Reviewed-by: Joerg Bornemann <joerg.bornemann@theqtcompany.com>
This commit is contained in:
@@ -44,6 +44,7 @@
|
||||
#include <qmldebug/qmldebugcommandlinearguments.h>
|
||||
|
||||
#include <QTcpServer>
|
||||
#include <QTemporaryFile>
|
||||
|
||||
using namespace QmlProfiler;
|
||||
using namespace ProjectExplorer;
|
||||
@@ -71,7 +72,7 @@ Analyzer::AnalyzerRunControl *LocalQmlProfilerRunner::createLocalRunControl(
|
||||
conf.executableArguments = sp.debuggeeArgs;
|
||||
conf.workingDirectory = sp.workingDirectory;
|
||||
conf.environment = sp.environment;
|
||||
|
||||
conf.socket = sp.analyzerSocket;
|
||||
conf.port = sp.analyzerPort;
|
||||
|
||||
if (conf.executable.isEmpty()) {
|
||||
@@ -92,6 +93,17 @@ Analyzer::AnalyzerRunControl *LocalQmlProfilerRunner::createLocalRunControl(
|
||||
return rc;
|
||||
}
|
||||
|
||||
QString LocalQmlProfilerRunner::findFreeSocket()
|
||||
{
|
||||
QTemporaryFile file;
|
||||
if (file.open()) {
|
||||
return file.fileName();
|
||||
} else {
|
||||
qWarning() << "Could not open a temporary file to find a debug socket.";
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
|
||||
quint16 LocalQmlProfilerRunner::findFreePort(QString &host)
|
||||
{
|
||||
QTcpServer server;
|
||||
@@ -121,15 +133,21 @@ LocalQmlProfilerRunner::~LocalQmlProfilerRunner()
|
||||
|
||||
void LocalQmlProfilerRunner::start()
|
||||
{
|
||||
QString arguments = QmlDebug::qmlDebugTcpArguments(QmlDebug::QmlProfilerServices,
|
||||
m_configuration.port);
|
||||
QString arguments = m_configuration.socket.isEmpty() ?
|
||||
QmlDebug::qmlDebugTcpArguments(QmlDebug::QmlProfilerServices,
|
||||
m_configuration.port) :
|
||||
QmlDebug::qmlDebugLocalArguments(QmlDebug::QmlProfilerServices,
|
||||
m_configuration.socket);
|
||||
|
||||
|
||||
if (!m_configuration.executableArguments.isEmpty())
|
||||
arguments += QLatin1Char(' ') + m_configuration.executableArguments;
|
||||
|
||||
if (QmlProfilerPlugin::debugOutput)
|
||||
qWarning("QmlProfiler: Launching %s:%d", qPrintable(m_configuration.executable),
|
||||
m_configuration.port);
|
||||
if (QmlProfilerPlugin::debugOutput) {
|
||||
qWarning("QmlProfiler: Launching %s:%s", qPrintable(m_configuration.executable),
|
||||
qPrintable(m_configuration.socket.isEmpty() ?
|
||||
QString::number(m_configuration.port) : m_configuration.socket));
|
||||
}
|
||||
|
||||
m_launcher.setWorkingDirectory(m_configuration.workingDirectory);
|
||||
m_launcher.setEnvironment(m_configuration.environment);
|
||||
|
||||
@@ -53,6 +53,7 @@ public:
|
||||
QString executable;
|
||||
QString executableArguments;
|
||||
quint16 port;
|
||||
QString socket;
|
||||
QString workingDirectory;
|
||||
Utils::Environment environment;
|
||||
};
|
||||
@@ -63,6 +64,7 @@ public:
|
||||
QString *errorMessage);
|
||||
|
||||
static quint16 findFreePort(QString &host);
|
||||
static QString findFreeSocket();
|
||||
|
||||
~LocalQmlProfilerRunner();
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ public:
|
||||
QTimer connectionTimer;
|
||||
int connectionAttempts;
|
||||
|
||||
QString localSocket;
|
||||
QString tcpHost;
|
||||
quint64 tcpPort;
|
||||
QString sysroot;
|
||||
@@ -107,6 +108,13 @@ void QmlProfilerClientManager::setTcpConnection(QString host, quint64 port)
|
||||
disconnectClient();
|
||||
}
|
||||
|
||||
void QmlProfilerClientManager::setLocalSocket(QString file)
|
||||
{
|
||||
d->localSocket = file;
|
||||
d->tcpPort = 0;
|
||||
connectLocalClient(file);
|
||||
}
|
||||
|
||||
void QmlProfilerClientManager::clearBufferedData()
|
||||
{
|
||||
if (d->qmlclientplugin)
|
||||
@@ -118,7 +126,7 @@ void QmlProfilerClientManager::discardPendingData()
|
||||
clearBufferedData();
|
||||
}
|
||||
|
||||
void QmlProfilerClientManager::connectClient(quint16 port)
|
||||
void QmlProfilerClientManager::connectTcpClient(quint16 port)
|
||||
{
|
||||
if (d->connection) {
|
||||
if (port == d->tcpPort) {
|
||||
@@ -129,22 +137,28 @@ void QmlProfilerClientManager::connectClient(quint16 port)
|
||||
}
|
||||
}
|
||||
|
||||
d->connection = new QmlDebugConnection;
|
||||
enableServices();
|
||||
connect(d->connection, &QmlDebugConnection::connected,
|
||||
this, &QmlProfilerClientManager::qmlDebugConnectionOpened);
|
||||
connect(d->connection, &QmlDebugConnection::disconnected,
|
||||
this, &QmlProfilerClientManager::qmlDebugConnectionClosed);
|
||||
connect(d->connection, &QmlDebugConnection::socketError,
|
||||
this, &QmlProfilerClientManager::qmlDebugConnectionError);
|
||||
connect(d->connection, &QmlDebugConnection::socketStateChanged,
|
||||
this, &QmlProfilerClientManager::qmlDebugConnectionStateChanged);
|
||||
createConnection();
|
||||
d->connectionTimer.start();
|
||||
d->tcpPort = port;
|
||||
}
|
||||
|
||||
void QmlProfilerClientManager::enableServices()
|
||||
void QmlProfilerClientManager::connectLocalClient(const QString &file)
|
||||
{
|
||||
if (d->connection) {
|
||||
if (file == d->localSocket)
|
||||
return;
|
||||
else
|
||||
delete d->connection;
|
||||
}
|
||||
|
||||
createConnection();
|
||||
d->localSocket = file;
|
||||
d->connection->startLocalServer(file);
|
||||
}
|
||||
|
||||
void QmlProfilerClientManager::createConnection()
|
||||
{
|
||||
d->connection = new QmlDebugConnection;
|
||||
QTC_ASSERT(d->profilerState, return);
|
||||
|
||||
disconnectClientSignals();
|
||||
@@ -155,6 +169,14 @@ void QmlProfilerClientManager::enableServices()
|
||||
d->profilerState->requestedFeatures());
|
||||
d->qmlclientplugin->setFlushInterval(d->flushInterval);
|
||||
connectClientSignals();
|
||||
connect(d->connection, &QmlDebugConnection::connected,
|
||||
this, &QmlProfilerClientManager::qmlDebugConnectionOpened);
|
||||
connect(d->connection, &QmlDebugConnection::disconnected,
|
||||
this, &QmlProfilerClientManager::qmlDebugConnectionClosed);
|
||||
connect(d->connection, &QmlDebugConnection::socketError,
|
||||
this, &QmlProfilerClientManager::qmlDebugConnectionError);
|
||||
connect(d->connection, &QmlDebugConnection::socketStateChanged,
|
||||
this, &QmlProfilerClientManager::qmlDebugConnectionStateChanged);
|
||||
}
|
||||
|
||||
void QmlProfilerClientManager::connectClientSignals()
|
||||
|
||||
@@ -52,6 +52,7 @@ public:
|
||||
|
||||
void registerProfilerStateManager(QmlProfilerStateManager *profilerState);
|
||||
void setTcpConnection(QString host, quint64 port);
|
||||
void setLocalSocket(QString file);
|
||||
|
||||
void clearBufferedData();
|
||||
void discardPendingData();
|
||||
@@ -65,7 +66,8 @@ signals:
|
||||
void connectionClosed();
|
||||
|
||||
public slots:
|
||||
void connectClient(quint16 port);
|
||||
void connectTcpClient(quint16 port);
|
||||
void connectLocalClient(const QString &file);
|
||||
void disconnectClient();
|
||||
|
||||
private slots:
|
||||
@@ -89,7 +91,7 @@ private:
|
||||
|
||||
void connectToClient();
|
||||
|
||||
void enableServices();
|
||||
void createConnection();
|
||||
void connectClientSignals();
|
||||
void disconnectClientSignals();
|
||||
|
||||
|
||||
@@ -96,6 +96,8 @@ QmlProfilerRunControl::QmlProfilerRunControl(const AnalyzerStartParameters &sp,
|
||||
this, &QmlProfilerRunControl::processIsRunning);
|
||||
connect(&d->m_outputParser, &QmlDebug::QmlOutputParser::noOutputMessage,
|
||||
this, [this](){processIsRunning(0);});
|
||||
connect(&d->m_outputParser, &QmlDebug::QmlOutputParser::connectingToSocketMessage,
|
||||
this, [this](){processIsRunning(0);});
|
||||
connect(&d->m_outputParser, &QmlDebug::QmlOutputParser::errorMessage,
|
||||
this, &QmlProfilerRunControl::wrongSetupMessageBox);
|
||||
}
|
||||
@@ -113,7 +115,7 @@ bool QmlProfilerRunControl::startEngine()
|
||||
|
||||
if (startParameters().analyzerPort != 0)
|
||||
emit processRunning(startParameters().analyzerPort);
|
||||
else
|
||||
else if (startParameters().analyzerSocket.isEmpty())
|
||||
d->m_noDebugOutputTimer.start();
|
||||
|
||||
d->m_profilerState->setCurrentState(QmlProfilerStateManager::AppRunning);
|
||||
|
||||
@@ -44,6 +44,8 @@
|
||||
#include <projectexplorer/project.h>
|
||||
#include <projectexplorer/session.h>
|
||||
#include <projectexplorer/target.h>
|
||||
#include <qtsupport/baseqtversion.h>
|
||||
#include <qtsupport/qtkitinformation.h>
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
@@ -79,7 +81,19 @@ static AnalyzerStartParameters createQmlProfilerStartParameters(RunConfiguration
|
||||
sp.debuggee = rc->executable();
|
||||
sp.debuggeeArgs = rc->commandLineArguments();
|
||||
sp.displayName = rc->displayName();
|
||||
sp.analyzerPort = LocalQmlProfilerRunner::findFreePort(sp.analyzerHost);
|
||||
|
||||
const QtSupport::BaseQtVersion *version =
|
||||
QtSupport::QtKitInformation::qtVersion(runConfiguration->target()->kit());
|
||||
if (version) {
|
||||
QtSupport::QtVersionNumber versionNumber = version->qtVersion();
|
||||
if (versionNumber.majorVersion >= 5 && versionNumber.minorVersion >= 6)
|
||||
sp.analyzerSocket = LocalQmlProfilerRunner::findFreeSocket();
|
||||
else
|
||||
sp.analyzerPort = LocalQmlProfilerRunner::findFreePort(sp.analyzerHost);
|
||||
} else {
|
||||
qWarning() << "Running QML profiler on Kit without Qt version??";
|
||||
sp.analyzerPort = LocalQmlProfilerRunner::findFreePort(sp.analyzerHost);
|
||||
}
|
||||
|
||||
return sp;
|
||||
}
|
||||
|
||||
@@ -214,10 +214,10 @@ AnalyzerRunControl *QmlProfilerTool::createRunControl(const AnalyzerStartParamet
|
||||
|
||||
engine->registerProfilerStateManager(d->m_profilerState);
|
||||
|
||||
bool isTcpConnection = true;
|
||||
|
||||
// FIXME: Check that there's something sensible in sp.connParams
|
||||
if (isTcpConnection)
|
||||
if (!sp.analyzerSocket.isEmpty())
|
||||
d->m_profilerConnections->setLocalSocket(sp.analyzerSocket);
|
||||
else
|
||||
d->m_profilerConnections->setTcpConnection(sp.analyzerHost, sp.analyzerPort);
|
||||
|
||||
//
|
||||
@@ -232,8 +232,9 @@ AnalyzerRunControl *QmlProfilerTool::createRunControl(const AnalyzerStartParamet
|
||||
|
||||
populateFileFinder(projectDirectory, sp.sysroot);
|
||||
|
||||
connect(engine, &QmlProfilerRunControl::processRunning,
|
||||
d->m_profilerConnections, &QmlProfilerClientManager::connectClient);
|
||||
if (sp.analyzerSocket.isEmpty())
|
||||
connect(engine, &QmlProfilerRunControl::processRunning,
|
||||
d->m_profilerConnections, &QmlProfilerClientManager::connectTcpClient);
|
||||
connect(d->m_profilerConnections, &QmlProfilerClientManager::connectionFailed,
|
||||
engine, &QmlProfilerRunControl::cancelProcess);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user