QbsProjectManager: Add selection of abis for the android target

If the target is android and the qt version has more than one abi
then display a widget to select them in the build configuration.

Change-Id: I9d3ab60a0a1f4aba2e1250c495fa25917b254287
Reviewed-by: Christian Kandeler <christian.kandeler@qt.io>
This commit is contained in:
Raphaël Cotty
2020-12-18 21:08:01 +01:00
parent 212e3b349a
commit 9b8be3b3d5
4 changed files with 155 additions and 12 deletions

View File

@@ -1266,6 +1266,14 @@ void MultiSelectionAspect::toMap(QVariantMap &data) const
saveToMap(data, d->m_value, QStringList()); saveToMap(data, d->m_value, QStringList());
} }
void MultiSelectionAspect::setVisibleDynamic(bool visible)
{
if (d->m_label)
d->m_label->setVisible(visible);
if (d->m_listView)
d->m_listView->setVisible(visible);
}
void MultiSelectionAspect::setDisplayStyle(MultiSelectionAspect::DisplayStyle style) void MultiSelectionAspect::setDisplayStyle(MultiSelectionAspect::DisplayStyle style)
{ {
d->m_displayStyle = style; d->m_displayStyle = style;

View File

@@ -225,6 +225,9 @@ public:
void fromMap(const QVariantMap &map) override; void fromMap(const QVariantMap &map) override;
void toMap(QVariantMap &map) const override; void toMap(QVariantMap &map) const override;
protected:
void setVisibleDynamic(bool visible) override;
private: private:
std::unique_ptr<Internal::MultiSelectionAspectPrivate> d; std::unique_ptr<Internal::MultiSelectionAspectPrivate> d;
}; };

View File

