qmakestep.cpp 21.2 KB
Newer Older
1
/**************************************************************************
con's avatar
con committed
2
3
4
**
** This file is part of Qt Creator
**
con's avatar
con committed
5
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
con's avatar
con committed
6
**
7
** Contact: Nokia Corporation (qt-info@nokia.com)
con's avatar
con committed
8
**
con's avatar
con committed
9
** No Commercial Usage
10
**
con's avatar
con committed
11
12
13
14
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
15
**
16
** GNU Lesser General Public License Usage
17
**
18
19
20
21
22
23
** 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.
24
**
con's avatar
con committed
25
26
27
28
29
30
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
con's avatar
con committed
31
**
32
**************************************************************************/
hjk's avatar
hjk committed
33

con's avatar
con committed
34
#include "qmakestep.h"
hjk's avatar
hjk committed
35

36
#include <projectexplorer/projectexplorerconstants.h>
37
#include <proparser/profileevaluator.h>
Tobias Hunger's avatar
Tobias Hunger committed
38
39
#include "qmakeparser.h"
#include "qt4buildconfiguration.h"
con's avatar
con committed
40
41
42
#include "qt4project.h"
#include "qt4projectmanagerconstants.h"
#include "qt4projectmanager.h"
Tobias Hunger's avatar
Tobias Hunger committed
43
#include "qt4target.h"
44
#include "qtversionmanager.h"
45
#include "debugginghelperbuildtask.h"
con's avatar
con committed
46

Tobias Hunger's avatar
Tobias Hunger committed
47
#include <projectexplorer/buildsteplist.h>
48
#include <projectexplorer/toolchain.h>
Tobias Hunger's avatar
Tobias Hunger committed
49

con's avatar
con committed
50
#include <coreplugin/icore.h>
51
#include <coreplugin/progressmanager/progressmanager.h>
hjk's avatar
hjk committed
52
#include <utils/qtcassert.h>
53
#include <utils/qtcprocess.h>
con's avatar
con committed
54

Tobias Hunger's avatar
Tobias Hunger committed
55
56
#include <QtCore/QDir>
#include <QtCore/QFile>
57
58
#include <qtconcurrent/runextensions.h>
#include <QtCore/QtConcurrentRun>
con's avatar
con committed
59
60
61
62
63

using namespace Qt4ProjectManager;
using namespace Qt4ProjectManager::Internal;
using namespace ProjectExplorer;

64
65
66
67
namespace {
const char * const QMAKE_BS_ID("QtProjectManager.QMakeBuildStep");

const char * const QMAKE_ARGUMENTS_KEY("QtProjectManager.QMakeBuildStep.QMakeArguments");
68
const char * const QMAKE_FORCED_KEY("QtProjectManager.QMakeBuildStep.QMakeForced");
69
const char * const QMAKE_QMLDEBUGLIB_KEY("QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary");
70
71
}

Tobias Hunger's avatar
Tobias Hunger committed
72
73
QMakeStep::QMakeStep(BuildStepList *bsl) :
    AbstractProcessStep(bsl, QLatin1String(QMAKE_BS_ID)),
74
75
    m_forced(false),
    m_linkQmlDebuggingLibrary(false)
con's avatar
con committed
76
{
77
    ctor();
con's avatar
con committed
78
79
}

Tobias Hunger's avatar
Tobias Hunger committed
80
81
QMakeStep::QMakeStep(BuildStepList *bsl, const QString &id) :
    AbstractProcessStep(bsl, id),
82
83
    m_forced(false),
    m_linkQmlDebuggingLibrary(false)
84
85
86
87
{
    ctor();
}

Tobias Hunger's avatar
Tobias Hunger committed
88
89
QMakeStep::QMakeStep(BuildStepList *bsl, QMakeStep *bs) :
    AbstractProcessStep(bsl, bs),
90
    m_forced(bs->m_forced),
91
92
    m_userArgs(bs->m_userArgs),
    m_linkQmlDebuggingLibrary(bs->m_linkQmlDebuggingLibrary)
