makestep.cpp 17.7 KB
Newer Older
hjk's avatar
hjk committed
1
/****************************************************************************
con's avatar
con committed
2
**
3
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
hjk's avatar
hjk committed
4
** Contact: http://www.qt-project.org/legal
con's avatar
con committed
5
**
hjk's avatar
hjk committed
6
** This file is part of Qt Creator.
con's avatar
con committed
7
**
hjk's avatar
hjk committed
8
9
10
11
12
13
14
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
15
**
16
** GNU Lesser General Public License Usage
hjk's avatar
hjk committed
17
18
19
20
21
22
23
24
25
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
con's avatar
con committed
26
27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
28
****************************************************************************/
hjk's avatar
hjk committed
29

con's avatar
con committed
30
#include "makestep.h"
31
#include "ui_makestep.h"
hjk's avatar
hjk committed
32

con's avatar
con committed
33
#include "qt4project.h"
34
#include "qt4nodes.h"
35
#include "qt4buildconfiguration.h"
con's avatar
con committed
36
37
#include "qt4projectmanagerconstants.h"

Tobias Hunger's avatar
Tobias Hunger committed
38
#include <projectexplorer/target.h>
39
#include <projectexplorer/toolchain.h>
Tobias Hunger's avatar
Tobias Hunger committed
40
#include <projectexplorer/buildsteplist.h>
41
#include <projectexplorer/gnumakeparser.h>
42
#include <projectexplorer/projectexplorer.h>
Tobias Hunger's avatar
Tobias Hunger committed
43
#include <projectexplorer/kitinformation.h>
44
#include <utils/qtcprocess.h>
45

46
47
#include <QDir>
#include <QFileInfo>
con's avatar
con committed
48
49

using ExtensionSystem::PluginManager;
hjk's avatar
hjk committed
50
using namespace ProjectExplorer;
con's avatar
con committed
51
52
53
using namespace Qt4ProjectManager;
using namespace Qt4ProjectManager::Internal;

54
namespace {
hjk's avatar
hjk committed
55
56
const char MAKESTEP_BS_ID[] = "Qt4ProjectManager.MakeStep";
const char MAKE_ARGUMENTS_KEY[] = "Qt4ProjectManager.MakeStep.MakeArguments";
57
const char AUTOMATICLY_ADDED_MAKE_ARGUMENTS_KEY[] = "Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments";
hjk's avatar
hjk committed
58
59
const char MAKE_COMMAND_KEY[] = "Qt4ProjectManager.MakeStep.MakeCommand";
const char CLEAN_KEY[] = "Qt4ProjectManager.MakeStep.Clean";
60
61
}

hjk's avatar
hjk committed
62
MakeStep::MakeStep(BuildStepList *bsl) :
63
    AbstractProcessStep(bsl, Core::Id(MAKESTEP_BS_ID)),
64
    m_clean(false)
65
{
66
    ctor();
67
68
}

hjk's avatar
hjk committed
69
MakeStep::MakeStep(BuildStepList *bsl, MakeStep *bs) :
Tobias Hunger's avatar
Tobias Hunger committed
70
    AbstractProcessStep(bsl, bs),
71
    m_clean(bs->m_clean),
72
    m_userArgs(bs->m_userArgs),
73
    m_makeCmd(bs->m_makeCmd)
con's avatar
con committed
74
{
75
76
    ctor();
}
con's avatar
con committed
77

hjk's avatar
hjk committed
78
MakeStep::MakeStep(BuildStepList *bsl, const Core::Id id) :
Tobias Hunger's avatar
Tobias Hunger committed
79
    AbstractProcessStep(bsl, id),
80
81
82
    m_clean(false)
{
    ctor();
con's avatar
con committed
83
84
}

85
void MakeStep::ctor()
con's avatar
con committed
86
{
Caroline Chao's avatar
Caroline Chao committed
87
    setDefaultDisplayName(tr("Make", "Qt MakeStep display name."));
88
}
con's avatar
con committed
89

90
91
92
93
94
void MakeStep::setMakeCommand(const QString &make)
{
    m_makeCmd = make;
}

95
96
MakeStep::~MakeStep()
{
con's avatar
con committed
97
98
}

dt's avatar
dt committed
99
100
101
102
103
Qt4BuildConfiguration *MakeStep::qt4BuildConfiguration() const
{
    return static_cast<Qt4BuildConfiguration *>(buildConfiguration());
}

104
105
106
107
108
void MakeStep::setClean(bool clean)
{
    m_clean = clean;
}

