diff options
author | Tobias Hunger <tobias.hunger@qt.io> | 2020-06-02 19:37:25 +0200 |
---|---|---|
committer | Tobias Hunger <tobias.hunger@qt.io> | 2020-06-03 08:04:50 +0000 |
commit | 2fea24fe6a63cded685bfac16c44e9b48413a635 (patch) | |
tree | 4fb83338e4b24f16af0fef6f3fdf55a11c6876a9 /src/plugins/cmakeprojectmanager/cmakebuildstep.cpp | |
parent | 10b63683fce6530fd47ae8d1c475283a68e508f4 (diff) |
CMake: Support building several targets with cmake --build
CMake supports this for a while now.
As a side effect this fixes QTCREATORBUG-23738, which was caused by the
radio button hack used to show that only one item could be selected at
a time.
Change-Id: I18cbe6c5ee3872edaf74b9d828bde1ac5bf63563
Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
Diffstat (limited to 'src/plugins/cmakeprojectmanager/cmakebuildstep.cpp')
-rw-r--r-- | src/plugins/cmakeprojectmanager/cmakebuildstep.cpp | 160 |
1 files changed, 75 insertions, 85 deletions
diff --git a/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp b/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp index fbacd50824c..da45772a13d 100644 --- a/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp +++ b/src/plugins/cmakeprojectmanager/cmakebuildstep.cpp @@ -41,11 +41,12 @@ #include <projectexplorer/runconfiguration.h> #include <projectexplorer/target.h> +#include <utils/algorithm.h> + #include <QBoxLayout> #include <QFormLayout> #include <QLineEdit> #include <QListWidget> -#include <QRadioButton> using namespace ProjectExplorer; @@ -66,14 +67,12 @@ public: explicit CMakeBuildStepConfigWidget(CMakeBuildStep *buildStep); private: - void itemChanged(QListWidgetItem *); + void itemsChanged(); void cmakeArgumentsEdited(); void toolArgumentsEdited(); void updateDetails(); void buildTargetsChanged(); - void updateBuildTarget(); - - QRadioButton *itemWidget(QListWidgetItem *item); + void updateBuildTargets(); CMakeBuildStep *m_buildStep; QLineEdit *m_cmakeArguments; @@ -96,13 +95,13 @@ CMakeBuildStep::CMakeBuildStep(BuildStepList *bsl, Core::Id id) : setDefaultDisplayName(tr("CMake Build")); // Set a good default build target: - if (m_buildTarget.isEmpty()) - setBuildTarget(defaultBuildTarget()); + if (m_buildTargets.isEmpty()) + setBuildTargets({defaultBuildTarget()}); setLowPriority(); connect(target(), &Target::parsingFinished, - this, &CMakeBuildStep::handleBuildTargetChanges); + this, &CMakeBuildStep::handleBuildTargetsChanges); } CMakeBuildConfiguration *CMakeBuildStep::cmakeBuildConfiguration() const @@ -110,12 +109,17 @@ CMakeBuildConfiguration *CMakeBuildStep::cmakeBuildConfiguration() const return static_cast<CMakeBuildConfiguration *>(buildConfiguration()); } -void CMakeBuildStep::handleBuildTargetChanges(bool success) +void CMakeBuildStep::handleBuildTargetsChanges(bool success) { if (!success) return; // Do not change when parsing failed. - if (!isCurrentExecutableTarget(m_buildTarget) && !knownBuildTargets().contains(m_buildTarget)) { - setBuildTarget(defaultBuildTarget()); + const QStringList results = Utils::filtered(m_buildTargets, [this](const QString &s) { + return knownBuildTargets().contains(s); + }); + if (results.isEmpty()) + setBuildTargets({defaultBuildTarget()}); + else { + setBuildTargets(results); } emit buildTargetsChanged(); } @@ -124,7 +128,7 @@ QVariantMap CMakeBuildStep::toMap() const { QVariantMap map(AbstractProcessStep::toMap()); // Use QStringList for compatibility with old files - map.insert(BUILD_TARGETS_KEY, QStringList(m_buildTarget)); + map.insert(BUILD_TARGETS_KEY, QStringList(m_buildTargets)); map.insert(CMAKE_ARGUMENTS_KEY, m_cmakeArguments); map.insert(TOOL_ARGUMENTS_KEY, m_toolArguments); return map; @@ -132,13 +136,11 @@ QVariantMap CMakeBuildStep::toMap() const bool CMakeBuildStep::fromMap(const QVariantMap &map) { - const QStringList targetList = map.value(BUILD_TARGETS_KEY).toStringList(); - if (!targetList.isEmpty()) - m_buildTarget = targetList.last(); + m_buildTargets = map.value(BUILD_TARGETS_KEY).toStringList(); m_cmakeArguments = map.value(CMAKE_ARGUMENTS_KEY).toString(); m_toolArguments = map.value(TOOL_ARGUMENTS_KEY).toString(); if (map.value(ADD_RUNCONFIGURATION_ARGUMENT_KEY, false).toBool()) - m_buildTarget = ADD_RUNCONFIGURATION_TEXT; + m_buildTargets = QStringList(ADD_RUNCONFIGURATION_TEXT); return BuildStep::fromMap(map); } @@ -163,7 +165,8 @@ bool CMakeBuildStep::init() } RunConfiguration *rc = target()->activeRunConfiguration(); - if (isCurrentExecutableTarget(m_buildTarget) && (!rc || rc->buildKey().isEmpty())) { + const bool buildCurrent = Utils::contains(m_buildTargets, [](const QString &s) { return isCurrentExecutableTarget(s); }); + if (buildCurrent && (!rc || rc->buildKey().isEmpty())) { emit addTask(BuildSystemTask(Task::Error, QCoreApplication::translate("ProjectExplorer::Task", "You asked to build the current Run Configuration's build target only, " @@ -189,7 +192,7 @@ bool CMakeBuildStep::init() } } - setIgnoreReturnValue(m_buildTarget == CMakeBuildStep::cleanTarget()); + setIgnoreReturnValue(m_buildTargets == QStringList(CMakeBuildStep::cleanTarget())); ProcessParameters *pp = processParameters(); pp->setMacroExpander(bc->macroExpander()); @@ -314,22 +317,22 @@ void CMakeBuildStep::stdOutput(const QString &output) } } -QString CMakeBuildStep::buildTarget() const +QStringList CMakeBuildStep::buildTargets() const { - return m_buildTarget; + return m_buildTargets; } bool CMakeBuildStep::buildsBuildTarget(const QString &target) const { - return target == m_buildTarget; + return m_buildTargets.contains(target); } -void CMakeBuildStep::setBuildTarget(const QString &buildTarget) +void CMakeBuildStep::setBuildTargets(const QStringList &buildTargets) { - if (m_buildTarget == buildTarget) + if (m_buildTargets == buildTargets) return; - m_buildTarget = buildTarget; - emit targetToBuildChanged(); + m_buildTargets = buildTargets; + emit targetsToBuildChanged(); } QString CMakeBuildStep::cmakeArguments() const @@ -359,24 +362,25 @@ Utils::CommandLine CMakeBuildStep::cmakeCommand(RunConfiguration *rc) const Utils::CommandLine cmd(tool ? tool->cmakeExecutable() : Utils::FilePath(), {}); cmd.addArgs({"--build", "."}); - QString target; - - if (isCurrentExecutableTarget(m_buildTarget)) { - if (rc) { - target = rc->buildKey(); - const int pos = target.indexOf("///::///"); - if (pos >= 0) { - target = target.mid(pos + 8); + cmd.addArg("--target"); + cmd.addArgs(Utils::transform(m_buildTargets, [rc](const QString &s) { + QString target = s; + if (isCurrentExecutableTarget(s)) { + if (rc) { + target = rc->buildKey(); + const int pos = target.indexOf("///::///"); + if (pos >= 0) { + target = target.mid(pos + 8); + } + } else { + target = "<i><" + tr(ADD_RUNCONFIGURATION_TEXT) + "></i>"; } - } else { - target = "<i><" + tr(ADD_RUNCONFIGURATION_TEXT) + "></i>"; } - } else { - target = m_buildTarget; - } + return target; + })); - cmd.addArgs({"--target", target}); - cmd.addArgs(m_cmakeArguments, Utils::CommandLine::Raw); + if (!m_cmakeArguments.isEmpty()) + cmd.addArgs(m_cmakeArguments, Utils::CommandLine::Raw); if (!m_toolArguments.isEmpty()) { cmd.addArg("--"); @@ -457,7 +461,7 @@ CMakeBuildStepConfigWidget::CMakeBuildStepConfigWidget(CMakeBuildStep *buildStep connect(m_cmakeArguments, &QLineEdit::textEdited, this, &CMakeBuildStepConfigWidget::cmakeArgumentsEdited); connect(m_toolArguments, &QLineEdit::textEdited, this, &CMakeBuildStepConfigWidget::toolArgumentsEdited); - connect(m_buildTargetsList, &QListWidget::itemChanged, this, &CMakeBuildStepConfigWidget::itemChanged); + connect(m_buildTargetsList, &QListWidget::itemChanged, this, &CMakeBuildStepConfigWidget::itemsChanged); connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::settingsChanged, this, &CMakeBuildStepConfigWidget::updateDetails); @@ -467,9 +471,9 @@ CMakeBuildStepConfigWidget::CMakeBuildStepConfigWidget(CMakeBuildStep *buildStep &CMakeBuildStepConfigWidget::buildTargetsChanged); connect(m_buildStep, - &CMakeBuildStep::targetToBuildChanged, + &CMakeBuildStep::targetsToBuildChanged, this, - &CMakeBuildStepConfigWidget::updateBuildTarget); + &CMakeBuildStepConfigWidget::updateBuildTargets); connect(m_buildStep->buildConfiguration(), &BuildConfiguration::environmentChanged, @@ -488,28 +492,32 @@ void CMakeBuildStepConfigWidget::toolArgumentsEdited() updateDetails(); } -void CMakeBuildStepConfigWidget::itemChanged(QListWidgetItem *item) +void CMakeBuildStepConfigWidget::itemsChanged() { - const QString target = - (item->checkState() == Qt::Checked) ? item->data(Qt::UserRole).toString() : CMakeBuildStep::allTarget(); - m_buildStep->setBuildTarget(target); + const QList<QListWidgetItem *> items = [this]() { + QList<QListWidgetItem *> items; + for (int row = 0; row < m_buildTargetsList->count(); ++row) + items.append(m_buildTargetsList->item(row)); + return items; + }(); + const QStringList targetsToBuild = Utils::transform(Utils::filtered(items, Utils::equal(&QListWidgetItem::checkState, Qt::Checked)), + [](const QListWidgetItem *i) { return i->data(Qt::UserRole).toString(); }); + m_buildStep->setBuildTargets(targetsToBuild); updateDetails(); } void CMakeBuildStepConfigWidget::buildTargetsChanged() { { - auto addItem = [this](const QString &buildTarget, - const QString &displayName) { - auto item = new QListWidgetItem(m_buildTargetsList); - auto button = new QRadioButton(displayName); - connect(button, &QRadioButton::toggled, this, [this, buildTarget](bool toggled) { - if (toggled) { - m_buildStep->setBuildTarget(buildTarget); - } - }); - m_buildTargetsList->setItemWidget(item, button); + QFont italics; + italics.setItalic(true); + + auto addItem = [italics, this](const QString &buildTarget, const QString &displayName, bool special = false) { + auto item = new QListWidgetItem(displayName, m_buildTargetsList); + item->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled); item->setData(Qt::UserRole, buildTarget); + if (special) + item->setFont(italics); }; QSignalBlocker blocker(m_buildTargetsList); @@ -518,52 +526,34 @@ void CMakeBuildStepConfigWidget::buildTargetsChanged() QStringList targetList = m_buildStep->knownBuildTargets(); targetList.sort(); - QFont italics; - italics.setItalic(true); + addItem(ADD_RUNCONFIGURATION_TEXT, tr(ADD_RUNCONFIGURATION_TEXT), true); - addItem(ADD_RUNCONFIGURATION_TEXT, tr(ADD_RUNCONFIGURATION_TEXT)); + foreach (const QString &buildTarget, CMakeBuildStep::specialTargets()) + addItem(buildTarget, buildTarget, true); foreach (const QString &buildTarget, targetList) addItem(buildTarget, buildTarget); - for (int i = 0; i < m_buildTargetsList->count(); ++i) { - QListWidgetItem *item = m_buildTargetsList->item(i); - const QString title = item->data(Qt::UserRole).toString(); - QRadioButton *radio = itemWidget(item); - - radio->setChecked(m_buildStep->buildsBuildTarget(title)); - - // Print utility targets in italics: - if (CMakeBuildStep::specialTargets().contains(title) || title == ADD_RUNCONFIGURATION_TEXT) - radio->setFont(italics); - } + updateBuildTargets(); } updateDetails(); } -void CMakeBuildStepConfigWidget::updateBuildTarget() +void CMakeBuildStepConfigWidget::updateBuildTargets() { - const QString buildTarget = m_buildStep->buildTarget(); + const QStringList buildTargets = m_buildStep->buildTargets(); { QSignalBlocker blocker(m_buildTargetsList); - for (int y = 0; y < m_buildTargetsList->count(); ++y) { - QListWidgetItem *item = m_buildTargetsList->item(y); - const QString itemTarget = item->data(Qt::UserRole).toString(); + for (int row = 0; row < m_buildTargetsList->count(); ++row) { + QListWidgetItem *item = m_buildTargetsList->item(row); + const QString title = item->data(Qt::UserRole).toString(); - if (itemTarget == buildTarget) { - QRadioButton *radio = itemWidget(item); - radio->setChecked(true); - } + item->setCheckState(m_buildStep->buildsBuildTarget(title) ? Qt::Checked : Qt::Unchecked); } } updateDetails(); } -QRadioButton *CMakeBuildStepConfigWidget::itemWidget(QListWidgetItem *item) -{ - return static_cast<QRadioButton *>(m_buildTargetsList->itemWidget(item)); -} - void CMakeBuildStepConfigWidget::updateDetails() { ProcessParameters param; |