93
{
94
95
96
97
98
    ctor();
}

void QMakeStep::ctor()
{
99
100
    //: QMakeStep default display name
    setDefaultDisplayName(tr("qmake"));
101
102
}

con's avatar
con committed
103
104
105
106
QMakeStep::~QMakeStep()
{
}

dt's avatar
dt committed
107
108
109
110
111
Qt4BuildConfiguration *QMakeStep::qt4BuildConfiguration() const
{
    return static_cast<Qt4BuildConfiguration *>(buildConfiguration());
}

dt's avatar
dt committed
112
113
114
115
116
117
118
///
/// Returns all arguments
/// That is: possbile subpath
/// spec
/// config arguemnts
/// moreArguments
/// user arguments
119
QString QMakeStep::allArguments(bool shorted)
con's avatar
con committed
120
{
121
    QString additonalArguments = m_userArgs;
dt's avatar
dt committed
122
    Qt4BuildConfiguration *bc = qt4BuildConfiguration();
con's avatar
con committed
123
    QStringList arguments;
124
    if (bc->subNodeBuild())
125
        arguments << QDir::toNativeSeparators(bc->subNodeBuild()->path());
126
127
128
    else if (shorted)
        arguments << QDir::toNativeSeparators(QFileInfo(
                buildConfiguration()->target()->project()->file()->fileName()).fileName());
129
    else
130
        arguments << QDir::toNativeSeparators(buildConfiguration()->target()->project()->file()->fileName());
con's avatar
con committed
131
132
    arguments << "-r";

133
134
135
136
137
    for (Utils::QtcProcess::ArgIterator ait(&additonalArguments); ait.next(); )
        if (ait.value() == QLatin1String("-spec"))
            goto haveSpec;
    arguments << "-spec" << bc->qtVersion()->mkspec();
  haveSpec:
138

dt's avatar
dt committed
139
    // Find out what flags we pass on to qmake
140
    arguments << bc->configCommandLineArguments();
dt's avatar
dt committed
141

142
143
    arguments << moreArguments();

144
145
146
    QString args = Utils::QtcProcess::joinArgs(arguments);
    Utils::QtcProcess::addArgs(&args, additonalArguments);
    return args;
dt's avatar
dt committed
147
148
}

dt's avatar
dt committed
149
150
151
152
///
/// moreArguments,
/// -unix for Maemo
/// -after OBJECTS_DIR, MOC_DIR, UI_DIR, RCC_DIR
153
/// QMAKE_VAR_QMLJSDEBUGGER_PATH
dt's avatar
dt committed
154
155
156
157
QStringList QMakeStep::moreArguments()
{
    Qt4BuildConfiguration *bc = qt4BuildConfiguration();
    QStringList arguments;
158
#if defined(Q_OS_WIN) || defined(Q_OS_MAC)
159
    ProjectExplorer::ToolChain *tc = bc->toolChain();
Robert Loehning's avatar
Robert Loehning committed
160
161
    if (tc && (tc->targetAbi().osFlavor() == ProjectExplorer::Abi::HarmattanLinuxFlavor
               || tc->targetAbi().osFlavor() == ProjectExplorer::Abi::MaemoLinuxFlavor))
ck's avatar
ck committed
162
163
        arguments << QLatin1String("-unix");
#endif
164
    if (!bc->qtVersion()->supportsShadowBuilds()) {
165
166
167
168
169
170
        // We have a target which does not allow shadow building.
        // But we really don't want to have the build artefacts in the source dir
        // so we try to hack around it, to make the common cases work.
        // This is a HACK, remove once the symbian make generator supports
        // shadow building
        arguments << QLatin1String("-after")
171
172
173
174
                  << QLatin1String("OBJECTS_DIR=obj")
                  << QLatin1String("MOC_DIR=moc")
                  << QLatin1String("UI_DIR=ui")
                  << QLatin1String("RCC_DIR=rcc");
175
    }
ck's avatar
ck committed
176

177
178
179
180
181
182
183
184
185
    if (m_linkQmlDebuggingLibrary
            && !bc->qtVersion()->qmlDebuggingHelperLibrary(true).isEmpty()) {
        // Do not turn debugger path into native path separators: Qmake does not like that!
        const QString debuggingHelperPath
                = QFileInfo(bc->qtVersion()->qmlDebuggingHelperLibrary(true)).dir().path();

        arguments << QLatin1String(Constants::QMAKEVAR_QMLJSDEBUGGER_PATH)
                     + QLatin1Char('=') + debuggingHelperPath;
    }
con's avatar
con committed
186
187
188
    return arguments;
}