109
110
111
112
113
bool MakeStep::isClean() const
{
    return m_clean;
}

114
115
116
117
118
QString MakeStep::makeCommand() const
{
    return m_makeCmd;
}

119
QVariantMap MakeStep::toMap() const
120
{
hjk's avatar
hjk committed
121
    QVariantMap map(AbstractProcessStep::toMap());
122
123
124
    map.insert(QLatin1String(MAKE_ARGUMENTS_KEY), m_userArgs);
    map.insert(QLatin1String(MAKE_COMMAND_KEY), m_makeCmd);
    map.insert(QLatin1String(CLEAN_KEY), m_clean);
125
    map.insert(QLatin1String(AUTOMATICLY_ADDED_MAKE_ARGUMENTS_KEY), automaticallyAddedArguments());
126
    return map;
127
128
}

129
130
131
132
133
134
135
136
QStringList MakeStep::automaticallyAddedArguments() const
{
    ToolChain *tc = ToolChainKitInformation::toolChain(target()->kit());
    if (!tc || tc->targetAbi().binaryFormat() == Abi::PEFormat)
        return QStringList();
    return QStringList() << QLatin1String("-w") << QLatin1String("-r");
}

137
bool MakeStep::fromMap(const QVariantMap &map)
138
{
139
    m_makeCmd = map.value(QLatin1String(MAKE_COMMAND_KEY)).toString();
140
    m_userArgs = map.value(QLatin1String(MAKE_ARGUMENTS_KEY)).toString();
141
    m_clean = map.value(QLatin1String(CLEAN_KEY)).toBool();
142
143
144
145
146
147
148
    QStringList oldAddedArgs
            = map.value(QLatin1String(AUTOMATICLY_ADDED_MAKE_ARGUMENTS_KEY)).toStringList();
    foreach (const QString &newArg, automaticallyAddedArguments()) {
        if (oldAddedArgs.contains(newArg))
            continue;
        m_userArgs.prepend(newArg + QLatin1Char(' '));
    }
149

hjk's avatar
hjk committed
150
    return AbstractProcessStep::fromMap(map);
151
152
}

