forked from qt-creator/qt-creator
Use QtcProcess for clangbackend
Change-Id: Ifdcdba765409a09861f81dd3dff405115a986801 Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
@@ -36,6 +36,8 @@
|
|||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
|
||||||
|
using namespace Utils;
|
||||||
|
|
||||||
namespace ClangBackEnd {
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
ConnectionClient::ConnectionClient(const QString &connectionName)
|
ConnectionClient::ConnectionClient(const QString &connectionName)
|
||||||
@@ -159,7 +161,7 @@ void ConnectionClient::restartProcessIfTimerIsNotResettedAndSocketIsEmpty()
|
|||||||
restartProcessAsynchronously();
|
restartProcessAsynchronously();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionClient::endProcess(QProcess *process)
|
void ConnectionClient::endProcess(QtcProcess *process)
|
||||||
{
|
{
|
||||||
if (isProcessRunning(process) && isConnected()) {
|
if (isProcessRunning(process) && isConnected()) {
|
||||||
sendEndMessage();
|
sendEndMessage();
|
||||||
@@ -167,15 +169,15 @@ void ConnectionClient::endProcess(QProcess *process)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionClient::terminateProcess(QProcess *process)
|
void ConnectionClient::terminateProcess(QtcProcess *process)
|
||||||
{
|
{
|
||||||
if (!Utils::HostOsInfo::isWindowsHost() && isProcessRunning()) {
|
if (!HostOsInfo::isWindowsHost() && isProcessRunning()) {
|
||||||
process->terminate();
|
process->terminate();
|
||||||
process->waitForFinished(1000);
|
process->waitForFinished(1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionClient::killProcess(QProcess *process)
|
void ConnectionClient::killProcess(QtcProcess *process)
|
||||||
{
|
{
|
||||||
if (isProcessRunning(process)) {
|
if (isProcessRunning(process)) {
|
||||||
process->kill();
|
process->kill();
|
||||||
@@ -213,7 +215,7 @@ void ConnectionClient::resetTemporaryDirectory()
|
|||||||
m_processCreator.resetTemporaryDirectory();
|
m_processCreator.resetTemporaryDirectory();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionClient::initializeProcess(QProcess *process)
|
void ConnectionClient::initializeProcess(QtcProcess *process)
|
||||||
{
|
{
|
||||||
connectStandardOutputAndError(process);
|
connectStandardOutputAndError(process);
|
||||||
|
|
||||||
@@ -299,7 +301,7 @@ bool ConnectionClient::waitForConnected()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
QProcess *ConnectionClient::processForTestOnly()
|
QtcProcess *ConnectionClient::processForTestOnly()
|
||||||
{
|
{
|
||||||
getProcessFromFuture();
|
getProcessFromFuture();
|
||||||
|
|
||||||
@@ -311,15 +313,15 @@ QIODevice *ConnectionClient::ioDevice()
|
|||||||
return m_localSocket;
|
return m_localSocket;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ConnectionClient::isProcessRunning(QProcess *process)
|
bool ConnectionClient::isProcessRunning(QtcProcess *process)
|
||||||
{
|
{
|
||||||
return process && process->state() == QProcess::Running;
|
return process && process->state() == QProcess::Running;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionClient::connectStandardOutputAndError(QProcess *process) const
|
void ConnectionClient::connectStandardOutputAndError(QtcProcess *process) const
|
||||||
{
|
{
|
||||||
connect(process, &QProcess::readyReadStandardOutput, this, &ConnectionClient::printStandardOutput);
|
connect(process, &QtcProcess::readyReadStandardOutput, this, &ConnectionClient::printStandardOutput);
|
||||||
connect(process, &QProcess::readyReadStandardError, this, &ConnectionClient::printStandardError);
|
connect(process, &QtcProcess::readyReadStandardError, this, &ConnectionClient::printStandardError);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectionClient::connectLocalSocketError() const
|
void ConnectionClient::connectLocalSocketError() const
|
||||||
|
@@ -28,6 +28,7 @@
|
|||||||
#include "clangcodemodelserverproxy.h"
|
#include "clangcodemodelserverproxy.h"
|
||||||
#include "lineprefixer.h"
|
#include "lineprefixer.h"
|
||||||
#include "processcreator.h"
|
#include "processcreator.h"
|
||||||
|
#include "processhandle.h"
|
||||||
|
|
||||||
#include <QLocalServer>
|
#include <QLocalServer>
|
||||||
#include <QLocalSocket>
|
#include <QLocalSocket>
|
||||||
@@ -37,9 +38,7 @@
|
|||||||
#include <future>
|
#include <future>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
namespace Utils { class QtcProcess; }
|
||||||
class QProcess;
|
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
class Utf8String;
|
class Utf8String;
|
||||||
class Utf8StringVector;
|
class Utf8StringVector;
|
||||||
@@ -77,7 +76,7 @@ public:
|
|||||||
bool waitForEcho();
|
bool waitForEcho();
|
||||||
bool waitForConnected();
|
bool waitForConnected();
|
||||||
|
|
||||||
QProcess *processForTestOnly();
|
Utils::QtcProcess *processForTestOnly();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void connectedToLocalSocket();
|
void connectedToLocalSocket();
|
||||||
@@ -103,22 +102,22 @@ protected:
|
|||||||
virtual void newConnectedServer(QLocalSocket *localSocket) = 0;
|
virtual void newConnectedServer(QLocalSocket *localSocket) = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool isProcessRunning(QProcess *process);
|
static bool isProcessRunning(Utils::QtcProcess *process);
|
||||||
void finishProcess(QProcessUniquePointer &&process);
|
void finishProcess(QProcessUniquePointer &&process);
|
||||||
void endProcess(QProcess *process);
|
void endProcess(Utils::QtcProcess *process);
|
||||||
void terminateProcess(QProcess *process);
|
void terminateProcess(Utils::QtcProcess *process);
|
||||||
void killProcess(QProcess *process);
|
void killProcess(Utils::QtcProcess *process);
|
||||||
void finishConnection();
|
void finishConnection();
|
||||||
void printLocalSocketError(QLocalSocket::LocalSocketError socketError);
|
void printLocalSocketError(QLocalSocket::LocalSocketError socketError);
|
||||||
void printStandardOutput();
|
void printStandardOutput();
|
||||||
void printStandardError();
|
void printStandardError();
|
||||||
void initializeProcess(QProcess *process);
|
void initializeProcess(Utils::QtcProcess *process);
|
||||||
|
|
||||||
void resetTemporaryDirectory();
|
void resetTemporaryDirectory();
|
||||||
|
|
||||||
void connectLocalSocketDisconnected();
|
void connectLocalSocketDisconnected();
|
||||||
void disconnectLocalSocketDisconnected();
|
void disconnectLocalSocketDisconnected();
|
||||||
void connectStandardOutputAndError(QProcess *process) const;
|
void connectStandardOutputAndError(Utils::QtcProcess *process) const;
|
||||||
void connectLocalSocketError() const;
|
void connectLocalSocketError() const;
|
||||||
void connectAliveTimer();
|
void connectAliveTimer();
|
||||||
void connectNewConnection();
|
void connectNewConnection();
|
||||||
|
@@ -28,10 +28,15 @@
|
|||||||
#include "processexception.h"
|
#include "processexception.h"
|
||||||
#include "processstartedevent.h"
|
#include "processstartedevent.h"
|
||||||
|
|
||||||
|
#include <utils/commandline.h>
|
||||||
|
#include <utils/qtcprocess.h>
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QTemporaryDir>
|
#include <QTemporaryDir>
|
||||||
|
|
||||||
|
using namespace Utils;
|
||||||
|
|
||||||
namespace ClangBackEnd {
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
@@ -56,7 +61,7 @@ void ProcessCreator::setArguments(const QStringList &arguments)
|
|||||||
m_arguments = arguments;
|
m_arguments = arguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessCreator::setEnvironment(const Utils::Environment &environment)
|
void ProcessCreator::setEnvironment(const Environment &environment)
|
||||||
{
|
{
|
||||||
m_environment = environment;
|
m_environment = environment;
|
||||||
}
|
}
|
||||||
@@ -65,10 +70,11 @@ std::future<QProcessUniquePointer> ProcessCreator::createProcess() const
|
|||||||
{
|
{
|
||||||
return std::async(std::launch::async, [&] {
|
return std::async(std::launch::async, [&] {
|
||||||
checkIfProcessPathExists();
|
checkIfProcessPathExists();
|
||||||
auto process = QProcessUniquePointer(new QProcess);
|
auto process = QProcessUniquePointer(new QtcProcess(ProcessMode::Writer));
|
||||||
process->setProcessChannelMode(QProcess::QProcess::ForwardedChannels);
|
process->setProcessChannelMode(QProcess::ForwardedChannels);
|
||||||
process->setProcessEnvironment(processEnvironment());
|
process->setEnvironment(processEnvironment());
|
||||||
process->start(m_processPath, m_arguments);
|
process->setCommand(CommandLine(FilePath::fromString(m_processPath), m_arguments));
|
||||||
|
process->start();
|
||||||
process->waitForStarted(5000);
|
process->waitForStarted(5000);
|
||||||
|
|
||||||
checkIfProcessWasStartingSuccessful(process.get());
|
checkIfProcessWasStartingSuccessful(process.get());
|
||||||
@@ -95,13 +101,13 @@ void ProcessCreator::checkIfProcessPathExists() const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessCreator::checkIfProcessWasStartingSuccessful(QProcess *process) const
|
void ProcessCreator::checkIfProcessWasStartingSuccessful(QtcProcess *process) const
|
||||||
{
|
{
|
||||||
if (process->exitStatus() == QProcess::CrashExit || process->exitCode() != 0)
|
if (process->exitStatus() == QProcess::CrashExit || process->exitCode() != 0)
|
||||||
dispatchProcessError(process);
|
dispatchProcessError(process);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessCreator::dispatchProcessError(QProcess *process) const
|
void ProcessCreator::dispatchProcessError(QtcProcess *process) const
|
||||||
{
|
{
|
||||||
switch (process->error()) {
|
switch (process->error()) {
|
||||||
case QProcess::UnknownError: {
|
case QProcess::UnknownError: {
|
||||||
@@ -158,24 +164,24 @@ const QTemporaryDir &ProcessCreator::temporaryDirectory() const
|
|||||||
|
|
||||||
void ProcessCreator::resetTemporaryDirectory()
|
void ProcessCreator::resetTemporaryDirectory()
|
||||||
{
|
{
|
||||||
m_temporaryDirectory = std::make_unique<Utils::TemporaryDirectory>(m_temporaryDirectoryPattern);
|
m_temporaryDirectory = std::make_unique<TemporaryDirectory>(m_temporaryDirectoryPattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
QProcessEnvironment ProcessCreator::processEnvironment() const
|
Environment ProcessCreator::processEnvironment() const
|
||||||
{
|
{
|
||||||
auto processEnvironment = QProcessEnvironment::systemEnvironment();
|
auto processEnvironment = Environment::systemEnvironment();
|
||||||
|
|
||||||
if (temporaryDirectory().isValid()) {
|
if (temporaryDirectory().isValid()) {
|
||||||
const QString temporaryDirectoryPath = temporaryDirectory().path();
|
const QString temporaryDirectoryPath = temporaryDirectory().path();
|
||||||
processEnvironment.insert("TMPDIR", temporaryDirectoryPath);
|
processEnvironment.appendOrSet("TMPDIR", temporaryDirectoryPath);
|
||||||
processEnvironment.insert("TMP", temporaryDirectoryPath);
|
processEnvironment.appendOrSet("TMP", temporaryDirectoryPath);
|
||||||
processEnvironment.insert("TEMP", temporaryDirectoryPath);
|
processEnvironment.appendOrSet("TEMP", temporaryDirectoryPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Utils::Environment &env = m_environment;
|
const Environment &env = m_environment;
|
||||||
for (auto it = env.constBegin(); it != env.constEnd(); ++it) {
|
for (auto it = env.constBegin(); it != env.constEnd(); ++it) {
|
||||||
if (env.isEnabled(it))
|
if (env.isEnabled(it))
|
||||||
processEnvironment.insert(env.key(it), env.expandedValueForKey(env.key(it)));
|
processEnvironment.appendOrSet(env.key(it), env.expandedValueForKey(env.key(it)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return processEnvironment;
|
return processEnvironment;
|
||||||
|
@@ -39,9 +39,13 @@
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QTemporaryDir;
|
class QTemporaryDir;
|
||||||
class QProcessEnvironment;
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
namespace Utils {
|
||||||
|
class Environment;
|
||||||
|
class QtcProcess;
|
||||||
|
}
|
||||||
|
|
||||||
namespace ClangBackEnd {
|
namespace ClangBackEnd {
|
||||||
|
|
||||||
class CLANGSUPPORT_EXPORT ProcessCreator
|
class CLANGSUPPORT_EXPORT ProcessCreator
|
||||||
@@ -62,12 +66,12 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void checkIfProcessPathExists() const;
|
void checkIfProcessPathExists() const;
|
||||||
void checkIfProcessWasStartingSuccessful(QProcess *process) const;
|
void checkIfProcessWasStartingSuccessful(Utils::QtcProcess *process) const;
|
||||||
[[noreturn]] void dispatchProcessError(QProcess *process) const;
|
[[noreturn]] void dispatchProcessError(Utils::QtcProcess *process) const;
|
||||||
void postProcessStartedEvent() const;
|
void postProcessStartedEvent() const;
|
||||||
[[noreturn]] void throwProcessException(const QString &message) const;
|
[[noreturn]] void throwProcessException(const QString &message) const;
|
||||||
|
|
||||||
QProcessEnvironment processEnvironment() const;
|
Utils::Environment processEnvironment() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<Utils::TemporaryDirectory> m_temporaryDirectory;
|
std::unique_ptr<Utils::TemporaryDirectory> m_temporaryDirectory;
|
||||||
|
@@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QProcess>
|
#include <utils/qtcprocess.h>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ namespace ClangBackEnd {
|
|||||||
class QProcessUniquePointerDeleter
|
class QProcessUniquePointerDeleter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void operator()(QProcess* process)
|
void operator()(Utils::QtcProcess* process)
|
||||||
{
|
{
|
||||||
process->kill();
|
process->kill();
|
||||||
process->waitForFinished();
|
process->waitForFinished();
|
||||||
@@ -42,6 +42,6 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
using QProcessUniquePointer = std::unique_ptr<QProcess, QProcessUniquePointerDeleter>;
|
using QProcessUniquePointer = std::unique_ptr<Utils::QtcProcess, QProcessUniquePointerDeleter>;
|
||||||
|
|
||||||
} // namespace ClangBackEnd
|
} // namespace ClangBackEnd
|
||||||
|
@@ -23,6 +23,9 @@ elseif (MINGW)
|
|||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wa,-mbig-obj")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wa,-mbig-obj")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
file(RELATIVE_PATH RELATIVE_TEST_PATH "${PROJECT_BINARY_DIR}" "${CMAKE_CURRENT_BINARY_DIR}")
|
||||||
|
file(RELATIVE_PATH TEST_RELATIVE_LIBEXEC_PATH "/${RELATIVE_TEST_PATH}" "/${IDE_LIBEXEC_PATH}")
|
||||||
|
|
||||||
add_qtc_test(unittest GTEST
|
add_qtc_test(unittest GTEST
|
||||||
INCLUDES
|
INCLUDES
|
||||||
BEFORE "../mockup"
|
BEFORE "../mockup"
|
||||||
@@ -40,6 +43,7 @@ add_qtc_test(unittest GTEST
|
|||||||
QTC_RESOURCE_DIR="${CMAKE_CURRENT_LIST_DIR}/../../../share/qtcreator"
|
QTC_RESOURCE_DIR="${CMAKE_CURRENT_LIST_DIR}/../../../share/qtcreator"
|
||||||
TESTDATA_DIR="${CMAKE_CURRENT_BINARY_DIR}/data"
|
TESTDATA_DIR="${CMAKE_CURRENT_BINARY_DIR}/data"
|
||||||
ECHOSERVER="$<TARGET_FILE_DIR:echo>/echo"
|
ECHOSERVER="$<TARGET_FILE_DIR:echo>/echo"
|
||||||
|
TEST_RELATIVE_LIBEXEC_PATH="${TEST_RELATIVE_LIBEXEC_PATH}"
|
||||||
SOURCES
|
SOURCES
|
||||||
abstractviewmock.h
|
abstractviewmock.h
|
||||||
clientserverinprocess-test.cpp
|
clientserverinprocess-test.cpp
|
||||||
|
@@ -56,6 +56,10 @@ QMAKE_LFLAGS += /INCREMENTAL
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_RELATIVE_LIBEXEC_PATH = $$relative_path($$IDE_LIBEXEC_PATH, $$OUT_PWD)
|
||||||
|
win32:TEST_RELATIVE_LIBEXEC_PATH=../$$TEST_RELATIVE_LIBEXEC_PATH
|
||||||
|
DEFINES += 'TEST_RELATIVE_LIBEXEC_PATH="\\\"$$TEST_RELATIVE_LIBEXEC_PATH\\\""'
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
clientserverinprocess-test.cpp \
|
clientserverinprocess-test.cpp \
|
||||||
clientserveroutsideprocess-test.cpp \
|
clientserveroutsideprocess-test.cpp \
|
||||||
|
@@ -98,6 +98,10 @@ Project {
|
|||||||
if (libclang.present) {
|
if (libclang.present) {
|
||||||
defines.push("CLANG_UNIT_TESTS");
|
defines.push("CLANG_UNIT_TESTS");
|
||||||
}
|
}
|
||||||
|
var absLibExecPath = FileInfo.joinPaths(qbs.installRoot, qbs.installPrefix,
|
||||||
|
qtc.ide_libexec_path);
|
||||||
|
var relLibExecPath = FileInfo.relativePath(destinationDirectory, absLibExecPath);
|
||||||
|
defines.push('TEST_RELATIVE_LIBEXEC_PATH="' + relLibExecPath + '"');
|
||||||
return defines;
|
return defines;
|
||||||
}
|
}
|
||||||
cpp.cxxFlags: {
|
cpp.cxxFlags: {
|
||||||
|
@@ -29,10 +29,12 @@
|
|||||||
#include <sqlitelibraryinitializer.h>
|
#include <sqlitelibraryinitializer.h>
|
||||||
|
|
||||||
#include <sqliteglobal.h>
|
#include <sqliteglobal.h>
|
||||||
|
#include <utils/launcherinterface.h>
|
||||||
#include <utils/temporarydirectory.h>
|
#include <utils/temporarydirectory.h>
|
||||||
|
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
|
#include <QScopeGuard>
|
||||||
|
|
||||||
#ifdef WITH_BENCHMARKS
|
#ifdef WITH_BENCHMARKS
|
||||||
#include <benchmark/benchmark.h>
|
#include <benchmark/benchmark.h>
|
||||||
@@ -58,7 +60,9 @@ int main(int argc, char *argv[])
|
|||||||
Sqlite::Database::activateLogging();
|
Sqlite::Database::activateLogging();
|
||||||
|
|
||||||
QGuiApplication application(argc, argv);
|
QGuiApplication application(argc, argv);
|
||||||
|
Utils::LauncherInterface::startLauncher(qApp->applicationDirPath() + '/'
|
||||||
|
+ QLatin1String(TEST_RELATIVE_LIBEXEC_PATH));
|
||||||
|
auto cleanup = qScopeGuard([] { Utils::LauncherInterface::stopLauncher(); });
|
||||||
testing::InitGoogleTest(&argc, argv);
|
testing::InitGoogleTest(&argc, argv);
|
||||||
#ifdef WITH_BENCHMARKS
|
#ifdef WITH_BENCHMARKS
|
||||||
benchmark::Initialize(&argc, argv);
|
benchmark::Initialize(&argc, argv);
|
||||||
|
Reference in New Issue
Block a user