189
bool QMakeStep::init()
con's avatar
con committed
190
{
dt's avatar
dt committed
191
    Qt4BuildConfiguration *qt4bc = qt4BuildConfiguration();
192
    const QtVersion *qtVersion = qt4bc->qtVersion();
con's avatar
con committed
193

194
    QString args = allArguments();
195
    QString workingDirectory;
196

197
198
199
200
    if (qt4bc->subNodeBuild())
        workingDirectory = qt4bc->subNodeBuild()->buildDir();
    else
        workingDirectory = qt4bc->buildDirectory();
con's avatar
con committed
201
202
203

    QString program = qtVersion->qmakeCommand();

Tobias Hunger's avatar
Tobias Hunger committed
204
    // Check whether we need to run qmake
205
    m_needToRunQMake = true;
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
    QString makefile = workingDirectory;

    if (qt4bc->subNodeBuild()) {
        if (!qt4bc->subNodeBuild()->makefile().isEmpty()) {
            makefile.append(qt4bc->subNodeBuild()->makefile());
        } else {
            makefile.append("/Makefile");
        }
    } else if (!qt4bc->makefile().isEmpty()) {
        makefile.append(qt4bc->makefile());
    } else {
        makefile.append("/Makefile");
    }

    if (QFileInfo(makefile).exists()) {
        QString qmakePath = QtVersionManager::findQMakeBinaryFromMakefile(makefile);
222
        if (qtVersion->qmakeCommand() == qmakePath) {
223
            m_needToRunQMake = !qt4bc->compareToImportFrom(makefile);
dt's avatar
dt committed
224
        }
con's avatar
con committed
225
226
227
228
    }

    if (m_forced) {
        m_forced = false;
229
        m_needToRunQMake = true;
con's avatar
con committed
230
231
    }

232
    setEnabled(m_needToRunQMake);
233
234
235
236
237
238
    ProcessParameters *pp = processParameters();
    pp->setMacroExpander(qt4bc->macroExpander());
    pp->setWorkingDirectory(workingDirectory);
    pp->setCommand(program);
    pp->setArguments(args);
    pp->setEnvironment(qt4bc->environment());
239

Tobias Hunger's avatar
Tobias Hunger committed
240
    setOutputParser(new QMakeParser);
dt's avatar
dt committed
241

dt's avatar
dt committed
242
243
244
245
246
    Qt4ProFileNode *node = qt4bc->qt4Target()->qt4Project()->rootProjectNode();
    if (qt4bc->subNodeBuild())
        node = qt4bc->subNodeBuild();
    QString proFile = node->path();

247
    m_tasks = qt4BuildConfiguration()->qtVersion()->reportIssues(proFile, workingDirectory);
dt's avatar
dt committed
248
    m_scriptTemplate = node->projectType() == ScriptTemplate;
dt's avatar
dt committed
249

Tobias Hunger's avatar
Tobias Hunger committed
250
    return AbstractProcessStep::init();
con's avatar
con committed
251
252
253
254
}