153
bool MakeStep::init()
con's avatar
con committed
154
{
dt's avatar
dt committed
155
    Qt4BuildConfiguration *bc = qt4BuildConfiguration();
156
157
    if (!bc)
        bc = qobject_cast<Qt4BuildConfiguration *>(target()->activeBuildConfiguration());
158

159
    m_tasks.clear();
Tobias Hunger's avatar
Tobias Hunger committed
160
    ToolChain *tc = ToolChainKitInformation::toolChain(target()->kit());
Tobias Hunger's avatar
Tobias Hunger committed
161
    if (!tc) {
162
163
164
        m_tasks.append(Task(Task::Error, tr("Qt Creator needs a compiler set up to build. Configure a compiler in the kit options."),
                            Utils::FileName(), -1,
                            Core::Id(ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM)));
165
        return true; // otherwise the tasks will not get reported
166
167
    }

hjk's avatar
hjk committed
168
    ProcessParameters *pp = processParameters();
169
170
    pp->setMacroExpander(bc->macroExpander());

171
172
173
174
175
    QString workingDirectory;
    if (bc->subNodeBuild())
        workingDirectory = bc->subNodeBuild()->buildDir();
    else
        workingDirectory = bc->buildDirectory();
176
    pp->setWorkingDirectory(workingDirectory);
con's avatar
con committed
177

178
    QString makeCmd = tc->makeCommand(bc->environment());
179
180
    if (!m_makeCmd.isEmpty())
        makeCmd = m_makeCmd;
181
    pp->setCommand(makeCmd);
con's avatar
con committed
182

183
184
    // If we are cleaning, then make can fail with a error code, but that doesn't mean
    // we should stop the clean queue
Tobias Hunger's avatar
Tobias Hunger committed
185
    // That is mostly so that rebuild works on a already clean project
186
    setIgnoreReturnValue(m_clean);
187
188

    QString args;
189

190
191
192
193
194
    Qt4ProjectManager::Qt4ProFileNode *subNode = bc->subNodeBuild();
    if (subNode) {
        QString makefile = subNode->makefile();
        if (makefile.isEmpty())
            makefile = QLatin1String("Makefile");
195
196
197
198
        // Use Makefile.Debug and Makefile.Release
        // for file builds, since the rules for that are
        // only in those files.
        if (subNode->isDebugAndRelease() && bc->fileNodeBuild()) {
199
200
201
202
203
204
            if (bc->buildType() == Qt4BuildConfiguration::Debug)
                makefile += QLatin1String(".Debug");
            else
                makefile += QLatin1String(".Release");
        }
        if (makefile != QLatin1String("Makefile")) {
205
            Utils::QtcProcess::addArg(&args, QLatin1String("-f"));
206
207
            Utils::QtcProcess::addArg(&args, makefile);
        }
208
        m_makeFileToCheck = QDir(workingDirectory).filePath(makefile);
209
210
211
212
    } else {
        if (!bc->makefile().isEmpty()) {
            Utils::QtcProcess::addArg(&args, QLatin1String("-f"));
            Utils::QtcProcess::addArg(&args, bc->makefile());
213
            m_makeFileToCheck = QDir(workingDirectory).filePath(bc->makefile());
214
        } else {
215
            m_makeFileToCheck = QDir(workingDirectory).filePath(QLatin1String("Makefile"));
216
217
218
        }
    }

219
    Utils::QtcProcess::addArgs(&args, m_userArgs);
220
221
222
223
224
225
226
227
228
229
    if (bc->fileNodeBuild() && subNode) {
        QString objectsDir = subNode->objectsDirectory();
        if (objectsDir.isEmpty()) {
            objectsDir = subNode->buildDir(bc);
            if (subNode->isDebugAndRelease()) {
                if (bc->buildType() == Qt4BuildConfiguration::Debug)
                    objectsDir += QLatin1String("/debug");
                else
                    objectsDir += QLatin1String("/release");
            }
Orgad Shaneh's avatar
Orgad Shaneh committed
230
        }
231
232
233
234
235
236
237
        QString relObjectsDir = QDir(pp->workingDirectory()).relativeFilePath(objectsDir);
        if (!relObjectsDir.isEmpty())
            relObjectsDir += QLatin1Char('/');
        QString objectFile = relObjectsDir +
                QFileInfo(bc->fileNodeBuild()->path()).baseName() +
                subNode->objectExtension();
        Utils::QtcProcess::addArg(&args, objectFile);
Orgad Shaneh's avatar
Orgad Shaneh committed
238
    }
239
    Utils::Environment env = bc->environment();
240
241
242
    // Force output to english for the parsers. Do this here and not in the toolchain's
    // addToEnvironment() to not screw up the users run environment.
    env.set(QLatin1String("LC_ALL"), QLatin1String("C"));
243
    // We also prepend "L" to the MAKEFLAGS, so that nmake / jom are less verbose
Tobias Hunger's avatar
Tobias Hunger committed
244
    if (tc && m_makeCmd.isEmpty()) {
hjk's avatar
hjk committed
245
246
        if (tc->targetAbi().os() == Abi::WindowsOS
                && tc->targetAbi().osFlavor() != Abi::WindowsMSysFlavor) {
247
248
            const QString makeFlags = QLatin1String("MAKEFLAGS");
            env.set(makeFlags, QLatin1Char('L') + env.value(makeFlags));
249
250
251
252
        }
    }

    pp->setEnvironment(env);
253
    pp->setArguments(args);
254
    pp->resolveAll();
con's avatar
con committed
255

256
257
    setOutputParser(new ProjectExplorer::GnuMakeParser());
    IOutputParser *parser = target()->kit()->createOutputParser();
dt's avatar
dt committed
258
    if (parser)
259
260
        appendOutputParser(parser);
    outputParser()->setWorkingDirectory(pp->effectiveWorkingDirectory());
Tobias Hunger's avatar
Tobias Hunger committed
261

Tobias Hunger's avatar
Tobias Hunger committed
262
    m_scriptTarget = (static_cast<Qt4Project *>(bc->target()->project())->rootQt4ProjectNode()->projectType() == ScriptTemplate);
Daniel Teske's avatar
Daniel Teske committed
263

Tobias Hunger's avatar
Tobias Hunger committed
264
    return AbstractProcessStep::init();
con's avatar
con committed
265
266
267
268
}

