forked from qt-creator/qt-creator
Make gnumake parser less noisy
* Do not report make warnings at all. * Do only report the first make error. * Do not report any make errors after a compile error. * Handle more variants of mingw makes * Actually parse stderr for errors
This commit is contained in:
@@ -38,16 +38,17 @@
|
|||||||
using namespace ProjectExplorer;
|
using namespace ProjectExplorer;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
const char * const MAKE_PATTERN("^(mingw(32|64)-|g)?make(\\[\\d+\\])?:\\s");
|
// optional full path, make executable name, optional exe extention, optional number in square brackets, colon space
|
||||||
|
const char * const MAKE_PATTERN("^(([A-Za-z]:)?[/\\\\][^:]*[/\\\\])?(mingw(32|64)-|g)?make(.exe)?(\\[\\d+\\])?:\\s");
|
||||||
}
|
}
|
||||||
|
|
||||||
GnuMakeParser::GnuMakeParser(const QString &dir) :
|
GnuMakeParser::GnuMakeParser(const QString &dir) :
|
||||||
m_alreadyFatal(false)
|
m_suppressIssues(false)
|
||||||
{
|
{
|
||||||
m_makeDir.setPattern(QLatin1String(MAKE_PATTERN) +
|
m_makeDir.setPattern(QLatin1String(MAKE_PATTERN) +
|
||||||
QLatin1String("(\\w+) directory .(.+).$"));
|
QLatin1String("(\\w+) directory .(.+).$"));
|
||||||
m_makeDir.setMinimal(true);
|
m_makeDir.setMinimal(true);
|
||||||
m_makeLine.setPattern(QLatin1String(MAKE_PATTERN) + QLatin1String("(.*)$"));
|
m_makeLine.setPattern(QLatin1String(MAKE_PATTERN) + QLatin1String("\\*\\*\\*\\s(.*)$"));
|
||||||
m_makeLine.setMinimal(true);
|
m_makeLine.setMinimal(true);
|
||||||
m_makefileError.setPattern(QLatin1String("^(.*):(\\d+):\\s\\*\\*\\*\\s(.*)$"));
|
m_makefileError.setPattern(QLatin1String("^(.*):(\\d+):\\s\\*\\*\\*\\s(.*)$"));
|
||||||
m_makefileError.setMinimal(true);
|
m_makefileError.setMinimal(true);
|
||||||
@@ -59,36 +60,23 @@ void GnuMakeParser::stdOutput(const QString &line)
|
|||||||
QString lne = line.trimmed();
|
QString lne = line.trimmed();
|
||||||
|
|
||||||
if (m_makeDir.indexIn(lne) > -1) {
|
if (m_makeDir.indexIn(lne) > -1) {
|
||||||
if (m_makeDir.cap(4) == "Leaving")
|
if (m_makeDir.cap(7) == "Leaving")
|
||||||
removeDirectory(m_makeDir.cap(5));
|
removeDirectory(m_makeDir.cap(8));
|
||||||
else
|
else
|
||||||
addDirectory(m_makeDir.cap(5));
|
addDirectory(m_makeDir.cap(8));
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Only ever report the first fatal message:
|
|
||||||
// Everything else will be follow-up issues.
|
|
||||||
if (m_makeLine.indexIn(lne) > -1) {
|
|
||||||
if (!m_alreadyFatal) {
|
|
||||||
QString message = m_makeLine.cap(4);
|
|
||||||
if (message.startsWith("Nothing to be done for "))
|
|
||||||
return;
|
|
||||||
Task task(Task::Warning,
|
|
||||||
message,
|
|
||||||
QString() /* filename */,
|
|
||||||
-1, /* line */
|
|
||||||
Constants::TASK_CATEGORY_BUILDSYSTEM);
|
|
||||||
if (message.startsWith(QLatin1String("*** "))) {
|
|
||||||
task.description = task.description.mid(4);
|
|
||||||
task.type = Task::Error;
|
|
||||||
m_alreadyFatal = true;
|
|
||||||
}
|
|
||||||
addTask(task);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IOutputParser::stdOutput(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GnuMakeParser::stdError(const QString &line)
|
||||||
|
{
|
||||||
|
QString lne = line.trimmed();
|
||||||
|
|
||||||
if (m_makefileError.indexIn(lne) > -1) {
|
if (m_makefileError.indexIn(lne) > -1) {
|
||||||
if (!m_alreadyFatal) {
|
if (!m_suppressIssues) {
|
||||||
m_alreadyFatal = true;
|
m_suppressIssues = true;
|
||||||
addTask(Task(Task::Error,
|
addTask(Task(Task::Error,
|
||||||
m_makefileError.cap(3),
|
m_makefileError.cap(3),
|
||||||
m_makefileError.cap(1),
|
m_makefileError.cap(1),
|
||||||
@@ -97,8 +85,19 @@ void GnuMakeParser::stdOutput(const QString &line)
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (m_makeLine.indexIn(lne) > -1) {
|
||||||
|
if (!m_suppressIssues) {
|
||||||
|
m_suppressIssues = true;
|
||||||
|
addTask(Task(Task::Error,
|
||||||
|
m_makeLine.cap(7),
|
||||||
|
QString() /* filename */,
|
||||||
|
-1, /* line */
|
||||||
|
Constants::TASK_CATEGORY_BUILDSYSTEM));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
IOutputParser::stdOutput(line);
|
IOutputParser::stdError(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GnuMakeParser::addDirectory(const QString &dir)
|
void GnuMakeParser::addDirectory(const QString &dir)
|
||||||
@@ -116,6 +115,12 @@ void GnuMakeParser::removeDirectory(const QString &dir)
|
|||||||
void GnuMakeParser::taskAdded(const Task &task)
|
void GnuMakeParser::taskAdded(const Task &task)
|
||||||
{
|
{
|
||||||
Task editable(task);
|
Task editable(task);
|
||||||
|
|
||||||
|
if (task.type == Task::Error) {
|
||||||
|
// assume that all make errors will be follow up errors:
|
||||||
|
m_suppressIssues = true;
|
||||||
|
}
|
||||||
|
|
||||||
QString filePath(QDir::cleanPath(task.file.trimmed()));
|
QString filePath(QDir::cleanPath(task.file.trimmed()));
|
||||||
|
|
||||||
if (!filePath.isEmpty() && !QDir::isAbsolutePath(filePath)) {
|
if (!filePath.isEmpty() && !QDir::isAbsolutePath(filePath)) {
|
||||||
@@ -149,7 +154,6 @@ QStringList GnuMakeParser::searchDirectories() const
|
|||||||
#ifdef WITH_TESTS
|
#ifdef WITH_TESTS
|
||||||
# include <QTest>
|
# include <QTest>
|
||||||
|
|
||||||
# include <QtCore/QDebug>
|
|
||||||
# include <QtCore/QUuid>
|
# include <QtCore/QUuid>
|
||||||
|
|
||||||
# include "outputparser_test.h"
|
# include "outputparser_test.h"
|
||||||
@@ -204,7 +208,7 @@ void ProjectExplorerPlugin::testGnuMakeParserParsing_data()
|
|||||||
QTest::newRow("make error")
|
QTest::newRow("make error")
|
||||||
<< QStringList()
|
<< QStringList()
|
||||||
<< QString::fromLatin1("make: *** No rule to make target `hello.c', needed by `hello.o'. Stop.")
|
<< QString::fromLatin1("make: *** No rule to make target `hello.c', needed by `hello.o'. Stop.")
|
||||||
<< OutputParserTester::STDOUT
|
<< OutputParserTester::STDERR
|
||||||
<< QString() << QString()
|
<< QString() << QString()
|
||||||
<< (QList<Task>()
|
<< (QList<Task>()
|
||||||
<< Task(Task::Error,
|
<< Task(Task::Error,
|
||||||
@@ -213,24 +217,12 @@ void ProjectExplorerPlugin::testGnuMakeParserParsing_data()
|
|||||||
Constants::TASK_CATEGORY_BUILDSYSTEM))
|
Constants::TASK_CATEGORY_BUILDSYSTEM))
|
||||||
<< QString()
|
<< QString()
|
||||||
<< QStringList();
|
<< QStringList();
|
||||||
QTest::newRow("make warning")
|
|
||||||
<< QStringList()
|
|
||||||
<< QString::fromLatin1("make: warning: ignoring old commands for target `xxx'")
|
|
||||||
<< OutputParserTester::STDOUT
|
|
||||||
<< QString() << QString()
|
|
||||||
<< (QList<Task>()
|
|
||||||
<< Task(Task::Warning,
|
|
||||||
QString::fromLatin1("warning: ignoring old commands for target `xxx'"),
|
|
||||||
QString(), -1,
|
|
||||||
Constants::TASK_CATEGORY_BUILDSYSTEM))
|
|
||||||
<< QString()
|
|
||||||
<< QStringList();
|
|
||||||
QTest::newRow("multiple fatals")
|
QTest::newRow("multiple fatals")
|
||||||
<< QStringList()
|
<< QStringList()
|
||||||
<< QString::fromLatin1("make[3]: *** [.obj/debug-shared/gnumakeparser.o] Error 1\n"
|
<< QString::fromLatin1("make[3]: *** [.obj/debug-shared/gnumakeparser.o] Error 1\n"
|
||||||
"make[3]: *** Waiting for unfinished jobs....\n"
|
"make[3]: *** Waiting for unfinished jobs....\n"
|
||||||
"make[2]: *** [sub-projectexplorer-make_default] Error 2")
|
"make[2]: *** [sub-projectexplorer-make_default] Error 2")
|
||||||
<< OutputParserTester::STDOUT
|
<< OutputParserTester::STDERR
|
||||||
<< QString() << QString()
|
<< QString() << QString()
|
||||||
<< (QList<Task>()
|
<< (QList<Task>()
|
||||||
<< Task(Task::Error,
|
<< Task(Task::Error,
|
||||||
@@ -242,7 +234,7 @@ void ProjectExplorerPlugin::testGnuMakeParserParsing_data()
|
|||||||
QTest::newRow("Makefile error")
|
QTest::newRow("Makefile error")
|
||||||
<< QStringList()
|
<< QStringList()
|
||||||
<< QString::fromLatin1("Makefile:360: *** missing separator (did you mean TAB instead of 8 spaces?). Stop.")
|
<< QString::fromLatin1("Makefile:360: *** missing separator (did you mean TAB instead of 8 spaces?). Stop.")
|
||||||
<< OutputParserTester::STDOUT
|
<< OutputParserTester::STDERR
|
||||||
<< QString() << QString()
|
<< QString() << QString()
|
||||||
<< (QList<Task>()
|
<< (QList<Task>()
|
||||||
<< Task(Task::Error,
|
<< Task(Task::Error,
|
||||||
@@ -251,12 +243,49 @@ void ProjectExplorerPlugin::testGnuMakeParserParsing_data()
|
|||||||
Constants::TASK_CATEGORY_BUILDSYSTEM))
|
Constants::TASK_CATEGORY_BUILDSYSTEM))
|
||||||
<< QString()
|
<< QString()
|
||||||
<< QStringList();
|
<< QStringList();
|
||||||
QTest::newRow("Nothing to be done")
|
QTest::newRow("mingw32-make error")
|
||||||
<< QStringList()
|
<< QStringList()
|
||||||
<< QString::fromLatin1("make[2]: Nothing to be done for `first<73>.")
|
<< QString::fromLatin1("mingw32-make[1]: *** [debug/qplotaxis.o] Error 1\n"
|
||||||
<< OutputParserTester::STDOUT
|
"mingw32-make: *** [debug] Error 2")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
<< QString() << QString()
|
<< QString() << QString()
|
||||||
<< QList<Task>()
|
<< (QList<Task>()
|
||||||
|
<< Task(Task::Error,
|
||||||
|
QString::fromLatin1("[debug/qplotaxis.o] Error 1"),
|
||||||
|
QString(), -1,
|
||||||
|
Constants::TASK_CATEGORY_BUILDSYSTEM))
|
||||||
|
<< QString()
|
||||||
|
<< QStringList();
|
||||||
|
QTest::newRow("mingw64-make error")
|
||||||
|
<< QStringList()
|
||||||
|
<< QString::fromLatin1("mingw64-make.exe[1]: *** [dynlib.inst] Error -1073741819")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< (QList<Task>()
|
||||||
|
<< Task(Task::Error,
|
||||||
|
QString::fromLatin1("[dynlib.inst] Error -1073741819"),
|
||||||
|
QString(), -1,
|
||||||
|
Constants::TASK_CATEGORY_BUILDSYSTEM))
|
||||||
|
<< QString()
|
||||||
|
<< QStringList();
|
||||||
|
QTest::newRow("pass-trough note")
|
||||||
|
<< QStringList()
|
||||||
|
<< QString::fromLatin1("/home/dev/creator/share/qtcreator/gdbmacros/gdbmacros.cpp:1079: note: initialized from here")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString::fromLatin1("/home/dev/creator/share/qtcreator/gdbmacros/gdbmacros.cpp:1079: note: initialized from here")
|
||||||
|
<< QList<ProjectExplorer::Task>()
|
||||||
|
<< QString()
|
||||||
|
<< QStringList();
|
||||||
|
QTest::newRow("Full path make exe")
|
||||||
|
<< QStringList()
|
||||||
|
<< QString::fromLatin1("C:\\Qt\\4.6.2-Symbian\\s60sdk\\epoc32\\tools\\make.exe: *** [sis] Error 2")
|
||||||
|
<< OutputParserTester::STDERR
|
||||||
|
<< QString() << QString()
|
||||||
|
<< (QList<Task>()
|
||||||
|
<< Task(Task::Error,
|
||||||
|
QString::fromLatin1("[sis] Error 2"),
|
||||||
|
QString(), -1,
|
||||||
|
Constants::TASK_CATEGORY_BUILDSYSTEM))
|
||||||
<< QString()
|
<< QString()
|
||||||
<< QStringList();
|
<< QStringList();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ public:
|
|||||||
explicit GnuMakeParser(const QString &dir = QString());
|
explicit GnuMakeParser(const QString &dir = QString());
|
||||||
|
|
||||||
virtual void stdOutput(const QString &line);
|
virtual void stdOutput(const QString &line);
|
||||||
|
virtual void stdError(const QString &line);
|
||||||
|
|
||||||
QStringList searchDirectories() const;
|
QStringList searchDirectories() const;
|
||||||
|
|
||||||
@@ -64,7 +65,7 @@ private:
|
|||||||
#if defined WITH_TESTS
|
#if defined WITH_TESTS
|
||||||
friend class ProjectExplorerPlugin;
|
friend class ProjectExplorerPlugin;
|
||||||
#endif
|
#endif
|
||||||
bool m_alreadyFatal;
|
bool m_suppressIssues;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ProjectExplorer
|
} // namespace ProjectExplorer
|
||||||
|
|||||||
Reference in New Issue
Block a user