void QMakeStep::run(QFutureInterface<bool> &fi)
{
dt's avatar
dt committed
255
    if (m_scriptTemplate) {
con's avatar
con committed
256
257
258
        fi.reportResult(true);
        return;
    }
259

260
    // Warn on common error conditions:
dt's avatar
dt committed
261

262
    bool canContinue = true;
dt's avatar
dt committed
263
    foreach (const ProjectExplorer::Task &t, m_tasks) {
264
265
266
267
268
        addTask(t);
        if (t.type == Task::Error)
            canContinue = false;
    }
    if (!canContinue) {
269
        emit addOutput(tr("Configuration is faulty, please check the Build Issues view for details."), BuildStep::MessageOutput);
270
271
        fi.reportResult(false);
        return;
272
273
    }

274
    if (!m_needToRunQMake) {
275
        emit addOutput(tr("Configuration unchanged, skipping qmake step."), BuildStep::MessageOutput);
con's avatar
con committed
276
277
278
        fi.reportResult(true);
        return;
    }
279

Tobias Hunger's avatar
Tobias Hunger committed
280
    AbstractProcessStep::run(fi);
con's avatar
con committed
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
}

void QMakeStep::setForced(bool b)
{
    m_forced = b;
}

bool QMakeStep::forced()
{
    return m_forced;
}

ProjectExplorer::BuildStepConfigWidget *QMakeStep::createConfigWidget()
{
    return new QMakeStepConfigWidget(this);
}

bool QMakeStep::immutable() const
{
dt's avatar
dt committed
300
    return false;
con's avatar
con committed
301
302
303
304
305
306
307
308
}

void QMakeStep::processStartupFailed()
{
    m_forced = true;
    AbstractProcessStep::processStartupFailed();
}

309
bool QMakeStep::processSucceeded(int exitCode, QProcess::ExitStatus status)
con's avatar
con committed
310
{
311
    bool result = AbstractProcessStep::processSucceeded(exitCode, status);
con's avatar
con committed
312
313
    if (!result)
        m_forced = true;
314
    qt4BuildConfiguration()->emitBuildDirectoryInitialized();
con's avatar
con committed
315
316
317
    return result;
}

318
void QMakeStep::setUserArguments(const QString &arguments)
319
{
320
321
    if (m_userArgs == arguments)
        return;
dt's avatar
dt committed
322
    m_userArgs = arguments;
323

324
    emit userArgumentsChanged();
325
326

    qt4BuildConfiguration()->emitQMakeBuildConfigurationChanged();
327
328
329
    qt4BuildConfiguration()->emitProFileEvaluteNeeded();
}

330
331
332
333
334
bool QMakeStep::isQmlDebuggingLibrarySupported(QString *reason) const
{
    if (qt4BuildConfiguration()->qtVersion()->hasQmlDebuggingLibrary())
        return true;

335
    if (!qt4BuildConfiguration()->qtVersion()->isValid()) {
336
337
338
339
340
        if (reason)
            *reason = tr("Invalid Qt version.");
        return false;
    }

341
    if (qt4BuildConfiguration()->qtVersion()->qtVersion() < QtVersionNumber(4, 7 ,0)) {
342
343
344
345
346
347
        if (reason)
            *reason = tr("Requires Qt 4.7.1 or newer.");
        return false;
    }

    if (reason)
348
        *reason = tr("Library not available. <a href='compile'>Compile...</a>");
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369

    return false;
}

bool QMakeStep::linkQmlDebuggingLibrary() const
{
    return m_linkQmlDebuggingLibrary;
}

void QMakeStep::setLinkQmlDebuggingLibrary(bool enable)
{
    if (m_linkQmlDebuggingLibrary == enable)
        return;
    m_linkQmlDebuggingLibrary = enable;

    emit linkQmlDebuggingLibraryChanged();

    qt4BuildConfiguration()->emitQMakeBuildConfigurationChanged();
    qt4BuildConfiguration()->emitProFileEvaluteNeeded();
}

370
371
372
QStringList QMakeStep::parserArguments()
{
    QStringList result;
373
374
375
376
377
378
    for (Utils::QtcProcess::ConstArgIterator ait(allArguments()); ait.next(); ) {
        const QString &arg = ait.value();
        if (arg.contains(QLatin1Char('='))) {
            result << arg;
        } else {
            for (int i = 0; i < ProFileOption::modeMapSize; ++i) {
379
380
                // Workaround: Apple GCC does not like ProFileOption::modeMap[i], because the array's bounds are not known
                if (QLatin1String((&ProFileOption::modeMap[0] + i)->qmakeOption) == arg) {
381
382
383
384
385
386
                    result << arg;
                    break;
                }
            }
        }
    }
387
    return result;
388
389
}

