ProjectExplorer: Allow to build a project in all configurations

Task-number: QTCREATORBUG-16815
Change-Id: I5c31878f005f8350b3e4aff88ad46ab93c804ce4
Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io>
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Christian Kandeler
2020-01-20 16:54:38 +01:00
parent 12ee28f090
commit 12184b9546
4 changed files with 146 additions and 45 deletions

View File

@@ -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.

View File

@@ -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<Target *> targetsForSelection(const Project *project,
ConfigSelection targetSelection)
{
if (targetSelection == ConfigSelection::All)
return project->targets();
return {project->activeTarget()};
}
static const QList<BuildConfiguration *> buildConfigsForSelection(const Target *target,
ConfigSelection configSelection)
{
if (configSelection == ConfigSelection::All)
return target->buildConfigurations();
return {target->activeBuildConfiguration()};
}
static int queue(const QList<Project *> &projects, const QList<Id> &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<Project *> &projects, const QList<Id> &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<Project *> &projects, const QList<Id> &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<Project *> &projects, const QList<Id> &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<Project *> &projects)
{
queue(projects, {Id(Constants::BUILDSTEPS_BUILD)});
queue(projects, {Id(Constants::BUILDSTEPS_BUILD)}, ConfigSelection::Active);
}
void BuildManager::cleanProjects(const QList<Project *> &projects)
{
queue(projects, {Id(Constants::BUILDSTEPS_CLEAN)});
queue(projects, {Id(Constants::BUILDSTEPS_CLEAN)}, ConfigSelection::Active);
}
void BuildManager::rebuildProjects(const QList<Project *> &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<Project *> &projects)
@@ -316,7 +346,7 @@ void BuildManager::deployProjects(const QList<Project *> &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);

View File

@@ -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<Project *> &projects);
static void cleanProjects(const QList<Project *> &projects);
static void rebuildProjects(const QList<Project *> &projects);

View File

@@ -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);