diff --git a/doc/src/projects/creator-only/creator-projects-building.qdoc b/doc/src/projects/creator-only/creator-projects-building.qdoc index 86b8b617489..92202b4e42f 100644 --- a/doc/src/projects/creator-only/creator-projects-building.qdoc +++ b/doc/src/projects/creator-only/creator-projects-building.qdoc @@ -78,6 +78,10 @@ \section1 Additional Build Commands + To build the current project in all its configurations, that is, for + all build configurations in all enabled kits, select + \uicontrol Build > \uicontrol {Build Project for all Configurations}. + To build all open projects, select \uicontrol Build > \uicontrol {Build All}. If building one application fails, \QC displays an error message and continues building the other applications. diff --git a/src/plugins/projectexplorer/buildmanager.cpp b/src/plugins/projectexplorer/buildmanager.cpp index e1bc5b2b008..f48f7530165 100644 --- a/src/plugins/projectexplorer/buildmanager.cpp +++ b/src/plugins/projectexplorer/buildmanager.cpp @@ -68,8 +68,24 @@ static QString msgProgress(int progress, int total) return BuildManager::tr("Finished %1 of %n steps", nullptr, total).arg(progress); } +static const QList targetsForSelection(const Project *project, + ConfigSelection targetSelection) +{ + if (targetSelection == ConfigSelection::All) + return project->targets(); + return {project->activeTarget()}; +} + +static const QList buildConfigsForSelection(const Target *target, + ConfigSelection configSelection) +{ + if (configSelection == ConfigSelection::All) + return target->buildConfigurations(); + return {target->activeBuildConfiguration()}; +} + static int queue(const QList &projects, const QList &stepIds, - const RunConfiguration *forRunConfig = nullptr) + ConfigSelection configSelection, const RunConfiguration *forRunConfig = nullptr) { if (!ProjectExplorerPlugin::saveModifiedFiles()) return -1; @@ -80,7 +96,7 @@ static int queue(const QList &projects, const QList &stepIds, StopBeforeBuild stopCondition = settings.stopBeforeBuild; if (stopCondition == StopBeforeBuild::SameApp && !forRunConfig) stopCondition = StopBeforeBuild::SameBuildDir; - const auto isStoppableRc = [&projects, stopCondition, forRunConfig](RunControl *rc) { + const auto isStoppableRc = [&projects, stopCondition, configSelection, forRunConfig](RunControl *rc) { if (!rc->isRunning()) return false; @@ -92,18 +108,20 @@ static int queue(const QList &projects, const QList &stepIds, case StopBeforeBuild::SameProject: return projects.contains(rc->project()); case StopBeforeBuild::SameBuildDir: - return Utils::contains(projects, [rc](Project *p) { - Target *t = p ? p->activeTarget() : nullptr; - BuildConfiguration *bc = t ? t->activeBuildConfiguration() : nullptr; - if (!bc) - return false; - if (!rc->runnable().executable.isChildOf(bc->buildDirectory())) - return false; + return Utils::contains(projects, [rc, configSelection](Project *p) { IDevice::ConstPtr device = rc->runnable().device; - if (device.isNull()) - device = DeviceKitAspect::device(t->kit()); - return !device.isNull() - && device->type() == Core::Id(Constants::DESKTOP_DEVICE_TYPE); + for (const Target * const t : targetsForSelection(p, configSelection)) { + if (device.isNull()) + device = DeviceKitAspect::device(t->kit()); + if (device.isNull() || device->type() != Constants::DESKTOP_DEVICE_TYPE) + continue; + for (const BuildConfiguration * const bc + : buildConfigsForSelection(t, configSelection)) { + if (rc->runnable().executable.isChildOf(bc->buildDirectory())) + return true; + } + } + return false; }); case StopBeforeBuild::SameApp: QTC_ASSERT(forRunConfig, return false); @@ -152,21 +170,28 @@ static int queue(const QList &projects, const QList &stepIds, } } foreach (Id id, stepIds) { + const bool isBuild = id == Constants::BUILDSTEPS_BUILD; + const bool isClean = id == Constants::BUILDSTEPS_CLEAN; + const bool isDeploy = id == Constants::BUILDSTEPS_DEPLOY; foreach (Project *pro, projects) { if (!pro || pro->needsConfiguration()) continue; BuildStepList *bsl = nullptr; - Target *target = pro->activeTarget(); - if (id == Constants::BUILDSTEPS_DEPLOY && target->activeDeployConfiguration()) - bsl = target->activeDeployConfiguration()->stepList(); - else if (id == Constants::BUILDSTEPS_BUILD && target->activeBuildConfiguration()) - bsl = target->activeBuildConfiguration()->buildSteps(); - else if (id == Constants::BUILDSTEPS_CLEAN && target->activeBuildConfiguration()) - bsl = target->activeBuildConfiguration()->cleanSteps(); - - if (!bsl || bsl->isEmpty()) - continue; - stepLists << bsl; + for (const Target * target : targetsForSelection(pro, configSelection)) { + if (isBuild || isClean) { + for (const BuildConfiguration * const bc + : buildConfigsForSelection(target, configSelection)) { + bsl = isBuild ? bc->buildSteps() : bc->cleanSteps(); + if (bsl && !bsl->isEmpty()) + stepLists << bsl; + } + continue; + } + if (isDeploy && target->activeDeployConfiguration()) + bsl = target->activeDeployConfiguration()->stepList(); + if (bsl && !bsl->isEmpty()) + stepLists << bsl; + } } } @@ -266,48 +291,53 @@ void BuildManager::extensionsInitialized() void BuildManager::buildProjectWithoutDependencies(Project *project) { - queue({project}, {Id(Constants::BUILDSTEPS_BUILD)}); + queue({project}, {Id(Constants::BUILDSTEPS_BUILD)}, ConfigSelection::Active); } void BuildManager::cleanProjectWithoutDependencies(Project *project) { - queue({project}, {Id(Constants::BUILDSTEPS_CLEAN)}); + queue({project}, {Id(Constants::BUILDSTEPS_CLEAN)}, ConfigSelection::Active); } void BuildManager::rebuildProjectWithoutDependencies(Project *project) { - queue({project}, {Id(Constants::BUILDSTEPS_CLEAN), Id(Constants::BUILDSTEPS_BUILD)}); + queue({project}, {Id(Constants::BUILDSTEPS_CLEAN), Id(Constants::BUILDSTEPS_BUILD)}, + ConfigSelection::Active); } -void BuildManager::buildProjectWithDependencies(Project *project) +void BuildManager::buildProjectWithDependencies(Project *project, ConfigSelection configSelection) { - queue(SessionManager::projectOrder(project), {Id(Constants::BUILDSTEPS_BUILD)}); + queue(SessionManager::projectOrder(project), {Id(Constants::BUILDSTEPS_BUILD)}, + configSelection); } -void BuildManager::cleanProjectWithDependencies(Project *project) +void BuildManager::cleanProjectWithDependencies(Project *project, ConfigSelection configSelection) { - queue(SessionManager::projectOrder(project), {Id(Constants::BUILDSTEPS_CLEAN)}); + queue(SessionManager::projectOrder(project), {Id(Constants::BUILDSTEPS_CLEAN)}, + configSelection); } -void BuildManager::rebuildProjectWithDependencies(Project *project) +void BuildManager::rebuildProjectWithDependencies(Project *project, ConfigSelection configSelection) { queue(SessionManager::projectOrder(project), - {Id(Constants::BUILDSTEPS_CLEAN), Id(Constants::BUILDSTEPS_BUILD)}); + {Id(Constants::BUILDSTEPS_CLEAN), Id(Constants::BUILDSTEPS_BUILD)}, + configSelection); } void BuildManager::buildProjects(const QList &projects) { - queue(projects, {Id(Constants::BUILDSTEPS_BUILD)}); + queue(projects, {Id(Constants::BUILDSTEPS_BUILD)}, ConfigSelection::Active); } void BuildManager::cleanProjects(const QList &projects) { - queue(projects, {Id(Constants::BUILDSTEPS_CLEAN)}); + queue(projects, {Id(Constants::BUILDSTEPS_CLEAN)}, ConfigSelection::Active); } void BuildManager::rebuildProjects(const QList &projects) { - queue(projects, {Id(Constants::BUILDSTEPS_CLEAN), Id(Constants::BUILDSTEPS_BUILD)}); + queue(projects, {Id(Constants::BUILDSTEPS_CLEAN), Id(Constants::BUILDSTEPS_BUILD)}, + ConfigSelection::Active); } void BuildManager::deployProjects(const QList &projects) @@ -316,7 +346,7 @@ void BuildManager::deployProjects(const QList &projects) if (ProjectExplorerPlugin::projectExplorerSettings().buildBeforeDeploy != BuildBeforeRunMode::Off) steps << Id(Constants::BUILDSTEPS_BUILD); steps << Id(Constants::BUILDSTEPS_DEPLOY); - queue(projects, steps); + queue(projects, steps, ConfigSelection::Active); } BuildForRunConfigStatus BuildManager::potentiallyBuildForRunConfig(RunConfiguration *rc) @@ -342,7 +372,8 @@ BuildForRunConfigStatus BuildManager::potentiallyBuildForRunConfig(RunConfigurat } Project * const pro = rc->target()->project(); - int queueCount = queue(SessionManager::projectOrder(pro), stepIds, rc); + const int queueCount = queue(SessionManager::projectOrder(pro), stepIds, + ConfigSelection::Active, rc); if (rc->target()->activeBuildConfiguration()) rc->target()->activeBuildConfiguration()->restrictNextBuild(nullptr); diff --git a/src/plugins/projectexplorer/buildmanager.h b/src/plugins/projectexplorer/buildmanager.h index 0c390714690..7a50f7c0f8a 100644 --- a/src/plugins/projectexplorer/buildmanager.h +++ b/src/plugins/projectexplorer/buildmanager.h @@ -40,6 +40,7 @@ class Task; class Project; enum class BuildForRunConfigStatus { Building, NotBuilding, BuildFailed }; +enum class ConfigSelection { All, Active }; class PROJECTEXPLORER_EXPORT BuildManager : public QObject { @@ -55,9 +56,12 @@ public: static void buildProjectWithoutDependencies(Project *project); static void cleanProjectWithoutDependencies(Project *project); static void rebuildProjectWithoutDependencies(Project *project); - static void buildProjectWithDependencies(Project *project); - static void cleanProjectWithDependencies(Project *project); - static void rebuildProjectWithDependencies(Project *project); + static void buildProjectWithDependencies( + Project *project, + ConfigSelection configSelection = ConfigSelection::Active + ); + static void cleanProjectWithDependencies(Project *project, ConfigSelection configSelection); + static void rebuildProjectWithDependencies(Project *project, ConfigSelection configSelection); static void buildProjects(const QList &projects); static void cleanProjects(const QList &projects); static void rebuildProjects(const QList &projects); diff --git a/src/plugins/projectexplorer/projectexplorer.cpp b/src/plugins/projectexplorer/projectexplorer.cpp index df815a626d6..b7f08aaa1fa 100644 --- a/src/plugins/projectexplorer/projectexplorer.cpp +++ b/src/plugins/projectexplorer/projectexplorer.cpp @@ -194,12 +194,14 @@ const char LOAD[] = "ProjectExplorer.Load"; const char UNLOAD[] = "ProjectExplorer.Unload"; const char UNLOADCM[] = "ProjectExplorer.UnloadCM"; const char CLEARSESSION[] = "ProjectExplorer.ClearSession"; +const char BUILDALLCONFIGS[] = "ProjectExplorer.BuildProjectForAllConfigs"; const char BUILDPROJECTONLY[] = "ProjectExplorer.BuildProjectOnly"; const char BUILDCM[] = "ProjectExplorer.BuildCM"; const char BUILDDEPENDCM[] = "ProjectExplorer.BuildDependenciesCM"; const char BUILDSESSION[] = "ProjectExplorer.BuildSession"; const char REBUILDPROJECTONLY[] = "ProjectExplorer.RebuildProjectOnly"; const char REBUILD[] = "ProjectExplorer.Rebuild"; +const char REBUILDALLCONFIGS[] = "ProjectExplorer.RebuildProjectForAllConfigs"; const char REBUILDCM[] = "ProjectExplorer.RebuildCM"; const char REBUILDDEPENDCM[] = "ProjectExplorer.RebuildDependenciesCM"; const char REBUILDSESSION[] = "ProjectExplorer.RebuildSession"; @@ -209,6 +211,7 @@ const char DEPLOYCM[] = "ProjectExplorer.DeployCM"; const char DEPLOYSESSION[] = "ProjectExplorer.DeploySession"; const char CLEANPROJECTONLY[] = "ProjectExplorer.CleanProjectOnly"; const char CLEAN[] = "ProjectExplorer.Clean"; +const char CLEANALLCONFIGS[] = "ProjectExplorer.CleanProjectForAllConfigs"; const char CLEANCM[] = "ProjectExplorer.CleanCM"; const char CLEANDEPENDCM[] = "ProjectExplorer.CleanDependenciesCM"; const char CLEANSESSION[] = "ProjectExplorer.CleanSession"; @@ -472,6 +475,7 @@ public: Utils::ParameterAction *m_unloadActionContextMenu; QAction *m_closeAllProjects; QAction *m_buildProjectOnlyAction; + Utils::ParameterAction *m_buildProjectForAllConfigsAction; Utils::ParameterAction *m_buildAction; Utils::ParameterAction *m_buildForRunConfigAction; Utils::ProxyAction *m_modeBarBuildAction; @@ -480,6 +484,7 @@ public: QAction *m_buildSessionAction; QAction *m_rebuildProjectOnlyAction; Utils::ParameterAction *m_rebuildAction; + Utils::ParameterAction *m_rebuildProjectForAllConfigsAction; QAction *m_rebuildActionContextMenu; QAction *m_rebuildDependenciesActionContextMenu; QAction *m_rebuildSessionAction; @@ -489,6 +494,7 @@ public: QAction *m_deployActionContextMenu; QAction *m_deploySessionAction; Utils::ParameterAction *m_cleanAction; + Utils::ParameterAction *m_cleanProjectForAllConfigsAction; QAction *m_cleanActionContextMenu; QAction *m_cleanDependenciesActionContextMenu; QAction *m_cleanSessionAction; @@ -1106,6 +1112,17 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er cmd->setDefaultKeySequence(QKeySequence(tr("Ctrl+B"))); mbuild->addAction(cmd, Constants::G_BUILD_BUILD); + dd->m_buildProjectForAllConfigsAction + = new Utils::ParameterAction(tr("Build Project for All Configurations"), + tr("Build Project \"%1\" for All Configurations"), + Utils::ParameterAction::AlwaysEnabled, this); + dd->m_buildProjectForAllConfigsAction->setIcon(buildIcon); + cmd = ActionManager::registerAction(dd->m_buildProjectForAllConfigsAction, + Constants::BUILDALLCONFIGS); + cmd->setAttribute(Command::CA_UpdateText); + cmd->setDescription(dd->m_buildProjectForAllConfigsAction->text()); + mbuild->addAction(cmd, Constants::G_BUILD_BUILD); + // Add to mode bar dd->m_modeBarBuildAction = new Utils::ProxyAction(this); dd->m_modeBarBuildAction->setObjectName("Build"); // used for UI introduction @@ -1141,6 +1158,16 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er cmd->setDescription(dd->m_rebuildAction->text()); mbuild->addAction(cmd, Constants::G_BUILD_REBUILD); + dd->m_rebuildProjectForAllConfigsAction + = new Utils::ParameterAction(tr("Rebuild Project for All Configurations"), + tr("Rebuild Project \"%1\" for All Configurations"), + Utils::ParameterAction::AlwaysEnabled, this); + cmd = ActionManager::registerAction(dd->m_rebuildProjectForAllConfigsAction, + Constants::REBUILDALLCONFIGS); + cmd->setAttribute(Command::CA_UpdateText); + cmd->setDescription(dd->m_rebuildProjectForAllConfigsAction->text()); + mbuild->addAction(cmd, Constants::G_BUILD_REBUILD); + // clean action dd->m_cleanAction = new Utils::ParameterAction(tr("Clean Project"), tr("Clean Project \"%1\""), Utils::ParameterAction::AlwaysEnabled, this); @@ -1149,6 +1176,16 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er cmd->setDescription(dd->m_cleanAction->text()); mbuild->addAction(cmd, Constants::G_BUILD_CLEAN); + dd->m_cleanProjectForAllConfigsAction + = new Utils::ParameterAction(tr("Clean Project for All Configurations"), + tr("Clean Project \"%1\" for All Configurations"), + Utils::ParameterAction::AlwaysEnabled, this); + cmd = ActionManager::registerAction(dd->m_cleanProjectForAllConfigsAction, + Constants::CLEANALLCONFIGS); + cmd->setAttribute(Command::CA_UpdateText); + cmd->setDescription(dd->m_cleanProjectForAllConfigsAction->text()); + mbuild->addAction(cmd, Constants::G_BUILD_CLEAN); + // cancel build action dd->m_cancelBuildAction = new QAction(Utils::Icons::STOP_SMALL.icon(), tr("Cancel Build"), this); cmd = ActionManager::registerAction(dd->m_cancelBuildAction, Constants::CANCELBUILD); @@ -1491,6 +1528,10 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er connect(dd->m_buildAction, &QAction::triggered, dd, [] { BuildManager::buildProjectWithDependencies(SessionManager::startupProject()); }); + connect(dd->m_buildProjectForAllConfigsAction, &QAction::triggered, dd, [] { + BuildManager::buildProjectWithDependencies(SessionManager::startupProject(), + ConfigSelection::All); + }); connect(dd->m_buildActionContextMenu, &QAction::triggered, dd, [] { BuildManager::buildProjectWithoutDependencies(ProjectTree::currentProject()); }); @@ -1515,13 +1556,19 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er BuildManager::rebuildProjectWithoutDependencies(SessionManager::startupProject()); }); connect(dd->m_rebuildAction, &QAction::triggered, dd, [] { - BuildManager::rebuildProjectWithDependencies(SessionManager::startupProject()); + BuildManager::rebuildProjectWithDependencies(SessionManager::startupProject(), + ConfigSelection::Active); + }); + connect(dd->m_rebuildProjectForAllConfigsAction, &QAction::triggered, dd, [] { + BuildManager::rebuildProjectWithDependencies(SessionManager::startupProject(), + ConfigSelection::All); }); connect(dd->m_rebuildActionContextMenu, &QAction::triggered, dd, [] { BuildManager::rebuildProjectWithoutDependencies(ProjectTree::currentProject()); }); connect(dd->m_rebuildDependenciesActionContextMenu, &QAction::triggered, dd, [] { - BuildManager::rebuildProjectWithDependencies(ProjectTree::currentProject()); + BuildManager::rebuildProjectWithDependencies(ProjectTree::currentProject(), + ConfigSelection::Active); }); connect(dd->m_rebuildSessionAction, &QAction::triggered, dd, [] { BuildManager::rebuildProjects(SessionManager::projectOrder()); @@ -1542,13 +1589,19 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er BuildManager::cleanProjectWithoutDependencies(SessionManager::startupProject()); }); connect(dd->m_cleanAction, &QAction::triggered, dd, [] { - BuildManager::cleanProjectWithDependencies(SessionManager::startupProject()); + BuildManager::cleanProjectWithDependencies(SessionManager::startupProject(), + ConfigSelection::Active); + }); + connect(dd->m_cleanProjectForAllConfigsAction, &QAction::triggered, dd, [] { + BuildManager::cleanProjectWithDependencies(SessionManager::startupProject(), + ConfigSelection::All); }); connect(dd->m_cleanActionContextMenu, &QAction::triggered, dd, [] { BuildManager::cleanProjectWithoutDependencies(ProjectTree::currentProject()); }); connect(dd->m_cleanDependenciesActionContextMenu, &QAction::triggered, dd, [] { - BuildManager::cleanProjectWithDependencies(ProjectTree::currentProject()); + BuildManager::cleanProjectWithDependencies(ProjectTree::currentProject(), + ConfigSelection::Active); }); connect(dd->m_cleanSessionAction, &QAction::triggered, dd, [] { BuildManager::cleanProjects(SessionManager::projectOrder()); @@ -2477,14 +2530,20 @@ void ProjectExplorerPluginPrivate::updateActions() // Normal actions m_buildAction->setParameter(projectName); + m_buildProjectForAllConfigsAction->setParameter(projectName); if (runConfig) m_buildForRunConfigAction->setParameter(runConfig->displayName()); m_rebuildAction->setParameter(projectName); + m_rebuildProjectForAllConfigsAction->setParameter(projectName); m_cleanAction->setParameter(projectName); + m_cleanProjectForAllConfigsAction->setParameter(projectName); m_buildAction->setEnabled(buildActionState.first); + m_buildProjectForAllConfigsAction->setEnabled(buildActionState.first); m_rebuildAction->setEnabled(buildActionState.first); + m_rebuildProjectForAllConfigsAction->setEnabled(buildActionState.first); m_cleanAction->setEnabled(buildActionState.first); + m_cleanProjectForAllConfigsAction->setEnabled(buildActionState.first); // The last condition is there to prevent offering this action for custom run configurations. m_buildForRunConfigAction->setEnabled(buildActionState.first @@ -2492,8 +2551,11 @@ void ProjectExplorerPluginPrivate::updateActions() && !runConfig->buildTargetInfo().projectFilePath.isEmpty()); m_buildAction->setToolTip(buildActionState.second); + m_buildProjectForAllConfigsAction->setToolTip(buildActionState.second); m_rebuildAction->setToolTip(buildActionState.second); + m_rebuildProjectForAllConfigsAction->setToolTip(buildActionState.second); m_cleanAction->setToolTip(buildActionState.second); + m_cleanProjectForAllConfigsAction->setToolTip(buildActionState.second); // Context menu actions m_setStartupProjectAction->setParameter(projectNameContextMenu);