390
QString QMakeStep::userArguments()
391
{
dt's avatar
dt committed
392
    return m_userArgs;
393
394
}

395
QVariantMap QMakeStep::toMap() const
396
{
397
398
    QVariantMap map(AbstractProcessStep::toMap());
    map.insert(QLatin1String(QMAKE_ARGUMENTS_KEY), m_userArgs);
399
    map.insert(QLatin1String(QMAKE_QMLDEBUGLIB_KEY), m_linkQmlDebuggingLibrary);
400
    map.insert(QLatin1String(QMAKE_FORCED_KEY), m_forced);
401
    return map;
402
403
}

404
bool QMakeStep::fromMap(const QVariantMap &map)
405
{
406
    m_userArgs = map.value(QLatin1String(QMAKE_ARGUMENTS_KEY)).toString();
407
    m_forced = map.value(QLatin1String(QMAKE_FORCED_KEY), false).toBool();
408
    m_linkQmlDebuggingLibrary = map.value(QLatin1String(QMAKE_QMLDEBUGLIB_KEY), false).toBool();
409
    return BuildStep::fromMap(map);
410
411
}

412
413
414
415
////
// QMakeStepConfigWidget
////

con's avatar
con committed
416
QMakeStepConfigWidget::QMakeStepConfigWidget(QMakeStep *step)
417
    : BuildStepConfigWidget(), m_step(step), m_ignoreChange(false)
con's avatar
con committed
418
419
420
{
    m_ui.setupUi(this);
    connect(m_ui.qmakeAdditonalArgumentsLineEdit, SIGNAL(textEdited(const QString&)),
421
422
423
            this, SLOT(qmakeArgumentsLineEdited()));
    connect(m_ui.buildConfigurationComboBox, SIGNAL(currentIndexChanged(int)),
            this, SLOT(buildConfigurationSelected()));
424
425
426
427
    connect(m_ui.qmlDebuggingLibraryCheckBox, SIGNAL(toggled(bool)),
            this, SLOT(linkQmlDebuggingLibraryChecked(bool)));
    connect(m_ui.qmlDebuggingWarningText, SIGNAL(linkActivated(QString)),
            this, SLOT(buildQmlDebuggingHelper()));
428
429
    connect(step, SIGNAL(userArgumentsChanged()),
            this, SLOT(userArgumentsChanged()));
430
431
    connect(step, SIGNAL(linkQmlDebuggingLibraryChanged()),
            this, SLOT(linkQmlDebuggingLibraryChanged()));
432
    connect(step->qt4BuildConfiguration(), SIGNAL(qtVersionChanged()),
433
            this, SLOT(qtVersionChanged()));
434
435
436
437
438
439
    connect(step->qt4BuildConfiguration(), SIGNAL(qmakeBuildConfigurationChanged()),
            this, SLOT(qmakeBuildConfigChanged()));
}

void QMakeStepConfigWidget::init()
{
440
    m_ui.qmakeAdditonalArgumentsLineEdit->setText(m_step->userArguments());
441
442
    m_ui.qmlDebuggingLibraryCheckBox->setEnabled(m_step->isQmlDebuggingLibrarySupported());
    m_ui.qmlDebuggingLibraryCheckBox->setChecked(m_step->linkQmlDebuggingLibrary());
443
444
445
446
447

    qmakeBuildConfigChanged();

    updateSummaryLabel();
    updateEffectiveQMakeCall();
448
    updateQmlDebuggingWarningsLabel();
con's avatar
con committed
449
450
}

dt's avatar
dt committed
451
452
453
454
455
QString QMakeStepConfigWidget::summaryText() const
{
    return m_summaryText;
}