void MakeStep::run(QFutureInterface<bool> & fi)
{
269
    bool canContinue = true;
hjk's avatar
hjk committed
270
    foreach (const Task &t, m_tasks) {
271
        addTask(t);
272
        canContinue = false;
273
274
    }
    if (!canContinue) {
275
        emit addOutput(tr("Configuration is faulty. Check the Issues view for details."), BuildStep::MessageOutput);
276
        fi.reportResult(false);
277
        emit finished();
278
279
280
        return;
    }

281
282
    if (m_scriptTarget) {
        fi.reportResult(true);
283
        emit finished();
284
285
286
287
288
289
290
        return;
    }

    if (!QFileInfo(m_makeFileToCheck).exists()) {
        if (!ignoreReturnValue())
            emit addOutput(tr("Cannot find Makefile. Check your build settings."), BuildStep::MessageOutput);
        fi.reportResult(ignoreReturnValue());
291
        emit finished();
292
293
294
        return;
    }

Tobias Hunger's avatar
Tobias Hunger committed
295
    AbstractProcessStep::run(fi);
con's avatar
con committed
296
297
}

298
299
300
bool MakeStep::processSucceeded(int exitCode, QProcess::ExitStatus status)
{
    // Symbian does retun 0, even on failed makes! So we check for fatal make errors here.
Tobias Hunger's avatar
Tobias Hunger committed
301
    if (outputParser() && outputParser()->hasFatalErrors())
302
        return false;
303
304
305
306

    return AbstractProcessStep::processSucceeded(exitCode, status);
}

con's avatar
con committed
307
308
bool MakeStep::immutable() const
{
dt's avatar
dt committed
309
    return false;
con's avatar
con committed
310
311
}

hjk's avatar
hjk committed
312
BuildStepConfigWidget *MakeStep::createConfigWidget()
con's avatar
con committed
313
314
315
316
{
    return new MakeStepConfigWidget(this);
}

317
QString MakeStep::userArguments()
318
{
319
    return m_userArgs;
320
321
}

322
void MakeStep::setUserArguments(const QString &arguments)
323
{
324
325
    m_userArgs = arguments;
    emit userArgumentsChanged();
326
327
}

con's avatar
con committed
328
MakeStepConfigWidget::MakeStepConfigWidget(MakeStep *makeStep)
329
    : BuildStepConfigWidget(), m_ui(new Internal::Ui::MakeStep), m_makeStep(makeStep), m_bc(0), m_ignoreChange(false)
con's avatar
con committed
330
{
331
    m_ui->setupUi(this);
332
333
334
335

    m_ui->makePathChooser->setExpectedKind(Utils::PathChooser::ExistingCommand);
    m_ui->makePathChooser->setBaseDirectory(Utils::PathChooser::homePath());

dt_'s avatar
dt_ committed
336

337
    const QString &makeCmd = m_makeStep->makeCommand();
dt_'s avatar
dt_ committed
338
339
340
341
342
    m_ui->makePathChooser->setPath(makeCmd);
    m_ui->makeArgumentsLineEdit->setText(m_makeStep->userArguments());

    updateDetails();

Tobias Hunger's avatar
Tobias Hunger committed
343
    connect(m_ui->makePathChooser, SIGNAL(changed(QString)),
344
            this, SLOT(makeEdited()));
345
    connect(m_ui->makeArgumentsLineEdit, SIGNAL(textEdited(QString)),
346
            this, SLOT(makeArgumentsLineEdited()));
347

348
349
    connect(makeStep, SIGNAL(userArgumentsChanged()),
            this, SLOT(userArgumentsChanged()));
350

hjk's avatar
hjk committed
351
    BuildConfiguration *bc = makeStep->buildConfiguration();
352
353
    if (!bc) {
        // That means the step is in the deploylist, so we listen to the active build config
Tobias Hunger's avatar
Tobias Hunger committed
354
        // changed signal and react to the buildDirectoryChanged() signal of the buildconfiguration
355
356
        bc = makeStep->target()->activeBuildConfiguration();
        m_bc = bc;
357
        connect (makeStep->target(), SIGNAL(activeBuildConfigurationChanged(ProjectExplorer::BuildConfiguration*)),
358
359
360
361
362
363
364
                 this, SLOT(activeBuildConfigurationChanged()));
    }

    if (bc) {
        connect(bc, SIGNAL(buildDirectoryChanged()),
                this, SLOT(updateDetails()));
    }
365

hjk's avatar
hjk committed
366
    connect(ProjectExplorerPlugin::instance(), SIGNAL(settingsChanged()),
367
            this, SLOT(updateDetails()));
Tobias Hunger's avatar
Tobias Hunger committed
368
    connect(m_makeStep->target(), SIGNAL(kitChanged()), this, SLOT(updateDetails()));
dt's avatar
dt committed
369
370
}

