Add option for parallel jobs to make step and use it by default

By default the make step uses idealThreadCount jobs, except if it finds
a "-j" option in the MAKEFLAGS variable. The user can opt-in to override
MAKEFLAGS anyhow, and can also choose a different number of build jobs
(including 1).

This option is available for unix-style make. It is not available on
Windows with MSVC tool chain, which would use either nmake (does not
support parallel jobs) or jom (does parallel building by default).

Task-number: QTCREATORBUG-18414
Change-Id: Ic0b5c732d899607ce67ef0b496cc758497a3113a
Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
This commit is contained in:
Eike Ziller
2018-05-25 15:13:16 +02:00
parent 88b065db3f
commit 005b0c1147
3 changed files with 145 additions and 6 deletions

View File

@@ -37,7 +37,11 @@
#include <coreplugin/id.h>
#include <coreplugin/variablechooser.h>
#include <utils/hostosinfo.h>
#include <utils/qtcprocess.h>
#include <utils/utilsicons.h>
#include <QThread>
using namespace Core;
@@ -45,6 +49,10 @@ const char BUILD_TARGETS_SUFFIX[] = ".BuildTargets";
const char MAKE_ARGUMENTS_SUFFIX[] = ".MakeArguments";
const char MAKE_COMMAND_SUFFIX[] = ".MakeCommand";
const char CLEAN_SUFFIX[] = ".Clean";
const char OVERRIDE_MAKEFLAGS_SUFFIX[] = ".OverrideMakeflags";
const char JOBCOUNT_SUFFIX[] = ".JobCount";
const char MAKEFLAGS[] = "MAKEFLAGS";
namespace ProjectExplorer {
@@ -53,7 +61,8 @@ MakeStep::MakeStep(BuildStepList *parent,
const QString &buildTarget,
const QStringList &availableTargets)
: AbstractProcessStep(parent, id),
m_availableTargets(availableTargets)
m_availableTargets(availableTargets),
m_userJobCount(defaultJobCount())
{
setDefaultDisplayName(defaultDisplayName());
if (!buildTarget.isEmpty())
@@ -158,6 +167,45 @@ Task MakeStep::makeCommandMissingTask()
Constants::TASK_CATEGORY_BUILDSYSTEM);
}
bool MakeStep::isJobCountSupported() const
{
const QList<ToolChain *> tcs = preferredToolChains(target()->kit());
const ToolChain *tc = tcs.isEmpty() ? nullptr : tcs.constFirst();
return tc
&& (tc->targetAbi().os() != Abi::WindowsOS
|| tc->targetAbi().osFlavor() == Abi::WindowsMSysFlavor);
}
int MakeStep::jobCount() const
{
return m_userJobCount;
}
void MakeStep::setJobCount(int count)
{
m_userJobCount = count;
}
bool MakeStep::jobCountOverridesMakeflags() const
{
return m_overrideMakeflags;
}
void MakeStep::setJobCountOverrideMakeflags(bool override)
{
m_overrideMakeflags = override;
}
bool MakeStep::makeflagsContainsJobCount() const
{
const Utils::Environment env = environment(buildConfiguration());
if (!env.hasKey(MAKEFLAGS))
return false;
const QStringList args = Utils::QtcProcess::splitArgs(env.value(MAKEFLAGS),
Utils::HostOsInfo::hostOs());
return Utils::anyOf(args, [](const QString &arg) { return arg.startsWith("-j"); });
}
Utils::Environment MakeStep::environment(BuildConfiguration *bc) const
{
Utils::Environment env = bc ? bc->environment() : Utils::Environment::systemEnvironment();
@@ -168,8 +216,7 @@ Utils::Environment MakeStep::environment(BuildConfiguration *bc) const
const ToolChain *tc = tcs.isEmpty() ? nullptr : tcs.constFirst();
if (tc && tc->targetAbi().os() == Abi::WindowsOS
&& tc->targetAbi().osFlavor() != Abi::WindowsMSysFlavor) {
const QString makeFlags = "MAKEFLAGS";
env.set(makeFlags, 'L' + env.value(makeFlags));
env.set(MAKEFLAGS, 'L' + env.value(MAKEFLAGS));
}
}
return env;
@@ -188,6 +235,12 @@ QVariantMap MakeStep::toMap() const
map.insert(id().withSuffix(MAKE_ARGUMENTS_SUFFIX).toString(), m_makeArguments);
map.insert(id().withSuffix(MAKE_COMMAND_SUFFIX).toString(), m_makeCommand);
map.insert(id().withSuffix(CLEAN_SUFFIX).toString(), m_clean);
const QString jobCountKey = id().withSuffix(JOBCOUNT_SUFFIX).toString();
if (m_userJobCount != defaultJobCount())
map.insert(jobCountKey, m_userJobCount);
else
map.remove(jobCountKey);
map.insert(id().withSuffix(OVERRIDE_MAKEFLAGS_SUFFIX).toString(), m_overrideMakeflags);
return map;
}
@@ -197,14 +250,27 @@ bool MakeStep::fromMap(const QVariantMap &map)
m_makeArguments = map.value(id().withSuffix(MAKE_ARGUMENTS_SUFFIX).toString()).toString();
m_makeCommand = map.value(id().withSuffix(MAKE_COMMAND_SUFFIX).toString()).toString();
m_clean = map.value(id().withSuffix(CLEAN_SUFFIX).toString()).toBool();
m_overrideMakeflags = map.value(id().withSuffix(OVERRIDE_MAKEFLAGS_SUFFIX).toString(), false).toBool();
m_userJobCount = map.value(id().withSuffix(JOBCOUNT_SUFFIX).toString(), defaultJobCount()).toInt();
return BuildStep::fromMap(map);
}
int MakeStep::defaultJobCount()
{
return QThread::idealThreadCount();
}
QStringList MakeStep::jobArguments() const
{
if (!isJobCountSupported() || (makeflagsContainsJobCount() && !jobCountOverridesMakeflags()))
return {};
return {"-j" + QString::number(m_userJobCount)};
}
QString MakeStep::allArguments() const
{
QString args = m_makeArguments;
Utils::QtcProcess::addArgs(&args, m_buildTargets);
Utils::QtcProcess::addArgs(&args, jobArguments() + m_buildTargets);
return args;
}
@@ -287,6 +353,10 @@ MakeStepConfigWidget::MakeStepConfigWidget(MakeStep *makeStep) :
m_ui->makeLineEdit->setHistoryCompleter("PE.MakeCommand.History");
m_ui->makeLineEdit->setPath(m_makeStep->makeCommand());
m_ui->makeArgumentsLineEdit->setText(m_makeStep->userArguments());
m_ui->nonOverrideWarning->setToolTip("<html><body><p>" +
tr("<code>MAKEFLAGS</code> specifies parallel jobs. Check \"%1\" to override.")
.arg(m_ui->overrideMakeflags->text()) + "</p></body></html>");
m_ui->nonOverrideWarning->setPixmap(Utils::Icons::WARNING.pixmap());
updateDetails();
connect(m_ui->targetsList, &QListWidget::itemChanged,
@@ -295,6 +365,14 @@ MakeStepConfigWidget::MakeStepConfigWidget(MakeStep *makeStep) :
this, &MakeStepConfigWidget::makeLineEditTextEdited);
connect(m_ui->makeArgumentsLineEdit, &QLineEdit::textEdited,
this, &MakeStepConfigWidget::makeArgumentsLineEditTextEdited);
connect(m_ui->userJobCount, qOverload<int>(&QSpinBox::valueChanged), this, [this](int value) {
m_makeStep->setJobCount(value);
updateDetails();
});
connect(m_ui->overrideMakeflags, &QCheckBox::stateChanged, this, [this](int state) {
m_makeStep->setJobCountOverrideMakeflags(state == Qt::Checked);
updateDetails();
});
connect(ProjectExplorerPlugin::instance(), &ProjectExplorerPlugin::settingsChanged,
this, &MakeStepConfigWidget::updateDetails);
@@ -341,6 +419,13 @@ void MakeStepConfigWidget::setSummaryText(const QString &text)
emit updateSummary();
}
void MakeStepConfigWidget::setUserJobCountVisible(bool visible)
{
m_ui->jobsLabel->setVisible(visible);
m_ui->userJobCount->setVisible(visible);
m_ui->overrideMakeflags->setVisible(visible);
}
void MakeStepConfigWidget::updateDetails()
{
BuildConfiguration *bc = m_makeStep->buildConfiguration();
@@ -360,6 +445,13 @@ void MakeStepConfigWidget::updateDetails()
return;
}
setUserJobCountVisible(m_makeStep->isJobCountSupported());
m_ui->userJobCount->setValue(m_makeStep->jobCount());
m_ui->overrideMakeflags->setCheckState(
m_makeStep->jobCountOverridesMakeflags() ? Qt::Checked : Qt::Unchecked);
m_ui->nonOverrideWarning->setVisible(m_makeStep->makeflagsContainsJobCount()
&& !m_makeStep->jobCountOverridesMakeflags());
ProcessParameters param;
param.setMacroExpander(bc->macroExpander());
param.setWorkingDirectory(bc->buildDirectory().toString());