456
457
458
459
460
QString QMakeStepConfigWidget::displayName() const
{
    return m_step->displayName();
}

461
void QMakeStepConfigWidget::qtVersionChanged()
462
{
463
    updateSummaryLabel();
dt's avatar
dt committed
464
    updateEffectiveQMakeCall();
465
466
}

467
void QMakeStepConfigWidget::qmakeBuildConfigChanged()
dt's avatar
dt committed
468
{
469
470
    Qt4BuildConfiguration *bc = m_step->qt4BuildConfiguration();
    bool debug = bc->qmakeBuildConfiguration() & QtVersion::DebugBuild;
Tobias Hunger's avatar
Tobias Hunger committed
471
472
473
    int index = debug ? 0 : 1;
    if (bc->qmakeBuildConfiguration() & QtVersion::BuildAll)
        index = 2;
474
    m_ignoreChange = true;
Tobias Hunger's avatar
Tobias Hunger committed
475
476
    m_ui.buildConfigurationComboBox->setCurrentIndex(index);

477
478
479
480
    m_ignoreChange = false;
    updateSummaryLabel();
    updateEffectiveQMakeCall();
}
dt's avatar
dt committed
481

482
483
484
485
void QMakeStepConfigWidget::userArgumentsChanged()
{
    if (m_ignoreChange)
        return;
486
    m_ui.qmakeAdditonalArgumentsLineEdit->setText(m_step->userArguments());
487
488
    updateSummaryLabel();
    updateEffectiveQMakeCall();
dt's avatar
dt committed
489
490
}

491
492
493
494
495
496
497
498
499
500
501
502
void QMakeStepConfigWidget::linkQmlDebuggingLibraryChanged()
{
    if (m_ignoreChange)
        return;
    m_ui.qmlDebuggingLibraryCheckBox->setEnabled(m_step->isQmlDebuggingLibrarySupported());
    m_ui.qmlDebuggingLibraryCheckBox->setChecked(m_step->linkQmlDebuggingLibrary());

    updateSummaryLabel();
    updateEffectiveQMakeCall();
    updateQmlDebuggingWarningsLabel();
}

503
void QMakeStepConfigWidget::qmakeArgumentsLineEdited()
con's avatar
con committed
504
{
505
    m_ignoreChange = true;
506
    m_step->setUserArguments(m_ui.qmakeAdditonalArgumentsLineEdit->text());
507
    m_ignoreChange = false;
508

509
    updateSummaryLabel();
510
    updateEffectiveQMakeCall();
con's avatar
con committed
511
512
}

513
void QMakeStepConfigWidget::buildConfigurationSelected()
con's avatar
con committed
514
{
515
516
517
518
    if (m_ignoreChange)
        return;
    Qt4BuildConfiguration *bc = m_step->qt4BuildConfiguration();
    QtVersion::QmakeBuildConfigs buildConfiguration = bc->qmakeBuildConfiguration();
Tobias Hunger's avatar
Tobias Hunger committed
519
520
521
522
523
524
525
526
527
528
    switch (m_ui.buildConfigurationComboBox->currentIndex()) {
    case 0:
        buildConfiguration = QtVersion::DebugBuild;
        break;
    case 1:
        buildConfiguration = 0;
        break;
    case 2:
        buildConfiguration = QtVersion::BuildAll;
        break;
con's avatar
con committed
529
    }
Tobias Hunger's avatar
Tobias Hunger committed
530

531
532
533
    m_ignoreChange = true;
    bc->setQMakeBuildConfiguration(buildConfiguration);
    m_ignoreChange = false;
con's avatar
con committed
534

535
536
    updateSummaryLabel();
    updateEffectiveQMakeCall();
con's avatar
con committed
537
538
}

539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
void QMakeStepConfigWidget::linkQmlDebuggingLibraryChecked(bool checked)
{
    if (m_ignoreChange)
        return;

    m_ignoreChange = true;
    m_step->setLinkQmlDebuggingLibrary(checked);
    m_ignoreChange = false;

    updateSummaryLabel();
    updateEffectiveQMakeCall();
    updateQmlDebuggingWarningsLabel();
}