371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
void MakeStepConfigWidget::activeBuildConfigurationChanged()
{
    if (m_bc) {
        disconnect(m_bc, SIGNAL(buildDirectoryChanged()),
                this, SLOT(updateDetails()));
    }

    m_bc = m_makeStep->target()->activeBuildConfiguration();
    updateDetails();

    if (m_bc) {
        connect(m_bc, SIGNAL(buildDirectoryChanged()),
                this, SLOT(updateDetails()));
    }
}

Tobias Hunger's avatar
Tobias Hunger committed
387
void MakeStepConfigWidget::setSummaryText(const QString &text)
388
{
Tobias Hunger's avatar
Tobias Hunger committed
389
390
391
392
    if (text == m_summaryText)
        return;
    m_summaryText = text;
    emit updateSummary();
393
394
}

Tobias Hunger's avatar
Tobias Hunger committed
395
MakeStepConfigWidget::~MakeStepConfigWidget()
396
{
Tobias Hunger's avatar
Tobias Hunger committed
397
    delete m_ui;
398
399
}

Tobias Hunger's avatar
Tobias Hunger committed
400
void MakeStepConfigWidget::updateDetails()
401
{
hjk's avatar
hjk committed
402
    ToolChain *tc
Tobias Hunger's avatar
Tobias Hunger committed
403
            = ToolChainKitInformation::toolChain(m_makeStep->target()->kit());
404
405
406
407
408
409
    Qt4BuildConfiguration *bc = m_makeStep->qt4BuildConfiguration();
    if (!bc)
        bc = qobject_cast<Qt4BuildConfiguration *>(m_makeStep->target()->activeBuildConfiguration());

    if (tc && bc)
        m_ui->makeLabel->setText(tr("Override %1:").arg(tc->makeCommand(bc->environment())));
Daniel Teske's avatar
Daniel Teske committed
410
411
    else
        m_ui->makeLabel->setText(tr("Make:"));
412

Tobias Hunger's avatar
Tobias Hunger committed
413
    if (!tc) {
Tobias Hunger's avatar
Tobias Hunger committed
414
        setSummaryText(tr("<b>Make:</b> %1").arg(ProjectExplorer::ToolChainKitInformation::msgNoToolChainInTarget()));
Tobias Hunger's avatar
Tobias Hunger committed
415
416
417
        return;
    }
    if (!bc) {
Caroline Chao's avatar
Caroline Chao committed
418
        setSummaryText(tr("<b>Make:</b> No Qt build configuration."));
Tobias Hunger's avatar
Tobias Hunger committed
419
420
        return;
    }
421

hjk's avatar
hjk committed
422
    ProcessParameters param;
423
424
    param.setMacroExpander(bc->macroExpander());
    param.setWorkingDirectory(bc->buildDirectory());
425
    QString makeCmd = tc->makeCommand(bc->environment());
426
427
    if (!m_makeStep->makeCommand().isEmpty())
        makeCmd = m_makeStep->makeCommand();
428
    param.setCommand(makeCmd);
429
430

    QString args = m_makeStep->userArguments();
431
432

    Utils::Environment env = bc->environment();
433
434
435
    // Force output to english for the parsers. Do this here and not in the toolchain's
    // addToEnvironment() to not screw up the users run environment.
    env.set(QLatin1String("LC_ALL"), QLatin1String("C"));
436
    // We prepend "L" to the MAKEFLAGS, so that nmake / jom are less verbose
437
    // FIXME doing this without the user having a way to override this is rather bad
Tobias Hunger's avatar
Tobias Hunger committed
438
    if (tc && m_makeStep->makeCommand().isEmpty()) {
hjk's avatar
hjk committed
439
440
        if (tc->targetAbi().os() == Abi::WindowsOS
                && tc->targetAbi().osFlavor() != Abi::WindowsMSysFlavor) {
441
442
            const QString makeFlags = QLatin1String("MAKEFLAGS");
            env.set(makeFlags, QLatin1Char('L') + env.value(makeFlags));
443
444
        }
    }
445
    param.setArguments(args);
446
    param.setEnvironment(env);
447
448

    if (param.commandMissing())
Tobias Hunger's avatar
Tobias Hunger committed
449
450
451
        setSummaryText(tr("<b>Make:</b> %1 not found in the environment.").arg(makeCmd)); // Override display text
    else
        setSummaryText(param.summaryInWorkdir(displayName()));
dt's avatar
dt committed
452
453
454
455
456
}

QString MakeStepConfigWidget::summaryText() const
{
    return m_summaryText;
con's avatar
con committed
457
458
459
460
461
462
463
}

