forked from qt-creator/qt-creator
Use QtcProcess for running extra compilers
Change-Id: I924acb2f303ba97c864a4503ad4681454c844303 Reviewed-by: Eike Ziller <eike.ziller@qt.io>
This commit is contained in:
@@ -39,6 +39,7 @@
|
|||||||
#include <texteditor/fontsettings.h>
|
#include <texteditor/fontsettings.h>
|
||||||
|
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
#include <utils/qtcprocess.h>
|
||||||
#include <utils/runextensions.h>
|
#include <utils/runextensions.h>
|
||||||
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
@@ -49,6 +50,8 @@
|
|||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QTextBlock>
|
#include <QTextBlock>
|
||||||
|
|
||||||
|
using namespace Utils;
|
||||||
|
|
||||||
namespace ProjectExplorer {
|
namespace ProjectExplorer {
|
||||||
|
|
||||||
Q_GLOBAL_STATIC(QThreadPool, s_extraCompilerThreadPool);
|
Q_GLOBAL_STATIC(QThreadPool, s_extraCompilerThreadPool);
|
||||||
@@ -58,7 +61,7 @@ class ExtraCompilerPrivate
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
const Project *project;
|
const Project *project;
|
||||||
Utils::FilePath source;
|
FilePath source;
|
||||||
FileNameToContentsHash contents;
|
FileNameToContentsHash contents;
|
||||||
Tasks issues;
|
Tasks issues;
|
||||||
QDateTime compileTime;
|
QDateTime compileTime;
|
||||||
@@ -71,13 +74,13 @@ public:
|
|||||||
void updateIssues();
|
void updateIssues();
|
||||||
};
|
};
|
||||||
|
|
||||||
ExtraCompiler::ExtraCompiler(const Project *project, const Utils::FilePath &source,
|
ExtraCompiler::ExtraCompiler(const Project *project, const FilePath &source,
|
||||||
const Utils::FilePaths &targets, QObject *parent) :
|
const FilePaths &targets, QObject *parent) :
|
||||||
QObject(parent), d(std::make_unique<ExtraCompilerPrivate>())
|
QObject(parent), d(std::make_unique<ExtraCompilerPrivate>())
|
||||||
{
|
{
|
||||||
d->project = project;
|
d->project = project;
|
||||||
d->source = source;
|
d->source = source;
|
||||||
foreach (const Utils::FilePath &target, targets)
|
for (const FilePath &target : targets)
|
||||||
d->contents.insert(target, QByteArray());
|
d->contents.insert(target, QByteArray());
|
||||||
d->timer.setSingleShot(true);
|
d->timer.setSingleShot(true);
|
||||||
|
|
||||||
@@ -105,7 +108,7 @@ ExtraCompiler::ExtraCompiler(const Project *project, const Utils::FilePath &sour
|
|||||||
|
|
||||||
// Use existing target files, where possible. Otherwise run the compiler.
|
// Use existing target files, where possible. Otherwise run the compiler.
|
||||||
QDateTime sourceTime = d->source.lastModified();
|
QDateTime sourceTime = d->source.lastModified();
|
||||||
foreach (const Utils::FilePath &target, targets) {
|
for (const FilePath &target : targets) {
|
||||||
QFileInfo targetFileInfo(target.toFileInfo());
|
QFileInfo targetFileInfo(target.toFileInfo());
|
||||||
if (!targetFileInfo.exists()) {
|
if (!targetFileInfo.exists()) {
|
||||||
d->dirty = true;
|
d->dirty = true;
|
||||||
@@ -132,22 +135,22 @@ const Project *ExtraCompiler::project() const
|
|||||||
return d->project;
|
return d->project;
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils::FilePath ExtraCompiler::source() const
|
FilePath ExtraCompiler::source() const
|
||||||
{
|
{
|
||||||
return d->source;
|
return d->source;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray ExtraCompiler::content(const Utils::FilePath &file) const
|
QByteArray ExtraCompiler::content(const FilePath &file) const
|
||||||
{
|
{
|
||||||
return d->contents.value(file);
|
return d->contents.value(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils::FilePaths ExtraCompiler::targets() const
|
FilePaths ExtraCompiler::targets() const
|
||||||
{
|
{
|
||||||
return d->contents.keys();
|
return d->contents.keys();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExtraCompiler::forEachTarget(std::function<void (const Utils::FilePath &)> func)
|
void ExtraCompiler::forEachTarget(std::function<void (const FilePath &)> func)
|
||||||
{
|
{
|
||||||
for (auto it = d->contents.constBegin(), end = d->contents.constEnd(); it != end; ++it)
|
for (auto it = d->contents.constBegin(), end = d->contents.constEnd(); it != end; ++it)
|
||||||
func(it.key());
|
func(it.key());
|
||||||
@@ -184,7 +187,7 @@ void ExtraCompiler::onTargetsBuilt(Project *project)
|
|||||||
if (d->compileTime.isValid() && d->compileTime >= sourceTime)
|
if (d->compileTime.isValid() && d->compileTime >= sourceTime)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
forEachTarget([&](const Utils::FilePath &target) {
|
forEachTarget([&](const FilePath &target) {
|
||||||
QFileInfo fi(target.toFileInfo());
|
QFileInfo fi(target.toFileInfo());
|
||||||
QDateTime generateTime = fi.exists() ? fi.lastModified() : QDateTime();
|
QDateTime generateTime = fi.exists() ? fi.lastModified() : QDateTime();
|
||||||
if (generateTime.isValid() && (generateTime > sourceTime)) {
|
if (generateTime.isValid() && (generateTime > sourceTime)) {
|
||||||
@@ -249,21 +252,21 @@ void ExtraCompiler::onEditorAboutToClose(Core::IEditor *editor)
|
|||||||
d->lastEditor = nullptr;
|
d->lastEditor = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils::Environment ExtraCompiler::buildEnvironment() const
|
Environment ExtraCompiler::buildEnvironment() const
|
||||||
{
|
{
|
||||||
if (Target *target = project()->activeTarget()) {
|
if (Target *target = project()->activeTarget()) {
|
||||||
if (BuildConfiguration *bc = target->activeBuildConfiguration()) {
|
if (BuildConfiguration *bc = target->activeBuildConfiguration()) {
|
||||||
return bc->environment();
|
return bc->environment();
|
||||||
} else {
|
} else {
|
||||||
Utils::EnvironmentItems changes =
|
EnvironmentItems changes =
|
||||||
EnvironmentKitAspect::environmentChanges(target->kit());
|
EnvironmentKitAspect::environmentChanges(target->kit());
|
||||||
Utils::Environment env = Utils::Environment::systemEnvironment();
|
Environment env = Environment::systemEnvironment();
|
||||||
env.modify(changes);
|
env.modify(changes);
|
||||||
return env;
|
return env;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Utils::Environment::systemEnvironment();
|
return Environment::systemEnvironment();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExtraCompiler::setCompileIssues(const Tasks &issues)
|
void ExtraCompiler::setCompileIssues(const Tasks &issues)
|
||||||
@@ -283,7 +286,7 @@ void ExtraCompilerPrivate::updateIssues()
|
|||||||
|
|
||||||
QList<QTextEdit::ExtraSelection> selections;
|
QList<QTextEdit::ExtraSelection> selections;
|
||||||
const QTextDocument *document = widget->document();
|
const QTextDocument *document = widget->document();
|
||||||
foreach (const Task &issue, issues) {
|
for (const Task &issue : qAsConst(issues)) {
|
||||||
QTextEdit::ExtraSelection selection;
|
QTextEdit::ExtraSelection selection;
|
||||||
QTextCursor cursor(document->findBlockByNumber(issue.line - 1));
|
QTextCursor cursor(document->findBlockByNumber(issue.line - 1));
|
||||||
cursor.movePosition(QTextCursor::StartOfLine);
|
cursor.movePosition(QTextCursor::StartOfLine);
|
||||||
@@ -300,7 +303,7 @@ void ExtraCompilerPrivate::updateIssues()
|
|||||||
widget->setExtraSelections(TextEditor::TextEditorWidget::CodeWarningsSelection, selections);
|
widget->setExtraSelections(TextEditor::TextEditorWidget::CodeWarningsSelection, selections);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExtraCompiler::setContent(const Utils::FilePath &file, const QByteArray &contents)
|
void ExtraCompiler::setContent(const FilePath &file, const QByteArray &contents)
|
||||||
{
|
{
|
||||||
auto it = d->contents.find(file);
|
auto it = d->contents.find(file);
|
||||||
if (it != d->contents.end()) {
|
if (it != d->contents.end()) {
|
||||||
@@ -327,8 +330,8 @@ QList<ExtraCompilerFactory *> ExtraCompilerFactory::extraCompilerFactories()
|
|||||||
return *factories();
|
return *factories();
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessExtraCompiler::ProcessExtraCompiler(const Project *project, const Utils::FilePath &source,
|
ProcessExtraCompiler::ProcessExtraCompiler(const Project *project, const FilePath &source,
|
||||||
const Utils::FilePaths &targets, QObject *parent) :
|
const FilePaths &targets, QObject *parent) :
|
||||||
ExtraCompiler(project, source, targets, parent)
|
ExtraCompiler(project, source, targets, parent)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
@@ -348,7 +351,7 @@ void ProcessExtraCompiler::run(const QByteArray &sourceContents)
|
|||||||
|
|
||||||
QFuture<FileNameToContentsHash> ProcessExtraCompiler::run()
|
QFuture<FileNameToContentsHash> ProcessExtraCompiler::run()
|
||||||
{
|
{
|
||||||
const Utils::FilePath fileName = source();
|
const FilePath fileName = source();
|
||||||
ContentProvider contents = [fileName]() {
|
ContentProvider contents = [fileName]() {
|
||||||
QFile file(fileName.toString());
|
QFile file(fileName.toString());
|
||||||
if (!file.open(QFile::ReadOnly | QFile::Text))
|
if (!file.open(QFile::ReadOnly | QFile::Text))
|
||||||
@@ -358,9 +361,9 @@ QFuture<FileNameToContentsHash> ProcessExtraCompiler::run()
|
|||||||
return runImpl(contents);
|
return runImpl(contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils::FilePath ProcessExtraCompiler::workingDirectory() const
|
FilePath ProcessExtraCompiler::workingDirectory() const
|
||||||
{
|
{
|
||||||
return Utils::FilePath();
|
return FilePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList ProcessExtraCompiler::arguments() const
|
QStringList ProcessExtraCompiler::arguments() const
|
||||||
@@ -389,7 +392,7 @@ QFuture<FileNameToContentsHash> ProcessExtraCompiler::runImpl(const ContentProvi
|
|||||||
connect(m_watcher, &QFutureWatcher<FileNameToContentsHash>::finished,
|
connect(m_watcher, &QFutureWatcher<FileNameToContentsHash>::finished,
|
||||||
this, &ProcessExtraCompiler::cleanUp);
|
this, &ProcessExtraCompiler::cleanUp);
|
||||||
|
|
||||||
m_watcher->setFuture(Utils::runAsync(extraCompilerThreadPool(),
|
m_watcher->setFuture(runAsync(extraCompilerThreadPool(),
|
||||||
&ProcessExtraCompiler::runInThread, this,
|
&ProcessExtraCompiler::runInThread, this,
|
||||||
command(), workingDirectory(), arguments(), provider,
|
command(), workingDirectory(), arguments(), provider,
|
||||||
buildEnvironment()));
|
buildEnvironment()));
|
||||||
@@ -398,9 +401,9 @@ QFuture<FileNameToContentsHash> ProcessExtraCompiler::runImpl(const ContentProvi
|
|||||||
|
|
||||||
void ProcessExtraCompiler::runInThread(
|
void ProcessExtraCompiler::runInThread(
|
||||||
QFutureInterface<FileNameToContentsHash> &futureInterface,
|
QFutureInterface<FileNameToContentsHash> &futureInterface,
|
||||||
const Utils::FilePath &cmd, const Utils::FilePath &workDir,
|
const FilePath &cmd, const FilePath &workDir,
|
||||||
const QStringList &args, const ContentProvider &provider,
|
const QStringList &args, const ContentProvider &provider,
|
||||||
const Utils::Environment &env)
|
const Environment &env)
|
||||||
{
|
{
|
||||||
if (cmd.isEmpty() || !cmd.toFileInfo().isExecutable())
|
if (cmd.isEmpty() || !cmd.toFileInfo().isExecutable())
|
||||||
return;
|
return;
|
||||||
@@ -409,29 +412,22 @@ void ProcessExtraCompiler::runInThread(
|
|||||||
if (sourceContents.isNull() || !prepareToRun(sourceContents))
|
if (sourceContents.isNull() || !prepareToRun(sourceContents))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QProcess process;
|
QtcProcess process;
|
||||||
|
|
||||||
process.setProcessEnvironment(env.toProcessEnvironment());
|
process.setEnvironment(env);
|
||||||
if (!workDir.isEmpty())
|
if (!workDir.isEmpty())
|
||||||
process.setWorkingDirectory(workDir.toString());
|
process.setWorkingDirectory(workDir.toString());
|
||||||
process.start(cmd.toString(), args, QIODevice::ReadWrite);
|
process.setCommand({ cmd, args });
|
||||||
if (!process.waitForStarted()) {
|
process.setWriteData(sourceContents);
|
||||||
handleProcessError(&process);
|
process.start();
|
||||||
|
if (!process.waitForStarted())
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
bool isCanceled = futureInterface.isCanceled();
|
|
||||||
if (!isCanceled) {
|
|
||||||
handleProcessStarted(&process, sourceContents);
|
|
||||||
forever {
|
|
||||||
bool done = process.waitForFinished(200);
|
|
||||||
isCanceled = futureInterface.isCanceled();
|
|
||||||
if (done || isCanceled)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
isCanceled |= process.state() == QProcess::Running;
|
while (!futureInterface.isCanceled())
|
||||||
if (isCanceled) {
|
if (process.waitForFinished(200))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (futureInterface.isCanceled()) {
|
||||||
process.kill();
|
process.kill();
|
||||||
process.waitForFinished();
|
process.waitForFinished();
|
||||||
return;
|
return;
|
||||||
|
@@ -40,7 +40,6 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
QT_FORWARD_DECLARE_CLASS(QProcess);
|
|
||||||
QT_FORWARD_DECLARE_CLASS(QThreadPool);
|
QT_FORWARD_DECLARE_CLASS(QThreadPool);
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@@ -49,6 +48,7 @@ template <typename T>
|
|||||||
class QFutureWatcher;
|
class QFutureWatcher;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
namespace Utils { class QtcProcess; }
|
||||||
|
|
||||||
namespace ProjectExplorer {
|
namespace ProjectExplorer {
|
||||||
|
|
||||||
@@ -126,10 +126,7 @@ protected:
|
|||||||
|
|
||||||
virtual bool prepareToRun(const QByteArray &sourceContents);
|
virtual bool prepareToRun(const QByteArray &sourceContents);
|
||||||
|
|
||||||
virtual void handleProcessError(QProcess *process) { Q_UNUSED(process) }
|
virtual FileNameToContentsHash handleProcessFinished(Utils::QtcProcess *process) = 0;
|
||||||
virtual void handleProcessStarted(QProcess *process, const QByteArray &sourceContents)
|
|
||||||
{ Q_UNUSED(process); Q_UNUSED(sourceContents) }
|
|
||||||
virtual FileNameToContentsHash handleProcessFinished(QProcess *process) = 0;
|
|
||||||
|
|
||||||
virtual Tasks parseIssues(const QByteArray &stdErr);
|
virtual Tasks parseIssues(const QByteArray &stdErr);
|
||||||
|
|
||||||
|
@@ -112,7 +112,7 @@ bool QScxmlcGenerator::prepareToRun(const QByteArray &sourceContents)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileNameToContentsHash QScxmlcGenerator::handleProcessFinished(QProcess *process)
|
FileNameToContentsHash QScxmlcGenerator::handleProcessFinished(Utils::QtcProcess *process)
|
||||||
{
|
{
|
||||||
Q_UNUSED(process)
|
Q_UNUSED(process)
|
||||||
const Utils::FilePath wd = workingDirectory();
|
const Utils::FilePath wd = workingDirectory();
|
||||||
|
@@ -47,7 +47,7 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Utils::FilePath tmpFile() const;
|
Utils::FilePath tmpFile() const;
|
||||||
ProjectExplorer::FileNameToContentsHash handleProcessFinished(QProcess *process) override;
|
ProjectExplorer::FileNameToContentsHash handleProcessFinished(Utils::QtcProcess *process) override;
|
||||||
bool prepareToRun(const QByteArray &sourceContents) override;
|
bool prepareToRun(const QByteArray &sourceContents) override;
|
||||||
ProjectExplorer::Tasks parseIssues(const QByteArray &processStderr) override;
|
ProjectExplorer::Tasks parseIssues(const QByteArray &processStderr) override;
|
||||||
|
|
||||||
|
@@ -32,11 +32,11 @@
|
|||||||
#include <projectexplorer/buildconfiguration.h>
|
#include <projectexplorer/buildconfiguration.h>
|
||||||
|
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
#include <utils/qtcprocess.h>
|
||||||
|
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
#include <QProcess>
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
|
||||||
using namespace ProjectExplorer;
|
using namespace ProjectExplorer;
|
||||||
@@ -70,7 +70,7 @@ QStringList UicGenerator::arguments() const
|
|||||||
return {"-p"};
|
return {"-p"};
|
||||||
}
|
}
|
||||||
|
|
||||||
FileNameToContentsHash UicGenerator::handleProcessFinished(QProcess *process)
|
FileNameToContentsHash UicGenerator::handleProcessFinished(Utils::QtcProcess *process)
|
||||||
{
|
{
|
||||||
FileNameToContentsHash result;
|
FileNameToContentsHash result;
|
||||||
if (process->exitStatus() != QProcess::NormalExit && process->exitCode() != 0)
|
if (process->exitStatus() != QProcess::NormalExit && process->exitCode() != 0)
|
||||||
@@ -87,12 +87,6 @@ FileNameToContentsHash UicGenerator::handleProcessFinished(QProcess *process)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UicGenerator::handleProcessStarted(QProcess *process, const QByteArray &sourceContents)
|
|
||||||
{
|
|
||||||
process->write(sourceContents);
|
|
||||||
process->closeWriteChannel();
|
|
||||||
}
|
|
||||||
|
|
||||||
FileType UicGeneratorFactory::sourceType() const
|
FileType UicGeneratorFactory::sourceType() const
|
||||||
{
|
{
|
||||||
return FileType::Form;
|
return FileType::Form;
|
||||||
|
@@ -42,8 +42,7 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
Utils::FilePath command() const override;
|
Utils::FilePath command() const override;
|
||||||
QStringList arguments() const override;
|
QStringList arguments() const override;
|
||||||
ProjectExplorer::FileNameToContentsHash handleProcessFinished(QProcess *process) override;
|
ProjectExplorer::FileNameToContentsHash handleProcessFinished(Utils::QtcProcess *process) override;
|
||||||
void handleProcessStarted(QProcess *process, const QByteArray &sourceContents) override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class UicGeneratorFactory : public ProjectExplorer::ExtraCompilerFactory
|
class UicGeneratorFactory : public ProjectExplorer::ExtraCompilerFactory
|
||||||
|
Reference in New Issue
Block a user