void QMakeStepConfigWidget::buildQmlDebuggingHelper()
{
    QtVersion *version = m_step->qt4BuildConfiguration()->qtVersion();
    DebuggingHelperBuildTask *buildTask = new DebuggingHelperBuildTask(version,
                                                                       DebuggingHelperBuildTask::QmlDebugging);

    connect(buildTask, SIGNAL(finished(int,DebuggingHelperBuildTask::Tools,QString)),
            this, SLOT(debuggingHelperBuildFinished()),
            Qt::QueuedConnection);

    QFuture<void> task = QtConcurrent::run(&DebuggingHelperBuildTask::run, buildTask);
    const QString taskName = tr("Building helpers");
    Core::ICore::instance()->progressManager()->addTask(task, taskName,
                                                        QLatin1String("Qt4ProjectManager::BuildHelpers"));
}

void QMakeStepConfigWidget::debuggingHelperBuildFinished()
{
    m_step->qt4BuildConfiguration()->qtVersion()->invalidateCache();
    m_ui.qmlDebuggingLibraryCheckBox->setChecked(m_step->linkQmlDebuggingLibrary());
    m_ui.qmlDebuggingLibraryCheckBox->setEnabled(m_step->isQmlDebuggingLibrarySupported());
    updateSummaryLabel();
    updateEffectiveQMakeCall();
    updateQmlDebuggingWarningsLabel();
}

579
void QMakeStepConfigWidget::updateSummaryLabel()
580
{
581
582
583
    Qt4BuildConfiguration *qt4bc = m_step->qt4BuildConfiguration();
    const QtVersion *qtVersion = qt4bc->qtVersion();
    if (!qtVersion) {
Friedemann Kleint's avatar
Friedemann Kleint committed
584
        m_summaryText = tr("<b>qmake:</b> No Qt version set. Cannot run qmake.");
585
        emit updateSummary();
586
        return;
587
588
589
    }

    // We don't want the full path to the .pro file
590
    QString args = m_step->allArguments(true);
591
592
    // And we only use the .pro filename not the full path
    QString program = QFileInfo(qtVersion->qmakeCommand()).fileName();
593
    m_summaryText = tr("<b>qmake:</b> %1 %2").arg(program, args);
594
    emit updateSummary();
595

596
597
}

598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
void QMakeStepConfigWidget::updateQmlDebuggingWarningsLabel()
{
    QString reason;
    m_ui.qmlDebuggingWarningText->clear();
    if (!m_step->isQmlDebuggingLibrarySupported(&reason)) {
        m_ui.qmlDebuggingWarningText->setText(reason);
    }

    if (m_step->linkQmlDebuggingLibrary()) {
        if (m_step->isQmlDebuggingLibrarySupported()) {
            m_ui.qmlDebuggingWarningText->setText("Might make your application vulnerable. Only use in a safe environment!");
        }
    }

    m_ui.qmlDebuggingWarningIcon->setVisible(!m_ui.qmlDebuggingWarningText->text().isEmpty());
}

615
616
void QMakeStepConfigWidget::updateEffectiveQMakeCall()
{
dt's avatar
dt committed
617
    Qt4BuildConfiguration *qt4bc = m_step->qt4BuildConfiguration();
618
    const QtVersion *qtVersion = qt4bc->qtVersion();
Tobias Hunger's avatar
Tobias Hunger committed
619
    QString program = QFileInfo(qtVersion->qmakeCommand()).fileName();
620
    m_ui.qmakeArgumentsEdit->setPlainText(program + QLatin1Char(' ') + m_step->allArguments());
con's avatar
con committed
621
622
}

dt's avatar
dt committed
623
624
625
626
////
// QMakeStepFactory
////

627
628
QMakeStepFactory::QMakeStepFactory(QObject *parent) :
    ProjectExplorer::IBuildStepFactory(parent)
