1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights. These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
32 **************************************************************************/
34 #include "debuggerrunner.h"
35 #include "debuggerruncontrolfactory.h"
37 #include "debuggeractions.h"
38 #include "debuggercore.h"
39 #include "debuggerengine.h"
40 #include "debuggermainwindow.h"
41 #include "debuggerplugin.h"
42 #include "debuggerstringutils.h"
43 #include "debuggerstartparameters.h"
44 #include "lldb/lldbenginehost.h"
45 #include "debuggertooltipmanager.h"
46 #include "qml/qmlengine.h"
52 #include <projectexplorer/abi.h>
53 #include <projectexplorer/debugginghelper.h>
54 #include <projectexplorer/project.h>
55 #include <projectexplorer/projectexplorerconstants.h>
56 #include <projectexplorer/target.h>
57 #include <projectexplorer/buildconfiguration.h>
58 #include <projectexplorer/outputformat.h>
59 #include <projectexplorer/toolchain.h>
60 #include <projectexplorer/applicationrunconfiguration.h> // For LocalApplication*
62 #include <utils/synchronousprocess.h>
63 #include <utils/qtcassert.h>
64 #include <utils/fancymainwindow.h>
65 #include <utils/qtcprocess.h>
66 #include <coreplugin/icore.h>
67 #include <utils/buildablehelperlibrary.h>
69 #include <QtCore/QDir>
70 #include <QtCore/QDebug>
71 #include <QtGui/QMessageBox>
73 using namespace ProjectExplorer;
74 using namespace Debugger::Internal;
81 bool isCdbEngineEnabled(); // Check the configuration page
82 bool checkCdbConfiguration(const DebuggerStartParameters &sp, ConfigurationCheck *check);
83 DebuggerEngine *createCdbEngine(const DebuggerStartParameters &sp,
84 DebuggerEngine *masterEngine, QString *error);
86 bool checkGdbConfiguration(const DebuggerStartParameters &sp, ConfigurationCheck *check);
87 DebuggerEngine *createGdbEngine(const DebuggerStartParameters &sp,
88 DebuggerEngine *masterEngine);
90 DebuggerEngine *createScriptEngine(const DebuggerStartParameters &sp);
91 DebuggerEngine *createPdbEngine(const DebuggerStartParameters &sp);
92 QmlEngine *createQmlEngine(const DebuggerStartParameters &sp,
93 DebuggerEngine *masterEngine);
94 DebuggerEngine *createQmlCppEngine(const DebuggerStartParameters &sp,
95 DebuggerEngineType slaveEngineType,
96 QString *errorMessage);
97 DebuggerEngine *createLldbEngine(const DebuggerStartParameters &sp);
99 extern QString msgNoBinaryForToolChain(const Abi &abi);
101 static const char *engineTypeName(DebuggerEngineType et)
104 case Debugger::NoEngineType:
106 case Debugger::GdbEngineType:
108 case Debugger::ScriptEngineType:
109 return "Script engine";
110 case Debugger::CdbEngineType:
112 case Debugger::PdbEngineType:
114 case Debugger::TcfEngineType:
116 case Debugger::QmlEngineType:
118 case Debugger::QmlCppEngineType:
119 return "QML C++ engine";
120 case Debugger::LldbEngineType:
121 return "LLDB engine";
122 case Debugger::AllEngineTypes:
128 static inline QString engineTypeNames(const QList<DebuggerEngineType> &l)
131 foreach (DebuggerEngineType et, l) {
133 rc.append(QLatin1String(", "));
134 rc += QLatin1String(engineTypeName(et));
139 static QString msgEngineNotAvailable(const char *engine)
141 return DebuggerPlugin::tr("The application requires the debugger engine '%1', "
142 "which is disabled.").arg(_(engine));
145 static inline QString msgEngineNotAvailable(DebuggerEngineType et)
147 return msgEngineNotAvailable(engineTypeName(et));
150 ////////////////////////////////////////////////////////////////////////
152 // DebuggerRunControlPrivate
154 ////////////////////////////////////////////////////////////////////////
156 class DebuggerRunControlPrivate
159 explicit DebuggerRunControlPrivate(DebuggerRunControl *parent,
160 RunConfiguration *runConfiguration);
162 DebuggerEngineType engineForExecutable(unsigned enabledEngineTypes,
163 const QString &executable);
164 DebuggerEngineType engineForMode(unsigned enabledEngineTypes,
165 DebuggerStartMode mode);
168 DebuggerRunControl *q;
169 DebuggerEngine *m_engine;
170 const QWeakPointer<RunConfiguration> m_myRunConfiguration;
174 DebuggerRunControlPrivate::DebuggerRunControlPrivate(DebuggerRunControl *parent,
175 RunConfiguration *runConfiguration)
178 , m_myRunConfiguration(runConfiguration)
183 } // namespace Internal
185 DebuggerRunControl::DebuggerRunControl(RunConfiguration *runConfiguration,
186 const DebuggerStartParameters &sp,
187 const QPair<DebuggerEngineType, DebuggerEngineType> &masterSlaveEngineTypes)
188 : RunControl(runConfiguration, Constants::DEBUGMODE),
189 d(new DebuggerRunControlPrivate(this, runConfiguration))
191 connect(this, SIGNAL(finished()), SLOT(handleFinished()));
192 // Create the engine. Could arguably be moved to the factory, but
193 // we still have a derived S60DebugControl. Should rarely fail, though.
194 QString errorMessage;
195 d->m_engine = masterSlaveEngineTypes.first == QmlCppEngineType ?
196 createQmlCppEngine(sp, masterSlaveEngineTypes.second, &errorMessage) :
197 DebuggerRunControlFactory::createEngine(masterSlaveEngineTypes.first, sp,
200 DebuggerToolTipManager::instance()->registerEngine(d->m_engine);
203 Core::ICore::instance()->showWarningWithOptions(DebuggerRunControl::tr("Debugger"), errorMessage);
207 DebuggerRunControl::~DebuggerRunControl()
210 if (DebuggerEngine *engine = d->m_engine) {
212 engine->disconnect();
217 const DebuggerStartParameters &DebuggerRunControl::startParameters() const
219 QTC_ASSERT(d->m_engine, return *(new DebuggerStartParameters()));
220 return d->m_engine->startParameters();
223 QString DebuggerRunControl::displayName() const
225 QTC_ASSERT(d->m_engine, return QString());
226 return d->m_engine->startParameters().displayName;
229 void DebuggerRunControl::setCustomEnvironment(Utils::Environment env)
231 QTC_ASSERT(d->m_engine, return);
232 d->m_engine->startParameters().environment = env;
235 void DebuggerRunControl::start()
237 QTC_ASSERT(d->m_engine, return);
238 debuggerCore()->runControlStarted(d->m_engine);
240 // We might get a synchronous startFailed() notification on Windows,
241 // when launching the process fails. Emit a proper finished() sequence.
245 d->m_engine->startDebugger(this);
248 appendMessage(tr("Debugging starts"), NormalMessageFormat);
251 void DebuggerRunControl::startFailed()
253 appendMessage(tr("Debugging has failed"), NormalMessageFormat);
254 d->m_running = false;
256 d->m_engine->handleStartFailed();
259 void DebuggerRunControl::handleFinished()
261 appendMessage(tr("Debugging has finished"), NormalMessageFormat);
263 d->m_engine->handleFinished();
264 debuggerCore()->runControlFinished(d->m_engine);
267 void DebuggerRunControl::showMessage(const QString &msg, int channel)
271 appendMessage(msg, StdOutFormatSameLine);
274 appendMessage(msg, StdErrFormatSameLine);
277 appendMessage(msg, NormalMessageFormat);
282 bool DebuggerRunControl::promptToStop(bool *optionalPrompt) const
284 QTC_ASSERT(isRunning(), return true;)
286 if (optionalPrompt && !*optionalPrompt)
289 const QString question = tr("A debugging session is still in progress. "
290 "Terminating the session in the current"
291 " state can leave the target in an inconsistent state."
292 " Would you still like to terminate it?");
293 return showPromptToStopDialog(tr("Close Debugging Session"), question,
294 QString(), QString(), optionalPrompt);
297 RunControl::StopResult DebuggerRunControl::stop()
299 QTC_ASSERT(d->m_engine, return StoppedSynchronously);
300 d->m_engine->quitDebugger();
301 return AsynchronousStop;
304 void DebuggerRunControl::debuggingFinished()
306 d->m_running = false;
310 bool DebuggerRunControl::isRunning() const
315 DebuggerEngine *DebuggerRunControl::engine()
317 QTC_ASSERT(d->m_engine, /**/);
321 RunConfiguration *DebuggerRunControl::runConfiguration() const
323 return d->m_myRunConfiguration.data();
326 ////////////////////////////////////////////////////////////////////////
328 // Engine detection logic: Detection functions depending on tool chain, binary,
329 // etc. Return a list of possible engines (order of prefererence) without
330 // consideration of configuration, etc.
332 ////////////////////////////////////////////////////////////////////////
334 static QList<DebuggerEngineType> enginesForToolChain(const Abi &toolChain)
336 QList<DebuggerEngineType> result;
337 switch (toolChain.binaryFormat()) {
339 case Abi::MachOFormat:
340 result.push_back(LldbEngineType);
341 result.push_back(GdbEngineType);
344 if (toolChain.osFlavor() == Abi::WindowsMSysFlavor) {
345 result.push_back(GdbEngineType);
346 result.push_back(CdbEngineType);
348 result.push_back(CdbEngineType);
349 result.push_back(GdbEngineType);
352 case Abi::RuntimeQmlFormat:
353 result.push_back(QmlEngineType);
361 static inline QList<DebuggerEngineType> enginesForScriptExecutables(const QString &executable)
363 QList<DebuggerEngineType> result;
364 if (executable.endsWith(_(".js"))) {
365 result.push_back(ScriptEngineType);
366 } else if (executable.endsWith(_(".py"))) {
367 result.push_back(PdbEngineType);
372 static QList<DebuggerEngineType> enginesForExecutable(const QString &executable)
374 QList<DebuggerEngineType> result = enginesForScriptExecutables(executable);
375 if (!result.isEmpty())
378 // A remote executable?
379 if (!executable.endsWith(_(".exe"), Qt::CaseInsensitive)) {
380 result.push_back(GdbEngineType);
384 // If a file has PDB files, it has been compiled by VS.
385 QStringList pdbFiles;
386 QString errorMessage;
387 if (getPDBFiles(executable, &pdbFiles, &errorMessage) && !pdbFiles.isEmpty()) {
388 result.push_back(CdbEngineType);
389 result.push_back(GdbEngineType);
392 // Fixme: Gdb should only be preferred if MinGW can positively be detected.
393 result.push_back(GdbEngineType);
394 result.push_back(CdbEngineType);
396 result.push_back(LldbEngineType);
397 result.push_back(GdbEngineType);
402 // Debugger type for mode.
403 static QList<DebuggerEngineType> enginesForMode(DebuggerStartMode startMode,
404 bool hardConstraintsOnly)
406 QList<DebuggerEngineType> result;
408 case Debugger::NoStartMode:
410 case Debugger::StartInternal:
411 case Debugger::StartExternal:
413 if (!hardConstraintsOnly) {
415 result.push_back(CdbEngineType); // Preferably Windows debugger for attaching locally.
417 result.push_back(GdbEngineType);
420 case Debugger::AttachCore:
421 case Debugger::StartRemoteGdb:
422 result.push_back(GdbEngineType);
424 case Debugger::AttachToRemote:
425 if (!hardConstraintsOnly) {
427 result.push_back(CdbEngineType);
429 result.push_back(GdbEngineType);
433 result.push_back(TcfEngineType);
435 case AttachCrashedExternal:
436 result.push_back(CdbEngineType); // Only CDB can do this
438 case StartRemoteEngine:
439 // FIXME: Unclear IPC override. Someone please have a better idea.
440 // For now thats the only supported IPC engine.
441 result.push_back(LldbEngineType);
447 // Engine detection logic: Call all detection functions in order.
449 static QList<DebuggerEngineType> engineTypes(const DebuggerStartParameters &sp)
451 // Script executables and certain start modes are 'hard constraints'.
452 QList<DebuggerEngineType> result = enginesForScriptExecutables(sp.executable);
453 if (!result.isEmpty())
456 result = enginesForMode(sp.startMode, true);
457 if (!result.isEmpty())
460 // 'hard constraints' done (with the exception of QML ABI checked here),
461 // further try to restrict available engines.
462 if (sp.toolChainAbi.isValid()) {
463 result = enginesForToolChain(sp.toolChainAbi);
464 if (!result.isEmpty())
468 // FIXME: 1 of 3 testing hacks.
469 if (sp.processArgs.startsWith(__("@tcf@ "))) {
470 result.push_back(GdbEngineType);
474 if (sp.startMode != AttachToRemote && !sp.executable.isEmpty())
475 result = enginesForExecutable(sp.executable);
476 if (!result.isEmpty())
479 result = enginesForMode(sp.startMode, false);
483 // Engine detection logic: ConfigurationCheck.
484 ConfigurationCheck::ConfigurationCheck() :
485 masterSlaveEngineTypes(NoEngineType, NoEngineType)
489 ConfigurationCheck::operator bool() const
491 return errorMessage.isEmpty() && errorDetails.isEmpty() && masterSlaveEngineTypes.first != NoEngineType;
494 QString ConfigurationCheck::errorDetailsString() const
496 return errorDetails.join(QLatin1String("\n\n"));
499 // Convenience helper to check whether an engine is enabled and configured
501 static inline bool canUseEngine(DebuggerEngineType et,
502 const DebuggerStartParameters &sp,
503 unsigned cmdLineEnabledEngines,
504 ConfigurationCheck *result)
507 if ((et & cmdLineEnabledEngines) == 0) {
508 result->errorDetails.push_back(DebuggerPlugin::tr("The debugger engine '%1' is disabled.").
509 arg(engineTypeName(et)));
514 case Debugger::CdbEngineType:
515 return checkCdbConfiguration(sp, result);
516 case Debugger::GdbEngineType:
517 return checkGdbConfiguration(sp, result);
525 \fn ConfigurationCheck checkDebugConfiguration(unsigned cmdLineEnabledEngines,
526 const DebuggerStartParameters &sp)
528 This is the master engine detection function that returns the
529 engine types for a given set of start parameters and checks their
533 DEBUGGER_EXPORT ConfigurationCheck checkDebugConfiguration(const DebuggerStartParameters &sp)
535 ConfigurationCheck result;
536 const unsigned activeLangs = debuggerCore()->activeLanguages();
537 const bool qmlLanguage = activeLangs & QmlLanguage;
538 const bool cppLanguage = activeLangs & CppLanguage;
540 qDebug().nospace() << "checkDebugConfiguration " << sp.toolChainAbi.toString()
541 << " Start mode=" << sp.startMode << " Executable=" << sp.executable
542 << " Debugger command=" << sp.debuggerCommand;
543 // Get all applicable types.
544 QList<DebuggerEngineType> requiredTypes;
545 if (qmlLanguage && !cppLanguage) {
546 requiredTypes.push_back(QmlEngineType);
548 requiredTypes = engineTypes(sp);
550 if (requiredTypes.isEmpty()) {
551 result.errorMessage = QLatin1String("Internal error: Unable to determine debugger engine type for this configuration");
555 qDebug() << " Required: " << engineTypeNames(requiredTypes);
556 // Filter out disables types, command line + current settings.
557 unsigned cmdLineEnabledEngines = debuggerCore()->enabledEngines();
559 if (!Core::ICore::instance()->settings()->value(QLatin1String("LLDB/enabled")).toBool())
560 cmdLineEnabledEngines &= ~LldbEngineType;
562 cmdLineEnabledEngines &= ~LldbEngineType;
564 DebuggerEngineType usableType = NoEngineType;
565 QList<DebuggerEngineType> unavailableTypes;
566 foreach (DebuggerEngineType et, requiredTypes) {
567 if (canUseEngine(et, sp, cmdLineEnabledEngines, &result)) {
571 unavailableTypes.push_back(et);
574 if (usableType == NoEngineType) {
575 if (requiredTypes.size() == 1) {
576 result.errorMessage = DebuggerPlugin::tr(
577 "The debugger engine '%1' required for debugging binaries of the type '%2'"
578 " is not configured correctly.").
579 arg(QLatin1String(engineTypeName(requiredTypes.front())), sp.toolChainAbi.toString());
581 result.errorMessage = DebuggerPlugin::tr(
582 "None of the debugger engines '%1' capable of debugging binaries of the type '%2'"
583 " is configured correctly.").
584 arg(engineTypeNames(requiredTypes), sp.toolChainAbi.toString());
589 qDebug() << "Configured engine: " << engineTypeName(usableType);
590 // Inform verbosely about MinGW-gdb/CDB fallbacks. Do not complain about LLDB, for now.
591 if (!result.errorDetails.isEmpty() && unavailableTypes.count(LldbEngineType) != unavailableTypes.size()) {
592 const QString msg = DebuggerPlugin::tr(
593 "The preferred debugger engine for debugging binaries of type '%1' is not available.\n"
594 "The debugger engine '%2' will be used as a fallback.\nDetails: %3").
595 arg(sp.toolChainAbi.toString(), engineTypeName(usableType),
596 result.errorDetails.join(QString(QLatin1Char('\n'))));
597 debuggerCore()->showMessage(msg, LogWarning);
598 showMessageBox(QMessageBox::Warning, "Warning", msg);
600 // Anything left: Happy.
601 result.errorMessage.clear();
602 result.errorDetails.clear();
603 if (qmlLanguage && cppLanguage) {
604 result.masterSlaveEngineTypes.first = QmlCppEngineType;
605 result.masterSlaveEngineTypes.second = usableType;
607 result.masterSlaveEngineTypes.first = usableType;
610 qDebug() << engineTypeName(result.masterSlaveEngineTypes.first) << engineTypeName(result.masterSlaveEngineTypes.second);
614 ////////////////////////////////////////////////////////////////////////
616 // DebuggerRunControlFactory
618 ////////////////////////////////////////////////////////////////////////
620 // A factory to create DebuggerRunControls
621 DebuggerRunControlFactory::DebuggerRunControlFactory(QObject *parent,
622 unsigned enabledEngines)
623 : IRunControlFactory(parent), m_enabledEngines(enabledEngines)
626 bool DebuggerRunControlFactory::canRun(RunConfiguration *runConfiguration, const QString &mode) const
628 // return mode == ProjectExplorer::Constants::DEBUGMODE;
629 return mode == Constants::DEBUGMODE
630 && qobject_cast<LocalApplicationRunConfiguration *>(runConfiguration);
633 QString DebuggerRunControlFactory::displayName() const
635 return DebuggerRunControl::tr("Debug");
638 // Find Qt installation by running qmake
639 static inline QString findQtInstallPath(const QString &qmakePath)
643 args.append(_("-query"));
644 args.append(_("QT_INSTALL_HEADERS"));
645 proc.start(qmakePath, args);
646 if (!proc.waitForStarted()) {
647 qWarning("%s: Cannot start '%s': %s", Q_FUNC_INFO, qPrintable(qmakePath),
648 qPrintable(proc.errorString()));
651 proc.closeWriteChannel();
652 if (!proc.waitForFinished()) {
653 Utils::SynchronousProcess::stopProcess(proc);
654 qWarning("%s: Timeout running '%s'.", Q_FUNC_INFO, qPrintable(qmakePath));
657 if (proc.exitStatus() != QProcess::NormalExit) {
658 qWarning("%s: '%s' crashed.", Q_FUNC_INFO, qPrintable(qmakePath));
661 const QByteArray ba = proc.readAllStandardOutput().trimmed();
662 QDir dir(QString::fromLocal8Bit(ba));
663 if (dir.exists() && dir.cdUp())
664 return dir.absolutePath();
668 static DebuggerStartParameters localStartParameters(RunConfiguration *runConfiguration)
670 DebuggerStartParameters sp;
671 QTC_ASSERT(runConfiguration, return sp);
672 LocalApplicationRunConfiguration *rc =
673 qobject_cast<LocalApplicationRunConfiguration *>(runConfiguration);
674 QTC_ASSERT(rc, return sp);
676 sp.startMode = StartInternal;
677 sp.environment = rc->environment();
678 sp.workingDirectory = rc->workingDirectory();
679 sp.executable = rc->executable();
680 sp.processArgs = rc->commandLineArguments();
681 sp.toolChainAbi = rc->abi();
682 sp.useTerminal = rc->runMode() == LocalApplicationRunConfiguration::Console;
683 sp.dumperLibrary = rc->dumperLibrary();
684 sp.dumperLibraryLocations = rc->dumperLibraryLocations();
686 if (const ProjectExplorer::Target *target = runConfiguration->target()) {
687 if (QByteArray(target->metaObject()->className()).contains("Qt4")) {
688 const QString qmake = Utils::BuildableHelperLibrary::findSystemQt(sp.environment);
689 if (!qmake.isEmpty())
690 sp.qtInstallPath = findQtInstallPath(qmake);
692 if (const ProjectExplorer::Project *project = target->project()) {
693 sp.projectDir = project->projectDirectory();
694 if (const ProjectExplorer::BuildConfiguration *buildConfig = target->activeBuildConfiguration()) {
695 sp.projectBuildDir = buildConfig->buildDirectory();
696 if (const ProjectExplorer::ToolChain *tc = buildConfig->toolChain())
697 sp.debuggerCommand = tc->debuggerCommand();
702 if (debuggerCore()->isActiveDebugLanguage(QmlLanguage)) {
703 sp.qmlServerAddress = _("127.0.0.1");
704 sp.qmlServerPort = runConfiguration->qmlDebugServerPort();
706 // Makes sure that all bindings go through the JavaScript engine, so that
707 // breakpoints are actually hit!
708 const QString optimizerKey = _("QML_DISABLE_OPTIMIZER");
709 if (!sp.environment.hasKey(optimizerKey)) {
710 sp.environment.set(optimizerKey, _("1"));
713 Utils::QtcProcess::addArg(&sp.processArgs, _("-qmljsdebugger=port:")
714 + QString::number(sp.qmlServerPort));
717 // FIXME: If it's not yet build this will be empty and not filled
718 // when rebuild as the runConfiguration is not stored and therefore
719 // cannot be used to retrieve the dumper location.
720 //qDebug() << "DUMPER: " << sp.dumperLibrary << sp.dumperLibraryLocations;
721 sp.displayName = rc->displayName();
726 RunControl *DebuggerRunControlFactory::create
727 (RunConfiguration *runConfiguration, const QString &mode)
729 QTC_ASSERT(mode == Constants::DEBUGMODE, return 0);
730 DebuggerStartParameters sp = localStartParameters(runConfiguration);
731 return create(sp, runConfiguration);
734 RunConfigWidget *DebuggerRunControlFactory::createConfigurationWidget
735 (RunConfiguration *runConfiguration)
737 // NBS TODO: Add GDB-specific configuration widget
738 Q_UNUSED(runConfiguration)
742 DebuggerRunControl *DebuggerRunControlFactory::create
743 (const DebuggerStartParameters &sp, RunConfiguration *runConfiguration)
745 const ConfigurationCheck check = checkDebugConfiguration(sp);
748 //appendMessage(errorMessage, true);
749 Core::ICore::instance()->showWarningWithOptions(DebuggerRunControl::tr("Debugger"),
750 check.errorMessage, check.errorDetailsString(), check.settingsCategory, check.settingsPage);
754 return new DebuggerRunControl(runConfiguration, sp, check.masterSlaveEngineTypes);
758 DebuggerRunControlFactory::createEngine(DebuggerEngineType et,
759 const DebuggerStartParameters &sp,
760 DebuggerEngine *masterEngine,
761 QString *errorMessage)
765 return createGdbEngine(sp, masterEngine);
766 case ScriptEngineType:
767 return createScriptEngine(sp);
769 return createCdbEngine(sp, masterEngine, errorMessage);
772 return createPdbEngine(sp);
775 return createQmlEngine(sp, masterEngine);
778 return createLldbEngine(sp);
782 *errorMessage = DebuggerRunControl::tr("Unable to create a debugger engine of the type '%1'").
783 arg(_(engineTypeName(et)));
788 } // namespace Debugger