forked from qt-creator/qt-creator
CMake: Parse cmake errors during project setup
Do warn on errors during initial cmake run. Change-Id: I520fdb8b83b9228ea71dcce050d1cab4c3e4f81a Reviewed-by: Tim Jenssen <tim.jenssen@theqtcompany.com>
This commit is contained in:
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include "builddirmanager.h"
|
#include "builddirmanager.h"
|
||||||
#include "cmakekitinformation.h"
|
#include "cmakekitinformation.h"
|
||||||
|
#include "cmakeparser.h"
|
||||||
#include "cmakeprojectmanager.h"
|
#include "cmakeprojectmanager.h"
|
||||||
#include "cmaketool.h"
|
#include "cmaketool.h"
|
||||||
|
|
||||||
@@ -237,23 +238,38 @@ void BuildDirManager::startCMake(CMakeTool *tool, const QString &generator,
|
|||||||
{
|
{
|
||||||
QTC_ASSERT(tool && tool->isValid(), return);
|
QTC_ASSERT(tool && tool->isValid(), return);
|
||||||
QTC_ASSERT(!m_cmakeProcess, return);
|
QTC_ASSERT(!m_cmakeProcess, return);
|
||||||
|
QTC_ASSERT(!m_parser, return);
|
||||||
|
|
||||||
// Make sure m_buildDir exists:
|
// Make sure m_buildDir exists:
|
||||||
const QString buildDirStr = m_buildDir.toString();
|
const QString buildDirStr = m_buildDir.toString();
|
||||||
QDir bDir = QDir(buildDirStr);
|
QDir bDir = QDir(buildDirStr);
|
||||||
bDir.mkpath(buildDirStr);
|
bDir.mkpath(buildDirStr);
|
||||||
|
|
||||||
|
m_parser = new CMakeParser;
|
||||||
|
QDir source = QDir(m_sourceDir.toString());
|
||||||
|
connect(m_parser, &ProjectExplorer::IOutputParser::addTask, m_parser,
|
||||||
|
[source](const ProjectExplorer::Task &task) {
|
||||||
|
if (task.file.isEmpty() || task.file.toFileInfo().isAbsolute()) {
|
||||||
|
ProjectExplorer::TaskHub::addTask(task);
|
||||||
|
} else {
|
||||||
|
ProjectExplorer::Task t = task;
|
||||||
|
t.file = Utils::FileName::fromString(source.absoluteFilePath(task.file.toString()));
|
||||||
|
ProjectExplorer::TaskHub::addTask(t);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Always use the sourceDir: If we are triggered because the build directory is getting deleted
|
// Always use the sourceDir: If we are triggered because the build directory is getting deleted
|
||||||
// then we are racing against CMakeCache.txt also getting deleted.
|
// then we are racing against CMakeCache.txt also getting deleted.
|
||||||
const QString srcDir = m_sourceDir.toString();
|
const QString srcDir = m_sourceDir.toString();
|
||||||
|
|
||||||
m_cmakeProcess = new Utils::QtcProcess(this);
|
m_cmakeProcess = new Utils::QtcProcess(this);
|
||||||
m_cmakeProcess->setProcessChannelMode(QProcess::MergedChannels);
|
|
||||||
m_cmakeProcess->setWorkingDirectory(buildDirStr);
|
m_cmakeProcess->setWorkingDirectory(buildDirStr);
|
||||||
m_cmakeProcess->setEnvironment(m_environment);
|
m_cmakeProcess->setEnvironment(m_environment);
|
||||||
|
|
||||||
connect(m_cmakeProcess, &QProcess::readyReadStandardOutput,
|
connect(m_cmakeProcess, &QProcess::readyReadStandardOutput,
|
||||||
this, &BuildDirManager::processCMakeOutput);
|
this, &BuildDirManager::processCMakeOutput);
|
||||||
|
connect(m_cmakeProcess, &QProcess::readyReadStandardError,
|
||||||
|
this, &BuildDirManager::processCMakeError);
|
||||||
connect(m_cmakeProcess, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
|
connect(m_cmakeProcess, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
|
||||||
this, &BuildDirManager::cmakeFinished);
|
this, &BuildDirManager::cmakeFinished);
|
||||||
|
|
||||||
@@ -263,9 +279,7 @@ void BuildDirManager::startCMake(CMakeTool *tool, const QString &generator,
|
|||||||
Utils::QtcProcess::addArg(&args, QString::fromLatin1("-G%1").arg(generator));
|
Utils::QtcProcess::addArg(&args, QString::fromLatin1("-G%1").arg(generator));
|
||||||
Utils::QtcProcess::addArgs(&args, toArguments(config));
|
Utils::QtcProcess::addArgs(&args, toArguments(config));
|
||||||
|
|
||||||
// Clear task cache:
|
|
||||||
ProjectExplorer::TaskHub::clearTasks(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM);
|
ProjectExplorer::TaskHub::clearTasks(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM);
|
||||||
m_toReport.clear();
|
|
||||||
|
|
||||||
m_cmakeProcess->setCommand(tool->cmakeExecutable().toString(), args);
|
m_cmakeProcess->setCommand(tool->cmakeExecutable().toString(), args);
|
||||||
m_cmakeProcess->start();
|
m_cmakeProcess->start();
|
||||||
@@ -277,55 +291,59 @@ void BuildDirManager::cmakeFinished(int code, QProcess::ExitStatus status)
|
|||||||
QTC_ASSERT(m_cmakeProcess, return);
|
QTC_ASSERT(m_cmakeProcess, return);
|
||||||
|
|
||||||
// process rest of the output:
|
// process rest of the output:
|
||||||
while (m_cmakeProcess->canReadLine())
|
processCMakeOutput();
|
||||||
processOutputLine(Utils::SynchronousProcess::normalizeNewlines(QString::fromLocal8Bit(m_cmakeProcess->readLine())));
|
processCMakeError();
|
||||||
QString rest = Utils::SynchronousProcess::normalizeNewlines(QString::fromLocal8Bit(m_cmakeProcess->readAllStandardOutput()));
|
|
||||||
if (!rest.isEmpty())
|
|
||||||
processOutputLine(rest);
|
|
||||||
|
|
||||||
QTC_CHECK(m_cmakeProcess->readAllStandardOutput().isEmpty());
|
m_parser->flush();
|
||||||
|
delete m_parser;
|
||||||
if (!m_toReport.description.isEmpty())
|
m_parser = nullptr;
|
||||||
ProjectExplorer::TaskHub::addTask(m_toReport);
|
|
||||||
m_toReport.clear();
|
|
||||||
|
|
||||||
m_cmakeProcess->deleteLater();
|
m_cmakeProcess->deleteLater();
|
||||||
m_cmakeProcess = nullptr;
|
m_cmakeProcess = nullptr;
|
||||||
|
|
||||||
extractData(); // try even if cmake failed...
|
extractData(); // try even if cmake failed...
|
||||||
|
|
||||||
|
QString msg;
|
||||||
if (status != QProcess::NormalExit)
|
if (status != QProcess::NormalExit)
|
||||||
Core::MessageManager::write(tr("*** cmake process crashed!"));
|
msg = tr("*** cmake process crashed!");
|
||||||
else if (code != 0)
|
else if (code != 0)
|
||||||
Core::MessageManager::write(tr("*** cmake process exited with exit code %s.").arg(code));
|
msg = tr("*** cmake process exited with exit code %1.").arg(code);
|
||||||
|
|
||||||
|
if (!msg.isEmpty()) {
|
||||||
|
Core::MessageManager::write(msg);
|
||||||
|
ProjectExplorer::TaskHub::addTask(ProjectExplorer::Task::Error, msg,
|
||||||
|
ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM);
|
||||||
|
}
|
||||||
|
|
||||||
emit dataAvailable();
|
emit dataAvailable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QString lineSplit(const QString &rest, const QByteArray &array, std::function<void(const QString &)> f)
|
||||||
|
{
|
||||||
|
QString tmp = rest + Utils::SynchronousProcess::normalizeNewlines(QString::fromLocal8Bit(array));
|
||||||
|
int start = 0;
|
||||||
|
int end = tmp.indexOf(QLatin1Char('\n'), start);
|
||||||
|
while (end >= 0) {
|
||||||
|
f(tmp.mid(start, end - start));
|
||||||
|
start = end + 1;
|
||||||
|
end = tmp.indexOf(QLatin1Char('\n'), start);
|
||||||
|
}
|
||||||
|
return tmp.mid(start);
|
||||||
|
}
|
||||||
|
|
||||||
void BuildDirManager::processCMakeOutput()
|
void BuildDirManager::processCMakeOutput()
|
||||||
{
|
{
|
||||||
QTC_ASSERT(m_cmakeProcess, return);
|
static QString rest;
|
||||||
while (m_cmakeProcess->canReadLine())
|
rest = lineSplit(rest, m_cmakeProcess->readAllStandardOutput(), [this](const QString &s) { Core::MessageManager::write(s); });
|
||||||
processOutputLine(QString::fromLocal8Bit(m_cmakeProcess->readLine()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BuildDirManager::processOutputLine(const QString &l)
|
void BuildDirManager::processCMakeError()
|
||||||
{
|
{
|
||||||
QString line = Utils::SynchronousProcess::normalizeNewlines(l);
|
static QString rest;
|
||||||
while (line.endsWith(QLatin1Char('\n')))
|
rest = lineSplit(rest, m_cmakeProcess->readAllStandardError(), [this](const QString &s) {
|
||||||
line.chop(1);
|
m_parser->stdError(s);
|
||||||
Core::MessageManager::write(line);
|
Core::MessageManager::write(s);
|
||||||
|
});
|
||||||
// Check for errors:
|
|
||||||
if (m_toReport.type == ProjectExplorer::Task::Unknown) {
|
|
||||||
m_toReport.category = ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM;
|
|
||||||
} else {
|
|
||||||
if (line.startsWith(QStringLiteral(" ")) || line.isEmpty()) {
|
|
||||||
m_toReport.description.append(QStringLiteral("\n") + line);
|
|
||||||
} else {
|
|
||||||
ProjectExplorer::TaskHub::addTask(m_toReport);
|
|
||||||
m_toReport.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
|||||||
@@ -44,7 +44,9 @@ QT_FORWARD_DECLARE_CLASS(QFileSystemWatcher);
|
|||||||
|
|
||||||
namespace ProjectExplorer {
|
namespace ProjectExplorer {
|
||||||
class FileNode;
|
class FileNode;
|
||||||
|
class IOutputParser;
|
||||||
class Kit;
|
class Kit;
|
||||||
|
class Task;
|
||||||
} // namespace ProjectExplorer
|
} // namespace ProjectExplorer
|
||||||
|
|
||||||
namespace CMakeProjectManager {
|
namespace CMakeProjectManager {
|
||||||
@@ -88,8 +90,7 @@ private:
|
|||||||
|
|
||||||
void cmakeFinished(int code, QProcess::ExitStatus status);
|
void cmakeFinished(int code, QProcess::ExitStatus status);
|
||||||
void processCMakeOutput();
|
void processCMakeOutput();
|
||||||
|
void processCMakeError();
|
||||||
void processOutputLine(const QString &line);
|
|
||||||
|
|
||||||
const Utils::FileName m_sourceDir;
|
const Utils::FileName m_sourceDir;
|
||||||
Utils::FileName m_buildDir;
|
Utils::FileName m_buildDir;
|
||||||
@@ -107,7 +108,7 @@ private:
|
|||||||
QList<ProjectExplorer::FileNode *> m_files;
|
QList<ProjectExplorer::FileNode *> m_files;
|
||||||
|
|
||||||
// For error reporting:
|
// For error reporting:
|
||||||
ProjectExplorer::Task m_toReport;
|
ProjectExplorer::IOutputParser *m_parser = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
|||||||
Reference in New Issue
Block a user