dt's avatar
dt committed
629
630
631
632
633
634
635
{
}

QMakeStepFactory::~QMakeStepFactory()
{
}

Tobias Hunger's avatar
Tobias Hunger committed
636
bool QMakeStepFactory::canCreate(BuildStepList *parent, const QString &id) const
dt's avatar
dt committed
637
{
Tobias Hunger's avatar
Tobias Hunger committed
638
    if (parent->id() != QLatin1String(ProjectExplorer::Constants::BUILDSTEPS_BUILD))
639
        return false;
Tobias Hunger's avatar
Tobias Hunger committed
640
    if (!qobject_cast<Qt4BuildConfiguration *>(parent->parent()))
641
642
        return false;
    return (id == QLatin1String(QMAKE_BS_ID));
dt's avatar
dt committed
643
644
}

Tobias Hunger's avatar
Tobias Hunger committed
645
ProjectExplorer::BuildStep *QMakeStepFactory::create(BuildStepList *parent, const QString &id)
dt's avatar
dt committed
646
{
Tobias Hunger's avatar
Tobias Hunger committed
647
    if (!canCreate(parent, id))
648
        return 0;
Tobias Hunger's avatar
Tobias Hunger committed
649
    return new QMakeStep(parent);
650
651
}

Tobias Hunger's avatar
Tobias Hunger committed
652
bool QMakeStepFactory::canClone(BuildStepList *parent, BuildStep *source) const
653
{
Tobias Hunger's avatar
Tobias Hunger committed
654
    return canCreate(parent, source->id());
dt's avatar
dt committed
655
656
}

Tobias Hunger's avatar
Tobias Hunger committed
657
ProjectExplorer::BuildStep *QMakeStepFactory::clone(BuildStepList *parent, ProjectExplorer::BuildStep *source)
dt's avatar
dt committed
658
{
Tobias Hunger's avatar
Tobias Hunger committed
659
    if (!canClone(parent, source))
660
        return 0;
Tobias Hunger's avatar
Tobias Hunger committed
661
    return new QMakeStep(parent, qobject_cast<QMakeStep *>(source));
dt's avatar
dt committed
662
663
}

Tobias Hunger's avatar
Tobias Hunger committed
664
bool QMakeStepFactory::canRestore(BuildStepList *parent, const QVariantMap &map) const
665
666
{
    QString id(ProjectExplorer::idFromMap(map));
Tobias Hunger's avatar
Tobias Hunger committed
667
    return canCreate(parent, id);
668
669
}

Tobias Hunger's avatar
Tobias Hunger committed
670
ProjectExplorer::BuildStep *QMakeStepFactory::restore(BuildStepList *parent, const QVariantMap &map)
dt's avatar
dt committed
671
{
Tobias Hunger's avatar
Tobias Hunger committed
672
    if (!canRestore(parent, map))
673
        return 0;
Tobias Hunger's avatar
Tobias Hunger committed
674
    QMakeStep *bs = new QMakeStep(parent);
675
676
677
678
    if (bs->fromMap(map))
        return bs;
    delete bs;
    return 0;
dt's avatar
dt committed
679
680
}

Tobias Hunger's avatar
Tobias Hunger committed
681
QStringList QMakeStepFactory::availableCreationIds(ProjectExplorer::BuildStepList *parent) const
682
{
Tobias Hunger's avatar
Tobias Hunger committed
683
684
    if (parent->id() == QLatin1String(ProjectExplorer::Constants::BUILDSTEPS_BUILD))
        if (Qt4BuildConfiguration *bc = qobject_cast<Qt4BuildConfiguration *>(parent->parent()))
685
686
            if (!bc->qmakeStep())
                return QStringList() << QLatin1String(QMAKE_BS_ID);
687
688
    return QStringList();
}
dt's avatar
dt committed
689

690
691
692
QString QMakeStepFactory::displayNameForId(const QString &id) const
{
    if (id == QLatin1String(QMAKE_BS_ID))
693
        return tr("qmake");
694
695
    return QString();
}