QString MakeStepConfigWidget::displayName() const
{
    return m_makeStep->displayName();
}

464
void MakeStepConfigWidget::userArgumentsChanged()
465
{
466
467
    if (m_ignoreChange)
        return;
468
    m_ui->makeArgumentsLineEdit->setText(m_makeStep->userArguments());
469
    updateDetails();
470
471
}

472
void MakeStepConfigWidget::makeEdited()
con's avatar
con committed
473
{
474
    m_makeStep->setMakeCommand(m_ui->makePathChooser->rawPath());
dt's avatar
dt committed
475
    updateDetails();
con's avatar
con committed
476
477
}

478
void MakeStepConfigWidget::makeArgumentsLineEdited()
con's avatar
con committed
479
{
480
    m_ignoreChange = true;
481
    m_makeStep->setUserArguments(m_ui->makeArgumentsLineEdit->text());
482
    m_ignoreChange = false;
dt's avatar
dt committed
483
    updateDetails();
con's avatar
con committed
484
}
dt's avatar
dt committed
485
486

///
487
// MakeStepFactory
dt's avatar
dt committed
488
489
///

490
MakeStepFactory::MakeStepFactory(QObject *parent) :
hjk's avatar
hjk committed
491
    IBuildStepFactory(parent)
dt's avatar
dt committed
492
493
494
495
496
497
498
{
}

MakeStepFactory::~MakeStepFactory()
{
}

hjk's avatar
hjk committed
499
bool MakeStepFactory::canCreate(BuildStepList *parent, const Core::Id id) const
dt's avatar
dt committed
500
{
501
502
503
    if (parent->target()->project()->id() == Constants::QT4PROJECT_ID)
        return id == MAKESTEP_BS_ID;
    return false;
dt's avatar
dt committed
504
505
}

hjk's avatar
hjk committed
506
BuildStep *MakeStepFactory::create(BuildStepList *parent, const Core::Id id)
dt's avatar
dt committed
507
{
Tobias Hunger's avatar
Tobias Hunger committed
508
    if (!canCreate(parent, id))
509
        return 0;
510
    MakeStep *step = new MakeStep(parent);
511
    if (parent->id() == ProjectExplorer::Constants::BUILDSTEPS_CLEAN) {
512
        step->setClean(true);
513
        step->setUserArguments(QLatin1String("clean"));
514
515
    }
    return step;
516
517
}

hjk's avatar
hjk committed
518
bool MakeStepFactory::canClone(BuildStepList *parent, BuildStep *source) const
519
{
Tobias Hunger's avatar
Tobias Hunger committed
520
    return canCreate(parent, source->id());
dt's avatar
dt committed
521
522
}

hjk's avatar
hjk committed
523
BuildStep *MakeStepFactory::clone(BuildStepList *parent, BuildStep *source)
dt's avatar
dt committed
524
{
Tobias Hunger's avatar
Tobias Hunger committed
525
    if (!canClone(parent, source))
526
527
528
529
        return 0;
    return new MakeStep(parent, static_cast<MakeStep *>(source));
}

hjk's avatar
hjk committed
530
bool MakeStepFactory::canRestore(BuildStepList *parent, const QVariantMap &map) const
531
{
hjk's avatar
hjk committed
532
    return canCreate(parent, idFromMap(map));
533
534
}

hjk's avatar
hjk committed
535
BuildStep *MakeStepFactory::restore(BuildStepList *parent, const QVariantMap &map)
536
{
Tobias Hunger's avatar
Tobias Hunger committed
537
    if (!canRestore(parent, map))
538
539
540
541
542
543
544
545
        return 0;
    MakeStep *bs(new MakeStep(parent));
    if (bs->fromMap(map))
        return bs;
    delete bs;
    return 0;
}

hjk's avatar
hjk committed
546
QList<Core::Id> MakeStepFactory::availableCreationIds(BuildStepList *parent) const
547
{
548
    if (parent->target()->project()->id() == Constants::QT4PROJECT_ID)
549
550
        return QList<Core::Id>() << Core::Id(MAKESTEP_BS_ID);
    return QList<Core::Id>();
dt's avatar
dt committed
551
552
}

553
QString MakeStepFactory::displayNameForId(const Core::Id id) const
dt's avatar
dt committed
554
{
555
    if (id == MAKESTEP_BS_ID)
556
557
        return tr("Make");
    return QString();
dt's avatar
dt committed
558
}