forked from qt-creator/qt-creator
Treat ApplicationLauncher as a special case of a DeviceApplicationRunner with an implicit desktop device. As a first step, lump the two implementations together. Change-Id: Ifa3ea3f38d320023050378555e2d256e762b6683 Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
203 lines
6.4 KiB
C++
203 lines
6.4 KiB
C++
/****************************************************************************
|
|
**
|
|
** Copyright (C) 2016 Denis Shienkov <denis.shienkov@gmail.com>
|
|
** Contact: https://www.qt.io/licensing/
|
|
**
|
|
** 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
|
|
** 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.
|
|
**
|
|
** 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.
|
|
**
|
|
****************************************************************************/
|
|
|
|
#include "baremetaldebugsupport.h"
|
|
#include "baremetalrunconfiguration.h"
|
|
#include "baremetaldevice.h"
|
|
|
|
#include "gdbserverprovider.h"
|
|
#include "gdbserverprovidermanager.h"
|
|
|
|
#include <debugger/debuggerruncontrol.h>
|
|
#include <debugger/debuggerstartparameters.h>
|
|
|
|
#include <projectexplorer/runnables.h>
|
|
|
|
#include <utils/qtcprocess.h>
|
|
|
|
using namespace ProjectExplorer;
|
|
|
|
namespace BareMetal {
|
|
namespace Internal {
|
|
|
|
BareMetalDebugSupport::BareMetalDebugSupport(Debugger::DebuggerRunControl *runControl)
|
|
: QObject(runControl)
|
|
, m_appLauncher(new ProjectExplorer::ApplicationLauncher(this))
|
|
, m_runControl(runControl)
|
|
, m_state(BareMetalDebugSupport::Inactive)
|
|
{
|
|
Q_ASSERT(runControl);
|
|
connect(m_runControl.data(), &Debugger::DebuggerRunControl::requestRemoteSetup,
|
|
this, &BareMetalDebugSupport::remoteSetupRequested);
|
|
connect(runControl, &Debugger::DebuggerRunControl::finished,
|
|
this, &BareMetalDebugSupport::debuggingFinished);
|
|
}
|
|
|
|
BareMetalDebugSupport::~BareMetalDebugSupport()
|
|
{
|
|
setFinished();
|
|
}
|
|
|
|
void BareMetalDebugSupport::remoteSetupRequested()
|
|
{
|
|
QTC_ASSERT(m_state == Inactive, return);
|
|
startExecution();
|
|
}
|
|
|
|
void BareMetalDebugSupport::debuggingFinished()
|
|
{
|
|
setFinished();
|
|
reset();
|
|
}
|
|
|
|
void BareMetalDebugSupport::remoteOutputMessage(const QByteArray &output)
|
|
{
|
|
QTC_ASSERT(m_state == Inactive || m_state == Running, return);
|
|
showMessage(QString::fromUtf8(output), Debugger::AppOutput);
|
|
}
|
|
|
|
void BareMetalDebugSupport::remoteErrorOutputMessage(const QByteArray &output)
|
|
{
|
|
QTC_ASSERT(m_state == Inactive, return);
|
|
showMessage(QString::fromUtf8(output), Debugger::AppError);
|
|
|
|
// FIXME: Should we here parse an outputn?
|
|
}
|
|
|
|
void BareMetalDebugSupport::remoteProcessStarted()
|
|
{
|
|
QTC_ASSERT(m_state == StartingRunner, return);
|
|
adapterSetupDone();
|
|
}
|
|
|
|
void BareMetalDebugSupport::appRunnerFinished(bool success)
|
|
{
|
|
if (m_state == Inactive)
|
|
return;
|
|
|
|
if (m_state == Running) {
|
|
if (!success)
|
|
m_runControl->notifyInferiorIll();
|
|
} else if (m_state == StartingRunner) {
|
|
Debugger::RemoteSetupResult result;
|
|
result.success = false;
|
|
result.reason = tr("Debugging failed.");
|
|
m_runControl->notifyEngineRemoteSetupFinished(result);
|
|
}
|
|
|
|
reset();
|
|
}
|
|
|
|
void BareMetalDebugSupport::progressReport(const QString &progressOutput)
|
|
{
|
|
showMessage(progressOutput + QLatin1Char('\n'), Debugger::LogStatus);
|
|
}
|
|
|
|
void BareMetalDebugSupport::appRunnerError(const QString &error)
|
|
{
|
|
if (m_state == Running) {
|
|
showMessage(error, Debugger::AppError);
|
|
m_runControl->notifyInferiorIll();
|
|
} else if (m_state != Inactive) {
|
|
adapterSetupFailed(error);
|
|
}
|
|
}
|
|
|
|
void BareMetalDebugSupport::adapterSetupDone()
|
|
{
|
|
m_state = Running;
|
|
Debugger::RemoteSetupResult result;
|
|
result.success = true;
|
|
m_runControl->notifyEngineRemoteSetupFinished(result);
|
|
}
|
|
|
|
void BareMetalDebugSupport::adapterSetupFailed(const QString &error)
|
|
{
|
|
debuggingFinished();
|
|
|
|
Debugger::RemoteSetupResult result;
|
|
result.success = false;
|
|
result.reason = tr("Initial setup failed: %1").arg(error);
|
|
m_runControl->notifyEngineRemoteSetupFinished(result);
|
|
}
|
|
|
|
void BareMetalDebugSupport::startExecution()
|
|
{
|
|
auto dev = qSharedPointerCast<const BareMetalDevice>(m_runControl->device());
|
|
QTC_ASSERT(dev, return);
|
|
|
|
const GdbServerProvider *p = GdbServerProviderManager::instance()->findProvider(
|
|
dev->gdbServerProviderId());
|
|
QTC_ASSERT(p, return);
|
|
|
|
m_state = StartingRunner;
|
|
showMessage(tr("Starting GDB server...") + QLatin1Char('\n'), Debugger::LogStatus);
|
|
|
|
connect(m_appLauncher, &ProjectExplorer::ApplicationLauncher::remoteStderr,
|
|
this, &BareMetalDebugSupport::remoteErrorOutputMessage);
|
|
connect(m_appLauncher, &ProjectExplorer::ApplicationLauncher::remoteStdout,
|
|
this, &BareMetalDebugSupport::remoteOutputMessage);
|
|
connect(m_appLauncher, &ProjectExplorer::ApplicationLauncher::remoteProcessStarted,
|
|
this, &BareMetalDebugSupport::remoteProcessStarted);
|
|
connect(m_appLauncher, &ProjectExplorer::ApplicationLauncher::finished,
|
|
this, &BareMetalDebugSupport::appRunnerFinished);
|
|
connect(m_appLauncher, &ProjectExplorer::ApplicationLauncher::reportProgress,
|
|
this, &BareMetalDebugSupport::progressReport);
|
|
connect(m_appLauncher, &ProjectExplorer::ApplicationLauncher::reportError,
|
|
this, &BareMetalDebugSupport::appRunnerError);
|
|
|
|
StandardRunnable r;
|
|
r.executable = p->executable();
|
|
// We need to wrap the command arguments depending on a host OS,
|
|
// as the bare metal's GDB servers are launched on a host,
|
|
// but not on a target.
|
|
r.commandLineArguments = Utils::QtcProcess::joinArgs(p->arguments(), Utils::HostOsInfo::hostOs());
|
|
m_appLauncher->start(r, dev);
|
|
}
|
|
|
|
void BareMetalDebugSupport::setFinished()
|
|
{
|
|
if (m_state == Inactive)
|
|
return;
|
|
if (m_state == Running)
|
|
m_appLauncher->stop();
|
|
m_state = Inactive;
|
|
}
|
|
|
|
void BareMetalDebugSupport::reset()
|
|
{
|
|
m_appLauncher->disconnect(this);
|
|
m_state = Inactive;
|
|
}
|
|
|
|
void BareMetalDebugSupport::showMessage(const QString &msg, int channel)
|
|
{
|
|
if (m_state != Inactive)
|
|
m_runControl->showMessage(msg, channel);
|
|
}
|
|
|
|
} // namespace Internal
|
|
} // namespace BareMetal
|