winrtdebugsupport.cpp 4.64 KB
Newer Older
1 2
/****************************************************************************
**
3 4
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
5 6 7 8 9 10 11
**
** 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
12 13 14
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
15
**
16 17 18 19 20 21 22
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 24 25 26 27 28 29 30 31 32
**
****************************************************************************/

#include "winrtdebugsupport.h"
#include "winrtrunconfiguration.h"
#include "winrtrunnerhelper.h"

#include <projectexplorer/target.h>
#include <projectexplorer/toolchain.h>

33 34
#include <qmldebug/qmldebugcommandlinearguments.h>

35 36 37
#include <QFileInfo>
#include <QLocalServer>
#include <QLocalSocket>
38
#include <QTcpServer>
39 40 41

#include <utils/qtcprocess.h>

hjk's avatar
hjk committed
42
using namespace Debugger;
43 44
using namespace ProjectExplorer;

hjk's avatar
hjk committed
45 46
namespace WinRt {
namespace Internal {
47

48
WinRtDebugSupport::WinRtDebugSupport(RunControl *runControl)
hjk's avatar
hjk committed
49
    : DebuggerRunTool(runControl)
50 51 52 53 54 55 56 57 58 59
{
    // FIXME: This is just working for local debugging;
    DebuggerStartParameters params;
    params.startMode = AttachExternal;
    // The first Thread needs to be resumed manually.
    params.commandsAfterConnect = "~0 m";

    QFileInfo debuggerHelper(QCoreApplication::applicationDirPath()
                             + QLatin1String("/winrtdebughelper.exe"));
    if (!debuggerHelper.isExecutable()) {
60 61 62
        reportFailure(tr("The WinRT debugging helper is missing from your Qt Creator "
                         "installation. It was assumed to be located at %1").arg(
                    debuggerHelper.absoluteFilePath()));
hjk's avatar
hjk committed
63
        return;
64 65
    }

hjk's avatar
hjk committed
66
    if (isQmlDebugging()) {
Ulf Hermann's avatar
Ulf Hermann committed
67
        Utils::Port qmlDebugPort;
68
        if (!getFreePort(qmlDebugPort))
hjk's avatar
hjk committed
69
            return;
70 71
        params.qmlServer.host = QHostAddress(QHostAddress::LocalHost).toString();
        params.qmlServer.port = qmlDebugPort;
72 73
    }

74 75 76 77
    QString errorMessage;
    m_runner = new WinRtRunnerHelper(this, &errorMessage);
    if (!errorMessage.isEmpty()) {
        reportFailure(errorMessage);
hjk's avatar
hjk committed
78
        return;
79
    }
80

81 82 83
    QLocalServer server;
    server.listen(QLatin1String("QtCreatorWinRtDebugPIDPipe"));

hjk's avatar
hjk committed
84 85
    m_runner->debug(debuggerHelper.absoluteFilePath());
    if (!m_runner->waitForStarted()) {
86
        reportFailure(tr("Cannot start the WinRT Runner Tool."));
hjk's avatar
hjk committed
87
        return;
88 89 90
    }

    if (!server.waitForNewConnection(10000)) {
91
        reportFailure(tr("Cannot establish connection to the WinRT debugging helper."));
hjk's avatar
hjk committed
92
        return;
93 94 95 96 97 98 99 100 101
    }

    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;
102
                params.attachPID = Utils::ProcessHandle(arg.last().toInt(&ok));
103
                if (!ok) {
104 105
                    reportFailure(tr("Cannot extract the PID from the WinRT debugging helper. "
                                     "(output: %1)").arg(QString::fromLocal8Bit(output)));
hjk's avatar
hjk committed
106
                    return;
107 108
                }
                server.close();
109
                setStartParameters(params);
hjk's avatar
hjk committed
110
                return;
111 112 113 114 115 116
            }
        }
    }

    server.close();

117 118
    reportFailure(tr("Cannot create an appropriate run control for "
                     "the current run configuration."));
hjk's avatar
hjk committed
119
}
120

121
bool WinRtDebugSupport::getFreePort(Utils::Port &qmlDebuggerPort)
hjk's avatar
hjk committed
122 123 124 125
{
    QTcpServer server;
    if (!server.listen(QHostAddress::LocalHost,
                       qmlDebuggerPort.isValid() ? qmlDebuggerPort.number() : 0)) {
126
        reportFailure(tr("Not enough free ports for QML debugging."));
hjk's avatar
hjk committed
127 128 129 130 131 132 133 134 135
        return false;
    }
    qmlDebuggerPort = Utils::Port(server.serverPort());
    return true;
}

WinRtDebugSupport::~WinRtDebugSupport()
{
    delete m_runner;
136 137 138 139
}

} // namespace Internal
} // namespace WinRt