aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/projectexplorer/project.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/projectexplorer/project.cpp')
-rw-r--r--src/plugins/projectexplorer/project.cpp160
1 files changed, 147 insertions, 13 deletions
diff --git a/src/plugins/projectexplorer/project.cpp b/src/plugins/projectexplorer/project.cpp
index fbd4f9e28fd..c021d9b1a64 100644
--- a/src/plugins/projectexplorer/project.cpp
+++ b/src/plugins/projectexplorer/project.cpp
@@ -11,15 +11,17 @@
#include "environmentaspect.h"
#include "kit.h"
#include "kitinformation.h"
+#include "msvctoolchain.h"
#include "projectexplorer.h"
#include "projectexplorerconstants.h"
#include "projectexplorertr.h"
+#include "projectmanager.h"
#include "projectnodes.h"
#include "runconfiguration.h"
#include "runconfigurationaspects.h"
-#include "session.h"
#include "target.h"
#include "taskhub.h"
+#include "toolchainmanager.h"
#include "userfileaccessor.h"
#include <coreplugin/idocument.h>
@@ -273,7 +275,7 @@ void Project::addTarget(std::unique_ptr<Target> &&t)
// check activeTarget:
if (!activeTarget())
- SessionManager::setActiveTarget(this, pointer, SetActive::Cascade);
+ setActiveTarget(pointer, SetActive::Cascade);
}
Target *Project::addTargetForDefaultKit()
@@ -309,7 +311,7 @@ bool Project::removeTarget(Target *target)
auto keep = take(d->m_targets, target);
if (target == d->m_activeTarget) {
Target *newActiveTarget = (d->m_targets.size() == 0 ? nullptr : d->m_targets.at(0).get());
- SessionManager::setActiveTarget(this, newActiveTarget, SetActive::Cascade);
+ setActiveTarget(newActiveTarget, SetActive::Cascade);
}
emit removedTarget(target);
@@ -326,7 +328,7 @@ Target *Project::activeTarget() const
return d->m_activeTarget;
}
-void Project::setActiveTarget(Target *target)
+void Project::setActiveTargetHelper(Target *target)
{
if (d->m_activeTarget == target)
return;
@@ -414,6 +416,29 @@ Target *Project::target(Kit *k) const
return findOrDefault(d->m_targets, equal(&Target::kit, k));
}
+void Project::setActiveTarget(Target *target, SetActive cascade)
+{
+ if (isShuttingDown())
+ return;
+
+ setActiveTargetHelper(target);
+
+ if (!target) // never cascade setting no target
+ return;
+
+ if (cascade != SetActive::Cascade || !ProjectManager::isProjectConfigurationCascading())
+ return;
+
+ Utils::Id kitId = target->kit()->id();
+ for (Project *otherProject : ProjectManager::projects()) {
+ if (otherProject == this)
+ continue;
+ if (Target *otherTarget = Utils::findOrDefault(otherProject->targets(),
+ [kitId](Target *t) { return t->kit()->id() == kitId; }))
+ otherProject->setActiveTargetHelper(otherTarget);
+ }
+}
+
Tasks Project::projectIssues(const Kit *k) const
{
Tasks result;
@@ -445,12 +470,12 @@ bool Project::copySteps(Target *sourceTarget, Target *newTarget)
sourceBc->buildSystem()->name()));
newTarget->addBuildConfiguration(newBc);
if (sourceTarget->activeBuildConfiguration() == sourceBc)
- SessionManager::setActiveBuildConfiguration(newTarget, newBc, SetActive::NoCascade);
+ newTarget->setActiveBuildConfiguration(newBc, SetActive::NoCascade);
}
if (!newTarget->activeBuildConfiguration()) {
QList<BuildConfiguration *> bcs = newTarget->buildConfigurations();
if (!bcs.isEmpty())
- SessionManager::setActiveBuildConfiguration(newTarget, bcs.first(), SetActive::NoCascade);
+ newTarget->setActiveBuildConfiguration(bcs.first(), SetActive::NoCascade);
}
for (DeployConfiguration *sourceDc : sourceTarget->deployConfigurations()) {
@@ -462,12 +487,12 @@ bool Project::copySteps(Target *sourceTarget, Target *newTarget)
newDc->setDisplayName(sourceDc->displayName());
newTarget->addDeployConfiguration(newDc);
if (sourceTarget->activeDeployConfiguration() == sourceDc)
- SessionManager::setActiveDeployConfiguration(newTarget, newDc, SetActive::NoCascade);
+ newTarget->setActiveDeployConfiguration(newDc, SetActive::NoCascade);
}
if (!newTarget->activeBuildConfiguration()) {
QList<DeployConfiguration *> dcs = newTarget->deployConfigurations();
if (!dcs.isEmpty())
- SessionManager::setActiveDeployConfiguration(newTarget, dcs.first(), SetActive::NoCascade);
+ newTarget->setActiveDeployConfiguration(dcs.first(), SetActive::NoCascade);
}
for (RunConfiguration *sourceRc : sourceTarget->runConfigurations()) {
@@ -846,6 +871,34 @@ const Node *Project::nodeForFilePath(const FilePath &filePath,
return nullptr;
}
+FilePaths Project::binariesForSourceFile(const FilePath &sourceFile) const
+{
+ if (!rootProjectNode())
+ return {};
+ const QList<Node *> fileNodes = rootProjectNode()->findNodes([&sourceFile](Node *n) {
+ return n->filePath() == sourceFile;
+ });
+ FilePaths binaries;
+ for (const Node * const fileNode : fileNodes) {
+ for (ProjectNode *projectNode = fileNode->parentProjectNode(); projectNode;
+ projectNode = projectNode->parentProjectNode()) {
+ if (!projectNode->isProduct())
+ continue;
+ if (projectNode->productType() == ProductType::App
+ || projectNode->productType() == ProductType::Lib) {
+ const QList<Node *> binaryNodes = projectNode->findNodes([](Node *n) {
+ return n->asFileNode() && (n->asFileNode()->fileType() == FileType::App
+ || n->asFileNode()->fileType() == FileType::Lib);
+
+ });
+ binaries << Utils::transform(binaryNodes, &Node::filePath);
+ }
+ break;
+ }
+ }
+ return binaries;
+}
+
void Project::setProjectLanguages(Context language)
{
if (d->m_projectLanguages == language)
@@ -1130,7 +1183,7 @@ void Project::addVariablesToMacroExpander(const QByteArray &prefix,
});
expander->registerVariable(fullPrefix + "Kit:Name",
//: %1 is something like "Active project"
- Tr::tr("%1: The name the active kit.").arg(descriptor),
+ Tr::tr("%1: The name of the active kit.").arg(descriptor),
[targetGetter]() -> QString {
if (const Target *const target = targetGetter())
return target->kit()->displayName();
@@ -1435,8 +1488,7 @@ void ProjectExplorerPlugin::testProject_multipleBuildConfigs()
Target * const target = theProject.project()->activeTarget();
QVERIFY(target);
QCOMPARE(target->buildConfigurations().size(), 6);
- SessionManager::setActiveBuildConfiguration(target, target->buildConfigurations().at(1),
- SetActive::Cascade);
+ target->setActiveBuildConfiguration(target->buildConfigurations().at(1), SetActive::Cascade);
BuildSystem * const bs = theProject.project()->activeTarget()->buildSystem();
QVERIFY(bs);
QCOMPARE(bs, target->activeBuildConfiguration()->buildSystem());
@@ -1452,12 +1504,94 @@ void ProjectExplorerPlugin::testProject_multipleBuildConfigs()
}
QVERIFY(!bs->isWaitingForParse() && !bs->isParsing());
- QCOMPARE(SessionManager::startupProject(), theProject.project());
+ QCOMPARE(ProjectManager::startupProject(), theProject.project());
QCOMPARE(ProjectTree::currentProject(), theProject.project());
QVERIFY(EditorManager::openEditor(projectDir.pathAppended("main.cpp")));
QVERIFY(ProjectTree::currentNode());
ProjectTree::instance()->expandAll();
- SessionManager::closeAllProjects(); // QTCREATORBUG-25655
+ ProjectManager::closeAllProjects(); // QTCREATORBUG-25655
+}
+
+void ProjectExplorerPlugin::testSourceToBinaryMapping()
+{
+ // Find suitable kit.
+ Kit * const kit = findOr(KitManager::kits(), nullptr, [](const Kit *k) {
+ return k->isValid() && ToolChainKitAspect::cxxToolChain(k);
+ });
+ if (!kit)
+ QSKIP("The test requires at least one kit with a toolchain.");
+
+ const auto toolchain = ToolChainKitAspect::cxxToolChain(kit);
+ QVERIFY(toolchain);
+ if (const auto msvcToolchain = dynamic_cast<Internal::MsvcToolChain *>(toolchain)) {
+ while (!msvcToolchain->environmentInitialized()) {
+ QSignalSpy parsingFinishedSpy(ToolChainManager::instance(),
+ &ToolChainManager::toolChainUpdated);
+ QVERIFY(parsingFinishedSpy.wait(10000));
+ }
+ }
+
+ // 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());
+
+ if (QLatin1String(QTest::currentDataTag()) == QLatin1String("qbs")) {
+ BuildManager::buildProjectWithoutDependencies(theProject.project());
+ if (BuildManager::isBuilding()) {
+ QSignalSpy buildingFinishedSpy(BuildManager::instance(), &BuildManager::buildQueueFinished);
+ QVERIFY(buildingFinishedSpy.wait(10000));
+ }
+ QVERIFY(!BuildManager::isBuilding());
+ QSignalSpy projectUpdateSpy(theProject.project(), &Project::fileListChanged);
+ QVERIFY(projectUpdateSpy.wait(5000));
+ }
+
+ // Check mapping
+ const auto binariesForSource = [&](const QString &fileName) {
+ return theProject.project()->binariesForSourceFile(projectDir.pathAppended(fileName));
+ };
+ 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