diff options
-rw-r--r-- | qbs/imports/QtcProduct.qbs | 9 | ||||
-rw-r--r-- | src/plugins/android/androidrunnerworker.cpp | 95 | ||||
-rw-r--r-- | src/plugins/android/androidrunnerworker.h | 6 | ||||
-rw-r--r-- | src/plugins/autotest/testresultmodel.cpp | 2 | ||||
-rw-r--r-- | src/plugins/debugger/gdb/gdbengine.cpp | 2 | ||||
-rw-r--r-- | src/plugins/help/textbrowserhelpviewer.cpp | 3 | ||||
-rw-r--r-- | src/plugins/qmljseditor/qmljsautocompleter.cpp | 2 |
7 files changed, 86 insertions, 33 deletions
diff --git a/qbs/imports/QtcProduct.qbs b/qbs/imports/QtcProduct.qbs index 0dc1e9b3b1f..1caf073e988 100644 --- a/qbs/imports/QtcProduct.qbs +++ b/qbs/imports/QtcProduct.qbs @@ -19,7 +19,14 @@ Product { Depends { name: "cpp" } Depends { name: "qtc" } - Depends { name: product.name + " dev headers"; required: false } + Depends { + name: product.name + " dev headers"; + required: false + Properties { + condition: Utilities.versionCompare(qbs.version, "1.13") >= 0 + enableFallback: false + } + } Depends { name: "Qt.core"; versionAtLeast: "5.9.0" } // TODO: Should fall back to what came from Qt.core for Qt < 5.7, but we cannot express that diff --git a/src/plugins/android/androidrunnerworker.cpp b/src/plugins/android/androidrunnerworker.cpp index 0b4021e9511..6497f50d627 100644 --- a/src/plugins/android/androidrunnerworker.cpp +++ b/src/plugins/android/androidrunnerworker.cpp @@ -53,6 +53,7 @@ namespace { Q_LOGGING_CATEGORY(androidRunWorkerLog, "qtc.android.run.androidrunnerworker", QtWarningMsg) +static const int GdbTempFileMaxCounter = 20; } using namespace std; @@ -248,19 +249,60 @@ bool AndroidRunnerWorker::runAdb(const QStringList &args, QString *stdOut, return result.success(); } -bool AndroidRunnerWorker::uploadFile(const QString &from, const QString &to, const QString &flags) +bool AndroidRunnerWorker::uploadGdbServer() { - QFile f(from); - if (!f.open(QIODevice::ReadOnly)) + // Push the gdbserver to temp location and then to package dir. + // the files can't be pushed directly to package because of permissions. + qCDebug(androidRunWorkerLog) << "Uploading GdbServer"; + + bool foundUnique = true; + auto cleanUp = [this, &foundUnique] (QString *p) { + if (foundUnique && !runAdb({"shell", "rm", "-f", *p})) + qCDebug(androidRunWorkerLog) << "Gdbserver cleanup failed."; + delete p; + }; + std::unique_ptr<QString, decltype (cleanUp)> + tempGdbServerPath(new QString("/data/local/tmp/%1"), cleanUp); + + // Get a unique temp file name for gdbserver copy + int count = 0; + while (deviceFileExists(tempGdbServerPath->arg(++count))) { + if (count > GdbTempFileMaxCounter) { + qCDebug(androidRunWorkerLog) << "Can not get temporary file name"; + foundUnique = false; + return false; + } + } + *tempGdbServerPath = tempGdbServerPath->arg(count); + + // Copy gdbserver to temp location + if (!runAdb({"push", m_gdbserverPath , *tempGdbServerPath})) { + qCDebug(androidRunWorkerLog) << "Gdbserver upload to temp directory failed"; return false; - runAdb({"shell", "run-as", m_packageName, "rm", to}); - const QByteArray data = f.readAll(); - QString output; - const bool res = runAdb({"shell", "run-as", m_packageName, QString("sh -c 'base64 -d > %1'").arg(to)}, - &output, data.toBase64()); - if (!res || output.contains("base64: not found")) + } + + // Copy gdbserver from temp location to app directory + if (!runAdb({"shell", "run-as", m_packageName, "cp" , *tempGdbServerPath, "./gdbserver"})) { + qCDebug(androidRunWorkerLog) << "Gdbserver copy from temp directory failed"; return false; - return runAdb({"shell", "run-as", m_packageName, "chmod", flags, to}); + } + QTC_ASSERT(runAdb({"shell", "run-as", m_packageName, "chmod", "+x", "./gdbserver"}), + qCDebug(androidRunWorkerLog) << "Gdbserver chmod +x failed."); + return true; +} + +bool AndroidRunnerWorker::deviceFileExists(const QString &filePath) +{ + QString output; + const bool success = runAdb({"shell", "ls", filePath, "2>/dev/null"}, &output); + return success && !output.trimmed().isEmpty(); +} + +bool AndroidRunnerWorker::packageFileExists(const QString &filePath) +{ + QString output; + const bool success = runAdb({"shell", "run-as", m_packageName, "ls", filePath, "2>/dev/null"}, &output); + return success && !output.trimmed().isEmpty(); } void AndroidRunnerWorker::adbKill(qint64 pid) @@ -403,26 +445,28 @@ void AndroidRunnerWorker::asyncStartHelper() // e.g. on Android 8 with NDK 10e runAdb({"shell", "run-as", m_packageName, "chmod", "a+x", packageDir.trimmed()}); - QString gdbServerExecutable; + QString gdbServerExecutable = "gdbserver"; QString gdbServerPrefix = "./lib/"; - if (m_gdbserverPath.isEmpty() || !uploadFile(m_gdbserverPath, "gdbserver")) { - // upload failed - check for old devices - QString output; - if (runAdb({"shell", "run-as", m_packageName, "ls", "lib/"}, &output)) { - for (const auto &line: output.split('\n')) { - if (line.indexOf("gdbserver") != -1/* || line.indexOf("lldb-server") != -1*/) { - gdbServerExecutable = line.trimmed(); - break; - } - } - } - if (gdbServerExecutable.isEmpty()) { + auto findGdbServer = [this, &gdbServerExecutable, gdbServerPrefix](const QString& gdbEx) { + if (!packageFileExists(gdbServerPrefix + gdbEx)) + return false; + gdbServerExecutable = gdbEx; + return true; + }; + + if (!findGdbServer("gdbserver") && !findGdbServer("libgdbserver.so")) { + // Armv8. symlink lib is not available. + // Kill the previous instances of gdbserver. Do this before copying the gdbserver. + runAdb({"shell", "run-as", m_packageName, "killall", gdbServerExecutable}); + if (!m_gdbserverPath.isEmpty() && uploadGdbServer()) { + gdbServerPrefix = "./"; + } else { emit remoteProcessFinished(tr("Cannot find/copy C++ debug server.")); return; } } else { - gdbServerPrefix = "./"; - gdbServerExecutable = "gdbserver"; + qCDebug(androidRunWorkerLog) << "Found GDB server under ./lib"; + runAdb({"shell", "run-as", m_packageName, "killall", gdbServerExecutable}); } QString debuggerServerErr; @@ -484,7 +528,6 @@ bool AndroidRunnerWorker::startDebuggerServer(const QString &packageDir, QString *errorStr) { QString gdbServerSocket = packageDir + "/debug-socket"; - runAdb({"shell", "run-as", m_packageName, "killall", gdbServerExecutable}); runAdb({"shell", "run-as", m_packageName, "rm", gdbServerSocket}); QString gdbProcessErr; diff --git a/src/plugins/android/androidrunnerworker.h b/src/plugins/android/androidrunnerworker.h index 5e5e51cd752..30da68fc2df 100644 --- a/src/plugins/android/androidrunnerworker.h +++ b/src/plugins/android/androidrunnerworker.h @@ -47,7 +47,6 @@ public: AndroidRunnerWorker(ProjectExplorer::RunWorker *runner, const QString &packageName); ~AndroidRunnerWorker() override; - bool uploadFile(const QString &from, const QString &to, const QString &flags = QString("+x")); bool runAdb(const QStringList &args, QString *stdOut = nullptr, const QByteArray &writeData = {}); void adbKill(qint64 pid); QStringList selector() const; @@ -71,10 +70,13 @@ signals: void remoteOutput(const QString &output); void remoteErrorOutput(const QString &output); -protected: +private: void asyncStartHelper(); bool startDebuggerServer(const QString &packageDir, const QString &gdbServerPrefix, const QString &gdbServerExecutable, QString *errorStr = nullptr); + bool deviceFileExists(const QString &filePath); + bool packageFileExists(const QString& filePath); + bool uploadGdbServer(); enum class JDBState { Idle, diff --git a/src/plugins/autotest/testresultmodel.cpp b/src/plugins/autotest/testresultmodel.cpp index c1d86342f00..6cabd39cbcf 100644 --- a/src/plugins/autotest/testresultmodel.cpp +++ b/src/plugins/autotest/testresultmodel.cpp @@ -145,7 +145,7 @@ void TestResultItem::updateResult(bool &changed, Result::Type addedChildType) ? Result::MessageTestCaseSuccess : old; break; default: - return; + break; } changed = old != newResult; if (changed) diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index b51afe098e5..8d2af5008a7 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -1714,7 +1714,7 @@ void GdbEngine::detachDebugger() { CHECK_STATE(InferiorStopOk); QTC_CHECK(runParameters().startMode != AttachCore); - DebuggerCommand cmd("detach", ExitRequest); + DebuggerCommand cmd("detach", NativeCommand | ExitRequest); cmd.callback = [this](const DebuggerResponse &) { CHECK_STATE(InferiorStopOk); notifyInferiorExited(); diff --git a/src/plugins/help/textbrowserhelpviewer.cpp b/src/plugins/help/textbrowserhelpviewer.cpp index e0f151c30b1..d729535fa38 100644 --- a/src/plugins/help/textbrowserhelpviewer.cpp +++ b/src/plugins/help/textbrowserhelpviewer.cpp @@ -430,7 +430,8 @@ void TextBrowserHelpWidget::mouseReleaseEvent(QMouseEvent *e) bool controlPressed = e->modifiers() & Qt::ControlModifier; const QString link = linkAt(e->pos()); - if ((controlPressed || e->button() == Qt::MidButton) && !link.isEmpty()) { + if (m_parent->isActionVisible(HelpViewer::Action::NewPage) + && (controlPressed || e->button() == Qt::MidButton) && !link.isEmpty()) { emit m_parent->newPageRequested(QUrl(link)); return; } diff --git a/src/plugins/qmljseditor/qmljsautocompleter.cpp b/src/plugins/qmljseditor/qmljsautocompleter.cpp index 281c80d860f..5c8dc78b68c 100644 --- a/src/plugins/qmljseditor/qmljsautocompleter.cpp +++ b/src/plugins/qmljseditor/qmljsautocompleter.cpp @@ -230,7 +230,7 @@ bool AutoCompleter::contextAllowsAutoQuotes(const QTextCursor &cursor, } // never insert ' into string literals, it adds spurious ' when writing contractions - if (textToInsert.at(0) == QLatin1Char('\'')) + if (textToInsert.at(0) == QLatin1Char('\'') && quote != '\'') return false; if (textToInsert.at(0) != quote || isCompleteStringLiteral(tokenText)) |