/**************************************************************************** | |
** | |
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). | |
** All rights reserved. | |
** Contact: Nokia Corporation (qt-info@nokia.com) | |
** | |
** This file is part of the qmake application of the Qt Toolkit. | |
** | |
** $QT_BEGIN_LICENSE:LGPL$ | |
** GNU Lesser General Public License Usage | |
** 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, 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. | |
** | |
** GNU General Public License Usage | |
** Alternatively, this file may be used under the terms of the GNU General | |
** Public License version 3.0 as published by the Free Software Foundation | |
** and appearing in the file LICENSE.GPL included in the packaging of this | |
** file. Please review the following information to ensure the GNU General | |
** Public License version 3.0 requirements will be met: | |
** http://www.gnu.org/copyleft/gpl.html. | |
** | |
** Other Usage | |
** Alternatively, this file may be used in accordance with the terms and | |
** conditions contained in a signed written agreement between you and Nokia. | |
** | |
** | |
** | |
** | |
** | |
** $QT_END_LICENSE$ | |
** | |
****************************************************************************/ | |
#include "symmake_sbsv2.h" | |
#include "initprojectdeploy_symbian.h" | |
#include <qstring.h> | |
#include <qstringlist.h> | |
#include <qdir.h> | |
#include <qdatetime.h> | |
#include <qdebug.h> | |
// Included from tools/shared | |
#include <symbian/epocroot_p.h> | |
SymbianSbsv2MakefileGenerator::SymbianSbsv2MakefileGenerator() : SymbianMakefileGenerator() { } | |
SymbianSbsv2MakefileGenerator::~SymbianSbsv2MakefileGenerator() { } | |
#define FLM_DEST_DIR "epoc32/tools/makefile_templates/qt" | |
#define FLM_SOURCE_DIR "/mkspecs/symbian-sbsv2/flm/qt" | |
#define PLATFORM_GCCE "gcce" | |
#define PLATFORM_WINSCW "winscw" | |
#define PLATFORM_ARM_PREFIX "arm" | |
#define BUILD_DEBUG "udeb" | |
#define BUILD_RELEASE "urel" | |
#define SBS_RVCT_PREFIX "rvct" | |
static QString winscwPlatform; | |
static QString armPlatformPrefix; | |
static QString gccePlatform; | |
static QString sbsRvctPrefix; | |
#if defined(Q_OS_UNIX) | |
extern char **environ; | |
#endif | |
static void fixFlmCmd(QString *cmdLine, const QMap<QString, QString> &commandsToReplace) | |
{ | |
// If commandItem starts with any $$QMAKE_* commands, do a replace for SBS equivalent. | |
// Command replacement is done only for the start of the command or right after | |
// concatenation operators (&& and ||), as otherwise unwanted replacements might occur. | |
static QString cmdFind(QLatin1String("(^|&&\\s*|\\|\\|\\s*)%1")); | |
static QString cmdReplace(QLatin1String("\\1%1")); | |
// $$escape_expand(\\n\\t) doesn't work for bld.inf files, but is often used as command | |
// separator, so replace it with "&&" command concatenator. | |
cmdLine->replace("\n\t", "&&"); | |
// Iterate command replacements in reverse alphabetical order of keys so | |
// that keys which are starts of other longer keys are iterated after longer keys. | |
QMapIterator<QString, QString> cmdIter(commandsToReplace); | |
cmdIter.toBack(); | |
while (cmdIter.hasPrevious()) { | |
cmdIter.previous(); | |
if (cmdLine->contains(cmdIter.key())) | |
cmdLine->replace(QRegExp(cmdFind.arg(cmdIter.key())), cmdReplace.arg(cmdIter.value())); | |
} | |
// Sbsv2 toolchain strips all backslashes (even double ones) from option parameters, so just | |
// assume all backslashes are directory separators and replace them with slashes. | |
// Problem: If some command actually needs backslashes for something else than dir separator, | |
// we are out of luck. | |
cmdLine->replace("\\", "/"); | |
} | |
// Copies Qt FLMs to correct location under epocroot. | |
// This is not done by configure as it is possible to change epocroot after configure. | |
void SymbianSbsv2MakefileGenerator::exportFlm() | |
{ | |
static bool flmExportDone = false; | |
if (!flmExportDone) { | |
QDir sourceDir = QDir(QLibraryInfo::location(QLibraryInfo::PrefixPath) + FLM_SOURCE_DIR); | |
QFileInfoList sourceInfos = sourceDir.entryInfoList(QDir::Files); | |
QDir destDir(qt_epocRoot() + FLM_DEST_DIR); | |
if (!destDir.exists()) { | |
if (destDir.mkpath(destDir.absolutePath())) | |
generatedDirs << destDir.absolutePath(); | |
} | |
foreach(QFileInfo item, sourceInfos) { | |
QFileInfo destInfo = QFileInfo(destDir.absolutePath() + "/" + item.fileName()); | |
if (!destInfo.exists() || destInfo.lastModified() != item.lastModified()) { | |
if (destInfo.exists()) | |
QFile::remove(destInfo.absoluteFilePath()); | |
if (QFile::copy(item.absoluteFilePath(), destInfo.absoluteFilePath())) | |
generatedFiles << destInfo.absoluteFilePath(); | |
else | |
fprintf(stderr, "Error: Could not copy '%s' -> '%s'\n", | |
qPrintable(item.absoluteFilePath()), | |
qPrintable(destInfo.absoluteFilePath())); | |
} | |
} | |
flmExportDone = true; | |
} | |
} | |
void SymbianSbsv2MakefileGenerator::findInstalledCompilerVersions(const QString &matchExpression, | |
const QString &versionPrefix, | |
QStringList *versionList) | |
{ | |
// No need to be able to find env variables on other operating systems, | |
// as only linux and windows have support for symbian-sbsv2 toolchain | |
#if defined(Q_OS_UNIX) || defined(Q_OS_WIN) | |
char *entry = 0; | |
int count = 0; | |
QRegExp matcher(matchExpression); | |
while ((entry = environ[count++])) { | |
if (matcher.exactMatch(QString::fromLocal8Bit(entry)) | |
&& fileInfo(matcher.cap(matcher.captureCount())).exists()) { | |
// First capture (index 0) is the whole match, which is skipped. | |
// Next n captures are version numbers, which are interesting. | |
// Final capture is the env var value, which we already used, so that is skipped, too. | |
int capture = 1; | |
int finalCapture = matcher.captureCount() - 1; | |
QString version = versionPrefix; | |
while (capture <= finalCapture) { | |
version.append(matcher.cap(capture)); | |
if (capture != finalCapture) | |
version.append(QLatin1Char('.')); | |
capture++; | |
} | |
*versionList << version; | |
} | |
} | |
#endif | |
} | |
void SymbianSbsv2MakefileGenerator::findGcceVersions(QStringList *gcceVersionList, | |
QString *defaultVersion) | |
{ | |
QString matchStr = QLatin1String("SBS_GCCE(\\d)(\\d)(\\d)BIN=(.*)"); | |
findInstalledCompilerVersions(matchStr, gccePlatform, gcceVersionList); | |
QString qtGcceVersion = QString::fromLocal8Bit(qgetenv("QT_GCCE_VERSION")); | |
if (!qtGcceVersion.isEmpty()) { | |
if (QRegExp("\\d+\\.\\d+\\.\\d+").exactMatch(qtGcceVersion)) { | |
*defaultVersion = gccePlatform + qtGcceVersion; | |
} else { | |
fprintf(stderr, "Warning: Variable QT_GCCE_VERSION ('%s') is in incorrect " | |
"format, expected format is: 'x.y.z'. Attempting to autodetect GCCE version.\n", | |
qPrintable(qtGcceVersion)); | |
} | |
} | |
if (defaultVersion->isEmpty() && gcceVersionList->size()) { | |
gcceVersionList->sort(); | |
*defaultVersion = gcceVersionList->last(); | |
} | |
} | |
void SymbianSbsv2MakefileGenerator::findRvctVersions(QStringList *rvctVersionList, | |
QString *defaultVersion) | |
{ | |
QString matchStr = QLatin1String("RVCT(\\d)(\\d)BIN=(.*)"); | |
findInstalledCompilerVersions(matchStr, sbsRvctPrefix, rvctVersionList); | |
QString qtRvctVersion = QString::fromLocal8Bit(qgetenv("QT_RVCT_VERSION")); | |
if (!qtRvctVersion.isEmpty()) { | |
if (QRegExp("\\d+\\.\\d+").exactMatch(qtRvctVersion)) { | |
*defaultVersion = sbsRvctPrefix + qtRvctVersion; | |
} else { | |
fprintf(stderr, "Warning: Variable QT_RVCT_VERSION ('%s') is in incorrect " | |
"format, expected format is: 'x.y'.\n", | |
qPrintable(qtRvctVersion)); | |
} | |
} | |
} | |
QString SymbianSbsv2MakefileGenerator::configClause(const QString &platform, | |
const QString &build, | |
const QString &compilerVersion, | |
const QString &clauseTemplate) | |
{ | |
QString retval; | |
if (QString::compare(platform, winscwPlatform) == 0) { | |
retval = clauseTemplate.arg(build); | |
} else if (platform.startsWith(armPlatformPrefix)) { | |
QString fixedCompilerVersion = compilerVersion; | |
fixedCompilerVersion.replace(".","_"); | |
retval = clauseTemplate.arg(platform.mid(sizeof(PLATFORM_ARM_PREFIX)-1)) | |
.arg(build) | |
.arg(fixedCompilerVersion); | |
} // else - Unsupported platform for makefile target, return empty clause | |
return retval; | |
} | |
void SymbianSbsv2MakefileGenerator::writeSbsDeploymentList(const DeploymentList& depList, QTextStream& t) | |
{ | |
for (int i = 0; i < depList.size(); ++i) { | |
t << "START EXTENSION qt/qmake_emulator_deployment" << endl; | |
QString fromItem = depList.at(i).from; | |
QString toItem = depList.at(i).to; | |
fromItem.replace("\\", "/"); | |
toItem.replace("\\", "/"); | |
#if defined(Q_OS_WIN) | |
// add drive if it doesn't have one yet | |
if (toItem.size() > 1 && toItem[1] != QLatin1Char(':')) | |
toItem.prepend(QDir::current().absolutePath().left(2)); | |
#endif | |
t << "OPTION DEPLOY_SOURCE " << fromItem << endl; | |
t << "OPTION DEPLOY_TARGET " << toItem << endl; | |
t << "END" << endl; | |
} | |
} | |
void SymbianSbsv2MakefileGenerator::writeMkFile(const QString& wrapperFileName, bool deploymentOnly) | |
{ | |
// Can't use extension makefile with sbsv2 | |
Q_UNUSED(wrapperFileName); | |
Q_UNUSED(deploymentOnly); | |
} | |
void SymbianSbsv2MakefileGenerator::writeWrapperMakefile(QFile& wrapperFile, bool isPrimaryMakefile) | |
{ | |
static QString debugBuild; | |
static QString releaseBuild; | |
static QString defaultGcceCompilerVersion; | |
static QString defaultRvctCompilerVersion; | |
static QStringList rvctVersions; | |
static QStringList gcceVersions; | |
static QStringList allArmCompilerVersions; | |
// Initialize static variables used in makefile creation | |
if (debugBuild.isEmpty()) { | |
debugBuild.append(QLatin1String(BUILD_DEBUG)); | |
releaseBuild.append(QLatin1String(BUILD_RELEASE)); | |
winscwPlatform.append(QLatin1String(PLATFORM_WINSCW)); | |
gccePlatform.append(QLatin1String(PLATFORM_GCCE)); | |
armPlatformPrefix.append(QLatin1String(PLATFORM_ARM_PREFIX)); | |
sbsRvctPrefix.append(QLatin1String(SBS_RVCT_PREFIX)); | |
findGcceVersions(&gcceVersions, &defaultGcceCompilerVersion); | |
findRvctVersions(&rvctVersions, &defaultRvctCompilerVersion); | |
allArmCompilerVersions << rvctVersions << gcceVersions; | |
if (!allArmCompilerVersions.size()) { | |
fprintf(stderr, "Warning: No HW compilers detected. " | |
"Please install either GCCE or RVCT compiler to enable release builds.\n"); | |
} | |
} | |
QStringList allPlatforms; | |
foreach(QString platform, project->values("SYMBIAN_PLATFORMS")) { | |
allPlatforms << platform.toLower(); | |
} | |
if (!gcceVersions.size()) | |
allPlatforms.removeAll(gccePlatform); | |
QString testClause; | |
if (project->isActiveConfig(SYMBIAN_TEST_CONFIG)) | |
testClause = QLatin1String(".test"); | |
else | |
testClause = QLatin1String(""); | |
// Note: armClause is used for gcce, too, which has a side effect | |
// of requiring armv* platform(s) in SYMBIAN_PLATFORMS in order | |
// to get any compiler version specific targets. | |
QString armClause = " -c " PLATFORM_ARM_PREFIX ".%1.%2.%3" + testClause; | |
QString genericArmClause; | |
if (defaultRvctCompilerVersion.isEmpty()) { | |
// Note: Argument %3 needs to be empty string in this version of clause | |
genericArmClause = " -c " PLATFORM_ARM_PREFIX "%1_%2%3" + testClause; | |
} else { | |
// If defaultRvctCompilerVersion is defined, use specific sbs clause for "generic" clause | |
genericArmClause = armClause; | |
} | |
QString winscwClause = " -c " PLATFORM_WINSCW "_%1.mwccinc" + testClause;; | |
QStringList armPlatforms = allPlatforms.filter(QRegExp("^" PLATFORM_ARM_PREFIX)); | |
if (!allArmCompilerVersions.size()) { | |
foreach (QString item, armPlatforms) { | |
allPlatforms.removeAll(item); | |
} | |
armPlatforms.clear(); | |
} | |
QStringList allClauses; | |
QStringList debugClauses; | |
QStringList releaseClauses; | |
// Only winscw and arm platforms are supported | |
QStringList debugPlatforms = allPlatforms; | |
QStringList releasePlatforms = allPlatforms; | |
releasePlatforms.removeAll(winscwPlatform); // No release for emulator | |
if (!releasePlatforms.size()) { | |
fprintf(stderr, "Warning: No valid release platforms in SYMBIAN_PLATFORMS (%s)\n" | |
"Most likely required compiler(s) are not properly installed.\n", | |
qPrintable(project->values("SYMBIAN_PLATFORMS").join(" "))); | |
} | |
if (debugPlatforms.contains(winscwPlatform)) | |
debugClauses << configClause(winscwPlatform, debugBuild, QString(), winscwClause); | |
foreach(QString item, armPlatforms) { | |
// Only use single clause per arm platform even if multiple compiler versions were found, | |
// otherwise we get makefile target collisions from sbsv2 toolchain. | |
if (rvctVersions.size()) { | |
debugClauses << configClause(item, debugBuild, defaultRvctCompilerVersion, genericArmClause); | |
releaseClauses << configClause(item, releaseBuild, defaultRvctCompilerVersion, genericArmClause); | |
} else { | |
debugClauses << configClause(item, debugBuild, defaultGcceCompilerVersion, armClause); | |
releaseClauses << configClause(item, releaseBuild, defaultGcceCompilerVersion, armClause); | |
} | |
} | |
allClauses << debugClauses << releaseClauses; | |
QTextStream t(&wrapperFile); | |
MakefileGenerator::writeHeader(t); | |
t << "MAKEFILE = " << fileInfo(wrapperFile.fileName()).fileName() << endl; | |
t << "QMAKE = " << var("QMAKE_QMAKE") << endl; | |
t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl; | |
t << "DEL_DIR = " << var("QMAKE_DEL_DIR") << endl; | |
t << "CHK_DIR_EXISTS = " << var("QMAKE_CHK_DIR_EXISTS") << endl; | |
t << "MKDIR = " << var("QMAKE_MKDIR") << endl; | |
t << "MOVE = " << var("QMAKE_MOVE") << endl; | |
t << "DEBUG_PLATFORMS = " << debugPlatforms.join(" ") << endl; | |
t << "RELEASE_PLATFORMS = " << releasePlatforms.join(" ") << endl; | |
t << "MAKE = make" << endl; | |
t << "SBS = sbs" << endl; | |
t << endl; | |
t << "DEFINES" << '\t' << " = " | |
<< varGlue("PRL_EXPORT_DEFINES","-D"," -D"," ") | |
<< varGlue("QMAKE_COMPILER_DEFINES", "-D", "-D", " ") | |
<< varGlue("DEFINES","-D"," -D","") << endl; | |
t << "INCPATH" << '\t' << " = "; | |
for (QMap<QString, QStringList>::iterator it = systeminclude.begin(); it != systeminclude.end(); ++it) { | |
QStringList values = it.value(); | |
for (int i = 0; i < values.size(); ++i) { | |
t << " -I\"" << values.at(i) << "\" "; | |
} | |
} | |
t << endl; | |
t << "first: default" << endl << endl; | |
if (!isPrimaryMakefile) { | |
t << "all:" << endl << endl; | |
t << "default: all" << endl << endl; | |
} else { | |
t << "all: debug release" << endl << endl; | |
if (debugPlatforms.contains(winscwPlatform)) | |
t << "default: debug-winscw"; | |
else if (debugPlatforms.size()) | |
t << "default: debug-" << debugPlatforms.first(); | |
else | |
t << "default: all"; | |
t << endl; | |
QString qmakeCmd = "\t$(QMAKE) \"" + project->projectFile() + "\" " + buildArgs(); | |
t << "qmake:" << endl; | |
t << qmakeCmd << endl; | |
t << endl; | |
t << BLD_INF_FILENAME ": " << project->projectFile() << endl; | |
t << qmakeCmd << endl; | |
t << endl; | |
QString locFileDep = generateLocFileTarget(t, qmakeCmd); | |
t << "debug: " << locFileDep << BLD_INF_FILENAME << endl; | |
t << "\t$(SBS)"; | |
foreach(QString clause, debugClauses) { | |
t << clause; | |
} | |
t << endl; | |
t << "clean-debug: " << BLD_INF_FILENAME << endl; | |
t << "\t$(SBS) reallyclean --toolcheck=off"; | |
foreach(QString clause, debugClauses) { | |
t << clause; | |
} | |
t << endl; | |
t << "freeze-debug: " << BLD_INF_FILENAME << endl; | |
t << "\t$(SBS) freeze"; | |
foreach(QString clause, debugClauses) { | |
t << clause; | |
} | |
t << endl; | |
t << "release: " << locFileDep << BLD_INF_FILENAME << endl; | |
t << "\t$(SBS)"; | |
foreach(QString clause, releaseClauses) { | |
t << clause; | |
} | |
t << endl; | |
t << "clean-release: " << BLD_INF_FILENAME << endl; | |
t << "\t$(SBS) reallyclean --toolcheck=off"; | |
foreach(QString clause, releaseClauses) { | |
t << clause; | |
} | |
t << endl; | |
t << "freeze-release: " << BLD_INF_FILENAME << endl; | |
t << "\t$(SBS) freeze"; | |
foreach(QString clause, releaseClauses) { | |
t << clause; | |
} | |
t << endl << endl; | |
QString defaultGcceArmVersion; | |
if (armPlatforms.size()) { | |
defaultGcceArmVersion = armPlatforms.first(); | |
} else { | |
defaultGcceArmVersion = QLatin1String("armv5"); | |
} | |
// For more specific builds, targets are in this form: | |
// release-armv5 - generic target, compiler version determined by toolchain or autodetection | |
// release-armv5-rvct4.0 - compiler version specific target | |
foreach(QString item, debugPlatforms) { | |
QString clause; | |
if (item.compare(winscwPlatform) == 0) | |
clause = configClause(item, debugBuild, QString(), winscwClause); | |
else if (item.compare(gccePlatform) == 0 ) | |
clause = configClause(defaultGcceArmVersion, debugBuild, defaultGcceCompilerVersion, armClause); | |
else // use generic arm clause | |
clause = configClause(item, debugBuild, defaultRvctCompilerVersion, genericArmClause); | |
t << "debug-" << item << ": " << locFileDep << BLD_INF_FILENAME << endl; | |
t << "\t$(SBS)" << clause << endl; | |
t << "clean-debug-" << item << ": " << BLD_INF_FILENAME << endl; | |
t << "\t$(SBS) reallyclean" << clause << endl; | |
t << "freeze-debug-" << item << ": " << BLD_INF_FILENAME << endl; | |
t << "\t$(SBS) freeze" << clause << endl; | |
} | |
foreach(QString item, releasePlatforms) { | |
QString clause; | |
if (item.compare(gccePlatform) == 0 ) | |
clause = configClause(defaultGcceArmVersion, releaseBuild, defaultGcceCompilerVersion, armClause); | |
else // use generic arm clause | |
clause = configClause(item, releaseBuild, defaultRvctCompilerVersion, genericArmClause); | |
t << "release-" << item << ": " << locFileDep << BLD_INF_FILENAME << endl; | |
t << "\t$(SBS)" << clause << endl; | |
t << "clean-release-" << item << ": " << BLD_INF_FILENAME << endl; | |
t << "\t$(SBS) reallyclean" << clause << endl; | |
t << "freeze-release-" << item << ": " << BLD_INF_FILENAME << endl; | |
t << "\t$(SBS) freeze" << clause << endl; | |
} | |
foreach(QString item, armPlatforms) { | |
foreach(QString compilerVersion, allArmCompilerVersions) { | |
QString debugClause = configClause(item, debugBuild, compilerVersion, armClause); | |
QString releaseClause = configClause(item, releaseBuild, compilerVersion, armClause); | |
t << "debug-" << item << "-" << compilerVersion << ": " << locFileDep << BLD_INF_FILENAME << endl; | |
t << "\t$(SBS)" << debugClause << endl; | |
t << "clean-debug-" << item << "-" << compilerVersion << ": " << BLD_INF_FILENAME << endl; | |
t << "\t$(SBS) reallyclean" << debugClause << endl; | |
t << "freeze-debug-" << item << "-" << compilerVersion << ": " << BLD_INF_FILENAME << endl; | |
t << "\t$(SBS) freeze" << debugClause << endl; | |
t << "release-" << item << "-" << compilerVersion << ": " << locFileDep << BLD_INF_FILENAME << endl; | |
t << "\t$(SBS)" << releaseClause << endl; | |
t << "clean-release-" << item << "-" << compilerVersion << ": " << BLD_INF_FILENAME << endl; | |
t << "\t$(SBS) reallyclean" << releaseClause << endl; | |
t << "freeze-release-" << item << "-" << compilerVersion << ": " << BLD_INF_FILENAME << endl; | |
t << "\t$(SBS) freeze" << releaseClause << endl; | |
} | |
} | |
t << endl; | |
t << "export: " << BLD_INF_FILENAME << endl; | |
t << "\t$(SBS) export"; | |
foreach(QString clause, allClauses) { | |
t << clause; | |
} | |
t << endl << endl; | |
t << "cleanexport: " << BLD_INF_FILENAME << endl; | |
t << "\t$(SBS) cleanexport"; | |
foreach(QString clause, allClauses) { | |
t << clause; | |
} | |
t << endl << endl; | |
// Typically one wants to freeze release binaries, so make plain freeze target equal to | |
// freeze-release. If freezing of debug binaries is needed for some reason, then | |
// freeze-debug target should be used. There is no point to try freezing both with one | |
// target as both produce the same def file. | |
t << "freeze: freeze-release" << endl << endl; | |
} | |
// Add all extra targets including extra compiler targets also to wrapper makefile, | |
// even though many of them may have already been added to bld.inf as FLMs. | |
// This is to enable use of targets like 'mocables', which call targets generated by extra compilers. | |
if (targetType != TypeSubdirs) { | |
t << extraTargetsCache; | |
t << extraCompilersCache; | |
} else { | |
QList<MakefileGenerator::SubTarget*> subtargets = findSubDirsSubTargets(); | |
writeSubTargets(t, subtargets, SubTargetSkipDefaultVariables|SubTargetSkipDefaultTargets); | |
qDeleteAll(subtargets); | |
} | |
generateDistcleanTargets(t); | |
// Do not check for tools when doing generic clean, as most tools are not actually needed for | |
// cleaning. Mainly this is relevant for environments that do not have winscw compiler. | |
t << "clean: " << BLD_INF_FILENAME << endl; | |
t << "\t-$(SBS) reallyclean --toolcheck=off"; | |
foreach(QString clause, allClauses) { | |
t << clause; | |
} | |
t << endl << endl; | |
t << endl; | |
} | |
void SymbianSbsv2MakefileGenerator::writeBldInfExtensionRulesPart(QTextStream& t, const QString &iconTargetFile) | |
{ | |
// Makes sure we have needed FLMs in place. | |
exportFlm(); | |
// Parse extra compilers data | |
QStringList defines; | |
QStringList incPath; | |
defines << varGlue("PRL_EXPORT_DEFINES","-D"," -D"," ") | |
<< varGlue("QMAKE_COMPILER_DEFINES", "-D", "-D", " ") | |
<< varGlue("DEFINES","-D"," -D",""); | |
for (QMap<QString, QStringList>::iterator it = systeminclude.begin(); it != systeminclude.end(); ++it) { | |
QStringList values = it.value(); | |
for (int i = 0; i < values.size(); ++i) { | |
incPath << QLatin1String(" -I\"") + values.at(i) + "\""; | |
} | |
} | |
QMap<QString, QString> commandsToReplace; | |
commandsToReplace.insert(project->values("QMAKE_COPY").join(" "), | |
project->values("QMAKE_SBSV2_COPY").join(" ")); | |
commandsToReplace.insert(project->values("QMAKE_COPY_DIR").join(" "), | |
project->values("QMAKE_SBSV2_COPY_DIR").join(" ")); | |
commandsToReplace.insert(project->values("QMAKE_MOVE").join(" "), | |
project->values("QMAKE_SBSV2_MOVE").join(" ")); | |
commandsToReplace.insert(project->values("QMAKE_DEL_FILE").join(" "), | |
project->values("QMAKE_SBSV2_DEL_FILE").join(" ")); | |
commandsToReplace.insert(project->values("QMAKE_MKDIR").join(" "), | |
project->values("QMAKE_SBSV2_MKDIR").join(" ")); | |
commandsToReplace.insert(project->values("QMAKE_DEL_DIR").join(" "), | |
project->values("QMAKE_SBSV2_DEL_DIR").join(" ")); | |
commandsToReplace.insert(project->values("QMAKE_DEL_TREE").join(" "), | |
project->values("QMAKE_SBSV2_DEL_TREE").join(" ")); | |
// Write extra compilers and targets to initialize QMAKE_ET_* variables | |
// Cache results to avoid duplicate calls when creating wrapper makefile | |
QTextStream extraCompilerStream(&extraCompilersCache); | |
QTextStream extraTargetStream(&extraTargetsCache); | |
writeExtraCompilerTargets(extraCompilerStream); | |
writeExtraTargets(extraTargetStream); | |
// Figure out everything the target depends on as we don't want to run extra targets that | |
// are not necessary. | |
QStringList allPreDeps; | |
foreach(QString item, project->values("PRE_TARGETDEPS")) { | |
allPreDeps.append(fileInfo(item).absoluteFilePath()); | |
} | |
foreach (QString item, project->values("GENERATED_SOURCES")) { | |
allPreDeps.append(fileInfo(item).absoluteFilePath()); | |
} | |
for (QMap<QString, QStringList>::iterator it = sources.begin(); it != sources.end(); ++it) { | |
QString currentSourcePath = it.key(); | |
QStringList values = it.value(); | |
for (int i = 0; i < values.size(); ++i) { | |
QString sourceFile = currentSourcePath + "/" + values.at(i); | |
QStringList deps = findDependencies(QDir::toNativeSeparators(sourceFile)); | |
foreach(QString depItem, deps) { | |
appendIfnotExist(allPreDeps, fileInfo(depItem).absoluteFilePath()); | |
} | |
} | |
} | |
// Write FLM rules for all extra targets and compilers that we depend on to build the target. | |
QStringList extraTargets; | |
extraTargets << project->values("QMAKE_EXTRA_TARGETS") << project->values("QMAKE_EXTRA_COMPILERS"); | |
foreach(QString item, extraTargets) { | |
foreach(QString targetItem, project->values(QLatin1String("QMAKE_INTERNAL_ET_PARSED_TARGETS.") + item)) { | |
// Make sure targetpath is absolute | |
QString absoluteTarget = fileInfo(targetItem).absoluteFilePath(); | |
if (allPreDeps.contains(absoluteTarget)) { | |
QStringList deps = project->values(QLatin1String("QMAKE_INTERNAL_ET_PARSED_DEPS.") + item + targetItem); | |
QString commandItem = project->values(QLatin1String("QMAKE_INTERNAL_ET_PARSED_CMD.") + item + targetItem).join(" "); | |
// Make sure all deps paths are absolute | |
QString absoluteDeps; | |
foreach (QString depItem, deps) { | |
if (!depItem.isEmpty()) { | |
absoluteDeps.append(fileInfo(depItem).absoluteFilePath()); | |
absoluteDeps.append(" "); | |
} | |
} | |
t << "START EXTENSION qt/qmake_extra_pre_targetdep.export" << endl; | |
t << "OPTION PREDEP_TARGET " << absoluteTarget << endl; | |
t << "OPTION DEPS " << absoluteDeps << endl; | |
if (commandItem.indexOf("$(INCPATH)") != -1) | |
commandItem.replace("$(INCPATH)", incPath.join(" ")); | |
if (commandItem.indexOf("$(DEFINES)") != -1) | |
commandItem.replace("$(DEFINES)", defines.join(" ")); | |
fixFlmCmd(&commandItem, commandsToReplace); | |
t << "OPTION COMMAND " << commandItem << endl; | |
t << "END" << endl; | |
} | |
} | |
} | |
t << endl; | |
// Write deployment rules | |
QString remoteTestPath = qt_epocRoot() + QLatin1String("epoc32/winscw/c/private/") + privateDirUid; | |
DeploymentList depList; | |
//write emulator deployment | |
t << "#if defined(WINSCW)" << endl; | |
initProjectDeploySymbian(project, depList, remoteTestPath, false, true, | |
QLatin1String(EMULATOR_DEPLOYMENT_PLATFORM), QString(), generatedDirs, generatedFiles); | |
writeSbsDeploymentList(depList, t); | |
t << "#endif" << endl; | |
//write ROM deployment | |
remoteTestPath = qt_epocRoot() + QLatin1String("epoc32/data/z/private/") + privateDirUid; | |
depList.clear(); | |
initProjectDeploySymbian(project, depList, remoteTestPath, false, true, | |
QLatin1String(ROM_DEPLOYMENT_PLATFORM), QString(), generatedDirs, generatedFiles); | |
writeSbsDeploymentList(depList, t); | |
t << endl; | |
// Write post link rules | |
if (!project->isEmpty("QMAKE_POST_LINK")) { | |
QString postLinkCmd = var("QMAKE_POST_LINK"); | |
fixFlmCmd(&postLinkCmd, commandsToReplace); | |
t << "START EXTENSION qt/qmake_post_link" << endl; | |
t << "OPTION POST_LINK_CMD " << postLinkCmd << endl; | |
t << "OPTION LINK_TARGET " << fixedTarget << QLatin1String(".") << getTargetExtension() << endl; | |
t << "END" << endl; | |
t << endl; | |
} | |
// Application icon generation | |
QStringList icons = project->values("ICON"); | |
if (icons.size()) { | |
QString icon = icons.first(); | |
if (icons.size() > 1) | |
fprintf(stderr, "Warning: Only first icon specified in ICON variable is used: '%s'.", qPrintable(icon)); | |
t << "START EXTENSION s60/mifconv" << endl; | |
QFileInfo iconInfo = fileInfo(icon); | |
QFileInfo bldinf(project->values("MAKEFILE").first()); | |
QString iconPath = bldinf.dir().relativeFilePath(iconInfo.path()); | |
QString iconFile = iconInfo.baseName(); | |
QFileInfo iconTargetInfo = fileInfo(iconTargetFile); | |
QString iconTarget = iconTargetInfo.fileName(); | |
t << "OPTION SOURCES -c32 " << iconFile << endl; | |
t << "OPTION SOURCEDIR " << iconPath << endl; | |
t << "OPTION TARGETFILE " << iconTarget << endl; | |
t << "OPTION SVGENCODINGVERSION 3" << endl; // Compatibility with S60 3.1 devices and up | |
t << "END" << endl; | |
} | |
t << "START EXTENSION qt/qmake_store_build" << endl; | |
t << "END" << endl; | |
t << endl; | |
// Handle QMAKE_CLEAN | |
QStringList cleanFiles = project->values("QMAKE_CLEAN"); | |
if (!cleanFiles.isEmpty()) { | |
QStringList absoluteCleanFiles; | |
foreach (QString cleanFile, cleanFiles) { | |
QFileInfo fi(cleanFile); | |
QString fileName = QLatin1String("\""); | |
fileName.append(fi.absoluteFilePath()); | |
fileName.append(QLatin1String("\"")); | |
absoluteCleanFiles << fileName; | |
} | |
t << "START EXTENSION qt/qmake_clean" << endl; | |
t << "OPTION CLEAN_FILES " << absoluteCleanFiles.join(" ") << endl; | |
t << "END" << endl; | |
} | |
t << endl; | |
} | |
void SymbianSbsv2MakefileGenerator::writeBldInfMkFilePart(QTextStream& t, bool addDeploymentExtension) | |
{ | |
// We don't generate extension makefile in sbsb2 | |
Q_UNUSED(t); | |
Q_UNUSED(addDeploymentExtension); | |
} | |
void SymbianSbsv2MakefileGenerator::appendAbldTempDirs(QStringList& sysincspaths, QString includepath) | |
{ | |
//Do nothing | |
Q_UNUSED(sysincspaths); | |
Q_UNUSED(includepath); | |
} |