View File

@@ -68,16 +68,27 @@ public:
static QString msgNoMakeCommand();
static Task makeCommandMissingTask();
bool isJobCountSupported() const;
int jobCount() const;
void setJobCount(int count);
bool jobCountOverridesMakeflags() const;
void setJobCountOverrideMakeflags(bool override);
bool makeflagsContainsJobCount() const;
Utils::Environment environment(BuildConfiguration *bc) const;
private:
QVariantMap toMap() const override;
bool fromMap(const QVariantMap &map) override;
static int defaultJobCount();
QStringList jobArguments() const;
QStringList m_buildTargets;
QStringList m_availableTargets;
QString m_makeArguments;
QString m_makeCommand;
int m_userJobCount = 4;
bool m_overrideMakeflags = false;
bool m_clean = false;
};
@@ -98,6 +109,7 @@ private:
void makeArgumentsLineEditTextEdited();
void updateDetails();
void setSummaryText(const QString &text);
void setUserJobCountVisible(bool visible);
Internal::Ui::MakeStep *m_ui;
MakeStep *m_makeStep;

View File

@@ -53,6 +53,13 @@
<widget class="QLineEdit" name="makeArgumentsLineEdit"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="jobsLabel">
<property name="text">
<string>Parallel jobs:</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="targetsLabel">
<property name="text">
<string>Targets:</string>
@@ -62,9 +69,37 @@
</property>
</widget>
</item>
<item row="2" column="1">
<item row="3" column="1">
<widget class="QListWidget" name="targetsList"/>
</item>
<item row="2" column="1">
<layout class="QHBoxLayout" name="jobLayout">
<item>
<widget class="QSpinBox" name="userJobCount">
<property name="minimum">
<number>1</number>
</property>
<property name="value">
<number>4</number>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="overrideMakeflags">
<property name="text">
<string>Override MAKEFLAGS</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="nonOverrideWarning">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>