androiddebugsupport.cpp 7.85 KB
Newer Older
1
/****************************************************************************
BogDan Vatra's avatar
BogDan Vatra committed
2
**
3 4
** Copyright (C) 2016 BogDan Vatra <bog_dan_ro@yahoo.com>
** Contact: https://www.qt.io/licensing/
BogDan Vatra's avatar
BogDan Vatra committed
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
BogDan Vatra's avatar
BogDan Vatra committed
7
**
hjk's avatar
hjk committed
8 9 10 11
** 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.
BogDan Vatra's avatar
BogDan Vatra committed
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.
BogDan Vatra's avatar
BogDan Vatra committed
23
**
hjk's avatar
hjk committed
24
****************************************************************************/
BogDan Vatra's avatar
BogDan Vatra committed
25 26 27 28 29

#include "androiddebugsupport.h"

#include "androidglobal.h"
#include "androidrunner.h"
Tobias Hunger's avatar
Tobias Hunger committed
30
#include "androidmanager.h"
31
#include "androidqtsupport.h"
BogDan Vatra's avatar
BogDan Vatra committed
32

Tobias Hunger's avatar
Tobias Hunger committed
33
#include <debugger/debuggerkitinformation.h>
34
#include <debugger/debuggerrunconfigurationaspect.h>
35
#include <debugger/debuggerruncontrol.h>
BogDan Vatra's avatar
BogDan Vatra committed
36 37
#include <debugger/debuggerstartparameters.h>

38 39
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/project.h>
Tobias Hunger's avatar
Tobias Hunger committed
40
#include <projectexplorer/target.h>
41
#include <projectexplorer/toolchain.h>
42

Tobias Hunger's avatar
Tobias Hunger committed
43
#include <qtsupport/qtkitinformation.h>
BogDan Vatra's avatar
BogDan Vatra committed
44

45 46
#include <utils/hostosinfo.h>

47
#include <QDirIterator>
Aurindam Jana's avatar
Aurindam Jana committed
48
#include <QTcpServer>
BogDan Vatra's avatar
BogDan Vatra committed
49 50 51 52 53 54 55 56 57 58 59 60 61

using namespace Debugger;
using namespace ProjectExplorer;

