diff --git a/src/plugins/autotest/testrunner.cpp b/src/plugins/autotest/testrunner.cpp index 3cac44d15d8..ad5ad1a5f51 100644 --- a/src/plugins/autotest/testrunner.cpp +++ b/src/plugins/autotest/testrunner.cpp @@ -320,7 +320,8 @@ void TestRunner::prepareToRunTests(TestRunMode mode) m_runMode = mode; ProjectExplorer::Internal::ProjectExplorerSettings projectExplorerSettings = ProjectExplorerPlugin::projectExplorerSettings(); - if (mode != TestRunMode::RunAfterBuild && projectExplorerSettings.buildBeforeDeploy + if (mode != TestRunMode::RunAfterBuild + && projectExplorerSettings.buildBeforeDeploy != ProjectExplorer::Internal::BuildBeforeRunMode::Off && !projectExplorerSettings.saveBeforeBuild) { if (!ProjectExplorerPlugin::saveModifiedFiles()) return; @@ -352,7 +353,8 @@ void TestRunner::prepareToRunTests(TestRunMode mode) m_targetConnect = connect(project, &Project::activeTargetChanged, [this]() { cancelCurrent(KitChanged); }); - if (!projectExplorerSettings.buildBeforeDeploy || mode == TestRunMode::DebugWithoutDeploy + if (projectExplorerSettings.buildBeforeDeploy == ProjectExplorer::Internal::BuildBeforeRunMode::Off + || mode == TestRunMode::DebugWithoutDeploy || mode == TestRunMode::RunWithoutDeploy || mode == TestRunMode::RunAfterBuild) { runOrDebugTests(); return; diff --git a/src/plugins/projectexplorer/buildconfiguration.cpp b/src/plugins/projectexplorer/buildconfiguration.cpp index 67c960ddfbb..446fde31ef1 100644 --- a/src/plugins/projectexplorer/buildconfiguration.cpp +++ b/src/plugins/projectexplorer/buildconfiguration.cpp @@ -403,6 +403,11 @@ bool BuildConfiguration::regenerateBuildFiles(Node *node) return false; } +void BuildConfiguration::restrictNextBuild(const RunConfiguration *rc) +{ + Q_UNUSED(rc); +} + BuildConfiguration::BuildType BuildConfiguration::buildType() const { return d->m_initialBuildType; diff --git a/src/plugins/projectexplorer/buildconfiguration.h b/src/plugins/projectexplorer/buildconfiguration.h index 55e7da41bd5..9f5fbad4c5a 100644 --- a/src/plugins/projectexplorer/buildconfiguration.h +++ b/src/plugins/projectexplorer/buildconfiguration.h @@ -43,6 +43,7 @@ class BuildStepList; class Kit; class NamedWidget; class Node; +class RunConfiguration; class Target; class PROJECTEXPLORER_EXPORT BuildConfiguration : public ProjectConfiguration @@ -87,6 +88,8 @@ public: virtual bool regenerateBuildFiles(Node *node); + virtual void restrictNextBuild(const RunConfiguration *rc); + enum BuildType { Unknown, Debug, diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index dead62ae052..4ed702b80c4 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -1387,8 +1387,17 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er } } - dd->m_projectExplorerSettings.buildBeforeDeploy = - s->value(Constants::BUILD_BEFORE_DEPLOY_SETTINGS_KEY, true).toBool(); + const QVariant buildBeforeDeploy = s->value(Constants::BUILD_BEFORE_DEPLOY_SETTINGS_KEY); + const QString buildBeforeDeployString = buildBeforeDeploy.toString(); + if (buildBeforeDeployString == "true") { // backward compatibility with QtC < 4.12 + dd->m_projectExplorerSettings.buildBeforeDeploy = BuildBeforeRunMode::WholeProject; + } else if (buildBeforeDeployString == "false") { + dd->m_projectExplorerSettings.buildBeforeDeploy = BuildBeforeRunMode::Off; + } else if (buildBeforeDeploy.isValid()) { + dd->m_projectExplorerSettings.buildBeforeDeploy + = static_cast(buildBeforeDeploy.toInt()); + } + dd->m_projectExplorerSettings.deployBeforeRun = s->value(Constants::DEPLOY_BEFORE_RUN_SETTINGS_KEY, true).toBool(); dd->m_projectExplorerSettings.saveBeforeBuild = @@ -1465,11 +1474,7 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er QTC_ASSERT(target, return); const RunConfiguration * const runConfig = target->activeRunConfiguration(); QTC_ASSERT(runConfig, return); - const auto buildKeyMatcher = [runConfig](const ProjectNode *candidate) { - return candidate->buildKey() == runConfig->buildKey(); - }; - ProjectNode * const productNode - = project->rootProjectNode()->findProjectNode(buildKeyMatcher); + ProjectNode * const productNode = runConfig->productNode(); QTC_ASSERT(productNode->isProduct(), return); productNode->build(); }); @@ -2023,7 +2028,7 @@ void ProjectExplorerPluginPrivate::savePersistentSettings() s->setValue(QLatin1String("ProjectExplorer/RecentProjects/FileNames"), fileNames); s->setValue(QLatin1String("ProjectExplorer/RecentProjects/DisplayNames"), displayNames); - s->setValue(Constants::BUILD_BEFORE_DEPLOY_SETTINGS_KEY, dd->m_projectExplorerSettings.buildBeforeDeploy); + s->setValue(Constants::BUILD_BEFORE_DEPLOY_SETTINGS_KEY, int(dd->m_projectExplorerSettings.buildBeforeDeploy)); s->setValue(Constants::DEPLOY_BEFORE_RUN_SETTINGS_KEY, dd->m_projectExplorerSettings.deployBeforeRun); s->setValue(Constants::SAVE_BEFORE_BUILD_SETTINGS_KEY, dd->m_projectExplorerSettings.saveBeforeBuild); s->setValue(Constants::USE_JOM_SETTINGS_KEY, dd->m_projectExplorerSettings.useJom); @@ -2599,7 +2604,7 @@ ProjectExplorerPluginPrivate::ProjectExplorerPluginPrivate() void ProjectExplorerPluginPrivate::deploy(QList projects) { QList steps; - if (m_projectExplorerSettings.buildBeforeDeploy) + if (m_projectExplorerSettings.buildBeforeDeploy != BuildBeforeRunMode::Off) steps << Id(Constants::BUILDSTEPS_BUILD); steps << Id(Constants::BUILDSTEPS_DEPLOY); queue(projects, steps); @@ -2878,14 +2883,25 @@ void ProjectExplorerPlugin::runRunConfiguration(RunConfiguration *rc, QList stepIds; if (!forceSkipDeploy && dd->m_projectExplorerSettings.deployBeforeRun) { - if (!BuildManager::isBuilding() && dd->m_projectExplorerSettings.buildBeforeDeploy) - stepIds << Id(Constants::BUILDSTEPS_BUILD); + if (!BuildManager::isBuilding()) { + switch (dd->m_projectExplorerSettings.buildBeforeDeploy) { + case BuildBeforeRunMode::AppOnly: + rc->target()->activeBuildConfiguration()->restrictNextBuild(rc); + Q_FALLTHROUGH(); + case BuildBeforeRunMode::WholeProject: + stepIds << Id(Constants::BUILDSTEPS_BUILD); + break; + case BuildBeforeRunMode::Off: + break; + } + } if (!BuildManager::isDeploying()) stepIds << Id(Constants::BUILDSTEPS_DEPLOY); } Project *pro = rc->target()->project(); int queueCount = dd->queue(SessionManager::projectOrder(pro), stepIds); + rc->target()->activeBuildConfiguration()->restrictNextBuild(nullptr); if (queueCount < 0) // something went wrong return; @@ -3022,7 +3038,7 @@ void ProjectExplorerPluginPrivate::updateDeployActions() && !BuildManager::isBuilding(currentProject) && hasDeploySettings(currentProject); - if (m_projectExplorerSettings.buildBeforeDeploy) { + if (m_projectExplorerSettings.buildBeforeDeploy != BuildBeforeRunMode::Off) { if (hasBuildSettings(project) && !buildSettingsEnabled(project).first) enableDeployActions = false; @@ -3042,7 +3058,7 @@ void ProjectExplorerPluginPrivate::updateDeployActions() m_deployProjectOnlyAction->setEnabled(enableDeployActions); bool enableDeploySessionAction = true; - if (m_projectExplorerSettings.buildBeforeDeploy) { + if (m_projectExplorerSettings.buildBeforeDeploy != BuildBeforeRunMode::Off) { auto hasDisabledBuildConfiguration = [](Project *project) { return project && project->activeTarget() && project->activeTarget()->activeBuildConfiguration() @@ -3095,7 +3111,7 @@ bool ProjectExplorerPlugin::canRunStartupProject(Core::Id runMode, QString *whyN return false; } - if (dd->m_projectExplorerSettings.buildBeforeDeploy + if (dd->m_projectExplorerSettings.buildBeforeDeploy != BuildBeforeRunMode::Off && dd->m_projectExplorerSettings.deployBeforeRun && !BuildManager::isBuilding(project) && hasBuildSettings(project)) { diff --git a/src/plugins/projectexplorer/projectexplorersettings.h b/src/plugins/projectexplorer/projectexplorersettings.h index 920f849fe11..f8314b665bd 100644 --- a/src/plugins/projectexplorer/projectexplorersettings.h +++ b/src/plugins/projectexplorer/projectexplorersettings.h @@ -35,13 +35,14 @@ namespace Internal { enum class TerminalMode { On, Off, Smart }; enum class AppOutputPaneMode { FlashOnOutput, PopupOnOutput, PopupOnFirstOutput }; +enum class BuildBeforeRunMode { Off, WholeProject, AppOnly }; class ProjectExplorerSettings { public: enum StopBeforeBuild { StopNone = 0, StopSameProject, StopAll, StopSameBuildDir }; - bool buildBeforeDeploy = true; + BuildBeforeRunMode buildBeforeDeploy = BuildBeforeRunMode::WholeProject; bool deployBeforeRun = true; bool saveBeforeBuild = false; bool useJom = true; diff --git a/src/plugins/projectexplorer/projectexplorersettingspage.cpp b/src/plugins/projectexplorer/projectexplorersettingspage.cpp index 5251eff14c8..744c1539dc4 100644 --- a/src/plugins/projectexplorer/projectexplorersettingspage.cpp +++ b/src/plugins/projectexplorer/projectexplorersettingspage.cpp @@ -75,6 +75,12 @@ ProjectExplorerSettingsWidget::ProjectExplorerSettingsWidget(QWidget *parent) : { m_ui.setupUi(this); setJomVisible(Utils::HostOsInfo::isWindowsHost()); + m_ui.buildBeforeDeployComboBox->addItem(tr("Do Not Build Anything"), + int(BuildBeforeRunMode::Off)); + m_ui.buildBeforeDeployComboBox->addItem(tr("Build the Whole Project"), + int(BuildBeforeRunMode::WholeProject)); + m_ui.buildBeforeDeployComboBox->addItem(tr("Build Only the Application to Be Run"), + int(BuildBeforeRunMode::AppOnly)); m_ui.directoryButtonGroup->setId(m_ui.currentDirectoryRadioButton, UseCurrentDirectory); m_ui.directoryButtonGroup->setId(m_ui.directoryRadioButton, UseProjectDirectory); @@ -97,7 +103,8 @@ void ProjectExplorerSettingsWidget::setJomVisible(bool v) ProjectExplorerSettings ProjectExplorerSettingsWidget::settings() const { - m_settings.buildBeforeDeploy = m_ui.buildProjectBeforeDeployCheckBox->isChecked(); + m_settings.buildBeforeDeploy = static_cast( + m_ui.buildBeforeDeployComboBox->currentData().toInt()); m_settings.deployBeforeRun = m_ui.deployProjectBeforeRunCheckBox->isChecked(); m_settings.saveBeforeBuild = m_ui.saveAllFilesCheckBox->isChecked(); m_settings.useJom = m_ui.jomCheckbox->isChecked(); @@ -117,7 +124,8 @@ ProjectExplorerSettings ProjectExplorerSettingsWidget::settings() const void ProjectExplorerSettingsWidget::setSettings(const ProjectExplorerSettings &pes) { m_settings = pes; - m_ui.buildProjectBeforeDeployCheckBox->setChecked(m_settings.buildBeforeDeploy); + m_ui.buildBeforeDeployComboBox->setCurrentIndex( + m_ui.buildBeforeDeployComboBox->findData(int(m_settings.buildBeforeDeploy))); m_ui.deployProjectBeforeRunCheckBox->setChecked(m_settings.deployBeforeRun); m_ui.saveAllFilesCheckBox->setChecked(m_settings.saveBeforeBuild); m_ui.jomCheckbox->setChecked(m_settings.useJom); diff --git a/src/plugins/projectexplorer/projectexplorersettingspage.ui b/src/plugins/projectexplorer/projectexplorersettingspage.ui index 80520451138..170e7e29c3f 100644 --- a/src/plugins/projectexplorer/projectexplorersettingspage.ui +++ b/src/plugins/projectexplorer/projectexplorersettingspage.ui @@ -67,88 +67,62 @@ Build and Run - - - - - Save all files before build - - - - - - - Always build project before deploying it - - - - - - - Always deploy project before running it - - - - + + Add linker library search paths to run environment - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - - - Asks before terminating the running application in response to clicking the stop button in Application Output. - - - Always ask before stopping applications - - - - - - - Creates suitable run configurations automatically when setting up a new kit. - - - Create suitable run configurations automatically - - - - + Clear issues list on new build - + Abort on error when building all projects - + + + + 0 + + + + + + + + Use jom instead of nmake + + + + + + + <i>jom</i> is a drop-in replacement for <i>nmake</i> which distributes the compilation process to multiple CPU cores. The latest binary is available at <a href="http://download.qt.io/official_releases/jom/">http://download.qt.io/official_releases/jom/</a>. Disable it if you experience problems with your builds. + + + true + + + 20 + + + true + + + + + + Enable this if your system becomes unresponsive while building. @@ -158,16 +132,50 @@ - + + + + Always deploy project before running it + + + + + + + Build before deploying: + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + Stop applications before building: - + @@ -208,14 +216,14 @@ - + Default for "Run in terminal": - + @@ -253,40 +261,24 @@ - - - - 0 + + + + Save all files before build - - - - - - - Use jom instead of nmake - - - - - - - <i>jom</i> is a drop-in replacement for <i>nmake</i> which distributes the compilation process to multiple CPU cores. The latest binary is available at <a href="http://download.qt.io/official_releases/jom/">http://download.qt.io/official_releases/jom/</a>. Disable it if you experience problems with your builds. - - - true - - - 20 - - - true - - - - + - + + + + Creates suitable run configurations automatically when setting up a new kit. + + + Create suitable run configurations automatically + + + + 12 @@ -310,17 +302,35 @@ + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + Asks before terminating the running application in response to clicking the stop button in Application Output. + + + Always ask before stopping applications + + + - widget_1 - automaticallyCreateRunConfiguration - saveAllFilesCheckBox - buildProjectBeforeDeployCheckBox - deployProjectBeforeRunCheckBox - promptToStopRunControlCheckBox - addLibraryPathsToRunEnvCheckBox - clearIssuesCheckBox - abortBuildAllOnErrorCheckBox - lowBuildPriorityCheckBox diff --git a/src/plugins/projectexplorer/runconfiguration.cpp b/src/plugins/projectexplorer/runconfiguration.cpp index a266dd58184..74959b5938c 100644 --- a/src/plugins/projectexplorer/runconfiguration.cpp +++ b/src/plugins/projectexplorer/runconfiguration.cpp @@ -33,6 +33,7 @@ #include "kitinformation.h" #include "project.h" #include "projectexplorer.h" +#include "projectnodes.h" #include "runconfigurationaspects.h" #include "runcontrol.h" #include "session.h" @@ -326,6 +327,13 @@ BuildTargetInfo RunConfiguration::buildTargetInfo() const return bs->buildTarget(m_buildKey); } +ProjectNode *RunConfiguration::productNode() const +{ + return project()->rootProjectNode()->findProjectNode([this](const ProjectNode *candidate) { + return candidate->buildKey() == buildKey(); + }); +} + bool RunConfiguration::fromMap(const QVariantMap &map) { if (!ProjectConfiguration::fromMap(map)) diff --git a/src/plugins/projectexplorer/runconfiguration.h b/src/plugins/projectexplorer/runconfiguration.h index 404b50b61b5..b154dae1c2d 100644 --- a/src/plugins/projectexplorer/runconfiguration.h +++ b/src/plugins/projectexplorer/runconfiguration.h @@ -45,6 +45,7 @@ namespace ProjectExplorer { class BuildConfiguration; class BuildSystem; class GlobalOrProjectAspect; +class ProjectNode; class Runnable; class RunConfigurationFactory; class RunConfiguration; @@ -155,6 +156,8 @@ public: // The BuildTargetInfo corresponding to the buildKey. BuildTargetInfo buildTargetInfo() const; + ProjectExplorer::ProjectNode *productNode() const; + template T *currentSettings(Core::Id id) const { if (auto a = qobject_cast(aspect(id))) diff --git a/src/plugins/qbsprojectmanager/qbsbuildconfiguration.cpp b/src/plugins/qbsprojectmanager/qbsbuildconfiguration.cpp index 1ce47c7043b..4cd7b63f55d 100644 --- a/src/plugins/qbsprojectmanager/qbsbuildconfiguration.cpp +++ b/src/plugins/qbsprojectmanager/qbsbuildconfiguration.cpp @@ -191,6 +191,17 @@ bool QbsBuildConfiguration::fromMap(const QVariantMap &map) return true; } +void QbsBuildConfiguration::restrictNextBuild(const RunConfiguration *rc) +{ + if (!rc) { + setProducts({}); + return; + } + const auto productNode = dynamic_cast(rc->productNode()); + QTC_ASSERT(productNode, return); + setProducts({productNode->fullDisplayName()}); +} + QbsBuildStep *QbsBuildConfiguration::qbsStep() const { return stepList(ProjectExplorer::Constants::BUILDSTEPS_BUILD)->firstOfType(); diff --git a/src/plugins/qbsprojectmanager/qbsbuildconfiguration.h b/src/plugins/qbsprojectmanager/qbsbuildconfiguration.h index e34151f058c..c92291a0b38 100644 --- a/src/plugins/qbsprojectmanager/qbsbuildconfiguration.h +++ b/src/plugins/qbsprojectmanager/qbsbuildconfiguration.h @@ -86,6 +86,7 @@ signals: private: bool fromMap(const QVariantMap &map) override; + void restrictNextBuild(const ProjectExplorer::RunConfiguration *rc) override; void triggerReparseIfActive(); QStringList m_changedFiles; diff --git a/src/plugins/qbsprojectmanager/qbsnodes.cpp b/src/plugins/qbsprojectmanager/qbsnodes.cpp index b4cea58f800..fc632447e79 100644 --- a/src/plugins/qbsprojectmanager/qbsnodes.cpp +++ b/src/plugins/qbsprojectmanager/qbsnodes.cpp @@ -135,11 +135,16 @@ QStringList QbsProductNode::targetApplications() const return QStringList{m_productData.value("target-executable").toString()}; } -QString QbsProductNode::buildKey() const +QString QbsProductNode::fullDisplayName() const { return m_productData.value("full-display-name").toString(); } +QString QbsProductNode::buildKey() const +{ + return fullDisplayName(); +} + QVariant QbsProductNode::data(Core::Id role) const { if (role == Android::Constants::AndroidDeploySettingsFile) { diff --git a/src/plugins/qbsprojectmanager/qbsnodes.h b/src/plugins/qbsprojectmanager/qbsnodes.h index 9c7457ad0ce..51c6a76094b 100644 --- a/src/plugins/qbsprojectmanager/qbsnodes.h +++ b/src/plugins/qbsprojectmanager/qbsnodes.h @@ -60,6 +60,7 @@ public: void build() override; QStringList targetApplications() const override; + QString fullDisplayName() const; QString buildKey() const override; const QJsonObject productData() const { return m_productData; } diff --git a/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp b/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp index f2647949196..2e852376e69 100644 --- a/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp +++ b/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.cpp @@ -886,4 +886,15 @@ bool QmakeBuildConfiguration::regenerateBuildFiles(Node *node) return true; } +void QmakeBuildConfiguration::restrictNextBuild(const RunConfiguration *rc) +{ + if (!rc) { + setSubNodeBuild(nullptr); + return; + } + const auto productNode = dynamic_cast(rc->productNode()); + QTC_ASSERT(productNode, return); + setSubNodeBuild(productNode); +} + } // namespace QmakeProjectManager diff --git a/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.h b/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.h index c1fd8420e22..edb27829216 100644 --- a/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.h +++ b/src/plugins/qmakeprojectmanager/qmakebuildconfiguration.h @@ -125,6 +125,8 @@ protected: bool regenerateBuildFiles(ProjectExplorer::Node *node = nullptr) override; private: + void restrictNextBuild(const ProjectExplorer::RunConfiguration *rc) override; + void kitChanged(); void toolChainUpdated(ProjectExplorer::ToolChain *tc); void qtVersionsChanged(const QList &, const QList &, const QList &changed);