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

#include "maemopackagecreationstep.h"

34
#include "maemoconstants.h"
ck's avatar
ck committed
35
36
#include "maemoglobal.h"
#include "maemopackagecreationwidget.h"
37
#include "qt4maemotarget.h"
38

39
#include <projectexplorer/projectexplorerconstants.h>
40
41
42
#include <qt4projectmanager/qt4buildconfiguration.h>
#include <qt4projectmanager/qt4project.h>
#include <qt4projectmanager/qt4target.h>
43
#include <qt4projectmanager/qt4buildconfiguration.h>
44
#include <utils/environment.h>
45
#include <utils/fileutils.h>
ck's avatar
ck committed
46

47
#include <QtCore/QDateTime>
ck's avatar
ck committed
48
#include <QtCore/QProcess>
49
#include <QtCore/QRegExp>
50

51
namespace {
52
    const QLatin1String MagicFileName(".qtcreator");
53
}
ck's avatar
ck committed
54

55
using namespace ProjectExplorer::Constants;
Tobias Hunger's avatar
Tobias Hunger committed
56
using ProjectExplorer::BuildStepList;
57
using ProjectExplorer::BuildStepConfigWidget;
58
using ProjectExplorer::Task;
59
using namespace Qt4ProjectManager;
60

61
namespace Madde {
62
63
namespace Internal {

64
const QLatin1String AbstractMaemoPackageCreationStep::DefaultVersionNumber("0.0.1");
65

66
AbstractMaemoPackageCreationStep::AbstractMaemoPackageCreationStep(BuildStepList *bsl,
67
    const QString &id) : AbstractPackagingStep(bsl, id)
68
69
70
{
}

71
AbstractMaemoPackageCreationStep::AbstractMaemoPackageCreationStep(BuildStepList *bsl,
72
    AbstractMaemoPackageCreationStep *other) : AbstractPackagingStep(bsl, other)
73
74
75
{
}

76
AbstractMaemoPackageCreationStep::~AbstractMaemoPackageCreationStep()
77
78
{
}
79

80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
bool AbstractMaemoPackageCreationStep::init()
{
    if (!AbstractPackagingStep::init())
        return false;
    m_packagingNeeded = isPackagingNeeded();
    if (!isPackagingNeeded())
        return true;

    if (!qt4BuildConfiguration()) {
        raiseError(tr("No Qt4 build configuration"));
        return false;
    }

    m_environment = qt4BuildConfiguration()->environment();
    if (qt4BuildConfiguration()->qmakeBuildConfiguration() & QtSupport::BaseQtVersion::DebugBuild) {
        m_environment.appendOrSet(QLatin1String("DEB_BUILD_OPTIONS"),
            QLatin1String("nostrip"), QLatin1String(" "));
    }

    if (!qt4BuildConfiguration()->qtVersion()) {
        raiseError(tr("Packaging failed: No Qt version."));
        return false;
    }

104
    m_qmakeCommand = qt4BuildConfiguration()->qtVersion()->qmakeCommand().toString();
105
106
107
108

    return true;
}

109
void AbstractMaemoPackageCreationStep::run(QFutureInterface<bool> &fi)
ck's avatar
ck committed
110
{
111
    if (!m_packagingNeeded) {
112
        emit addOutput(tr("Package up to date."), MessageOutput);
113
114
        fi.reportResult(true);
        return;
115
    }
ck's avatar
ck committed
116

117
    setPackagingStarted();
118
119
120
121
122
123
    // TODO: Make the build process asynchronous; i.e. no waitFor()-functions etc.
    QProcess * const buildProc = new QProcess;
    connect(buildProc, SIGNAL(readyReadStandardOutput()), this,
        SLOT(handleBuildOutput()));
    connect(buildProc, SIGNAL(readyReadStandardError()), this,
        SLOT(handleBuildOutput()));
124
    emit addOutput(tr("Creating package file ..."), MessageOutput);
125
    const bool success = createPackage(buildProc, fi);
126
127
    disconnect(buildProc, 0, this, 0);
    buildProc->deleteLater();
128
    if (success)
129
        emit addOutput(tr("Package created."), BuildStep::MessageOutput);
130
    setPackagingFinished(success);
131
    fi.reportResult(success);
132
133
}

134
BuildStepConfigWidget *AbstractMaemoPackageCreationStep::createConfigWidget()
135
{
136
    return new MaemoPackageCreationWidget(this);
ck's avatar
ck committed
137
138
}

139
void AbstractMaemoPackageCreationStep::handleBuildOutput()
140
{
141
    QProcess * const buildProc = qobject_cast<QProcess *>(sender());
Christian Kandeler's avatar
Christian Kandeler committed
142
143
    if (!buildProc)
        return;
144
145
    QByteArray stdOut = buildProc->readAllStandardOutput();
    stdOut.replace('\0', QByteArray()); // Output contains NUL characters.
146
    if (!stdOut.isEmpty())
147
        emit addOutput(QString::fromLocal8Bit(stdOut), BuildStep::NormalOutput,
148
                BuildStep::DontAppendNewline);
149
150
    QByteArray errorOut = buildProc->readAllStandardError();
    errorOut.replace('\0', QByteArray());
151
    if (!errorOut.isEmpty()) {
152
153
        emit addOutput(QString::fromLocal8Bit(errorOut), BuildStep::ErrorOutput,
            BuildStep::DontAppendNewline);
154
155
156
    }
}

157
const Qt4BuildConfiguration *AbstractMaemoPackageCreationStep::qt4BuildConfiguration() const
ck's avatar
ck committed
158
{
159
    return static_cast<Qt4BuildConfiguration *>(target()->activeBuildConfiguration());
ck's avatar
ck committed
160
161
}

162
AbstractQt4MaemoTarget *AbstractMaemoPackageCreationStep::maemoTarget() const
163
{
164
    return qobject_cast<AbstractQt4MaemoTarget *>(target());
165
166
}

167
AbstractDebBasedQt4MaemoTarget *AbstractMaemoPackageCreationStep::debBasedMaemoTarget() const
168
{
169
    return qobject_cast<AbstractDebBasedQt4MaemoTarget*>(target());
170
171
}

172
AbstractRpmBasedQt4MaemoTarget *AbstractMaemoPackageCreationStep::rpmBasedMaemoTarget() const
Christian Kandeler's avatar
Christian Kandeler committed
173
{
174
    return qobject_cast<AbstractRpmBasedQt4MaemoTarget*>(target());
Christian Kandeler's avatar
Christian Kandeler committed
175
176
}

177
bool AbstractMaemoPackageCreationStep::isPackagingNeeded() const
ck's avatar
ck committed
178
{
179
    if (AbstractPackagingStep::isPackagingNeeded())
180
        return true;
181
    return isMetaDataNewerThan(QFileInfo(packageFilePath()).lastModified());
182
183
}

184
QString AbstractMaemoPackageCreationStep::packageFileName() const
185
{
186
187
188
189
    QString error;
    const QString &version = versionString(&error);
    if (version.isEmpty())
        return QString();
Christian Kandeler's avatar
Christian Kandeler committed
190
191
    QFileInfo fi(maemoTarget()->packageFileName());
    const QString baseName = replaceDots(fi.completeBaseName());
192
    return baseName + QLatin1Char('.') + fi.suffix();
193
194
}

195
QString AbstractMaemoPackageCreationStep::versionString(QString *error) const
196
{
197
    return maemoTarget()->projectVersion(error);
198
199
}

200
bool AbstractMaemoPackageCreationStep::setVersionString(const QString &version, QString *error)
201
{
202
    const bool success = maemoTarget()->setProjectVersion(version, error);
203
204
205
    if (success)
        emit packageFilePathChanged();
    return success;
206
207
}

208
QString AbstractMaemoPackageCreationStep::nativePath(const QFile &file)
209
210
211
212
{
    return QDir::toNativeSeparators(QFileInfo(file).filePath());
}

213
214
215
bool AbstractMaemoPackageCreationStep::callPackagingCommand(QProcess *proc,
    const QStringList &arguments)
{
216
217
218
219
    proc->setEnvironment(m_environment.toStringList());
    proc->setWorkingDirectory(cachedPackageDirectory());

    const QString madCommand = MaemoGlobal::madCommand(m_qmakeCommand);
220
221
222
223
    const QString cmdLine = madCommand + QLatin1Char(' ')
        + arguments.join(QLatin1String(" "));
    emit addOutput(tr("Package Creation: Running command '%1'.").arg(cmdLine),
        BuildStep::MessageOutput);
224
    MaemoGlobal::callMad(*proc, arguments, m_qmakeCommand, true);
225
    if (!proc->waitForStarted()) {
226
        raiseError(tr("Packaging failed: Could not start command '%1'. Reason: %2")
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
            .arg(cmdLine, proc->errorString()));
        return false;
    }
    proc->waitForFinished(-1);
    if (proc->error() != QProcess::UnknownError || proc->exitCode() != 0) {
        QString mainMessage = tr("Packaging Error: Command '%1' failed.")
            .arg(cmdLine);
        if (proc->error() != QProcess::UnknownError)
            mainMessage += tr(" Reason: %1").arg(proc->errorString());
        else
            mainMessage += tr("Exit code: %1").arg(proc->exitCode());
        raiseError(mainMessage);
        return false;
    }
    return true;
}

void AbstractMaemoPackageCreationStep::preparePackagingProcess(QProcess *proc,
245
    const Qt4BuildConfiguration *bc, const QString &workingDir)
246
{
247
    Utils::Environment env = bc->environment();
248
    if (bc->qmakeBuildConfiguration() & QtSupport::BaseQtVersion::DebugBuild) {
249
250
        env.appendOrSet(QLatin1String("DEB_BUILD_OPTIONS"),
            QLatin1String("nostrip"), QLatin1String(" "));
251
    }
252
    proc->setEnvironment(env.toStringList());
253
254
255
    proc->setWorkingDirectory(workingDir);
}

256
QString AbstractMaemoPackageCreationStep::replaceDots(const QString &name) const
257
{
258
259
260
261
262
263
    // Idiotic OVI store requirement for N900 (but not allowed for N9 ...).
    if (qobject_cast<Qt4Maemo5Target *>(target())) {
        QString adaptedName = name;
        return adaptedName.replace(QLatin1Char('.'), QLatin1Char('_'));
    }
    return name;
264
265
}

266
267
268
////////////////
// MaemoDebianPackageCreationStep
////////////////
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290

MaemoDebianPackageCreationStep::MaemoDebianPackageCreationStep(BuildStepList *bsl)
    : AbstractMaemoPackageCreationStep(bsl, CreatePackageId)
{
    ctor();
}

const QString MaemoDebianPackageCreationStep::CreatePackageId
    = QLatin1String("MaemoDebianPackageCreationStep");

MaemoDebianPackageCreationStep::MaemoDebianPackageCreationStep(BuildStepList *buildConfig,
    MaemoDebianPackageCreationStep *other)
        : AbstractMaemoPackageCreationStep(buildConfig, other)
{
    ctor();
}

void MaemoDebianPackageCreationStep::ctor()
{
    setDefaultDisplayName(tr("Create Debian Package"));
}

291
292
293
294
bool MaemoDebianPackageCreationStep::init()
{
    if (!AbstractMaemoPackageCreationStep::init())
        return false;
295
    m_maddeRoot = MaemoGlobal::maddeRoot(qt4BuildConfiguration()->qtVersion()->qmakeCommand().toString());
296
    m_projectDirectory = project()->projectDirectory();
297
298
299
300
301
302
303
304
    m_pkgFileName = maemoTarget()->packageFileName();
    m_packageName = maemoTarget()->packageName();
    m_templatesDirPath = debBasedMaemoTarget()->debianDirPath();
    m_debugBuild = qt4BuildConfiguration()->qmakeBuildConfiguration() & QtSupport::BaseQtVersion::DebugBuild;
    checkProjectName();
    return true;
}

305
306
bool MaemoDebianPackageCreationStep::createPackage(QProcess *buildProc,
    const QFutureInterface<bool> &fi)
307
{
308
    Q_UNUSED(fi);
309
    const bool inSourceBuild = QFileInfo(cachedPackageDirectory()) == QFileInfo(m_projectDirectory);
310
311
312
313
314
315
316
    if (!copyDebianFiles(inSourceBuild))
        return false;
    const QStringList args = QStringList() << QLatin1String("dpkg-buildpackage")
        << QLatin1String("-nc") << QLatin1String("-uc") << QLatin1String("-us");
    if (!callPackagingCommand(buildProc, args))
        return false;

317
    QFile::remove(cachedPackageFilePath());
318
319

    // Workaround for non-working dh_builddeb --destdir=.
320
    if (!QDir(cachedPackageDirectory()).isRoot()) {
321
322
        QString error;
        if (!error.isEmpty())
323
            raiseError(tr("Packaging failed: Could not get package name."));
324
        const QString changesSourceFileName = QFileInfo(m_pkgFileName).completeBaseName()
325
                + QLatin1String(".changes");
326
        const QString changesTargetFileName = replaceDots(QFileInfo(m_pkgFileName).completeBaseName())
327
                + QLatin1String(".changes");
328
329
        const QString packageSourceDir = cachedPackageDirectory() + QLatin1String("/../");
        const QString packageSourceFilePath = packageSourceDir + m_pkgFileName;
330
        const QString changesSourceFilePath = packageSourceDir + changesSourceFileName;
331
        const QString changesTargetFilePath
332
            = cachedPackageDirectory() + QLatin1Char('/') + changesTargetFileName;
333
        QFile::remove(changesTargetFilePath);
334
        if (!QFile::rename(packageSourceFilePath, cachedPackageFilePath())
335
                || !QFile::rename(changesSourceFilePath, changesTargetFilePath)) {
Friedemann Kleint's avatar
Friedemann Kleint committed
336
            raiseError(tr("Packaging failed: Could not move package files from '%1' to '%2'.")
337
                .arg(packageSourceDir, cachedPackageDirectory()));
338
339
340
341
            return false;
        }
    }

342
343
    if (inSourceBuild)
        callPackagingCommand(buildProc, QStringList() << QLatin1String("dh_clean"));
344
345
346
347
348
349
350
351
352
353
    return true;
}

bool MaemoDebianPackageCreationStep::isMetaDataNewerThan(const QDateTime &packageDate) const
{
    const QString debianPath = debBasedMaemoTarget()->debianDirPath();
    if (packageDate <= QFileInfo(debianPath).lastModified())
        return true;
    const QStringList debianFiles = debBasedMaemoTarget()->debianFiles();
    foreach (const QString &debianFile, debianFiles) {
354
        const QString absFilePath = debianPath + QLatin1Char('/') + debianFile;
355
356
357
358
359
360
361
362
363
        if (packageDate <= QFileInfo(absFilePath).lastModified())
            return true;
    }
    return false;
}

void MaemoDebianPackageCreationStep::checkProjectName()
{
    const QRegExp legalName(QLatin1String("[0-9-+a-z\\.]+"));
364
    if (!legalName.exactMatch(project()->displayName())) {
365
366
367
368
369
370
371
372
373
374
375
        emit addTask(Task(Task::Warning,
            tr("Your project name contains characters not allowed in "
               "Debian packages.\nThey must only use lower-case letters, "
               "numbers, '-', '+' and '.'.\n""We will try to work around that, "
               "but you may experience problems."),
            QString(), -1, TASK_CATEGORY_BUILDSYSTEM));
    }
}

bool MaemoDebianPackageCreationStep::copyDebianFiles(bool inSourceBuild)
{
376
    const QString debianDirPath = cachedPackageDirectory() + QLatin1String("/debian");
377
378
379
380
    const QString magicFilePath
        = debianDirPath + QLatin1Char('/') + MagicFileName;
    if (inSourceBuild && QFileInfo(debianDirPath).isDir()
        && !QFileInfo(magicFilePath).exists()) {
381
382
383
384
385
        raiseError(tr("Packaging failed: Foreign debian directory detected. "
            "You are not using a shadow build and there is a debian "
            "directory in your project root ('%1'). Qt Creator will not "
            "overwrite that directory. Please remove it or use the "
            "shadow build feature.").arg(QDir::toNativeSeparators(debianDirPath)));
386
387
388
        return false;
    }
    QString error;
389
    if (!Utils::FileUtils::removeRecursively(debianDirPath, &error)) {
390
391
        raiseError(tr("Packaging failed: Could not remove directory '%1': %2")
            .arg(debianDirPath, error));
392
393
        return false;
    }
394
    QDir buildDir(cachedPackageDirectory());
395
    if (!buildDir.mkdir("debian")) {
396
        raiseError(tr("Could not create Debian directory '%1'.").arg(debianDirPath));
397
398
        return false;
    }
399
    QDir templatesDir(m_templatesDirPath);
400
401
    const QStringList &files = templatesDir.entryList(QDir::Files);
    foreach (const QString &fileName, files) {
402
        const QString srcFile = m_templatesDirPath + QLatin1Char('/') + fileName;
403
        QString newFileName = fileName;
404
        if (newFileName == Qt4HarmattanTarget::aegisManifestFileName())
405
            newFileName = m_packageName + QLatin1String(".aegis");
406

407
        const QString destFile = debianDirPath + QLatin1Char('/') + newFileName;
408
409
410
        if (fileName == QLatin1String("rules")) {
            if (!adaptRulesFile(srcFile, destFile))
                return false;
411
412
413
414
415
416
417
418
419
420
            continue;
        }

        if (newFileName == maemoTarget()->packageName() + QLatin1String(".aegis")) {
            Utils::FileReader reader;
            if (!reader.fetch(srcFile)) {
                raiseError(tr("Could not read manifest file '%1': %2.")
                    .arg(QDir::toNativeSeparators(srcFile), reader.errorString()));
                return false;
            }
421
422
423

            if (reader.data().isEmpty() || reader.data().startsWith("AutoGenerateAegisFile"))
                continue;
424
425
426
427
428
429
430
431
432
433
434
435
436
            if (reader.data().startsWith("NoAegisFile")) {
                QFile targetFile(destFile);
                if (!targetFile.open(QIODevice::WriteOnly)) {
                    raiseError(tr("Could not write manifest file '%1': %2.")
                        .arg(QDir::toNativeSeparators(destFile), targetFile.errorString()));
                    return false;
                }
                continue;
            }
        }

        if (!QFile::copy(srcFile, destFile)) {
            raiseError(tr("Could not copy file '%1' to '%2'.")
437
                .arg(QDir::toNativeSeparators(srcFile), QDir::toNativeSeparators(destFile)));
438
439
440
441
442
443
444
445
446
447
448
449
450
451
            return false;
        }
    }

    QFile magicFile(magicFilePath);
    if (!magicFile.open(QIODevice::WriteOnly)) {
        raiseError(tr("Error: Could not create file '%1'.")
            .arg(QDir::toNativeSeparators(magicFilePath)));
        return false;
    }

    return true;
}

452
QString MaemoDebianPackageCreationStep::packagingCommand(const QString &maddeRoot, const QString &commandName)
453
454
455
{
    QString perl;
#ifdef Q_OS_WIN
456
    perl = maddeRoot + QLatin1String("/bin/perl.exe ");
457
#endif
458
    return perl + maddeRoot + QLatin1String("/madbin/") + commandName;
459
460
}

461
void MaemoDebianPackageCreationStep::ensureShlibdeps(QByteArray &rulesContent)
462
463
464
465
466
{
    QString contentAsString = QString::fromLocal8Bit(rulesContent);
    const QString whiteSpace(QLatin1String("[ \\t]*"));
    const QString pattern = QLatin1String("\\n") + whiteSpace
        + QLatin1Char('#') + whiteSpace + QLatin1String("dh_shlibdeps")
467
        + QLatin1String("([^\\n]*)\\n");
468
    contentAsString.replace(QRegExp(pattern),
469
        QLatin1String("\n\tdh_shlibdeps\\1\n"));
470
471
472
    rulesContent = contentAsString.toLocal8Bit();
}

473
474
bool MaemoDebianPackageCreationStep::adaptRulesFile(
    const QString &templatePath, const QString &rulesFilePath)
475
{
476
477
478
479
    Utils::FileReader reader;
    if (!reader.fetch(templatePath)) {
        raiseError(reader.errorString());
        return false;
480
    }
481
    QByteArray content = reader.data();
482
    // Always check for dependencies in release builds.
483
    if (!m_debugBuild)
484
485
        ensureShlibdeps(content);

486
487
488
489
490
491
492
493
494
    Utils::FileSaver saver(rulesFilePath);
    saver.write(content);
    if (!saver.finalize()) {
        raiseError(saver.errorString());
        return false;
    }
    QFile rulesFile(rulesFilePath);
    rulesFile.setPermissions(rulesFile.permissions() | QFile::ExeUser);
    return true;
495
496
}

497
498
499
/////////////////
// MaemoRpmPackageCreationStep
/////////////////
500
501
502

MaemoRpmPackageCreationStep::MaemoRpmPackageCreationStep(BuildStepList *bsl)
    : AbstractMaemoPackageCreationStep(bsl, CreatePackageId)
503
{
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
    ctor();
}

MaemoRpmPackageCreationStep::MaemoRpmPackageCreationStep(BuildStepList *buildConfig,
    MaemoRpmPackageCreationStep *other)
        : AbstractMaemoPackageCreationStep(buildConfig, other)
{
    ctor();
}

void MaemoRpmPackageCreationStep::ctor()
{
    setDefaultDisplayName(tr("Create RPM Package"));
}

519
520
521
522
523
524
525
bool MaemoRpmPackageCreationStep::init()
{
    m_specFile = rpmBasedMaemoTarget()->specFilePath();
    m_packageFileName = rpmBasedMaemoTarget()->packageFileName();
    return AbstractMaemoPackageCreationStep::init();
}

526
527
bool MaemoRpmPackageCreationStep::createPackage(QProcess *buildProc,
    const QFutureInterface<bool> &fi)
528
{
529
    Q_UNUSED(fi);
530
    const QStringList args = QStringList() << QLatin1String("rrpmbuild")
531
        << QLatin1String("-bb") << m_specFile;
532
533
    if (!callPackagingCommand(buildProc, args))
        return false;
534
    QFile::remove(cachedPackageFilePath());
535
    const QString packageSourceFilePath = rpmBuildDir() + QLatin1Char('/')
536
537
        + m_packageFileName;
    if (!QFile::rename(packageSourceFilePath, cachedPackageFilePath())) {
538
        raiseError(tr("Packaging failed: Could not move package file from %1 to %2.")
539
            .arg(packageSourceFilePath, cachedPackageFilePath()));
540
541
542
543
        return false;
    }

    return true;
544
545
}

546
547
548
549
550
551
552
bool MaemoRpmPackageCreationStep::isMetaDataNewerThan(const QDateTime &packageDate) const
{
    const QDateTime specFileChangeDate
        = QFileInfo(rpmBasedMaemoTarget()->specFilePath()).lastModified();
    return packageDate <= specFileChangeDate;
}

553
QString MaemoRpmPackageCreationStep::rpmBuildDir() const
Christian Kandeler's avatar
Christian Kandeler committed
554
{
555
    return cachedPackageDirectory() + QLatin1String("/rrpmbuild");
Christian Kandeler's avatar
Christian Kandeler committed
556
557
}

558
559
560
const QString MaemoRpmPackageCreationStep::CreatePackageId
    = QLatin1String("MaemoRpmPackageCreationStep");

561
} // namespace Internal
562
} // namespace Madde