diff options
author | Christian Kandeler <christian.kandeler@qt.io> | 2019-07-11 17:48:09 +0200 |
---|---|---|
committer | Christian Kandeler <christian.kandeler@qt.io> | 2019-07-12 14:36:05 +0000 |
commit | 52a58afc794c441bb32bea6ca7f6ac021e0c372b (patch) | |
tree | 024b497d4172743a0bcf1f8edcdc396d13b14a51 /src | |
parent | 333b33edbe9805e00772c68c7a7f47c8394b786b (diff) |
ProjectExplorer: Add lld output parser
Fixes: QTCREATORBUG-22623
Change-Id: I2c38466cf7206e07d1cb77520ce502179e3cc82f
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/plugins/projectexplorer/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/plugins/projectexplorer/gccparser.cpp | 127 | ||||
-rw-r--r-- | src/plugins/projectexplorer/ldparser.cpp | 2 | ||||
-rw-r--r-- | src/plugins/projectexplorer/linuxiccparser.cpp | 2 | ||||
-rw-r--r-- | src/plugins/projectexplorer/lldparser.cpp | 76 | ||||
-rw-r--r-- | src/plugins/projectexplorer/lldparser.h | 39 | ||||
-rw-r--r-- | src/plugins/projectexplorer/projectexplorer.pro | 2 | ||||
-rw-r--r-- | src/plugins/projectexplorer/projectexplorer.qbs | 1 |
8 files changed, 249 insertions, 1 deletions
diff --git a/src/plugins/projectexplorer/CMakeLists.txt b/src/plugins/projectexplorer/CMakeLists.txt index c9413c2385..5df2906b71 100644 --- a/src/plugins/projectexplorer/CMakeLists.txt +++ b/src/plugins/projectexplorer/CMakeLists.txt @@ -109,6 +109,7 @@ add_qtc_plugin(ProjectExplorer kitmodel.cpp kitmodel.h kitoptionspage.cpp kitoptionspage.h ldparser.cpp ldparser.h + lldparser.cpp lldparser.h linuxiccparser.cpp linuxiccparser.h localenvironmentaspect.cpp localenvironmentaspect.h makestep.cpp makestep.h makestep.ui diff --git a/src/plugins/projectexplorer/gccparser.cpp b/src/plugins/projectexplorer/gccparser.cpp index d6521cde99..ef88b51403 100644 --- a/src/plugins/projectexplorer/gccparser.cpp +++ b/src/plugins/projectexplorer/gccparser.cpp @@ -25,6 +25,7 @@ #include "gccparser.h" #include "ldparser.h" +#include "lldparser.h" #include "task.h" #include "projectexplorerconstants.h" #include "buildmanager.h" @@ -34,6 +35,7 @@ #include <utils/qtcassert.h> using namespace ProjectExplorer; +using namespace Utils; // opt. drive letter + filename: (2 brackets) static const char FILE_PATTERN[] = "(<command[ -]line>|([A-Za-z]:)?[^:]+):"; @@ -58,6 +60,7 @@ GccParser::GccParser() m_regExpGccNames.setPattern(QLatin1String(COMMAND_PATTERN)); QTC_CHECK(m_regExpGccNames.isValid()); + appendOutputParser(new Internal::LldParser); appendOutputParser(new LdParser); } @@ -875,6 +878,130 @@ void ProjectExplorerPlugin::testGccOutputParsers_data() ) << QString(); + const auto task = [categoryCompile](Task::TaskType type, const QString &msg, + const QString &file = {}, int line = -1) { + return Task(type, msg, FilePath::fromString(file), line, categoryCompile); + }; + const auto errorTask = [&task](const QString &msg, const QString &file = {}, int line = -1) { + return task(Task::Error, msg, file, line); + }; + const auto unknownTask = [&task](const QString &msg, const QString &file = {}, int line = -1) { + return task(Task::Unknown, msg, file, line); + }; + QTest::newRow("lld: undefined reference with debug info") + << "ld.lld: error: undefined symbol: func()\n" + ">>> referenced by test.cpp:5\n" + ">>> /tmp/ccg8pzRr.o:(main)\n" + "collect2: error: ld returned 1 exit status" + << OutputParserTester::STDERR << QString() << QString() + << Tasks{ + errorTask("ld.lld: error: undefined symbol: func()"), + unknownTask("referenced by test.cpp:5", "test.cpp", 5), + unknownTask("/tmp/ccg8pzRr.o:(main)", "/tmp/ccg8pzRr.o"), + errorTask("collect2: error: ld returned 1 exit status")} + << QString(); + QTest::newRow("lld: undefined reference with debug info (more verbose format)") + << "ld.lld: error: undefined symbol: someFunc()\n" + ">>> referenced by main.cpp:10 (/tmp/untitled4/main.cpp:10)\n" + ">>> /tmp/Debug4/untitled4.5abe06ac/3a52ce780950d4d9/main.cpp.o:(main)\n" + "clang-8: error: linker command failed with exit code 1 (use -v to see invocation)" + << OutputParserTester::STDERR << QString() + << QString("clang-8: error: linker command failed with exit code 1 (use -v to see invocation)\n") + << Tasks{ + errorTask("ld.lld: error: undefined symbol: someFunc()"), + unknownTask("referenced by main.cpp:10 (/tmp/untitled4/main.cpp:10)", + "/tmp/untitled4/main.cpp", 10), + unknownTask("/tmp/Debug4/untitled4.5abe06ac/3a52ce780950d4d9/main.cpp.o:(main)", + "/tmp/Debug4/untitled4.5abe06ac/3a52ce780950d4d9/main.cpp.o")} + << QString(); + QTest::newRow("lld: undefined reference without debug info") + << "ld.lld: error: undefined symbol: func()\n" + ">>> referenced by test.cpp\n" + ">>> /tmp/ccvjyJph.o:(main)\n" + "collect2: error: ld returned 1 exit status" + << OutputParserTester::STDERR << QString() << QString() + << Tasks{ + errorTask("ld.lld: error: undefined symbol: func()"), + unknownTask("referenced by test.cpp", "test.cpp"), + unknownTask("/tmp/ccvjyJph.o:(main)", "/tmp/ccvjyJph.o"), + errorTask("collect2: error: ld returned 1 exit status")} + << QString(); + if (HostOsInfo::isWindowsHost()) { + QTest::newRow("lld: undefined reference with mingw") + << "lld-link: error: undefined symbol: __Z4funcv\n" + ">>> referenced by C:\\Users\\orgads\\AppData\\Local\\Temp\\cccApKoz.o:(.text)\n" + "collect2.exe: error: ld returned 1 exit status" + << OutputParserTester::STDERR << QString() << QString() + << Tasks{ + errorTask("lld-link: error: undefined symbol: __Z4funcv"), + unknownTask("referenced by C:\\Users\\orgads\\AppData\\Local\\Temp\\cccApKoz.o:(.text)", + "C:/Users/orgads/AppData/Local/Temp/cccApKoz.o"), + errorTask("collect2.exe: error: ld returned 1 exit status")} + << QString(); + } + QTest::newRow("lld: multiple definitions with debug info") + << "ld.lld: error: duplicate symbol: func()\n" + ">>> defined at test1.cpp:1\n" + ">>> test1.o:(func())\n" + ">>> defined at test1.cpp:1\n" + ">>> test1.o:(.text+0x0)\n" + "collect2: error: ld returned 1 exit status" + << OutputParserTester::STDERR << QString() << QString() + << Tasks{ + errorTask("ld.lld: error: duplicate symbol: func()"), + unknownTask("defined at test1.cpp:1", "test1.cpp", 1), + unknownTask("test1.o:(func())", "test1.o"), + unknownTask("defined at test1.cpp:1", "test1.cpp", 1), + unknownTask("test1.o:(.text+0x0)", "test1.o"), + errorTask("collect2: error: ld returned 1 exit status")} + << QString(); + QTest::newRow("lld: multiple definitions with debug info (more verbose format)") + << "ld.lld: error: duplicate symbol: theFunc()\n" + ">>> defined at file.cpp:1 (/tmp/untitled3/file.cpp:1)\n" + ">>> /tmp/Debug/untitled3.dade828b/3a52ce780950d4d9/file.cpp.o:(theFunc())\n" + ">>> defined at main.cpp:5 (/tmp/untitled3/main.cpp:5)\n" + ">>> /tmp/Debug/untitled3.dade828b/3a52ce780950d4d9/main.cpp.o:(.text+0x0)\n" + "collect2: error: ld returned 1 exit status" + << OutputParserTester::STDERR << QString() << QString() + << Tasks{ + errorTask("ld.lld: error: duplicate symbol: theFunc()"), + unknownTask("defined at file.cpp:1 (/tmp/untitled3/file.cpp:1)", + "/tmp/untitled3/file.cpp", 1), + unknownTask("/tmp/Debug/untitled3.dade828b/3a52ce780950d4d9/file.cpp.o:(theFunc())", + "/tmp/Debug/untitled3.dade828b/3a52ce780950d4d9/file.cpp.o"), + unknownTask("defined at main.cpp:5 (/tmp/untitled3/main.cpp:5)", + "/tmp/untitled3/main.cpp", 5), + unknownTask("/tmp/Debug/untitled3.dade828b/3a52ce780950d4d9/main.cpp.o:(.text+0x0)", + "/tmp/Debug/untitled3.dade828b/3a52ce780950d4d9/main.cpp.o"), + errorTask("collect2: error: ld returned 1 exit status")} + << QString(); + QTest::newRow("lld: multiple definitions without debug info") + << "ld.lld: error: duplicate symbol: func()\n" + ">>> defined at test1.cpp\n" + ">>> test1.o:(func())\n" + ">>> defined at test1.cpp\n" + ">>> test1.o:(.text+0x0)\n" + "collect2: error: ld returned 1 exit status" + << OutputParserTester::STDERR << QString() << QString() + << Tasks{ + errorTask("ld.lld: error: duplicate symbol: func()"), + unknownTask("defined at test1.cpp", "test1.cpp"), + unknownTask("test1.o:(func())", "test1.o"), + unknownTask("defined at test1.cpp", "test1.cpp"), + unknownTask("test1.o:(.text+0x0)", "test1.o"), + errorTask("collect2: error: ld returned 1 exit status")} + << QString(); + if (HostOsInfo::isWindowsHost()) { + QTest::newRow("lld: multiple definitions with mingw") + << "lld-link: error: duplicate symbol: __Z4funcv in test1.o and in test2.o\n" + "collect2.exe: error: ld returned 1 exit status" + << OutputParserTester::STDERR << QString() << QString() + << Tasks{ + errorTask("lld-link: error: duplicate symbol: __Z4funcv in test1.o and in test2.o"), + errorTask("collect2.exe: error: ld returned 1 exit status", {})} + << QString(); + } + QTest::newRow("Mac: ranlib warning") << QString::fromLatin1("ranlib: file: lib/libtest.a(Test0.cpp.o) has no symbols") << OutputParserTester::STDERR diff --git a/src/plugins/projectexplorer/ldparser.cpp b/src/plugins/projectexplorer/ldparser.cpp index 9ce56bf7dd..919c9db30b 100644 --- a/src/plugins/projectexplorer/ldparser.cpp +++ b/src/plugins/projectexplorer/ldparser.cpp @@ -65,7 +65,7 @@ void LdParser::stdError(const QString &line) return; } - if (lne.startsWith(QLatin1String("collect2:"))) { + if (lne.startsWith("collect2:") || lne.startsWith("collect2.exe:")) { Task task = Task(Task::Error, lne /* description */, Utils::FilePath() /* filename */, diff --git a/src/plugins/projectexplorer/linuxiccparser.cpp b/src/plugins/projectexplorer/linuxiccparser.cpp index 6572f47d66..a333d00ca5 100644 --- a/src/plugins/projectexplorer/linuxiccparser.cpp +++ b/src/plugins/projectexplorer/linuxiccparser.cpp @@ -25,6 +25,7 @@ #include "linuxiccparser.h" #include "ldparser.h" +#include "lldparser.h" #include "projectexplorerconstants.h" #include <utils/qtcassert.h> @@ -62,6 +63,7 @@ LinuxIccParser::LinuxIccParser() : m_pchInfoLine.setMinimal(true); QTC_CHECK(m_pchInfoLine.isValid()); + appendOutputParser(new Internal::LldParser); appendOutputParser(new LdParser); } diff --git a/src/plugins/projectexplorer/lldparser.cpp b/src/plugins/projectexplorer/lldparser.cpp new file mode 100644 index 0000000000..0f8ffe7476 --- /dev/null +++ b/src/plugins/projectexplorer/lldparser.cpp @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "lldparser.h" + +#include "projectexplorerconstants.h" +#include "task.h" + +#include <utils/fileutils.h> + +#include <QStringList> + +namespace ProjectExplorer { +namespace Internal { + +void LldParser::stdError(const QString &line) +{ + const QString trimmedLine = rightTrimmed(line); + if (trimmedLine.contains("error:") && trimmedLine.contains("lld")) { + emit addTask({Task::Error, trimmedLine, Utils::FilePath(), -1, + Constants::TASK_CATEGORY_COMPILE}); + return; + } + static const QStringList prefixes{">>> referenced by ", ">>> defined at ", ">>> "}; + for (const QString &prefix : prefixes) { + if (!trimmedLine.startsWith(prefix)) + continue; + int lineNo = -1; + const int locOffset = trimmedLine.lastIndexOf(':'); + if (locOffset != -1) { + const int endLocOffset = trimmedLine.indexOf(')', locOffset); + const int numberWidth = endLocOffset == -1 ? -1 : endLocOffset - locOffset - 1; + bool isNumber = true; + lineNo = trimmedLine.mid(locOffset + 1, numberWidth).toInt(&isNumber); + if (!isNumber) + lineNo = -1; + } + int filePathOffset = trimmedLine.lastIndexOf('(', locOffset); + if (filePathOffset != -1) + ++filePathOffset; + else + filePathOffset = prefix.length(); + const int filePathLen = locOffset == -1 ? -1 : locOffset - filePathOffset; + const auto file = Utils::FilePath::fromUserInput( + trimmedLine.mid(filePathOffset, filePathLen).trimmed()); + emit addTask({Task::Unknown, trimmedLine.mid(4).trimmed(), file, lineNo, + Constants::TASK_CATEGORY_COMPILE}); + return; + } + IOutputParser::stdError(line); +} + +} // namespace Internal +} // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/lldparser.h b/src/plugins/projectexplorer/lldparser.h new file mode 100644 index 0000000000..c459880f8e --- /dev/null +++ b/src/plugins/projectexplorer/lldparser.h @@ -0,0 +1,39 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include "ioutputparser.h" + +namespace ProjectExplorer { +namespace Internal { + +class LldParser : public IOutputParser +{ + void stdError(const QString &line) override; +}; + +} // namespace Internal +} // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/projectexplorer.pro b/src/plugins/projectexplorer/projectexplorer.pro index 097fcb6da5..1196d6f95e 100644 --- a/src/plugins/projectexplorer/projectexplorer.pro +++ b/src/plugins/projectexplorer/projectexplorer.pro @@ -102,6 +102,7 @@ HEADERS += projectexplorer.h \ miniprojecttargetselector.h \ buildenvironmentwidget.h \ ldparser.h \ + lldparser.h \ linuxiccparser.h \ runconfigurationaspects.h \ processparameters.h \ @@ -253,6 +254,7 @@ SOURCES += projectexplorer.cpp \ miniprojecttargetselector.cpp \ buildenvironmentwidget.cpp \ ldparser.cpp \ + lldparser.cpp \ linuxiccparser.cpp \ runconfigurationaspects.cpp \ taskhub.cpp \ diff --git a/src/plugins/projectexplorer/projectexplorer.qbs b/src/plugins/projectexplorer/projectexplorer.qbs index 395c1cced9..a2b5f6e3b2 100644 --- a/src/plugins/projectexplorer/projectexplorer.qbs +++ b/src/plugins/projectexplorer/projectexplorer.qbs @@ -91,6 +91,7 @@ Project { "kitmodel.cpp", "kitmodel.h", "kitoptionspage.cpp", "kitoptionspage.h", "ldparser.cpp", "ldparser.h", + "lldparser.cpp", "lldparser.h", "linuxiccparser.cpp", "linuxiccparser.h", "localenvironmentaspect.cpp", "localenvironmentaspect.h", "makestep.cpp", "makestep.h", "makestep.ui", |