ProjectExplorer: Add infrastructure for source -> binary mapping

Task-number: QTCREATORBUG-28815
Change-Id: Ib692981e92f5a395dbe400c2cd48042479f12c78
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
Christian Kandeler
2023-03-15 13:43:59 +01:00
parent 6dc7bfb818
commit 76d2e7a4f3
14 changed files with 146 additions and 1 deletions

View File

@@ -7,16 +7,17 @@
#include "cmakeprojectconstants.h"
#include "cmakeprojectimporter.h"
#include "cmakeprojectmanagertr.h"
#include "cmaketool.h"
#include <coreplugin/icontext.h>
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/buildinfo.h>
#include <projectexplorer/buildsteplist.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/projectnodes.h>
#include <projectexplorer/target.h>
#include <projectexplorer/taskhub.h>
#include <qtsupport/qtkitinformation.h>
using namespace ProjectExplorer;
using namespace Utils;
@@ -237,4 +238,17 @@ ProjectExplorer::DeploymentKnowledge CMakeProject::deploymentKnowledge() const
: DeploymentKnowledge::Bad;
}
void CMakeProject::configureAsExampleProject(ProjectExplorer::Kit *kit)
{
QList<BuildInfo> infoList;
const QList<Kit *> kits(kit != nullptr ? QList<Kit *>({kit}) : KitManager::kits());
for (Kit *k : kits) {
if (QtSupport::QtKitAspect::qtVersion(k) != nullptr) {
if (auto factory = BuildConfigurationFactory::find(k, projectFilePath()))
infoList << factory->allAvailableSetups(k, projectFilePath());
}
}
setup(infoList);
}
} // namespace CMakeProjectManager

View File

@@ -36,6 +36,8 @@ protected:
private:
ProjectExplorer::DeploymentKnowledge deploymentKnowledge() const override;
void configureAsExampleProject(ProjectExplorer::Kit *kit) override;
Internal::PresetsData combinePresets(Internal::PresetsData &cmakePresetsData,
Internal::PresetsData &cmakeUserPresetsData);
void setupBuildPresets(Internal::PresetsData &presetsData);

View File

@@ -869,6 +869,13 @@ const Node *Project::nodeForFilePath(const FilePath &filePath,
return nullptr;
}
FilePaths Project::binariesForSourceFile(const Utils::FilePath &sourceFile) const
{
Q_UNUSED(sourceFile);
// TODO: QTCREATORBUG-28815
return {};
}
void Project::setProjectLanguages(Context language)
{
if (d->m_projectLanguages == language)
@@ -1482,6 +1489,76 @@ void ProjectExplorerPlugin::testProject_multipleBuildConfigs()
ProjectManager::closeAllProjects(); // QTCREATORBUG-25655
}
void ProjectExplorerPlugin::testSourceToBinaryMapping()
{
// Find suitable kit.
Kit * const kit = findOr(KitManager::kits(), nullptr, [](const Kit *k) {
return k->isValid();
});
if (!kit)
QSKIP("The test requires at least one valid kit.");
// Copy project from qrc.
QTemporaryDir * const tempDir = TemporaryDirectory::masterTemporaryDirectory();
QVERIFY(tempDir->isValid());
const FilePath projectDir = FilePath::fromString(tempDir->path() + "/multi-target-project");
if (!projectDir.exists()) {
const auto result = FilePath(":/projectexplorer/testdata/multi-target-project")
.copyRecursively(projectDir);
QVERIFY2(result, qPrintable(result.error()));
const QFileInfoList files = QDir(projectDir.toString()).entryInfoList(QDir::Files);
for (const QFileInfo &f : files)
QFile(f.absoluteFilePath()).setPermissions(f.permissions() | QFile::WriteUser);
}
// Load Project.
QFETCH(QString, projectFileName);
const auto theProject = openProject(projectDir.pathAppended(projectFileName));
if (theProject.errorMessage().contains("text/")) {
QSKIP("This test requires the presence of the qmake/cmake/qbs project managers "
"to be fully functional");
}
QVERIFY2(theProject, qPrintable(theProject.errorMessage()));
theProject.project()->configureAsExampleProject(kit);
QCOMPARE(theProject.project()->targets().size(), 1);
Target * const target = theProject.project()->activeTarget();
QVERIFY(target);
BuildSystem * const bs = target->buildSystem();
QVERIFY(bs);
QCOMPARE(bs, target->activeBuildConfiguration()->buildSystem());
if (bs->isWaitingForParse() || bs->isParsing()) {
QSignalSpy parsingFinishedSpy(bs, &BuildSystem::parsingFinished);
QVERIFY(parsingFinishedSpy.wait(10000));
}
QVERIFY(!bs->isWaitingForParse() && !bs->isParsing());
// Build project.
BuildManager::buildProjectWithoutDependencies(theProject.project());
if (BuildManager::isBuilding()) {
QSignalSpy buildingFinishedSpy(BuildManager::instance(), &BuildManager::buildQueueFinished);
QVERIFY(buildingFinishedSpy.wait(10000));
}
QVERIFY(!BuildManager::isBuilding());
// Check mapping
const auto binariesForSource = [&](const QString &fileName) {
return theProject.project()->binariesForSourceFile(projectDir.pathAppended(fileName));
};
QEXPECT_FAIL(0, "QTCREATORBUG-28815", Abort);
QCOMPARE(binariesForSource("multi-target-project-main.cpp").size(), 1);
QCOMPARE(binariesForSource("multi-target-project-lib.cpp").size(), 1);
QCOMPARE(binariesForSource("multi-target-project-shared.h").size(), 2);
}
void ProjectExplorerPlugin::testSourceToBinaryMapping_data()
{
QTest::addColumn<QString>("projectFileName");
QTest::addRow("cmake") << "CMakeLists.txt";
QTest::addRow("qbs") << "multi-target-project.qbs";
QTest::addRow("qmake") << "multi-target-project.pro";
}
#endif // WITH_TESTS
} // namespace ProjectExplorer

