diff --git a/projectmanagers/cmake/cmakeimportjsonjob.cpp b/projectmanagers/cmake/cmakeimportjsonjob.cpp --- a/projectmanagers/cmake/cmakeimportjsonjob.cpp +++ b/projectmanagers/cmake/cmakeimportjsonjob.cpp @@ -103,26 +103,6 @@ return data; } -QHash importTargets(const Path& targetsFilePath, const QString& sourceDir, const KDevelop::Path &buildDir) -{ - const QString buildPath = buildDir.toLocalFile(); - QHash targets; - QFile targetsFile(targetsFilePath.toLocalFile()); - if (!targetsFile.open(QIODevice::ReadOnly)) { - qCDebug(CMAKE) << "Couldn't find the Targets file in" << targetsFile.fileName(); - } - const QRegularExpression rx(QStringLiteral("^(.*)/CMakeFiles/(.*).dir$")); - for(; !targetsFile.atEnd(); ) { - const QByteArray line = targetsFile.readLine(); - auto match = rx.match(QString::fromUtf8(line)); - if (!match.isValid()) - qCDebug(CMAKE) << "invalid match for" << line; - const QString sourcePath = match.captured(1).replace(buildPath, sourceDir); - targets[KDevelop::Path(sourcePath)].append(match.captured(2)); - } - return targets; -} - QVector importTestSuites(const Path &buildDir) { QVector ret; @@ -159,7 +139,7 @@ { return ImportData { importCommands(commandsFile), - importTargets(targetsFilePath, sourceDir, buildPath), + CMake::enumerateTargets(targetsFilePath, sourceDir, buildPath), importTestSuites(buildPath) }; } diff --git a/projectmanagers/cmake/cmakemanager.cpp b/projectmanagers/cmake/cmakemanager.cpp --- a/projectmanagers/cmake/cmakemanager.cpp +++ b/projectmanagers/cmake/cmakemanager.cpp @@ -269,7 +269,7 @@ } foreach (const QString& name, dirTargets) { - if (!name.endsWith("_automoc")) + if (!name.endsWith("_automoc") && name != "edit_cache" && name != "rebuild_cache") new CMakeTargetItem(folder, name); } diff --git a/projectmanagers/cmake/cmakeutils.h b/projectmanagers/cmake/cmakeutils.h --- a/projectmanagers/cmake/cmakeutils.h +++ b/projectmanagers/cmake/cmakeutils.h @@ -101,6 +101,11 @@ KDEVCMAKECOMMON_EXPORT bool hasProjectRootRelative( KDevelop::IProject* project ); /** + * Extracts target names from builddir/CMakeFiles/TargetDirectories.txt and maps corresponding source locations to them. + */ + + KDEVCMAKECOMMON_EXPORT QHash enumerateTargets(const KDevelop::Path& targetsFilePath, const QString& sourceDir, const KDevelop::Path &buildDir); + /** * Convenience function to get the project root. */ KDEVCMAKECOMMON_EXPORT KDevelop::Path projectRoot( KDevelop::IProject* project ); diff --git a/projectmanagers/cmake/cmakeutils.cpp b/projectmanagers/cmake/cmakeutils.cpp --- a/projectmanagers/cmake/cmakeutils.cpp +++ b/projectmanagers/cmake/cmakeutils.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -232,6 +233,28 @@ return false; } +QHash enumerateTargets(const KDevelop::Path& targetsFilePath, const QString& sourceDir, const KDevelop::Path &buildDir) +{ + const QString buildPath = buildDir.toLocalFile(); + QHash targets; + QFile targetsFile(targetsFilePath.toLocalFile()); + if (!targetsFile.open(QIODevice::ReadOnly)) { + qCDebug(CMAKE) << "Couldn't find the Targets file in" << targetsFile.fileName(); + } + + QTextStream targetsFileStream(&targetsFile); + const QRegularExpression rx(QStringLiteral("^(.*)/CMakeFiles/(.*).dir$")); + while (!targetsFileStream.atEnd()) { + const QString line = targetsFileStream.readLine(); + auto match = rx.match(line); + if (!match.isValid()) + qCDebug(CMAKE) << "invalid match for" << line; + const QString sourcePath = match.captured(1).replace(buildPath, sourceDir); + targets[KDevelop::Path(sourcePath)].append(match.captured(2)); + } + return targets; +} + KDevelop::Path projectRoot(KDevelop::IProject* project) { if (!project) { diff --git a/projectmanagers/cmake/tests/test_cmakemanager.h b/projectmanagers/cmake/tests/test_cmakemanager.h --- a/projectmanagers/cmake/tests/test_cmakemanager.h +++ b/projectmanagers/cmake/tests/test_cmakemanager.h @@ -49,6 +49,7 @@ void testQt5App(); void testQt5AppOld(); void testKF5App(); + void testEnumerateTargets(); void testFaultyTarget(); }; diff --git a/projectmanagers/cmake/tests/test_cmakemanager.cpp b/projectmanagers/cmake/tests/test_cmakemanager.cpp --- a/projectmanagers/cmake/tests/test_cmakemanager.cpp +++ b/projectmanagers/cmake/tests/test_cmakemanager.cpp @@ -20,6 +20,7 @@ #include "test_cmakemanager.h" #include "testhelpers.h" #include "cmakemodelitems.h" +#include "cmakeutils.h" #include #include @@ -300,6 +301,33 @@ QCOMPARE(subdirectoryFooItems.size(), 4); // three items for the targets, one item for the plain file } +void TestCMakeManager::testEnumerateTargets() +{ + QString currentDir = QDir::currentPath(); + + QTemporaryFile targetDirectoriesFile("./TargetDirectories.txt"); + QTemporaryDir subdir("."); + + auto opened = targetDirectoriesFile.open(); + QVERIFY(opened); + QVERIFY(subdir.isValid()); + + const QString targetDirectoriesContent = currentDir + "/CMakeFiles/first_target.dir\n" + + currentDir + "/CMakeFiles/second_target.dir\r\n" + + currentDir + "/" + subdir.path() + "/CMakeFiles/third_target.dir"; + + targetDirectoriesFile.write(targetDirectoriesContent.toLatin1()); + targetDirectoriesFile.close(); + + QHash targets = + CMake::enumerateTargets(Path(targetDirectoriesFile.fileName()), + currentDir, Path(currentDir)); + + QCOMPARE(targets.value(Path(currentDir)).value(0), QStringLiteral("first_target")); + QCOMPARE(targets.value(Path(currentDir)).value(1), QStringLiteral("second_target")); + QCOMPARE(targets.value(Path(currentDir + subdir.path())).value(0), QStringLiteral("third_target")); +} + void TestCMakeManager::testFaultyTarget() { loadProject("faulty_target");