forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/10.0'
Conflicts: src/plugins/android/androidrunnerworker.cpp src/plugins/qtsupport/exampleslistmodel.cpp Change-Id: I1628528dbc0ffe874b49bbe022da5933b1348057
This commit is contained in:
@@ -51,6 +51,7 @@ namespace Android {
|
|||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
static const QString pidPollingScript = QStringLiteral("while [ -d /proc/%1 ]; do sleep 1; done");
|
static const QString pidPollingScript = QStringLiteral("while [ -d /proc/%1 ]; do sleep 1; done");
|
||||||
|
static const QRegularExpression userIdPattern("u(\\d+)_a");
|
||||||
|
|
||||||
static int APP_START_TIMEOUT = 45000;
|
static int APP_START_TIMEOUT = 45000;
|
||||||
static bool isTimedOut(const chrono::high_resolution_clock::time_point &start,
|
static bool isTimedOut(const chrono::high_resolution_clock::time_point &start,
|
||||||
@@ -77,8 +78,10 @@ static qint64 extractPID(const QString &output, const QString &packageName)
|
|||||||
return pid;
|
return pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void findProcessPID(QPromise<qint64> &promise, QStringList selector,
|
static void findProcessPIDAndUser(QPromise<PidUserPair> &promise,
|
||||||
const QString &packageName, bool preNougat)
|
QStringList selector,
|
||||||
|
const QString &packageName,
|
||||||
|
bool preNougat)
|
||||||
{
|
{
|
||||||
if (packageName.isEmpty())
|
if (packageName.isEmpty())
|
||||||
return;
|
return;
|
||||||
@@ -108,8 +111,32 @@ static void findProcessPID(QPromise<qint64> &promise, QStringList selector,
|
|||||||
} while ((processPID == -1 || processPID == 0) && !isTimedOut(start) && !promise.isCanceled());
|
} while ((processPID == -1 || processPID == 0) && !isTimedOut(start) && !promise.isCanceled());
|
||||||
|
|
||||||
qCDebug(androidRunWorkerLog) << "PID found:" << processPID << ", PreNougat:" << preNougat;
|
qCDebug(androidRunWorkerLog) << "PID found:" << processPID << ", PreNougat:" << preNougat;
|
||||||
|
|
||||||
|
qint64 processUser = 0;
|
||||||
|
if (processPID > 0 && !promise.isCanceled()) {
|
||||||
|
args = {selector};
|
||||||
|
args.append({"shell", "ps", "-o", "user", "-p"});
|
||||||
|
args.append(QString::number(processPID));
|
||||||
|
QtcProcess proc;
|
||||||
|
proc.setCommand({adbPath, args});
|
||||||
|
proc.runBlocking();
|
||||||
|
const QString out = proc.allOutput();
|
||||||
|
if (!out.isEmpty()) {
|
||||||
|
QRegularExpressionMatch match;
|
||||||
|
qsizetype matchPos = out.indexOf(userIdPattern, 0, &match);
|
||||||
|
if (matchPos >= 0 && match.capturedLength(1) > 0) {
|
||||||
|
bool ok = false;
|
||||||
|
processUser = match.captured(1).toInt(&ok);
|
||||||
|
if (!ok)
|
||||||
|
processUser = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qCDebug(androidRunWorkerLog) << "USER found:" << processUser;
|
||||||
|
|
||||||
if (!promise.isCanceled())
|
if (!promise.isCanceled())
|
||||||
promise.addResult(processPID);
|
promise.addResult(PidUserPair(processPID, processUser));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void deleter(QProcess *p)
|
static void deleter(QProcess *p)
|
||||||
@@ -325,13 +352,16 @@ bool AndroidRunnerWorker::uploadDebugServer(const QString &debugServerFileName)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList adbArgs = {"shell", "run-as", m_packageName};
|
||||||
|
if (m_processUser > 0)
|
||||||
|
adbArgs << "--user" << QString::number(m_processUser);
|
||||||
// Copy gdbserver from temp location to app directory
|
// Copy gdbserver from temp location to app directory
|
||||||
if (!runAdb({"shell", "run-as", m_packageName, "cp" , tempDebugServerPath, debugServerFileName})) {
|
if (!runAdb(adbArgs + QStringList({"cp" , tempDebugServerPath, debugServerFileName}))) {
|
||||||
qCDebug(androidRunWorkerLog) << "Debug server copy from temp directory failed";
|
qCDebug(androidRunWorkerLog) << "Debug server copy from temp directory failed";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool ok = runAdb({"shell", "run-as", m_packageName, "chmod", "777", debugServerFileName});
|
const bool ok = runAdb(adbArgs + QStringList({"chmod", "777", debugServerFileName}));
|
||||||
QTC_ASSERT(ok, qCDebug(androidRunWorkerLog) << "Debug server chmod 777 failed.");
|
QTC_ASSERT(ok, qCDebug(androidRunWorkerLog) << "Debug server chmod 777 failed.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -346,7 +376,11 @@ bool AndroidRunnerWorker::deviceFileExists(const QString &filePath)
|
|||||||
bool AndroidRunnerWorker::packageFileExists(const QString &filePath)
|
bool AndroidRunnerWorker::packageFileExists(const QString &filePath)
|
||||||
{
|
{
|
||||||
QString output;
|
QString output;
|
||||||
const bool success = runAdb({"shell", "run-as", m_packageName, "ls", filePath, "2>/dev/null"}, &output);
|
QStringList adbArgs = {"shell", "run-as", m_packageName};
|
||||||
|
if (m_processUser > 0)
|
||||||
|
adbArgs << "--user" << QString::number(m_processUser);
|
||||||
|
const bool success = runAdb(adbArgs + QStringList({"ls", filePath, "2>/dev/null"}),
|
||||||
|
&output);
|
||||||
return success && !output.trimmed().isEmpty();
|
return success && !output.trimmed().isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -513,62 +547,8 @@ void AndroidRunnerWorker::asyncStartHelper()
|
|||||||
|
|
||||||
QStringList args({"shell", "am", "start"});
|
QStringList args({"shell", "am", "start"});
|
||||||
args << "-n" << m_intentName;
|
args << "-n" << m_intentName;
|
||||||
if (m_useCppDebugger) {
|
if (m_useCppDebugger)
|
||||||
args << "-D";
|
args << "-D";
|
||||||
// run-as <package-name> pwd fails on API 22 so route the pwd through shell.
|
|
||||||
QString packageDir;
|
|
||||||
if (!runAdb({"shell", "run-as", m_packageName, "/system/bin/sh", "-c", "pwd"},
|
|
||||||
&packageDir)) {
|
|
||||||
emit remoteProcessFinished(Tr::tr("Failed to find application directory."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add executable flag to package dir. Gdb can't connect to running server on device on
|
|
||||||
// e.g. on Android 8 with NDK 10e
|
|
||||||
runAdb({"shell", "run-as", m_packageName, "chmod", "a+x", packageDir.trimmed()});
|
|
||||||
|
|
||||||
if (!m_debugServerPath.exists()) {
|
|
||||||
QString msg = Tr::tr("Cannot find C++ debug server in NDK installation.");
|
|
||||||
if (m_useLldb)
|
|
||||||
msg += "\n" + Tr::tr("The lldb-server binary has not been found.");
|
|
||||||
emit remoteProcessFinished(msg);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString debugServerFile;
|
|
||||||
if (m_useLldb) {
|
|
||||||
debugServerFile = "./lldb-server";
|
|
||||||
runAdb({"shell", "run-as", m_packageName, "killall", "lldb-server"});
|
|
||||||
if (!uploadDebugServer(debugServerFile)) {
|
|
||||||
emit remoteProcessFinished(Tr::tr("Cannot copy C++ debug server."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (packageFileExists("./lib/gdbserver")) {
|
|
||||||
debugServerFile = "./lib/gdbserver";
|
|
||||||
qCDebug(androidRunWorkerLog) << "Found GDB server " + debugServerFile;
|
|
||||||
runAdb({"shell", "run-as", m_packageName, "killall", "gdbserver"});
|
|
||||||
} else if (packageFileExists("./lib/libgdbserver.so")) {
|
|
||||||
debugServerFile = "./lib/libgdbserver.so";
|
|
||||||
qCDebug(androidRunWorkerLog) << "Found GDB server " + debugServerFile;
|
|
||||||
runAdb({"shell", "run-as", m_packageName, "killall", "libgdbserver.so"});
|
|
||||||
} else {
|
|
||||||
// Armv8. symlink lib is not available.
|
|
||||||
debugServerFile = "./gdbserver";
|
|
||||||
// Kill the previous instances of gdbserver. Do this before copying the gdbserver.
|
|
||||||
runAdb({"shell", "run-as", m_packageName, "killall", "gdbserver"});
|
|
||||||
if (!uploadDebugServer("./gdbserver")) {
|
|
||||||
emit remoteProcessFinished(Tr::tr("Cannot copy C++ debug server."));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
QString debuggerServerErr;
|
|
||||||
if (!startDebuggerServer(packageDir, debugServerFile, &debuggerServerErr)) {
|
|
||||||
emit remoteProcessFinished(debuggerServerErr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_qmlDebugServices != QmlDebug::NoQmlDebugServices) {
|
if (m_qmlDebugServices != QmlDebug::NoQmlDebugServices) {
|
||||||
// currently forward to same port on device and host
|
// currently forward to same port on device and host
|
||||||
@@ -624,17 +604,79 @@ void AndroidRunnerWorker::asyncStartHelper()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AndroidRunnerWorker::startNativeDebugging()
|
||||||
|
{
|
||||||
|
// run-as <package-name> pwd fails on API 22 so route the pwd through shell.
|
||||||
|
QString packageDir;
|
||||||
|
QStringList adbArgs = {"shell", "run-as", m_packageName};
|
||||||
|
if (m_processUser > 0)
|
||||||
|
adbArgs << "--user" << QString::number(m_processUser);
|
||||||
|
if (!runAdb(adbArgs + QStringList({"/system/bin/sh", "-c", "pwd"}),
|
||||||
|
&packageDir)) {
|
||||||
|
emit remoteProcessFinished(Tr::tr("Failed to find application directory."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Add executable flag to package dir. Gdb can't connect to running server on device on
|
||||||
|
// e.g. on Android 8 with NDK 10e
|
||||||
|
runAdb(adbArgs + QStringList({"chmod", "a+x", packageDir.trimmed()}));
|
||||||
|
if (!m_debugServerPath.exists()) {
|
||||||
|
QString msg = Tr::tr("Cannot find C++ debug server in NDK installation.");
|
||||||
|
if (m_useLldb)
|
||||||
|
msg += "\n" + Tr::tr("The lldb-server binary has not been found.");
|
||||||
|
emit remoteProcessFinished(msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString debugServerFile;
|
||||||
|
if (m_useLldb) {
|
||||||
|
debugServerFile = "./lldb-server";
|
||||||
|
runAdb(adbArgs + QStringList({"killall", "lldb-server"}));
|
||||||
|
if (!uploadDebugServer(debugServerFile)) {
|
||||||
|
emit remoteProcessFinished(Tr::tr("Cannot copy C++ debug server."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (packageFileExists("./lib/gdbserver")) {
|
||||||
|
debugServerFile = "./lib/gdbserver";
|
||||||
|
qCDebug(androidRunWorkerLog) << "Found GDB server " + debugServerFile;
|
||||||
|
runAdb(adbArgs + QStringList({"killall", "gdbserver"}));
|
||||||
|
} else if (packageFileExists("./lib/libgdbserver.so")) {
|
||||||
|
debugServerFile = "./lib/libgdbserver.so";
|
||||||
|
qCDebug(androidRunWorkerLog) << "Found GDB server " + debugServerFile;
|
||||||
|
runAdb(adbArgs + QStringList({"killall", "libgdbserver.so"}));
|
||||||
|
} else {
|
||||||
|
// Armv8. symlink lib is not available.
|
||||||
|
debugServerFile = "./gdbserver";
|
||||||
|
// Kill the previous instances of gdbserver. Do this before copying the gdbserver.
|
||||||
|
runAdb(adbArgs + QStringList({"killall", "gdbserver"}));
|
||||||
|
if (!uploadDebugServer("./gdbserver")) {
|
||||||
|
emit remoteProcessFinished(Tr::tr("Cannot copy C++ debug server."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QString debuggerServerErr;
|
||||||
|
if (!startDebuggerServer(packageDir, debugServerFile, &debuggerServerErr)) {
|
||||||
|
emit remoteProcessFinished(debuggerServerErr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool AndroidRunnerWorker::startDebuggerServer(const QString &packageDir,
|
bool AndroidRunnerWorker::startDebuggerServer(const QString &packageDir,
|
||||||
const QString &debugServerFile,
|
const QString &debugServerFile,
|
||||||
QString *errorStr)
|
QString *errorStr)
|
||||||
{
|
{
|
||||||
|
QStringList adbArgs = {"shell", "run-as", m_packageName};
|
||||||
|
if (m_processUser > 0)
|
||||||
|
adbArgs << "--user" << QString::number(m_processUser);
|
||||||
if (m_useLldb) {
|
if (m_useLldb) {
|
||||||
QString lldbServerErr;
|
QString lldbServerErr;
|
||||||
QStringList lldbServerArgs = selector();
|
QStringList lldbServerArgs = selector();
|
||||||
lldbServerArgs << "shell" << "run-as" << m_packageName << debugServerFile
|
lldbServerArgs += adbArgs;
|
||||||
<< "platform"
|
lldbServerArgs << debugServerFile
|
||||||
// << "--server" // Can lead to zombie servers
|
<< "platform"
|
||||||
<< "--listen" << QString("*:%1").arg(m_localDebugServerPort.toString());
|
// << "--server" // Can lead to zombie servers
|
||||||
|
<< "--listen" << QString("*:%1").arg(m_localDebugServerPort.toString());
|
||||||
m_debugServerProcess.reset(AndroidManager::runAdbCommandDetached(lldbServerArgs, &lldbServerErr));
|
m_debugServerProcess.reset(AndroidManager::runAdbCommandDetached(lldbServerArgs, &lldbServerErr));
|
||||||
|
|
||||||
if (!m_debugServerProcess) {
|
if (!m_debugServerProcess) {
|
||||||
@@ -648,12 +690,13 @@ bool AndroidRunnerWorker::startDebuggerServer(const QString &packageDir,
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
QString gdbServerSocket = packageDir + "/debug-socket";
|
QString gdbServerSocket = packageDir + "/debug-socket";
|
||||||
runAdb({"shell", "run-as", m_packageName, "rm", gdbServerSocket});
|
runAdb(adbArgs + QStringList({"rm", gdbServerSocket}));
|
||||||
|
|
||||||
QString gdbProcessErr;
|
QString gdbProcessErr;
|
||||||
QStringList gdbServerErr = selector();
|
QStringList gdbServerErr = selector();
|
||||||
gdbServerErr << "shell" << "run-as" << m_packageName << debugServerFile
|
gdbServerErr += adbArgs;
|
||||||
<< "--multi" << "+" + gdbServerSocket;
|
gdbServerErr << debugServerFile
|
||||||
|
<< "--multi" << "+" + gdbServerSocket;
|
||||||
m_debugServerProcess.reset(AndroidManager::runAdbCommandDetached(gdbServerErr, &gdbProcessErr));
|
m_debugServerProcess.reset(AndroidManager::runAdbCommandDetached(gdbServerErr, &gdbProcessErr));
|
||||||
|
|
||||||
if (!m_debugServerProcess) {
|
if (!m_debugServerProcess) {
|
||||||
@@ -683,9 +726,12 @@ void AndroidRunnerWorker::asyncStart()
|
|||||||
{
|
{
|
||||||
asyncStartHelper();
|
asyncStartHelper();
|
||||||
|
|
||||||
m_pidFinder = Utils::onResultReady(
|
m_pidFinder = Utils::onResultReady(Utils::asyncRun(findProcessPIDAndUser,
|
||||||
Utils::asyncRun(findProcessPID, selector(),m_packageName, m_isPreNougat), this,
|
selector(),
|
||||||
bind(&AndroidRunnerWorker::onProcessIdChanged, this, _1));
|
m_packageName,
|
||||||
|
m_isPreNougat),
|
||||||
|
this,
|
||||||
|
bind(&AndroidRunnerWorker::onProcessIdChanged, this, _1));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidRunnerWorker::asyncStop()
|
void AndroidRunnerWorker::asyncStop()
|
||||||
@@ -793,13 +839,16 @@ void AndroidRunnerWorker::removeForwardPort(const QString &port)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AndroidRunnerWorker::onProcessIdChanged(qint64 pid)
|
void AndroidRunnerWorker::onProcessIdChanged(PidUserPair pidUser)
|
||||||
{
|
{
|
||||||
|
qint64 pid = pidUser.first;
|
||||||
|
qint64 user = pidUser.second;
|
||||||
// Don't write to m_psProc from a different thread
|
// Don't write to m_psProc from a different thread
|
||||||
QTC_ASSERT(QThread::currentThread() == thread(), return);
|
QTC_ASSERT(QThread::currentThread() == thread(), return);
|
||||||
qCDebug(androidRunWorkerLog) << "Process ID changed from:" << m_processPID
|
qCDebug(androidRunWorkerLog) << "Process ID changed from:" << m_processPID
|
||||||
<< "to:" << pid;
|
<< "to:" << pid;
|
||||||
m_processPID = pid;
|
m_processPID = pid;
|
||||||
|
m_processUser = user;
|
||||||
if (pid == -1) {
|
if (pid == -1) {
|
||||||
emit remoteProcessFinished(QLatin1String("\n\n") + Tr::tr("\"%1\" died.")
|
emit remoteProcessFinished(QLatin1String("\n\n") + Tr::tr("\"%1\" died.")
|
||||||
.arg(m_packageName));
|
.arg(m_packageName));
|
||||||
@@ -813,6 +862,8 @@ void AndroidRunnerWorker::onProcessIdChanged(qint64 pid)
|
|||||||
for (const QString &entry: std::as_const(m_afterFinishAdbCommands))
|
for (const QString &entry: std::as_const(m_afterFinishAdbCommands))
|
||||||
runAdb(entry.split(' ', Qt::SkipEmptyParts));
|
runAdb(entry.split(' ', Qt::SkipEmptyParts));
|
||||||
} else {
|
} else {
|
||||||
|
if (m_useCppDebugger)
|
||||||
|
startNativeDebugging();
|
||||||
// In debugging cases this will be funneled to the engine to actually start
|
// In debugging cases this will be funneled to the engine to actually start
|
||||||
// and attach gdb. Afterwards this ends up in handleRemoteDebuggerRunning() below.
|
// and attach gdb. Afterwards this ends up in handleRemoteDebuggerRunning() below.
|
||||||
emit remoteProcessStarted(m_localDebugServerPort, m_qmlServer, m_processPID);
|
emit remoteProcessStarted(m_localDebugServerPort, m_qmlServer, m_processPID);
|
||||||
@@ -824,7 +875,7 @@ void AndroidRunnerWorker::onProcessIdChanged(qint64 pid)
|
|||||||
m_psIsAlive->setObjectName("IsAliveProcess");
|
m_psIsAlive->setObjectName("IsAliveProcess");
|
||||||
m_psIsAlive->setProcessChannelMode(QProcess::MergedChannels);
|
m_psIsAlive->setProcessChannelMode(QProcess::MergedChannels);
|
||||||
connect(m_psIsAlive.get(), &QProcess::finished,
|
connect(m_psIsAlive.get(), &QProcess::finished,
|
||||||
this, bind(&AndroidRunnerWorker::onProcessIdChanged, this, -1));
|
this, bind(&AndroidRunnerWorker::onProcessIdChanged, this, PidUserPair(-1, -1)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -10,6 +10,7 @@
|
|||||||
#include <utils/port.h>
|
#include <utils/port.h>
|
||||||
|
|
||||||
#include <QFuture>
|
#include <QFuture>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QProcess;
|
class QProcess;
|
||||||
@@ -26,6 +27,8 @@ namespace Internal {
|
|||||||
|
|
||||||
const int MIN_SOCKET_HANDSHAKE_PORT = 20001;
|
const int MIN_SOCKET_HANDSHAKE_PORT = 20001;
|
||||||
|
|
||||||
|
using PidUserPair = std::pair<qint64, qint64>;
|
||||||
|
|
||||||
class AndroidRunnerWorker : public QObject
|
class AndroidRunnerWorker : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -61,6 +64,7 @@ signals:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void asyncStartHelper();
|
void asyncStartHelper();
|
||||||
|
void startNativeDebugging();
|
||||||
bool startDebuggerServer(const QString &packageDir, const QString &debugServerFile, QString *errorStr = nullptr);
|
bool startDebuggerServer(const QString &packageDir, const QString &debugServerFile, QString *errorStr = nullptr);
|
||||||
bool deviceFileExists(const QString &filePath);
|
bool deviceFileExists(const QString &filePath);
|
||||||
bool packageFileExists(const QString& filePath);
|
bool packageFileExists(const QString& filePath);
|
||||||
@@ -72,7 +76,7 @@ private:
|
|||||||
Waiting,
|
Waiting,
|
||||||
Settled
|
Settled
|
||||||
};
|
};
|
||||||
void onProcessIdChanged(qint64 pid);
|
void onProcessIdChanged(PidUserPair pidUser);
|
||||||
using Deleter = void (*)(QProcess *);
|
using Deleter = void (*)(QProcess *);
|
||||||
|
|
||||||
// Create the processes and timer in the worker thread, for correct thread affinity
|
// Create the processes and timer in the worker thread, for correct thread affinity
|
||||||
@@ -83,11 +87,12 @@ private:
|
|||||||
QStringList m_afterFinishAdbCommands;
|
QStringList m_afterFinishAdbCommands;
|
||||||
QStringList m_amStartExtraArgs;
|
QStringList m_amStartExtraArgs;
|
||||||
qint64 m_processPID = -1;
|
qint64 m_processPID = -1;
|
||||||
|
qint64 m_processUser = -1;
|
||||||
std::unique_ptr<QProcess, Deleter> m_adbLogcatProcess;
|
std::unique_ptr<QProcess, Deleter> m_adbLogcatProcess;
|
||||||
std::unique_ptr<QProcess, Deleter> m_psIsAlive;
|
std::unique_ptr<QProcess, Deleter> m_psIsAlive;
|
||||||
QByteArray m_stdoutBuffer;
|
QByteArray m_stdoutBuffer;
|
||||||
QByteArray m_stderrBuffer;
|
QByteArray m_stderrBuffer;
|
||||||
QFuture<qint64> m_pidFinder;
|
QFuture<PidUserPair> m_pidFinder;
|
||||||
bool m_useCppDebugger = false;
|
bool m_useCppDebugger = false;
|
||||||
bool m_useLldb = false; // FIXME: Un-implemented currently.
|
bool m_useLldb = false; // FIXME: Un-implemented currently.
|
||||||
QmlDebug::QmlDebugServicesPreset m_qmlDebugServices;
|
QmlDebug::QmlDebugServicesPreset m_qmlDebugServices;
|
||||||
|
@@ -177,6 +177,7 @@ clang::format::FormatStyle qtcStyle()
|
|||||||
style.Standard = FormatStyle::LS_Cpp11;
|
style.Standard = FormatStyle::LS_Cpp11;
|
||||||
style.TabWidth = 4;
|
style.TabWidth = 4;
|
||||||
style.UseTab = FormatStyle::UT_Never;
|
style.UseTab = FormatStyle::UT_Never;
|
||||||
|
style.Standard = FormatStyle::LS_Auto;
|
||||||
return style;
|
return style;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -519,8 +519,8 @@ ClangTool::ClangTool(const QString &name, Utils::Id id)
|
|||||||
mainLayout->addWidget(m_infoBarWidget);
|
mainLayout->addWidget(m_infoBarWidget);
|
||||||
mainLayout->addWidget(m_diagnosticView);
|
mainLayout->addWidget(m_diagnosticView);
|
||||||
auto mainWidget = new QWidget;
|
auto mainWidget = new QWidget;
|
||||||
mainWidget->setObjectName("ClangTidyClazyIssuesView");
|
mainWidget->setObjectName(id.toString() + "IssuesView");
|
||||||
mainWidget->setWindowTitle(Tr::tr("Clang-Tidy and Clazy"));
|
mainWidget->setWindowTitle(name);
|
||||||
mainWidget->setLayout(mainLayout);
|
mainWidget->setLayout(mainLayout);
|
||||||
|
|
||||||
m_perspective.addWindow(mainWidget, Perspective::SplitVertical, nullptr);
|
m_perspective.addWindow(mainWidget, Perspective::SplitVertical, nullptr);
|
||||||
|
@@ -1256,6 +1256,12 @@ static void addCMakeConfigurePresetToInitialArguments(QStringList &initialArgume
|
|||||||
const QString presetItemArg = presetItem.toArgument();
|
const QString presetItemArg = presetItem.toArgument();
|
||||||
const QString presetItemArgNoType = presetItemArg.left(presetItemArg.indexOf(":"));
|
const QString presetItemArgNoType = presetItemArg.left(presetItemArg.indexOf(":"));
|
||||||
|
|
||||||
|
static QSet<QByteArray> defaultKitMacroValues{"CMAKE_C_COMPILER",
|
||||||
|
"CMAKE_CXX_COMPILER",
|
||||||
|
"QT_QMAKE_EXECUTABLE",
|
||||||
|
"QT_HOST_PATH",
|
||||||
|
"CMAKE_PROJECT_INCLUDE_BEFORE"};
|
||||||
|
|
||||||
auto it = std::find_if(initialArguments.begin(),
|
auto it = std::find_if(initialArguments.begin(),
|
||||||
initialArguments.end(),
|
initialArguments.end(),
|
||||||
[presetItemArgNoType](const QString &arg) {
|
[presetItemArgNoType](const QString &arg) {
|
||||||
@@ -1266,6 +1272,11 @@ static void addCMakeConfigurePresetToInitialArguments(QStringList &initialArgume
|
|||||||
QString &arg = *it;
|
QString &arg = *it;
|
||||||
CMakeConfigItem argItem = CMakeConfigItem::fromString(arg.mid(2)); // skip -D
|
CMakeConfigItem argItem = CMakeConfigItem::fromString(arg.mid(2)); // skip -D
|
||||||
|
|
||||||
|
// These values have Qt Creator macro names pointing to the Kit values
|
||||||
|
// which are preset expanded values used when the Kit was created
|
||||||
|
if (defaultKitMacroValues.contains(argItem.key) && argItem.value.startsWith("%{"))
|
||||||
|
continue;
|
||||||
|
|
||||||
// For multi value path variables append the non Qt path
|
// For multi value path variables append the non Qt path
|
||||||
if (argItem.key == "CMAKE_PREFIX_PATH" || argItem.key == "CMAKE_FIND_ROOT_PATH") {
|
if (argItem.key == "CMAKE_PREFIX_PATH" || argItem.key == "CMAKE_FIND_ROOT_PATH") {
|
||||||
QStringList presetValueList = presetItem.expandedValue(k).split(";");
|
QStringList presetValueList = presetItem.expandedValue(k).split(";");
|
||||||
@@ -1276,7 +1287,7 @@ static void addCMakeConfigurePresetToInitialArguments(QStringList &initialArgume
|
|||||||
QStringList argItemPaths = argItemExpandedValue.split(";");
|
QStringList argItemPaths = argItemExpandedValue.split(";");
|
||||||
for (const QString &argPath : argItemPaths) {
|
for (const QString &argPath : argItemPaths) {
|
||||||
const FilePath argFilePath = FilePath::fromString(argPath);
|
const FilePath argFilePath = FilePath::fromString(argPath);
|
||||||
const FilePath presetFilePath = FilePath::fromString(presetPath);
|
const FilePath presetFilePath = FilePath::fromUserInput(presetPath);
|
||||||
|
|
||||||
if (argFilePath == presetFilePath)
|
if (argFilePath == presetFilePath)
|
||||||
return true;
|
return true;
|
||||||
@@ -1291,12 +1302,10 @@ static void addCMakeConfigurePresetToInitialArguments(QStringList &initialArgume
|
|||||||
}
|
}
|
||||||
|
|
||||||
arg = argItem.toArgument();
|
arg = argItem.toArgument();
|
||||||
} else if (argItem.key == "CMAKE_C_COMPILER" || argItem.key == "CMAKE_CXX_COMPILER"
|
} else if (argItem.key == "CMAKE_TOOLCHAIN_FILE") {
|
||||||
|| argItem.key == "QT_QMAKE_EXECUTABLE" || argItem.key == "QT_HOST_PATH"
|
|
||||||
|| argItem.key == "CMAKE_PROJECT_INCLUDE_BEFORE"
|
|
||||||
|| argItem.key == "CMAKE_TOOLCHAIN_FILE") {
|
|
||||||
const FilePath argFilePath = FilePath::fromString(argItem.expandedValue(k));
|
const FilePath argFilePath = FilePath::fromString(argItem.expandedValue(k));
|
||||||
const FilePath presetFilePath = FilePath::fromUtf8(presetItem.value);
|
const FilePath presetFilePath = FilePath::fromUserInput(
|
||||||
|
QString::fromUtf8(presetItem.value));
|
||||||
|
|
||||||
if (argFilePath != presetFilePath)
|
if (argFilePath != presetFilePath)
|
||||||
arg = presetItem.toArgument();
|
arg = presetItem.toArgument();
|
||||||
|
@@ -103,7 +103,9 @@ Internal::PresetsData CMakeProject::combinePresets(Internal::PresetsData &cmakeP
|
|||||||
|
|
||||||
auto resolveInherits = [](auto &presetsHash, auto &presetsList) {
|
auto resolveInherits = [](auto &presetsHash, auto &presetsList) {
|
||||||
Utils::sort(presetsList, [](const auto &left, const auto &right) {
|
Utils::sort(presetsList, [](const auto &left, const auto &right) {
|
||||||
if (!left.inherits || left.inherits.value().contains(right.name))
|
const bool sameInheritance = left.inherits && right.inherits
|
||||||
|
&& left.inherits.value() == right.inherits.value();
|
||||||
|
if (!left.inherits || left.inherits.value().contains(right.name) || sameInheritance)
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
@@ -209,23 +209,11 @@ static CMakeConfig configurationFromPresetProbe(
|
|||||||
? configurePreset.cacheVariables.value()
|
? configurePreset.cacheVariables.value()
|
||||||
: CMakeConfig();
|
: CMakeConfig();
|
||||||
|
|
||||||
auto expandCacheValue =
|
const QString cmakeMakeProgram = cache.stringValueOf("CMAKE_MAKE_PROGRAM");
|
||||||
[configurePreset, env, sourceDirectory, cache](const QString &key) -> QString {
|
const QString toolchainFile = cache.stringValueOf("CMAKE_TOOLCHAIN_FILE");
|
||||||
QString result = cache.stringValueOf(key.toUtf8());
|
const QString prefixPath = cache.stringValueOf("CMAKE_PREFIX_PATH");
|
||||||
CMakePresets::Macros::expand(configurePreset, env, sourceDirectory, result);
|
const QString findRootPath = cache.stringValueOf("CMAKE_FIND_ROOT_PATH");
|
||||||
|
const QString qtHostPath = cache.stringValueOf("QT_HOST_PATH");
|
||||||
// all usages involve file paths, so make sure they are cleaned up
|
|
||||||
const FilePaths paths = transform(result.split(";"), &FilePath::fromUserInput);
|
|
||||||
result = transform(paths, &FilePath::path).join(";");
|
|
||||||
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
const QString cmakeMakeProgram = expandCacheValue("CMAKE_MAKE_PROGRAM");
|
|
||||||
const QString toolchainFile = expandCacheValue("CMAKE_TOOLCHAIN_FILE");
|
|
||||||
const QString prefixPath = expandCacheValue("CMAKE_PREFIX_PATH");
|
|
||||||
const QString findRootPath = expandCacheValue("CMAKE_FIND_ROOT_PATH");
|
|
||||||
const QString qtHostPath = expandCacheValue("QT_HOST_PATH");
|
|
||||||
|
|
||||||
if (!cmakeMakeProgram.isEmpty()) {
|
if (!cmakeMakeProgram.isEmpty()) {
|
||||||
args.emplace_back(
|
args.emplace_back(
|
||||||
@@ -662,6 +650,8 @@ QList<void *> CMakeProjectImporter::examineDirectory(const FilePath &importPath,
|
|||||||
projectDirectory(),
|
projectDirectory(),
|
||||||
data->buildDirectory);
|
data->buildDirectory);
|
||||||
|
|
||||||
|
CMakePresets::Macros::updateCacheVariables(configurePreset, env, projectDirectory());
|
||||||
|
|
||||||
const CMakeConfig cache = configurePreset.cacheVariables
|
const CMakeConfig cache = configurePreset.cacheVariables
|
||||||
? configurePreset.cacheVariables.value()
|
? configurePreset.cacheVariables.value()
|
||||||
: CMakeConfig();
|
: CMakeConfig();
|
||||||
@@ -710,10 +700,7 @@ QList<void *> CMakeProjectImporter::examineDirectory(const FilePath &importPath,
|
|||||||
data->cmakePresetDefaultConfigHash
|
data->cmakePresetDefaultConfigHash
|
||||||
= CMakeConfigurationKitAspect::computeDefaultConfigHash(config, data->cmakeBinary);
|
= CMakeConfigurationKitAspect::computeDefaultConfigHash(config, data->cmakeBinary);
|
||||||
|
|
||||||
QString cmakeBuildType = QString::fromUtf8(cache.valueOf("CMAKE_BUILD_TYPE"));
|
QByteArrayList buildConfigurationTypes = {cache.valueOf("CMAKE_BUILD_TYPE")};
|
||||||
CMakePresets::Macros::expand(configurePreset, env, projectDirectory(), cmakeBuildType);
|
|
||||||
|
|
||||||
QByteArrayList buildConfigurationTypes = {cmakeBuildType.toUtf8()};
|
|
||||||
if (buildConfigurationTypes.front().isEmpty()) {
|
if (buildConfigurationTypes.front().isEmpty()) {
|
||||||
buildConfigurationTypes.clear();
|
buildConfigurationTypes.clear();
|
||||||
QByteArray buildConfigurationTypesString = cache.valueOf("CMAKE_CONFIGURATION_TYPES");
|
QByteArray buildConfigurationTypesString = cache.valueOf("CMAKE_CONFIGURATION_TYPES");
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
#include "presetsmacros.h"
|
#include "presetsmacros.h"
|
||||||
#include "presetsparser.h"
|
#include "presetsparser.h"
|
||||||
|
|
||||||
|
#include <utils/algorithm.h>
|
||||||
#include <utils/environment.h>
|
#include <utils/environment.h>
|
||||||
#include <utils/filepath.h>
|
#include <utils/filepath.h>
|
||||||
#include <utils/hostosinfo.h>
|
#include <utils/hostosinfo.h>
|
||||||
@@ -295,6 +296,47 @@ void updateInstallDir(PresetsDetails::ConfigurePreset &configurePreset,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void updateCacheVariables(PresetsDetails::ConfigurePreset &configurePreset,
|
||||||
|
const Utils::Environment &env,
|
||||||
|
const Utils::FilePath &sourceDirectory)
|
||||||
|
{
|
||||||
|
using namespace Utils;
|
||||||
|
|
||||||
|
if (!configurePreset.cacheVariables)
|
||||||
|
return;
|
||||||
|
|
||||||
|
CMakeConfig cache = configurePreset.cacheVariables.value();
|
||||||
|
|
||||||
|
static const QSet<QByteArray> pathKeys{"CMAKE_C_COMPILER",
|
||||||
|
"CMAKE_CXX_COMPILER",
|
||||||
|
"CMAKE_PREFIX_PATH",
|
||||||
|
"CMAKE_FIND_ROOT_PATH",
|
||||||
|
"CMAKE_MAKE_PROGRAM",
|
||||||
|
"CMAKE_TOOLCHAIN_FILE",
|
||||||
|
"QT_HOST_PATH",
|
||||||
|
"QT_QMAKE_EXECUTABLE",
|
||||||
|
"CMAKE_SYSROOT"};
|
||||||
|
|
||||||
|
auto expandCacheValue =
|
||||||
|
[configurePreset, env, sourceDirectory, cache](const QByteArray &key) {
|
||||||
|
QString result = cache.stringValueOf(key);
|
||||||
|
CMakePresets::Macros::expand(configurePreset, env, sourceDirectory, result);
|
||||||
|
|
||||||
|
if (pathKeys.contains(key)) {
|
||||||
|
const FilePaths paths = transform(result.split(";"), &FilePath::fromUserInput);
|
||||||
|
result = transform(paths, &FilePath::path).join(";");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.toUtf8();
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto &item : cache)
|
||||||
|
item.value = expandCacheValue(item.key);
|
||||||
|
|
||||||
|
configurePreset.cacheVariables = cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class PresetType>
|
template<class PresetType>
|
||||||
void expandConditionValues(const PresetType &preset,
|
void expandConditionValues(const PresetType &preset,
|
||||||
const Utils::Environment &env,
|
const Utils::Environment &env,
|
||||||
|
@@ -60,6 +60,14 @@ void updateToolchainFile(PresetsDetails::ConfigurePreset &configurePreset,
|
|||||||
void updateInstallDir(PresetsDetails::ConfigurePreset &configurePreset,
|
void updateInstallDir(PresetsDetails::ConfigurePreset &configurePreset,
|
||||||
const Utils::Environment &env,
|
const Utils::Environment &env,
|
||||||
const Utils::FilePath &sourceDirectory);
|
const Utils::FilePath &sourceDirectory);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the cacheVariables parameter of the configurePreset with the expanded prameter values.
|
||||||
|
* Including macro expansion and relative paths resolving.
|
||||||
|
*/
|
||||||
|
void updateCacheVariables(PresetsDetails::ConfigurePreset &configurePreset,
|
||||||
|
const Utils::Environment &env,
|
||||||
|
const Utils::FilePath &sourceDirectory);
|
||||||
/**
|
/**
|
||||||
* Expands the condition values and then evaluates the condition object of the preset and returns
|
* Expands the condition values and then evaluates the condition object of the preset and returns
|
||||||
* the boolean result.
|
* the boolean result.
|
||||||
|
@@ -44,6 +44,7 @@ static bool debugExamples()
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const char kSelectedExampleSetKey[] = "WelcomePage/SelectedExampleSet";
|
static const char kSelectedExampleSetKey[] = "WelcomePage/SelectedExampleSet";
|
||||||
|
Q_GLOBAL_STATIC_WITH_ARGS(QVersionNumber, minQtVersionForCategories, (6, 5, 1));
|
||||||
|
|
||||||
void ExampleSetModel::writeCurrentIdToSettings(int currentIndex) const
|
void ExampleSetModel::writeCurrentIdToSettings(int currentIndex) const
|
||||||
{
|
{
|
||||||
@@ -117,7 +118,7 @@ void ExampleSetModel::recreateModel(const QtVersions &qtVersions)
|
|||||||
beginResetModel();
|
beginResetModel();
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
QSet<QString> extraManifestDirs;
|
QHash<FilePath, int> extraManifestDirs;
|
||||||
for (int i = 0; i < m_extraExampleSets.size(); ++i) {
|
for (int i = 0; i < m_extraExampleSets.size(); ++i) {
|
||||||
const ExtraExampleSet &set = m_extraExampleSets.at(i);
|
const ExtraExampleSet &set = m_extraExampleSets.at(i);
|
||||||
auto newItem = new QStandardItem();
|
auto newItem = new QStandardItem();
|
||||||
@@ -127,14 +128,19 @@ void ExampleSetModel::recreateModel(const QtVersions &qtVersions)
|
|||||||
newItem->setData(i, Qt::UserRole + 3);
|
newItem->setData(i, Qt::UserRole + 3);
|
||||||
appendRow(newItem);
|
appendRow(newItem);
|
||||||
|
|
||||||
extraManifestDirs.insert(set.manifestPath);
|
extraManifestDirs.insert(FilePath::fromUserInput(set.manifestPath), i);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (QtVersion *version : qtVersions) {
|
for (QtVersion *version : qtVersions) {
|
||||||
// sanitize away qt versions that have already been added through extra sets
|
// Sanitize away qt versions that have already been added through extra sets.
|
||||||
if (extraManifestDirs.contains(version->docsPath().toString())) {
|
// This way we do not have entries for Qt/Android, Qt/Desktop, Qt/MinGW etc pp,
|
||||||
|
// but only the one "QtX X.Y.Z" entry that is registered as an example set by the installer.
|
||||||
|
if (extraManifestDirs.contains(version->docsPath())) {
|
||||||
|
m_extraExampleSets[extraManifestDirs.value(version->docsPath())].qtVersion
|
||||||
|
= version->qtVersion();
|
||||||
if (debugExamples()) {
|
if (debugExamples()) {
|
||||||
qWarning() << "Not showing Qt version because manifest path is already added through InstalledExamples settings:"
|
qWarning() << "Not showing Qt version because manifest path is already added "
|
||||||
|
"through InstalledExamples settings:"
|
||||||
<< version->displayName();
|
<< version->displayName();
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
@@ -330,10 +336,11 @@ static bool sortByHighlightedAndName(ExampleItem *first, ExampleItem *second)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static QList<std::pair<Section, QList<ExampleItem *>>> getCategories(
|
static QList<std::pair<Section, QList<ExampleItem *>>> getCategories(
|
||||||
const QList<ExampleItem *> &items)
|
const QList<ExampleItem *> &items, bool sortIntoCategories)
|
||||||
{
|
{
|
||||||
static const QString otherDisplayName = Tr::tr("Other", "Category for all other examples");
|
static const QString otherDisplayName = Tr::tr("Other", "Category for all other examples");
|
||||||
const bool useCategories = qtcEnvironmentVariableIsSet("QTC_USE_EXAMPLE_CATEGORIES");
|
const bool useCategories = sortIntoCategories
|
||||||
|
|| qtcEnvironmentVariableIsSet("QTC_USE_EXAMPLE_CATEGORIES");
|
||||||
QList<ExampleItem *> other;
|
QList<ExampleItem *> other;
|
||||||
QMap<QString, QList<ExampleItem *>> categoryMap;
|
QMap<QString, QList<ExampleItem *>> categoryMap;
|
||||||
if (useCategories) {
|
if (useCategories) {
|
||||||
@@ -378,10 +385,11 @@ void ExamplesViewController::updateExamples()
|
|||||||
{
|
{
|
||||||
QString examplesInstallPath;
|
QString examplesInstallPath;
|
||||||
QString demosInstallPath;
|
QString demosInstallPath;
|
||||||
|
QVersionNumber qtVersion;
|
||||||
|
|
||||||
const QStringList sources = m_exampleSetModel->exampleSources(&examplesInstallPath,
|
const QStringList sources = m_exampleSetModel->exampleSources(&examplesInstallPath,
|
||||||
&demosInstallPath);
|
&demosInstallPath,
|
||||||
|
&qtVersion);
|
||||||
m_view->clear();
|
m_view->clear();
|
||||||
|
|
||||||
QList<ExampleItem *> items;
|
QList<ExampleItem *> items;
|
||||||
@@ -418,7 +426,9 @@ void ExamplesViewController::updateExamples()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const QList<std::pair<Section, QList<ExampleItem *>>> sections = getCategories(items);
|
const bool sortIntoCategories = qtVersion >= *minQtVersionForCategories;
|
||||||
|
const QList<std::pair<Section, QList<ExampleItem *>>> sections
|
||||||
|
= getCategories(items, sortIntoCategories);
|
||||||
for (int i = 0; i < sections.size(); ++i) {
|
for (int i = 0; i < sections.size(); ++i) {
|
||||||
m_view->addSection(sections.at(i).first,
|
m_view->addSection(sections.at(i).first,
|
||||||
static_container_cast<ListItem *>(sections.at(i).second));
|
static_container_cast<ListItem *>(sections.at(i).second));
|
||||||
@@ -486,7 +496,9 @@ QtVersion *ExampleSetModel::findHighestQtVersion(const QtVersions &versions) con
|
|||||||
return newVersion;
|
return newVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList ExampleSetModel::exampleSources(QString *examplesInstallPath, QString *demosInstallPath)
|
QStringList ExampleSetModel::exampleSources(QString *examplesInstallPath,
|
||||||
|
QString *demosInstallPath,
|
||||||
|
QVersionNumber *qtVersion)
|
||||||
{
|
{
|
||||||
QStringList sources;
|
QStringList sources;
|
||||||
|
|
||||||
@@ -504,6 +516,8 @@ QStringList ExampleSetModel::exampleSources(QString *examplesInstallPath, QStrin
|
|||||||
manifestScanPath = exampleSet.manifestPath;
|
manifestScanPath = exampleSet.manifestPath;
|
||||||
examplesPath = exampleSet.examplesPath;
|
examplesPath = exampleSet.examplesPath;
|
||||||
demosPath = exampleSet.examplesPath;
|
demosPath = exampleSet.examplesPath;
|
||||||
|
if (qtVersion)
|
||||||
|
*qtVersion = exampleSet.qtVersion;
|
||||||
} else if (currentType == ExampleSetModel::QtExampleSet) {
|
} else if (currentType == ExampleSetModel::QtExampleSet) {
|
||||||
const int qtId = getQtId(m_selectedExampleSetIndex);
|
const int qtId = getQtId(m_selectedExampleSetIndex);
|
||||||
const QtVersions versions = QtVersionManager::versions();
|
const QtVersions versions = QtVersionManager::versions();
|
||||||
@@ -512,6 +526,8 @@ QStringList ExampleSetModel::exampleSources(QString *examplesInstallPath, QStrin
|
|||||||
manifestScanPath = version->docsPath().toString();
|
manifestScanPath = version->docsPath().toString();
|
||||||
examplesPath = version->examplesPath().toString();
|
examplesPath = version->examplesPath().toString();
|
||||||
demosPath = version->demosPath().toString();
|
demosPath = version->demosPath().toString();
|
||||||
|
if (qtVersion)
|
||||||
|
*qtVersion = version->qtVersion();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -28,6 +28,10 @@ public:
|
|||||||
QString displayName;
|
QString displayName;
|
||||||
QString manifestPath;
|
QString manifestPath;
|
||||||
QString examplesPath;
|
QString examplesPath;
|
||||||
|
// qtVersion is set by recreateModel for extra sets that correspond to actual Qt versions.
|
||||||
|
// This is needed for the decision to show categories or not based on the Qt version
|
||||||
|
// (which is not ideal).
|
||||||
|
QVersionNumber qtVersion;
|
||||||
};
|
};
|
||||||
static QVector<ExtraExampleSet> pluginRegisteredExampleSets();
|
static QVector<ExtraExampleSet> pluginRegisteredExampleSets();
|
||||||
|
|
||||||
@@ -35,7 +39,9 @@ public:
|
|||||||
|
|
||||||
int selectedExampleSet() const { return m_selectedExampleSetIndex; }
|
int selectedExampleSet() const { return m_selectedExampleSetIndex; }
|
||||||
void selectExampleSet(int index);
|
void selectExampleSet(int index);
|
||||||
QStringList exampleSources(QString *examplesInstallPath, QString *demosInstallPath);
|
QStringList exampleSources(QString *examplesInstallPath,
|
||||||
|
QString *demosInstallPath,
|
||||||
|
QVersionNumber *qtVersion);
|
||||||
bool selectedQtSupports(const Utils::Id &target) const;
|
bool selectedQtSupports(const Utils::Id &target) const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
Submodule src/shared/qbs updated: 289aac0aa1...e002680feb
@@ -12,7 +12,6 @@ of the Qt installation from the online installer.
|
|||||||
It's easiest to use installations of the official opensource Qt packages. Just install the
|
It's easiest to use installations of the official opensource Qt packages. Just install the
|
||||||
Qt version for the respective toolchain with the components (if available):
|
Qt version for the respective toolchain with the components (if available):
|
||||||
- (Desktop) <toolchain> <bitness>, e.g. Desktop gcc 64-bit
|
- (Desktop) <toolchain> <bitness>, e.g. Desktop gcc 64-bit
|
||||||
- Qt Quick Controls (if available)
|
|
||||||
- Qt Script (Qt5 only)
|
- Qt Script (Qt5 only)
|
||||||
|
|
||||||
The exact versions and toolchains are:
|
The exact versions and toolchains are:
|
||||||
|
@@ -18,6 +18,7 @@ def main():
|
|||||||
expectBuildToFail = []
|
expectBuildToFail = []
|
||||||
if platform.system() in ('Microsoft', 'Windows'):
|
if platform.system() in ('Microsoft', 'Windows'):
|
||||||
expectConfigureToFail = [ Targets.DESKTOP_5_4_1_GCC ] # gcc 4.9 does not know C++17
|
expectConfigureToFail = [ Targets.DESKTOP_5_4_1_GCC ] # gcc 4.9 does not know C++17
|
||||||
|
expectBuildToFail = [ Targets.DESKTOP_5_10_1_DEFAULT ] # fails to handle constexpr correctly
|
||||||
|
|
||||||
for kit, config in availableConfigs:
|
for kit, config in availableConfigs:
|
||||||
selectBuildConfig(kit, config)
|
selectBuildConfig(kit, config)
|
||||||
|
@@ -35,7 +35,7 @@ def __checkKits__():
|
|||||||
if llvmForBuild is not None:
|
if llvmForBuild is not None:
|
||||||
internalClangExe = os.path.join(llvmForBuild, "bin", "clang")
|
internalClangExe = os.path.join(llvmForBuild, "bin", "clang")
|
||||||
if platform.system() in ("Microsoft", "Windows"):
|
if platform.system() in ("Microsoft", "Windows"):
|
||||||
internalClangExe.append(".exe")
|
internalClangExe += ".exe"
|
||||||
if os.path.exists(internalClangExe):
|
if os.path.exists(internalClangExe):
|
||||||
expectedCompilers.append(internalClangExe)
|
expectedCompilers.append(internalClangExe)
|
||||||
foundCompilers = []
|
foundCompilers = []
|
||||||
|
Reference in New Issue
Block a user