View File

@@ -110,6 +110,7 @@ public:
bool isKnownFile(const Utils::FilePath &filename) const;
const Node *nodeForFilePath(const Utils::FilePath &filePath,
const NodeMatcher &extraMatcher = {}) const;
Utils::FilePaths binariesForSourceFile(const Utils::FilePath &sourceFile) const;
virtual QVariantMap toMap() const;

View File

@@ -261,6 +261,9 @@ private slots:
void testProject_projectTree();
void testProject_multipleBuildConfigs();
void testSourceToBinaryMapping();
void testSourceToBinaryMapping_data();
void testSessionSwitch();
#endif // WITH_TESTS
};

View File

@@ -86,5 +86,13 @@
<file>images/settingscategory_cpp@2x.png</file>
<file>images/importasproject.png</file>
<file>images/importasproject@2x.png</file>
<file>testdata/multi-target-project/CMakeLists.txt</file>
<file>testdata/multi-target-project/multi-target-project-app.pro</file>
<file>testdata/multi-target-project/multi-target-project-lib.cpp</file>
<file>testdata/multi-target-project/multi-target-project-lib.pro</file>
<file>testdata/multi-target-project/multi-target-project-main.cpp</file>
<file>testdata/multi-target-project/multi-target-project-shared.h</file>
<file>testdata/multi-target-project/multi-target-project.pro</file>
<file>testdata/multi-target-project/multi-target-project.qbs</file>
</qresource>
</RCC>

View File

@@ -0,0 +1,3 @@
project(multi-target-project)
add_executable(multi-target-project-app multi-target-project-main.cpp multi-target-project-shared.h)
add_library(multi-target-project-lib STATIC multi-target-project-lib.cpp multi-target-project-shared.h)

View File

@@ -0,0 +1,4 @@
TARGET = app
CONFIG -= qt
SOURCES = multi-target-project-main.cpp
HEADERS = multi-target-project-shared.h

View File

@@ -0,0 +1,6 @@
#include "multi-target-project-shared.h"
int increaseNumber()
{
return getNumber() + 1;
}

View File

@@ -0,0 +1,4 @@
TEMPLATE = lib
CONFIG += static
SOURCES = multi-target-project-lib.cpp
HEADERS = multi-target-project-shared.h

View File

@@ -0,0 +1,6 @@
#include "multi-target-project-shared.h"
int main()
{
return getNumber();
}

View File

@@ -0,0 +1,3 @@
#pragma once
inline int getNumber() { return 5; }

View File

@@ -0,0 +1,4 @@
TEMPLATE = subdirs
app.file = multi-target-project-app.pro
lib.file = multi-target-project-lib.pro
SUBDIRS = app lib

View File

@@ -0,0 +1,10 @@
Project {
CppApplication {
name: "app"
files: ["multi-target-project-main.cpp", "multi-target-project-shared.h"]
}
StaticLibrary {
Depends { name: "cpp" }
files: ["multi-target-project-lib.cpp", "multi-target-project-shared.h"]
}
}