namespace Android {
namespace Internal {

static const char * const qMakeVariables[] = {
         "QT_INSTALL_LIBS",
         "QT_INSTALL_PLUGINS",
         "QT_INSTALL_IMPORTS"
};

62 63 64 65 66 67 68 69 70 71
static QStringList qtSoPaths(QtSupport::BaseQtVersion *qtVersion)
{
    if (!qtVersion)
        return QStringList();

    QSet<QString> paths;
    for (uint i = 0; i < sizeof qMakeVariables / sizeof qMakeVariables[0]; ++i) {
        QString path = qtVersion->qmakeProperty(qMakeVariables[i]);
        if (path.isNull())
            continue;
72
        QDirIterator it(path, QStringList("*.so"), QDir::Files, QDirIterator::Subdirectories);
73 74 75 76 77 78 79
        while (it.hasNext()) {
            it.next();
            paths.insert(it.fileInfo().absolutePath());
        }
    }
    return paths.toList();
}
BogDan Vatra's avatar
BogDan Vatra committed
80

81 82 83 84 85 86 87 88
static QStringList uniquePaths(const QStringList &files)
{
    QSet<QString> paths;
    foreach (const QString &file, files)
        paths<<QFileInfo(file).absolutePath();
    return paths.toList();
}

89 90 91 92 93 94 95 96 97
static QString toNdkArch(const QString &arch)
{
    if (arch == QLatin1String("armeabi-v7a") || arch == QLatin1String("armeabi"))
        return QLatin1String("arch-arm");
    if (arch == QLatin1String("arm64-v8a"))
        return QLatin1String("arch-arm64");
    return QLatin1String("arch-") + arch;
}

98
RunControl *AndroidDebugSupport::createDebugRunControl(AndroidRunConfiguration *runConfig, QString *errorMessage)
BogDan Vatra's avatar
BogDan Vatra committed
99
{
100 101
    Target *target = runConfig->target();

BogDan Vatra's avatar
BogDan Vatra committed
102 103
    DebuggerStartParameters params;
    params.startMode = AttachToRemoteServer;
104
    params.displayName = AndroidManager::packageName(target);
105
    params.remoteSetupNeeded = true;
106
    params.useContinueInsteadOfRun = true;
107 108
    if (!Utils::HostOsInfo::isWindowsHost()) // Workaround for NDK 11c(b?)
        params.useTargetAsync = true;
109

110
    auto aspect = runConfig->extraAspect<DebuggerRunConfigurationAspect>();
111
    if (aspect->useCppDebugger()) {
Tobias Hunger's avatar
Tobias Hunger committed
112
        Kit *kit = target->kit();
113
        params.symbolFile = target->activeBuildConfiguration()->buildDirectory().toString()
114
                                     + QLatin1String("/app_process");
115
        params.skipExecutableValidation = true;
116
        params.remoteChannel = runConfig->remoteChannel();
117
        params.solibSearchPath = AndroidManager::androidQtSupport(target)->soLibSearchPath(target);
Tobias Hunger's avatar
Tobias Hunger committed
118
        QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(kit);
119
        params.solibSearchPath.append(qtSoPaths(version));
120
        params.solibSearchPath.append(uniquePaths(AndroidManager::androidQtSupport(target)->androidExtraLibs(target)));
121 122 123
        params.sysRoot = AndroidConfigurations::currentConfig().ndkLocation().appendPath(QLatin1String("platforms"))
                                                     .appendPath(QLatin1String("android-") + QString::number(AndroidManager::minimumSDK(target)))
                                                     .appendPath(toNdkArch(AndroidManager::targetArch(target))).toString();
124
    }
125
    if (aspect->useQmlDebugger()) {
Aurindam Jana's avatar
Aurindam Jana committed
126 127 128
        QTcpServer server;
        QTC_ASSERT(server.listen(QHostAddress::LocalHost)
                   || server.listen(QHostAddress::LocalHostIPv6), return 0);
129
        params.qmlServer.host = server.serverAddress().toString();
130
        //TODO: Not sure if these are the right paths.
131 132 133
        Kit *kit = target->kit();
        QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(kit);
        if (version) {
134
            const QString qmlQtDir = version->qmakeProperty("QT_INSTALL_QML");
135 136
            params.additionalSearchDirectories = QStringList(qmlQtDir);
        }
137
    }
BogDan Vatra's avatar
BogDan Vatra committed
138

139
    DebuggerRunControl * const debuggerRunControl = createDebuggerRunControl(params, runConfig, errorMessage);
BogDan Vatra's avatar
BogDan Vatra committed
140 141 142 143 144 145
    new AndroidDebugSupport(runConfig, debuggerRunControl);
    return debuggerRunControl;
}

AndroidDebugSupport::AndroidDebugSupport(AndroidRunConfiguration *runConfig,
    DebuggerRunControl *runControl)
146 147 148
    : QObject(runControl),
      m_runControl(runControl),
      m_runner(new AndroidRunner(this, runConfig, runControl->runMode()))
BogDan Vatra's avatar
BogDan Vatra committed
149
{
150 151
    QTC_ASSERT(runControl, return);

hjk's avatar
hjk committed
152 153
    connect(m_runControl, &RunControl::finished,
            m_runner, &AndroidRunner::stop);
154

hjk's avatar
hjk committed
155 156
    connect(m_runControl, &DebuggerRunControl::requestRemoteSetup,
            m_runner, &AndroidRunner::start);
Aurindam Jana's avatar
Aurindam Jana committed
157

hjk's avatar
hjk committed
158 159
    // FIXME: Move signal to base class and generalize handling.
    connect(m_runControl, &DebuggerRunControl::aboutToNotifyInferiorSetupOk,
160
            m_runner, &AndroidRunner::remoteDebuggerRunning);
BogDan Vatra's avatar
BogDan Vatra committed
161

162 163
    connect(m_runner, &AndroidRunner::remoteServerRunning,
        [this](const QByteArray &serverChannel, int pid) {
hjk's avatar
hjk committed
164 165
            QTC_ASSERT(m_runControl, return);
            m_runControl->notifyEngineRemoteServerRunning(serverChannel, pid);
166 167 168 169 170 171 172 173
        });

    connect(m_runner, &AndroidRunner::remoteProcessStarted,
            this, &AndroidDebugSupport::handleRemoteProcessStarted);

    connect(m_runner, &AndroidRunner::remoteProcessFinished,
        [this](const QString &errorMsg) {
            QTC_ASSERT(m_runControl, return);
174
            m_runControl->appendMessage(errorMsg, Utils::DebugFormat);
hjk's avatar
hjk committed
175
            QMetaObject::invokeMethod(m_runControl, "notifyInferiorExited", Qt::QueuedConnection);
176 177 178
        });

    connect(m_runner, &AndroidRunner::remoteErrorOutput,
179
        [this](const QString &output) {
hjk's avatar
hjk committed
180
            QTC_ASSERT(m_runControl, return);
181
            m_runControl->showMessage(output, AppError);
182 183 184
        });

    connect(m_runner, &AndroidRunner::remoteOutput,
185
        [this](const QString &output) {
hjk's avatar
hjk committed
186
            QTC_ASSERT(m_runControl, return);
187
            m_runControl->showMessage(output, AppOutput);
188
        });
hjk's avatar
hjk committed
189 190
}

Ulf Hermann's avatar
Ulf Hermann committed
191
void AndroidDebugSupport::handleRemoteProcessStarted(Utils::Port gdbServerPort, Utils::Port qmlPort)
BogDan Vatra's avatar
BogDan Vatra committed
192
{
193 194
    disconnect(m_runner, &AndroidRunner::remoteProcessStarted,
               this, &AndroidDebugSupport::handleRemoteProcessStarted);
hjk's avatar
hjk committed
195
    QTC_ASSERT(m_runControl, return);
196 197 198 199
    RemoteSetupResult result;
    result.success = true;
    result.gdbServerPort = gdbServerPort;
    result.qmlServerPort = qmlPort;
hjk's avatar
hjk committed
200
    m_runControl->notifyEngineRemoteSetupFinished(result);
BogDan Vatra's avatar
BogDan Vatra committed
201 202 203
}

} // namespace Internal
hjk's avatar
hjk committed
204
} // namespace Android