@@ -38,6 +38,7 @@
#include <projectexplorer/projectexplorerconstants.h> #include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/target.h> #include <projectexplorer/target.h>
#include <qtsupport/qtkitinformation.h>
#include <qtsupport/qtversionmanager.h> #include <qtsupport/qtversionmanager.h>
#include <utils/aspects.h> #include <utils/aspects.h>
@@ -68,11 +69,98 @@ const char QBS_INSTALL[] = "Qbs.Install";
const char QBS_CLEAN_INSTALL_ROOT[] = "Qbs.CleanInstallRoot"; const char QBS_CLEAN_INSTALL_ROOT[] = "Qbs.CleanInstallRoot";
using namespace ProjectExplorer; using namespace ProjectExplorer;
using namespace QtSupport;
using namespace Utils; using namespace Utils;
namespace QbsProjectManager { namespace QbsProjectManager {
namespace Internal { namespace Internal {
class QTSUPPORT_EXPORT ArchitecturesAspect : public Utils::MultiSelectionAspect
{
Q_OBJECT
public:
ArchitecturesAspect();
void setKit(const ProjectExplorer::Kit *kit) { m_kit = kit; }
void addToLayout(Utils::LayoutBuilder &builder) override;
QStringList selectedArchitectures() const;
void setSelectedArchitectures(const QStringList& architectures);
bool isManagedByTarget() const { return m_isManagedByTarget; }
private:
void setVisibleDynamic(bool visible) final;
const ProjectExplorer::Kit *m_kit = nullptr;
QMap<QString, QString> m_abisToArchMap;
bool m_isManagedByTarget = false;
};
ArchitecturesAspect::ArchitecturesAspect()
{
m_abisToArchMap = {
{ProjectExplorer::Constants::ANDROID_ABI_ARMEABI_V7A, "armv7a"},
{ProjectExplorer::Constants::ANDROID_ABI_ARM64_V8A, "arm64"},
{ProjectExplorer::Constants::ANDROID_ABI_X86, "x86"},
{ProjectExplorer::Constants::ANDROID_ABI_X86_64, "x86_64"}};
setAllValues(m_abisToArchMap.keys());
}
void ArchitecturesAspect::addToLayout(LayoutBuilder &builder)
{
MultiSelectionAspect::addToLayout(builder);
const auto changeHandler = [this] {
const BaseQtVersion *qtVersion = QtKitAspect::qtVersion(m_kit);
if (!qtVersion) {
setVisibleDynamic(false);
return;
}
const Abis abis = qtVersion->qtAbis();
if (abis.size() <= 1) {
setVisibleDynamic(false);
return;
}
bool isAndroid = Utils::anyOf(abis, [](const Abi &abi) {
return abi.osFlavor() == Abi::OSFlavor::AndroidLinuxFlavor;
});
if (!isAndroid) {
setVisibleDynamic(false);
return;
}
setVisibleDynamic(true);
};
connect(KitManager::instance(), &KitManager::kitsChanged, builder.layout(), changeHandler);
connect(this, &ArchitecturesAspect::changed, builder.layout(), changeHandler);
changeHandler();
}
QStringList ArchitecturesAspect::selectedArchitectures() const
{
QStringList architectures;
for (const auto &abi : value()) {
if (m_abisToArchMap.contains(abi))
architectures << m_abisToArchMap[abi];
}
return architectures;
}
void ArchitecturesAspect::setVisibleDynamic(bool visible)
{
MultiSelectionAspect::setVisibleDynamic(visible);
m_isManagedByTarget = visible;
}
void ArchitecturesAspect::setSelectedArchitectures(const QStringList& architectures)
{
QStringList newValue;
for (auto i = m_abisToArchMap.constBegin(); i != m_abisToArchMap.constEnd(); ++i) {
if (architectures.contains(i.value()))
newValue << i.key();
}
if (newValue != value())
setValue(newValue);
}
class QbsBuildStepConfigWidget : public QWidget class QbsBuildStepConfigWidget : public QWidget
{ {
Q_OBJECT Q_OBJECT
@@ -142,6 +230,11 @@ QbsBuildStep::QbsBuildStep(BuildStepList *bsl, Utils::Id id) :
m_buildVariant->addOption(tr("Debug")); m_buildVariant->addOption(tr("Debug"));
m_buildVariant->addOption(tr("Release")); m_buildVariant->addOption(tr("Release"));
m_selectedAbis = addAspect<ArchitecturesAspect>();
m_selectedAbis->setLabelText(tr("ABIs:"));
m_selectedAbis->setDisplayStyle(MultiSelectionAspect::DisplayStyle::ListView);
m_selectedAbis->setKit(target()->kit());
m_keepGoing = addAspect<BoolAspect>(); m_keepGoing = addAspect<BoolAspect>();
m_keepGoing->setSettingsKey(QBS_KEEP_GOING); m_keepGoing->setSettingsKey(QBS_KEEP_GOING);
m_keepGoing->setToolTip(tr("Keep going when errors occur (if at all possible).")); m_keepGoing->setToolTip(tr("Keep going when errors occur (if at all possible)."));
@@ -188,6 +281,8 @@ QbsBuildStep::QbsBuildStep(BuildStepList *bsl, Utils::Id id) :
connect(m_forceProbes, &BaseAspect::changed, this, &QbsBuildStep::updateState); connect(m_forceProbes, &BaseAspect::changed, this, &QbsBuildStep::updateState);
connect(m_buildVariant, &SelectionAspect::changed, this, &QbsBuildStep::changeBuildVariant); connect(m_buildVariant, &SelectionAspect::changed, this, &QbsBuildStep::changeBuildVariant);
connect(m_selectedAbis, &SelectionAspect::changed, [this] {
setConfiguredArchitectures(m_selectedAbis->selectedArchitectures()); });
} }
QbsBuildStep::~QbsBuildStep() QbsBuildStep::~QbsBuildStep()
@@ -501,6 +596,23 @@ void QbsBuildStep::updateState()
emit qbsConfigurationChanged(); emit qbsConfigurationChanged();
} }
void QbsBuildStep::setConfiguredArchitectures(const QStringList &architectures)
{
if (configuredArchitectures() == architectures)
return;
if (architectures.isEmpty())
m_qbsConfiguration.remove(Constants::QBS_ARCHITECTURES);
else
m_qbsConfiguration.insert(Constants::QBS_ARCHITECTURES, architectures.join(','));
emit qbsConfigurationChanged();
}
QStringList QbsBuildStep::configuredArchitectures() const
{
return m_qbsConfiguration[Constants::QBS_ARCHITECTURES].toString().split(',',
Qt::SkipEmptyParts);
}
QbsBuildStepData QbsBuildStep::stepData() const QbsBuildStepData QbsBuildStep::stepData() const
{ {
QbsBuildStepData data; QbsBuildStepData data;
@@ -558,6 +670,7 @@ QbsBuildStepConfigWidget::QbsBuildStepConfigWidget(QbsBuildStep *step) :
LayoutBuilder builder(this); LayoutBuilder builder(this);
builder.addRow(m_qbsStep->m_buildVariant); builder.addRow(m_qbsStep->m_buildVariant);
builder.addRow(m_qbsStep->m_selectedAbis);
builder.addRow(m_qbsStep->m_maxJobCount); builder.addRow(m_qbsStep->m_maxJobCount);
builder.addRow({tr("Properties:"), propertyEdit}); builder.addRow({tr("Properties:"), propertyEdit});
@@ -600,16 +713,25 @@ void QbsBuildStepConfigWidget::updateState()
updatePropertyEdit(m_qbsStep->qbsConfiguration(QbsBuildStep::PreserveVariables)); updatePropertyEdit(m_qbsStep->qbsConfiguration(QbsBuildStep::PreserveVariables));
installDirChooser->setFilePath(m_qbsStep->installRoot(QbsBuildStep::PreserveVariables)); installDirChooser->setFilePath(m_qbsStep->installRoot(QbsBuildStep::PreserveVariables));
defaultInstallDirCheckBox->setChecked(!m_qbsStep->hasCustomInstallRoot()); defaultInstallDirCheckBox->setChecked(!m_qbsStep->hasCustomInstallRoot());
m_qbsStep->m_selectedAbis->setSelectedArchitectures(m_qbsStep->configuredArchitectures());
} }
const auto qbsBuildConfig = static_cast<QbsBuildConfiguration *>(qbsStep()->buildConfiguration()); const auto qbsBuildConfig = static_cast<QbsBuildConfiguration *>(m_qbsStep->buildConfiguration());
QString command = qbsBuildConfig->equivalentCommandLine(qbsStep()->stepData()); QString command = qbsBuildConfig->equivalentCommandLine(m_qbsStep->stepData());
for (int i = 0; i < m_propertyCache.count(); ++i) { for (int i = 0; i < m_propertyCache.count(); ++i) {
command += ' ' + m_propertyCache.at(i).name + ':' + m_propertyCache.at(i).effectiveValue; command += ' ' + m_propertyCache.at(i).name + ':' + m_propertyCache.at(i).effectiveValue;
} }
if (m_qbsStep->m_selectedAbis->isManagedByTarget()) {
QStringList selectedArchitectures = m_qbsStep->configuredArchitectures();
if (!selectedArchitectures.isEmpty()) {
command += ' ' + QLatin1String(Constants::QBS_ARCHITECTURES) + ':' +
selectedArchitectures.join(',');
}
}
const auto addToCommand = [&command](TriState ts, const QString &key) { const auto addToCommand = [&command](TriState ts, const QString &key) {
if (ts == TriState::Enabled) if (ts == TriState::Enabled)
command.append(' ').append(key).append(":true"); command.append(' ').append(key).append(":true");
@@ -644,6 +766,8 @@ void QbsBuildStepConfigWidget::updatePropertyEdit(const QVariantMap &data)
editable.remove(Constants::QBS_CONFIG_QUICK_COMPILER_KEY); editable.remove(Constants::QBS_CONFIG_QUICK_COMPILER_KEY);
editable.remove(Constants::QBS_FORCE_PROBES_KEY); editable.remove(Constants::QBS_FORCE_PROBES_KEY);
editable.remove(Constants::QBS_INSTALL_ROOT_KEY); editable.remove(Constants::QBS_INSTALL_ROOT_KEY);
if (m_qbsStep->m_selectedAbis->isManagedByTarget())
editable.remove(Constants::QBS_ARCHITECTURES);
QStringList propertyList; QStringList propertyList;
for (QVariantMap::const_iterator i = editable.constBegin(); i != editable.constEnd(); ++i) for (QVariantMap::const_iterator i = editable.constBegin(); i != editable.constEnd(); ++i)
@@ -665,42 +789,44 @@ void QbsBuildStep::changeBuildVariant()
void QbsBuildStepConfigWidget::changeUseDefaultInstallDir(bool useDefault) void QbsBuildStepConfigWidget::changeUseDefaultInstallDir(bool useDefault)
{ {
m_ignoreChange = true; m_ignoreChange = true;
QVariantMap config = qbsStep()->qbsConfiguration(QbsBuildStep::PreserveVariables); QVariantMap config = m_qbsStep->qbsConfiguration(QbsBuildStep::PreserveVariables);
installDirChooser->setEnabled(!useDefault); installDirChooser->setEnabled(!useDefault);
if (useDefault) if (useDefault)
config.remove(Constants::QBS_INSTALL_ROOT_KEY); config.remove(Constants::QBS_INSTALL_ROOT_KEY);
else else
config.insert(Constants::QBS_INSTALL_ROOT_KEY, installDirChooser->rawPath()); config.insert(Constants::QBS_INSTALL_ROOT_KEY, installDirChooser->rawPath());
qbsStep()->setQbsConfiguration(config); m_qbsStep->setQbsConfiguration(config);
m_ignoreChange = false; m_ignoreChange = false;
} }
void QbsBuildStepConfigWidget::changeInstallDir(const QString &dir) void QbsBuildStepConfigWidget::changeInstallDir(const QString &dir)
{ {
if (!qbsStep()->hasCustomInstallRoot()) if (!m_qbsStep->hasCustomInstallRoot())
return; return;
m_ignoreChange = true; m_ignoreChange = true;
QVariantMap config = qbsStep()->qbsConfiguration(QbsBuildStep::PreserveVariables); QVariantMap config = m_qbsStep->qbsConfiguration(QbsBuildStep::PreserveVariables);
config.insert(Constants::QBS_INSTALL_ROOT_KEY, dir); config.insert(Constants::QBS_INSTALL_ROOT_KEY, dir);
qbsStep()->setQbsConfiguration(config); m_qbsStep->setQbsConfiguration(config);
m_ignoreChange = false; m_ignoreChange = false;
} }
void QbsBuildStepConfigWidget::applyCachedProperties() void QbsBuildStepConfigWidget::applyCachedProperties()
{ {
QVariantMap data; QVariantMap data;
const QVariantMap tmp = qbsStep()->qbsConfiguration(QbsBuildStep::PreserveVariables); const QVariantMap tmp = m_qbsStep->qbsConfiguration(QbsBuildStep::PreserveVariables);
// Insert values set up with special UIs: // Insert values set up with special UIs:
data.insert(Constants::QBS_CONFIG_PROFILE_KEY, data.insert(Constants::QBS_CONFIG_PROFILE_KEY,
tmp.value(Constants::QBS_CONFIG_PROFILE_KEY)); tmp.value(Constants::QBS_CONFIG_PROFILE_KEY));
data.insert(Constants::QBS_CONFIG_VARIANT_KEY, data.insert(Constants::QBS_CONFIG_VARIANT_KEY,
tmp.value(Constants::QBS_CONFIG_VARIANT_KEY)); tmp.value(Constants::QBS_CONFIG_VARIANT_KEY));
const QStringList additionalSpecialKeys({Constants::QBS_CONFIG_DECLARATIVE_DEBUG_KEY, QStringList additionalSpecialKeys({Constants::QBS_CONFIG_DECLARATIVE_DEBUG_KEY,
Constants::QBS_CONFIG_QUICK_DEBUG_KEY, Constants::QBS_CONFIG_QUICK_DEBUG_KEY,
Constants::QBS_CONFIG_QUICK_COMPILER_KEY, Constants::QBS_CONFIG_QUICK_COMPILER_KEY,
Constants::QBS_CONFIG_SEPARATE_DEBUG_INFO_KEY, Constants::QBS_CONFIG_SEPARATE_DEBUG_INFO_KEY,
Constants::QBS_INSTALL_ROOT_KEY}); Constants::QBS_INSTALL_ROOT_KEY});
if (m_qbsStep->m_selectedAbis->isManagedByTarget())
additionalSpecialKeys << Constants::QBS_ARCHITECTURES;
for (const QString &key : additionalSpecialKeys) { for (const QString &key : additionalSpecialKeys) {
const auto it = tmp.constFind(key); const auto it = tmp.constFind(key);
if (it != tmp.cend()) if (it != tmp.cend())
@@ -713,7 +839,7 @@ void QbsBuildStepConfigWidget::applyCachedProperties()
} }
m_ignoreChange = true; m_ignoreChange = true;
qbsStep()->setQbsConfiguration(data); m_qbsStep->setQbsConfiguration(data);
m_ignoreChange = false; m_ignoreChange = false;
} }
@@ -734,16 +860,18 @@ bool QbsBuildStepConfigWidget::validateProperties(Utils::FancyLineEdit *edit, QS
} }
QList<Property> properties; QList<Property> properties;
const MacroExpander * const expander = qbsStep()->macroExpander(); const MacroExpander * const expander = m_qbsStep->macroExpander();
foreach (const QString &rawArg, argList) { foreach (const QString &rawArg, argList) {
int pos = rawArg.indexOf(':'); int pos = rawArg.indexOf(':');
if (pos > 0) { if (pos > 0) {
const QString propertyName = rawArg.left(pos); const QString propertyName = rawArg.left(pos);
static const QStringList specialProperties{ QStringList specialProperties{
Constants::QBS_CONFIG_PROFILE_KEY, Constants::QBS_CONFIG_VARIANT_KEY, Constants::QBS_CONFIG_PROFILE_KEY, Constants::QBS_CONFIG_VARIANT_KEY,
Constants::QBS_CONFIG_QUICK_DEBUG_KEY, Constants::QBS_CONFIG_QUICK_COMPILER_KEY, Constants::QBS_CONFIG_QUICK_DEBUG_KEY, Constants::QBS_CONFIG_QUICK_COMPILER_KEY,
Constants::QBS_INSTALL_ROOT_KEY, Constants::QBS_CONFIG_SEPARATE_DEBUG_INFO_KEY, Constants::QBS_INSTALL_ROOT_KEY, Constants::QBS_CONFIG_SEPARATE_DEBUG_INFO_KEY,
}; };
if (m_qbsStep->m_selectedAbis->isManagedByTarget())
specialProperties << Constants::QBS_ARCHITECTURES;
if (specialProperties.contains(propertyName)) { if (specialProperties.contains(propertyName)) {
if (errorMessage) { if (errorMessage) {
*errorMessage = tr("Property \"%1\" cannot be set here. " *errorMessage = tr("Property \"%1\" cannot be set here. "

View File

@@ -37,6 +37,7 @@ class ErrorInfo;
class QbsProject; class QbsProject;
class QbsSession; class QbsSession;
class ArchitecturesAspect;
class QbsBuildStepConfigWidget; class QbsBuildStepConfigWidget;
class QbsBuildStep final : public ProjectExplorer::BuildStep class QbsBuildStep final : public ProjectExplorer::BuildStep
@@ -102,6 +103,7 @@ private:
const QString &message, const QString &file, int line); const QString &message, const QString &file, int line);
void setBuildVariant(const QString &variant); void setBuildVariant(const QString &variant);
void setConfiguredArchitectures(const QStringList &architectures);
QString profile() const; QString profile() const;
void parseProject(); void parseProject();
@@ -110,9 +112,11 @@ private:
void updateState(); void updateState();
void changeBuildVariant(); void changeBuildVariant();
QStringList configuredArchitectures() const;
QVariantMap m_qbsConfiguration; QVariantMap m_qbsConfiguration;
Utils::SelectionAspect *m_buildVariant = nullptr; Utils::SelectionAspect *m_buildVariant = nullptr;
ArchitecturesAspect *m_selectedAbis = nullptr;
Utils::IntegerAspect *m_maxJobCount = nullptr; Utils::IntegerAspect *m_maxJobCount = nullptr;
Utils::BoolAspect *m_keepGoing = nullptr; Utils::BoolAspect *m_keepGoing = nullptr;
Utils::BoolAspect *m_showCommandLines = nullptr; Utils::BoolAspect *m_showCommandLines = nullptr;