forked from qt-creator/qt-creator
This is usually used in a wrong or at least misleading way. Replace most of the usages by newly introduced GeneralMessageFormat as most of the replaced usages just print to General Messages and using any of the existing formats would change the layout of the text. Except for some special debug output inside the valgrind plugin that can use one of the existing formats which also makes it easier to spot them and the runners which print QC internal output. Task-number: QTCREATORBUG-24560 Change-Id: I824dc4250b2f3e4656bab8676b45c98e3407d59c Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
198 lines
6.5 KiB
C++
198 lines
6.5 KiB
C++
/****************************************************************************
|
|
**
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
|
** Author: Nicolas Arnaud-Cormos, KDAB (nicolas.arnaud-cormos@kdab.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 "valgrindengine.h"
|
|
#include "valgrindsettings.h"
|
|
#include "valgrindplugin.h"
|
|
|
|
#include <debugger/analyzer/analyzermanager.h>
|
|
|
|
#include <coreplugin/icore.h>
|
|
#include <coreplugin/ioutputpane.h>
|
|
#include <coreplugin/progressmanager/progressmanager.h>
|
|
#include <coreplugin/progressmanager/futureprogress.h>
|
|
#include <extensionsystem/pluginmanager.h>
|
|
|
|
#include <projectexplorer/projectexplorericons.h>
|
|
#include <projectexplorer/runconfiguration.h>
|
|
#include <projectexplorer/runconfigurationaspects.h>
|
|
|
|
#include <QApplication>
|
|
|
|
#define VALGRIND_DEBUG_OUTPUT 0
|
|
|
|
using namespace Debugger;
|
|
using namespace Core;
|
|
using namespace Utils;
|
|
using namespace ProjectExplorer;
|
|
|
|
namespace Valgrind {
|
|
namespace Internal {
|
|
|
|
ValgrindToolRunner::ValgrindToolRunner(RunControl *runControl)
|
|
: RunWorker(runControl)
|
|
{
|
|
runControl->setIcon(ProjectExplorer::Icons::ANALYZER_START_SMALL_TOOLBAR);
|
|
setSupportsReRunning(false);
|
|
|
|
m_settings.fromMap(runControl->settingsData(ANALYZER_VALGRIND_SETTINGS));
|
|
}
|
|
|
|
void ValgrindToolRunner::start()
|
|
{
|
|
FutureProgress *fp = ProgressManager::addTimedTask(m_progress, progressTitle(), "valgrind", 100);
|
|
fp->setKeepOnFinish(FutureProgress::HideOnFinish);
|
|
connect(fp, &FutureProgress::canceled,
|
|
this, &ValgrindToolRunner::handleProgressCanceled);
|
|
connect(fp, &FutureProgress::finished,
|
|
this, &ValgrindToolRunner::handleProgressFinished);
|
|
m_progress.reportStarted();
|
|
|
|
#if VALGRIND_DEBUG_OUTPUT
|
|
emit outputReceived(tr("Valgrind options: %1").arg(toolArguments().join(' ')), LogMessageFormat);
|
|
emit outputReceived(tr("Working directory: %1").arg(runnable().workingDirectory), LogMessageFormat);
|
|
emit outputReceived(tr("Command line arguments: %1").arg(runnable().debuggeeArgs), LogMessageFormat);
|
|
#endif
|
|
|
|
CommandLine valgrind{m_settings.valgrindExecutable()};
|
|
valgrind.addArgs(genericToolArguments());
|
|
valgrind.addArgs(toolArguments());
|
|
|
|
m_runner.setValgrindCommand(valgrind);
|
|
m_runner.setDevice(device());
|
|
m_runner.setDebuggee(runnable());
|
|
|
|
if (auto aspect = runControl()->aspect<TerminalAspect>())
|
|
m_runner.setUseTerminal(aspect->useTerminal());
|
|
|
|
connect(&m_runner, &ValgrindRunner::processOutputReceived,
|
|
this, &ValgrindToolRunner::receiveProcessOutput);
|
|
connect(&m_runner, &ValgrindRunner::valgrindExecuted,
|
|
this, [this](const QString &commandLine) {
|
|
appendMessage(commandLine, NormalMessageFormat);
|
|
});
|
|
connect(&m_runner, &ValgrindRunner::processErrorReceived,
|
|
this, &ValgrindToolRunner::receiveProcessError);
|
|
connect(&m_runner, &ValgrindRunner::finished,
|
|
this, &ValgrindToolRunner::runnerFinished);
|
|
|
|
if (!m_runner.start()) {
|
|
m_progress.cancel();
|
|
reportFailure();
|
|
return;
|
|
}
|
|
|
|
reportStarted();
|
|
}
|
|
|
|
void ValgrindToolRunner::stop()
|
|
{
|
|
m_isStopping = true;
|
|
m_runner.stop();
|
|
}
|
|
|
|
FilePath ValgrindToolRunner::executable() const
|
|
{
|
|
return runnable().executable;
|
|
}
|
|
|
|
QStringList ValgrindToolRunner::genericToolArguments() const
|
|
{
|
|
QString smcCheckValue;
|
|
|
|
switch (m_settings.selfModifyingCodeDetection()) {
|
|
case ValgrindBaseSettings::DetectSmcNo:
|
|
smcCheckValue = "none";
|
|
break;
|
|
case ValgrindBaseSettings::DetectSmcEverywhere:
|
|
smcCheckValue = "all";
|
|
break;
|
|
case ValgrindBaseSettings::DetectSmcEverywhereButFile:
|
|
smcCheckValue = "all-non-file";
|
|
break;
|
|
case ValgrindBaseSettings::DetectSmcStackOnly:
|
|
default:
|
|
smcCheckValue = "stack";
|
|
break;
|
|
}
|
|
return {"--smc-check=" + smcCheckValue};
|
|
}
|
|
|
|
void ValgrindToolRunner::handleProgressCanceled()
|
|
{
|
|
m_progress.reportCanceled();
|
|
m_progress.reportFinished();
|
|
}
|
|
|
|
void ValgrindToolRunner::handleProgressFinished()
|
|
{
|
|
QApplication::alert(ICore::dialogParent(), 3000);
|
|
}
|
|
|
|
void ValgrindToolRunner::runnerFinished()
|
|
{
|
|
appendMessage(tr("Analyzing finished."), NormalMessageFormat);
|
|
|
|
m_progress.reportFinished();
|
|
|
|
disconnect(&m_runner, &ValgrindRunner::processOutputReceived,
|
|
this, &ValgrindToolRunner::receiveProcessOutput);
|
|
disconnect(&m_runner, &ValgrindRunner::finished,
|
|
this, &ValgrindToolRunner::runnerFinished);
|
|
|
|
reportStopped();
|
|
}
|
|
|
|
void ValgrindToolRunner::receiveProcessOutput(const QString &output, OutputFormat format)
|
|
{
|
|
appendMessage(output, format);
|
|
}
|
|
|
|
void ValgrindToolRunner::receiveProcessError(const QString &message, QProcess::ProcessError error)
|
|
{
|
|
if (error == QProcess::FailedToStart) {
|
|
const QString valgrind = m_settings.valgrindExecutable();
|
|
if (!valgrind.isEmpty())
|
|
appendMessage(tr("Error: \"%1\" could not be started: %2").arg(valgrind, message), ErrorMessageFormat);
|
|
else
|
|
appendMessage(tr("Error: no Valgrind executable set."), ErrorMessageFormat);
|
|
} else if (m_isStopping && error == QProcess::Crashed) { // process gets killed on stop
|
|
appendMessage(tr("Process terminated."), ErrorMessageFormat);
|
|
} else {
|
|
appendMessage(tr("Process exited with return value %1\n").arg(message), NormalMessageFormat);
|
|
}
|
|
|
|
if (m_isStopping)
|
|
return;
|
|
|
|
QObject *obj = ExtensionSystem::PluginManager::getObjectByName("AppOutputPane");
|
|
if (auto pane = qobject_cast<IOutputPane *>(obj))
|
|
pane->popup(IOutputPane::NoModeSwitch);
|
|
}
|
|
|
|
} // namespace Internal
|
|
} // namepsace Valgrind
|