diff -r 41300fa6a67c -r f7bc934e204c qmake/generators/symbian/symmake.cpp --- a/qmake/generators/symbian/symmake.cpp Tue Feb 02 00:43:10 2010 +0200 +++ b/qmake/generators/symbian/symmake.cpp Wed Mar 31 11:06:36 2010 +0300 @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** @@ -40,7 +40,6 @@ ****************************************************************************/ #include "symmake.h" -#include "initprojectdeploy_symbian.h" #include #include @@ -50,25 +49,34 @@ #include #include #include -#include +#include + +// Included from tools/shared +#include #define RESOURCE_DIRECTORY_MMP "/resource/apps" #define RESOURCE_DIRECTORY_RESOURCE "\\\\resource\\\\apps\\\\" #define REGISTRATION_RESOURCE_DIRECTORY_HW "/private/10003a3f/import/apps" #define PLUGIN_COMMON_DEF_FILE_FOR_MMP "./plugin_common.def" #define PLUGIN_COMMON_DEF_FILE_ACTUAL "plugin_commonU.def" -#define BLD_INF_FILENAME_LEN (sizeof(BLD_INF_FILENAME) - 1) #define BLD_INF_RULES_BASE "BLD_INF_RULES." #define BLD_INF_TAG_PLATFORMS "prj_platforms" #define BLD_INF_TAG_MMPFILES "prj_mmpfiles" #define BLD_INF_TAG_TESTMMPFILES "prj_testmmpfiles" #define BLD_INF_TAG_EXTENSIONS "prj_extensions" +#define BLD_INF_TAG_TESTEXTENSIONS "prj_testextensions" #define RSS_RULES "RSS_RULES" #define RSS_RULES_BASE "RSS_RULES." #define RSS_TAG_NBROFICONS "number_of_icons" #define RSS_TAG_ICONFILE "icon_file" +#define RSS_TAG_HEADER "header" +#define RSS_TAG_SERVICE_LIST "service_list" +#define RSS_TAG_FILE_OWNERSHIP_LIST "file_ownership_list" +#define RSS_TAG_DATATYPE_LIST "datatype_list" +#define RSS_TAG_FOOTER "footer" +#define RSS_TAG_DEFAULT "default_rules" // Same as just giving rules without tag #define MMP_TARGET "TARGET" #define MMP_TARGETTYPE "TARGETTYPE" @@ -90,22 +98,32 @@ #define MMP_END_RESOURCE "END" #define SIS_TARGET "sis" +#define INSTALLER_SIS_TARGET "installer_sis" +#define ROM_STUB_SIS_TARGET "stub_sis" #define OK_SIS_TARGET "ok_sis" +#define OK_INSTALLER_SIS_TARGET "ok_installer_sis" +#define OK_ROM_STUB_SIS_TARGET "ok_stub_sis" #define FAIL_SIS_NOPKG_TARGET "fail_sis_nopkg" #define FAIL_SIS_NOCACHE_TARGET "fail_sis_nocache" -#define RESTORE_BUILD_TARGET "restore_build" #define PRINT_FILE_CREATE_ERROR(filename) fprintf(stderr, "Error: Could not create '%s'\n", qPrintable(filename)); +#define MANUFACTURER_NOTE_FILE "manufacturer_note.txt" +#define DEFAULT_MANUFACTURER_NOTE \ + "The package is not supported for devices from this manufacturer. Please try the selfsigned " \ + "version of the package instead." + QString SymbianMakefileGenerator::fixPathForMmp(const QString& origPath, const QDir& parentDir) { static QString epocRootStr; if (epocRootStr.isEmpty()) { - QFileInfo efi(epocRoot()); - epocRootStr = efi.canonicalFilePath(); - if (epocRootStr.isEmpty()) { + epocRootStr = epocRoot(); + QFileInfo efi(epocRootStr); + if (!efi.exists() || epocRootStr.isEmpty()) { fprintf(stderr, "Unable to resolve epocRoot '%s' to real dir on current drive, defaulting to '/' for mmp paths\n", qPrintable(epocRoot())); epocRootStr = "/"; + } else { + epocRootStr = efi.absoluteFilePath(); } if (!epocRootStr.endsWith("/")) epocRootStr += "/"; @@ -129,53 +147,26 @@ return resultPath; } -QString SymbianMakefileGenerator::canonizePath(const QString& origPath) +QString SymbianMakefileGenerator::absolutizePath(const QString& origPath) { - // Since current path gets appended almost always anyway, use it as default - // for nonexisting paths. - static QString defaultPath; - if (defaultPath.isEmpty()) { - QFileInfo fi("."); - defaultPath = fi.canonicalFilePath(); - } - // Prepend epocroot to any paths beginning with "/epoc32/" QString resultPath = QDir::fromNativeSeparators(origPath); - QString tempPath(resultPath); - bool isEpoc = false; - if (resultPath.startsWith("/epoc32/", Qt::CaseInsensitive)) { - isEpoc = true; + if (resultPath.startsWith("/epoc32/", Qt::CaseInsensitive)) resultPath = QDir::fromNativeSeparators(epocRoot()) + resultPath.mid(1); - } QFileInfo fi(fileInfo(resultPath)); - if(fi.isDir()) { - if (isEpoc) - resultPath = fi.absoluteFilePath();//canonicalFilePath(); - else - resultPath = fi.canonicalFilePath(); + + // Since origPath can be something given in HEADERS, we need to check if we are dealing + // with a file or a directory. In case the origPath doesn't yet exist, isFile() returns + // false and we default to assuming it is a dir. + if (fi.isFile()) { + resultPath = fi.absolutePath(); } else { - if (isEpoc) - resultPath = fi.absolutePath();//canonicalPath(); - else - resultPath = fi.canonicalPath(); - } - //some fix for the not existed EPOC32\include folder - if (isEpoc) { - int index = resultPath.lastIndexOf("/epoc32/"); - QString tmpRes = resultPath.mid(index); - if (tmpRes != tempPath) { - //we have the problems for not existed include directory - //change the path - resultPath.replace(tmpRes, tempPath); - } + resultPath = fi.absoluteFilePath(); } resultPath = QDir::cleanPath(resultPath); - if (resultPath.isEmpty()) - resultPath = defaultPath; - return resultPath; } @@ -217,7 +208,7 @@ QString numberOfIcons; QString iconFile; - QStringList userRssRules; + QMap userRssRules; readRssRules(numberOfIcons, iconFile, userRssRules); // Get the application translations and convert to symbian OS lang code, i.e. decical number @@ -225,6 +216,8 @@ // Generate pkg files if there are any actual files to deploy bool generatePkg = false; + DeploymentList depList; + if (targetType == TypeExe) { generatePkg = true; } else { @@ -237,10 +230,10 @@ } if (generatePkg) { - generatePkgFile(iconFile); + generatePkgFile(iconFile, depList); } - writeBldInfContent(t, generatePkg, iconFile); + writeBldInfContent(t, generatePkg, iconFile, depList); // Generate empty wrapper makefile here, because wrapper makefile must exist before writeMkFile, // but all required data is not yet available. @@ -248,7 +241,9 @@ QString wrapperFileName("Makefile"); QString outputFileName = fileInfo(Option::output.fileName()).fileName(); if (outputFileName != BLD_INF_FILENAME) { - wrapperFileName.append(".").append((outputFileName.size() > BLD_INF_FILENAME_LEN && outputFileName.left(BLD_INF_FILENAME_LEN) == BLD_INF_FILENAME) ? outputFileName.mid(8) : outputFileName); + wrapperFileName.append(".").append(outputFileName.startsWith(BLD_INF_FILENAME) + ? outputFileName.mid(sizeof(BLD_INF_FILENAME)) + : outputFileName); isPrimaryMakefile = false; } @@ -286,7 +281,7 @@ writeMmpFile(mmpFilename, symbianLangCodes); if (targetType == TypeExe) { - if (!project->values("CONFIG").contains("no_icon", Qt::CaseInsensitive)) { + if (!project->isActiveConfig("no_icon")) { writeRegRssFile(userRssRules); writeRssFile(numberOfIcons, iconFile); writeLocFile(symbianLangCodes); @@ -301,7 +296,7 @@ return true; } -void SymbianMakefileGenerator::generatePkgFile(const QString &iconFile) +void SymbianMakefileGenerator::generatePkgFile(const QString &iconFile, DeploymentList &depList) { QString pkgFilename = QString("%1_template.%2") .arg(fixedTarget) @@ -315,25 +310,58 @@ generatePrint(fileInfo(pkgFile.fileName()).absoluteFilePath()); } generatedFiles << pkgFile.fileName(); + QTextStream t(&pkgFile); + + QString installerSisHeader = project->values("DEPLOYMENT.installer_header").join("\n"); + if (installerSisHeader.isEmpty()) + installerSisHeader = "0xA000D7CE"; // Use default self-signable UID if not defined + + QString wrapperStreamBuffer; + QTextStream tw(&wrapperStreamBuffer); + + QString dateStr = QDateTime::currentDateTime().toString(Qt::ISODate); // Header info - QTextStream t(&pkgFile); - t << QString("; %1 generated by qmake at %2").arg(pkgFilename).arg(QDateTime::currentDateTime().toString(Qt::ISODate)) << endl; - t << "; This file is generated by qmake and should not be modified by the user" << endl; - t << ";" << endl << endl; + QString wrapperPkgFilename = QString("%1_installer.%2") + .arg(fixedTarget) + .arg("pkg"); + QString headerComment = "; %1 generated by qmake at %2\n" + "; This file is generated by qmake and should not be modified by the user\n" + ";\n\n"; + t << headerComment.arg(pkgFilename).arg(dateStr); + tw << headerComment.arg(wrapperPkgFilename).arg(dateStr); // Construct QStringList from pkg_prerules since we need search it before printed to file + // Note: Though there can't be more than one language or header line, use stringlists + // in case user wants comments to go with the rules. QStringList rawPkgPreRules; + QStringList languageRules; + QStringList headerRules; foreach(QString deploymentItem, project->values("DEPLOYMENT")) { foreach(QString pkgrulesItem, project->values(deploymentItem + ".pkg_prerules")) { QStringList pkgrulesValue = project->values(pkgrulesItem); // If there is no stringlist defined for a rule, use rule name directly // This is convenience for defining single line mmp statements if (pkgrulesValue.isEmpty()) { - rawPkgPreRules << pkgrulesItem; + if (pkgrulesItem.startsWith("&")) + languageRules << pkgrulesItem; + else if (pkgrulesItem.startsWith("#")) + headerRules << pkgrulesItem; + else + rawPkgPreRules << pkgrulesItem; } else { - foreach(QString pkgrule, pkgrulesValue) { - rawPkgPreRules << pkgrule; + if (containsStartWithItem('&', pkgrulesValue)) { + foreach(QString pkgrule, pkgrulesValue) { + languageRules << pkgrule; + } + } else if (containsStartWithItem('#', pkgrulesValue)) { + foreach(QString pkgrule, pkgrulesValue) { + headerRules << pkgrule; + } + } else { + foreach(QString pkgrule, pkgrulesValue) { + rawPkgPreRules << pkgrule; + } } } } @@ -341,46 +369,76 @@ // Apply some defaults if specific data does not exist in PKG pre-rules - if (!containsStartWithItem('&', rawPkgPreRules)) { + if (languageRules.isEmpty()) { // language, (*** hardcoded to english atm, should be parsed from TRANSLATIONS) - t << "; Language" << endl; - t << "&EN" << endl << endl; - } else { + languageRules << "; Language\n&EN\n\n"; + } else if (headerRules.isEmpty()) { // In case user defines langs, he must take care also about SIS header - if (!containsStartWithItem('#', rawPkgPreRules)) - fprintf(stderr, "Warning: If language is defined with DEPLOYMENT pkg_prerules, also the SIS header must be defined\n"); + fprintf(stderr, "Warning: If language is defined with DEPLOYMENT pkg_prerules, also the SIS header must be defined\n"); } + t << languageRules.join("\n") << endl; + tw << languageRules.join("\n") << endl; + // name of application, UID and version QString applicationVersion = project->first("VERSION").isEmpty() ? "1,0,0" : project->first("VERSION").replace('.', ','); + QString sisHeader = "; SIS header: name, uid, version\n#{\"%1\"},(%2),%3\n\n"; + QString visualTarget = escapeFilePath(fileFixify(project->first("TARGET"))); + visualTarget = removePathSeparators(visualTarget); + QString wrapperTarget = visualTarget + " installer"; - if (!containsStartWithItem('#', rawPkgPreRules)) { - QString visualTarget = escapeFilePath(fileFixify(project->first("TARGET"))); - visualTarget = removePathSeparators(visualTarget); - - t << "; SIS header: name, uid, version" << endl; - t << QString("#{\"%1\"},(%2),%3").arg(visualTarget).arg(uid3).arg(applicationVersion) << endl << endl; + if (installerSisHeader.startsWith("0x", Qt::CaseInsensitive)) { + tw << sisHeader.arg(wrapperTarget).arg(installerSisHeader).arg(applicationVersion); + } else { + tw << installerSisHeader << endl; } + if (headerRules.isEmpty()) + t << sisHeader.arg(visualTarget).arg(uid3).arg(applicationVersion); + else + t << headerRules.join("\n") << endl; + // Localized vendor name + QString vendorName; if (!containsStartWithItem('%', rawPkgPreRules)) { - t << "; Localised Vendor name" << endl; - t << "%{\"Vendor\"}" << endl << endl; + vendorName += "; Localised Vendor name\n%{\"Vendor\"}\n\n"; } // Unique vendor name if (!containsStartWithItem(':', rawPkgPreRules)) { - t << "; Unique Vendor name" << endl; - t << ":\"Vendor\"" << endl << endl; + vendorName += "; Unique Vendor name\n:\"Vendor\"\n\n"; } + t << vendorName; + tw << vendorName; + // PKG pre-rules - these are added before actual file installations i.e. SIS package body if (rawPkgPreRules.size()) { - t << "; Manual PKG pre-rules from PRO files" << endl; + QString comment = "\n; Manual PKG pre-rules from PRO files\n"; + t << comment; + tw << comment; + foreach(QString item, rawPkgPreRules) { + // Only regular pkg file should have package dependencies or pkg header if that is + // defined using prerules. + if (!item.startsWith("(") && !item.startsWith("#")) { + tw << item << endl; + } t << item << endl; } t << endl; + tw << endl; + } + + // Begin Manufacturer block + if (!project->values("DEPLOYMENT.manufacturers").isEmpty()) { + QString manufacturerStr("IF "); + foreach(QString manufacturer, project->values("DEPLOYMENT.manufacturers")) { + manufacturerStr.append(QString("(MANUFACTURER)=(%1) OR \n ").arg(manufacturer)); + } + // Remove the final OR + manufacturerStr.chop(8); + t << manufacturerStr << endl; } // Install paths on the phone *** should be dynamic at some point @@ -392,7 +450,6 @@ QString epocReleasePath = QString("%1epoc32/release/$(PLATFORM)/$(TARGET)") .arg(epocRoot()); - if (targetType == TypeExe) { // deploy .exe file t << "; Executable and default resource files" << endl; @@ -404,7 +461,7 @@ .arg(exeFile) << endl; // deploy rsc & reg_rsc file - if (!project->values("CONFIG").contains("no_icon", Qt::CaseInsensitive)) { + if (!project->isActiveConfig("no_icon")) { t << QString("\"%1epoc32/data/z/resource/apps/%2\" - \"%3\\%4\"") .arg(epocRoot()) .arg(fixedTarget + ".rsc") @@ -427,17 +484,31 @@ } // deploy any additional DEPLOYMENT files - DeploymentList depList; QString remoteTestPath; remoteTestPath = QString("!:\\private\\%1").arg(privateDirUid); + QString zDir = epocRoot() + QLatin1String("epoc32/data/z"); initProjectDeploySymbian(project, depList, remoteTestPath, true, "$(PLATFORM)", "$(TARGET)", generatedDirs, generatedFiles); if (depList.size()) t << "; DEPLOYMENT" << endl; for (int i = 0; i < depList.size(); ++i) { - t << QString("\"%1\" - \"%2\"") - .arg(QString(depList.at(i).from).replace('\\','/')) - .arg(depList.at(i).to) << endl; + QString from = depList.at(i).from; + QString to = depList.at(i).to; + + // Deploy anything not already deployed from under epoc32 instead from under + // \epoc32\data\z\ to enable using pkg file without rebuilding + // the project, which can be useful for some binary only distributions. + if (!from.contains(QLatin1String("epoc32"), Qt::CaseInsensitive)) { + from = to; + if (from.size() > 1 && from.at(1) == QLatin1Char(':')) + from = from.mid(2); + from.prepend(zDir); + } else { + if (from.size() > 1 && from.at(1) == QLatin1Char(':')) + from = from.mid(2); + } + + t << QString("\"%1\" - \"%2\"").arg(from.replace('\\','/')).arg(to) << endl; } t << endl; @@ -458,6 +529,54 @@ t << endl; } } + + // Close Manufacturer block + if (!project->values("DEPLOYMENT.manufacturers").isEmpty()) { + QString manufacturerFailNoteFile; + if (project->values("DEPLOYMENT.manufacturers.fail_note").isEmpty()) { + manufacturerFailNoteFile = QString("%1_" MANUFACTURER_NOTE_FILE).arg(uid3); + QFile ft(manufacturerFailNoteFile); + if (ft.open(QIODevice::WriteOnly)) { + generatedFiles << ft.fileName(); + QTextStream t2(&ft); + + t2 << QString(DEFAULT_MANUFACTURER_NOTE) << endl; + } else { + PRINT_FILE_CREATE_ERROR(manufacturerFailNoteFile) + } + } else { + manufacturerFailNoteFile = project->values("DEPLOYMENT.manufacturers.fail_note").join(""); + } + + t << "ELSEIF NOT(0) ; MANUFACTURER" << endl + << "\"" << fileInfo(manufacturerFailNoteFile).absoluteFilePath() << "\"" + << " - \"\", FILETEXT, TEXTEXIT" << endl + << "ENDIF ; MANUFACTURER" << endl; + } + + // Write wrapper pkg + if (!installerSisHeader.isEmpty()) { + QFile wrapperPkgFile(wrapperPkgFilename); + if (!wrapperPkgFile.open(QIODevice::WriteOnly | QIODevice::Text)) { + PRINT_FILE_CREATE_ERROR(wrapperPkgFilename); + return; + } + + generatedFiles << wrapperPkgFile.fileName(); + QTextStream twf(&wrapperPkgFile); + + twf << wrapperStreamBuffer << endl; + + // Wrapped files deployment + QString currentPath = qmake_getpwd(); + QString sisName = QString("%1.sis").arg(fixedTarget); + twf << "\"" << currentPath << "/" << sisName << "\" - \"c:\\adm\\" << sisName << "\"" << endl; + + QString bootStrapPath = QLibraryInfo::location(QLibraryInfo::PrefixPath); + bootStrapPath.append("/smartinstaller.sis"); + QFileInfo fi(fileInfo(bootStrapPath)); + twf << "@\"" << fi.absoluteFilePath() << "\",(0x2002CCCD)" << endl; + } } bool SymbianMakefileGenerator::containsStartWithItem(const QChar &c, const QStringList& src) @@ -474,7 +593,7 @@ void SymbianMakefileGenerator::writeCustomDefFile() { - if (targetType == TypePlugin && !project->values("CONFIG").contains("stdbinary", Qt::CaseInsensitive)) { + if (targetType == TypePlugin && !project->isActiveConfig("stdbinary")) { // Create custom def file for plugin QFile ft(QLatin1String(PLUGIN_COMMON_DEF_FILE_ACTUAL)); @@ -515,6 +634,15 @@ fixedTarget = escapeFilePath(fileFixify(project->first("TARGET"))); fixedTarget = removePathSeparators(fixedTarget); removeSpecialCharacters(fixedTarget); + + translationFileName = escapeFilePath(fileFixify(project->first("TRANSLATIONS"))); + if (!translationFileName.isEmpty()){ + translationFileName.chop(3); + translationFileName = removePathSeparators(translationFileName); + removeSpecialCharacters(translationFileName); + } + else + translationFileName = fixedTarget; if (0 != project->values("QMAKE_PLATFORM").size()) platform = varGlue("QMAKE_PLATFORM", "", " ", ""); @@ -542,9 +670,9 @@ targetType = TypeExe; else if ((project->values("TEMPLATE")).contains("lib")) { // Check CONFIG to see if we are to build staticlib or dll - if (project->values("CONFIG").contains("staticlib") || project->values("CONFIG").contains("static")) + if (project->isActiveConfig("staticlib") || project->isActiveConfig("static")) targetType = TypeLib; - else if (project->values("CONFIG").contains("plugin")) + else if (project->isActiveConfig("plugin")) targetType = TypePlugin; else targetType = TypeDll; @@ -554,7 +682,7 @@ if (0 != project->values("TARGET.UID2").size()) { uid2 = project->first("TARGET.UID2"); - } else if (project->values("CONFIG").contains("stdbinary", Qt::CaseInsensitive)) { + } else if (project->isActiveConfig("stdbinary")) { uid2 = "0x20004C45"; } else { if (targetType == TypeExe) { @@ -625,7 +753,7 @@ srcpaths << project->values("UI_DIR"); QDir current = QDir::current(); - QString canonizedCurrent = canonizePath("."); + QString absolutizedCurrent = absolutizePath("."); for (int j = 0; j < srcpaths.size(); ++j) { QFileInfo fi(fileInfo(srcpaths.at(j))); @@ -633,10 +761,10 @@ if (fi.suffix().startsWith("c")) { if (fi.filePath().length() > fi.fileName().length()) { appendIfnotExist(srcincpaths, fi.path()); - sources[canonizePath(fi.path())] += fi.fileName(); + sources[absolutizePath(fi.path())] += fi.fileName(); } else { - sources[canonizedCurrent] += fi.fileName(); - appendIfnotExist(srcincpaths, canonizedCurrent); + sources[absolutizedCurrent] += fi.fileName(); + appendIfnotExist(srcincpaths, absolutizedCurrent); } } } @@ -650,7 +778,7 @@ incpaths << project->values("UI_DIR"); for (int j = 0; j < incpaths.size(); ++j) { - QString includepath = canonizePath(incpaths.at(j)); + QString includepath = absolutizePath(incpaths.at(j)); appendIfnotExist(sysincspaths, includepath); appendAbldTempDirs(sysincspaths, includepath); } @@ -692,15 +820,13 @@ QStringList restrictedMmpKeywords; bool inResourceBlock = false; - overridableMmpKeywords << QLatin1String(MMP_TARGETTYPE); + overridableMmpKeywords << QLatin1String(MMP_TARGETTYPE) << QLatin1String(MMP_EPOCHEAPSIZE); restrictableMmpKeywords << QLatin1String(MMP_TARGET) << QLatin1String(MMP_SECUREID) - << QLatin1String(MMP_OPTION_CW) << QLatin1String(MMP_OPTION_ARMCC) - << QLatin1String(MMP_OPTION_GCCE) << QLatin1String(MMP_LINKEROPTION_CW) - << QLatin1String(MMP_LINKEROPTION_ARMCC) << QLatin1String(MMP_LINKEROPTION_GCCE) + << QLatin1String(MMP_LINKEROPTION_CW) << QLatin1String(MMP_LINKEROPTION_ARMCC) + << QLatin1String(MMP_LINKEROPTION_GCCE) << QLatin1String(MMP_CAPABILITY) << QLatin1String(MMP_EPOCALLOWDLLDATA) - << QLatin1String(MMP_EPOCHEAPSIZE) << QLatin1String(MMP_EPOCSTACKSIZE) - << QLatin1String(MMP_UID) << QLatin1String(MMP_VENDORID) - << QLatin1String(MMP_VERSION); + << QLatin1String(MMP_EPOCSTACKSIZE) << QLatin1String(MMP_UID) + << QLatin1String(MMP_VENDORID) << QLatin1String(MMP_VERSION); foreach (QString item, project->values("MMP_RULES")) { if (project->values(item).isEmpty()) { @@ -825,7 +951,7 @@ } t << endl; - if (!project->values("CONFIG").contains("static") && !project->values("CONFIG").contains("staticlib")) { + if (!project->isActiveConfig("static") && !project->isActiveConfig("staticlib")) { writeMmpFileLibraryPart(t); } @@ -874,11 +1000,12 @@ void SymbianMakefileGenerator::writeMmpFileTargetPart(QTextStream& t) { bool skipTargetType = overriddenMmpKeywords.contains(MMP_TARGETTYPE); + bool skipEpocHeapSize = overriddenMmpKeywords.contains(MMP_EPOCHEAPSIZE); if (targetType == TypeExe) { t << MMP_TARGET "\t\t" << fixedTarget << ".exe" << endl; if (!skipTargetType) { - if (project->values("CONFIG").contains("stdbinary", Qt::CaseInsensitive)) + if (project->isActiveConfig("stdbinary")) t << MMP_TARGETTYPE "\t\tSTDEXE" << endl; else t << MMP_TARGETTYPE "\t\tEXE" << endl; @@ -886,7 +1013,7 @@ } else if (targetType == TypeDll || targetType == TypePlugin) { t << MMP_TARGET "\t\t" << fixedTarget << ".dll" << endl; if (!skipTargetType) { - if (project->values("CONFIG").contains("stdbinary", Qt::CaseInsensitive)) + if (project->isActiveConfig("stdbinary")) t << MMP_TARGETTYPE "\t\tSTDDLL" << endl; else t << MMP_TARGETTYPE "\t\tDLL" << endl; @@ -894,7 +1021,7 @@ } else if (targetType == TypeLib) { t << MMP_TARGET "\t\t" << fixedTarget << ".lib" << endl; if (!skipTargetType) { - if (project->values("CONFIG").contains("stdbinary", Qt::CaseInsensitive)) + if (project->isActiveConfig("stdbinary")) t << MMP_TARGETTYPE "\t\tSTDLIB" << endl; else t << MMP_TARGETTYPE "\t\tLIB" << endl; @@ -925,12 +1052,12 @@ if (0 != project->first("TARGET.EPOCSTACKSIZE").size()) t << MMP_EPOCSTACKSIZE "\t\t" << project->first("TARGET.EPOCSTACKSIZE") << endl; - if (0 != project->values("TARGET.EPOCHEAPSIZE").size()) + if (!skipEpocHeapSize && 0 != project->values("TARGET.EPOCHEAPSIZE").size()) t << MMP_EPOCHEAPSIZE "\t\t" << project->values("TARGET.EPOCHEAPSIZE").join(" ") << endl; if (0 != project->values("TARGET.EPOCALLOWDLLDATA").size()) t << MMP_EPOCALLOWDLLDATA << endl; - if (targetType == TypePlugin && !project->values("CONFIG").contains("stdbinary", Qt::CaseInsensitive)) { + if (targetType == TypePlugin && !project->isActiveConfig("stdbinary")) { // Use custom def file for Qt plugins t << "DEFFILE " PLUGIN_COMMON_DEF_FILE_FOR_MMP << endl; } @@ -946,7 +1073,7 @@ void SymbianMakefileGenerator::writeMmpFileResourcePart(QTextStream& t, QStringList &symbianLangCodes) { if ((targetType == TypeExe) && - !project->values("CONFIG").contains("no_icon", Qt::CaseInsensitive)) { + !project->isActiveConfig("no_icon")) { QString locTarget = fixedTarget; locTarget.append(".rss"); @@ -1153,6 +1280,16 @@ t << MMP_OPTION_CW " " << cw << endl; if (!armcc.isEmpty()) t << MMP_OPTION_ARMCC " " << armcc << endl; + + foreach(QString armccVersion, project->values("VERSION_FLAGS.ARMCC")) { + QStringList currentValues = project->values("QMAKE_CXXFLAGS." + armccVersion); + if (currentValues.size()) { + t << "#if defined(" << armccVersion << ")" << endl; + t << MMP_OPTION_ARMCC " " << currentValues.join(" ") << endl; + t << "#endif" << endl; + } + } + if (!gcce.isEmpty()) t << MMP_OPTION_GCCE " " << gcce << endl; @@ -1218,7 +1355,7 @@ } } -void SymbianMakefileGenerator::writeBldInfContent(QTextStream &t, bool addDeploymentExtension, const QString &iconFile) +void SymbianMakefileGenerator::writeBldInfContent(QTextStream &t, bool addDeploymentExtension, const QString &iconFile, DeploymentList &depList) { // Read user defined bld inf rules @@ -1265,6 +1402,10 @@ fixedItem = item; } + QString condition; + if (!project->isEmpty(item + ".condition")) + condition = project->first(item + ".condition"); + QFileInfo subdir(fileInfo(fixedItem)); QString relativePath = directory.relativeFilePath(fixedItem); QString subdirFileName = subdir.completeBaseName(); @@ -1293,9 +1434,16 @@ bldinfDefine = bldinfDefine.toUpper(); removeSpecialCharacters(bldinfDefine); + if (!condition.isEmpty()) + t << "#if defined(" << condition << ")" << endl; + t << "#ifndef " << bldinfDefine << endl; - t << "\t#include \"" << QDir::toNativeSeparators(bldinfFilename) << "\"" << endl; - t << "#endif // " << bldinfDefine << endl; + t << "\t#include \"" << bldinfFilename << "\"" << endl; + t << "#endif" << endl; + + if (!condition.isEmpty()) + t << "#endif" << endl; + } // Add supported project platforms @@ -1313,7 +1461,7 @@ // Add project mmps and old style extension makefiles QString mmpTag; - if (project->values("CONFIG").contains("symbian_test", Qt::CaseInsensitive)) + if (project->isActiveConfig(SYMBIAN_TEST_CONFIG)) mmpTag = QLatin1String(BLD_INF_TAG_TESTMMPFILES); else mmpTag = QLatin1String(BLD_INF_TAG_MMPFILES); @@ -1336,16 +1484,22 @@ t << item << endl; userBldInfRules.remove(mmpTag); - t << endl << BLD_INF_TAG_EXTENSIONS << endl << endl; + QString extensionTag; + if (project->isActiveConfig(SYMBIAN_TEST_CONFIG)) + extensionTag = QLatin1String(BLD_INF_TAG_TESTEXTENSIONS); + else + extensionTag = QLatin1String(BLD_INF_TAG_EXTENSIONS); + + t << endl << extensionTag << endl << endl; // Generate extension rules writeBldInfExtensionRulesPart(t, iconFile); - userItems = userBldInfRules.value(BLD_INF_TAG_EXTENSIONS); + userItems = userBldInfRules.value(extensionTag); foreach(QString item, userItems) t << item << endl; - userBldInfRules.remove(BLD_INF_TAG_EXTENSIONS); + userBldInfRules.remove(extensionTag); // Add rest of the user defined content @@ -1355,80 +1509,9 @@ foreach(QString item, userItems) t << item << endl; } - if (project->values("CONFIG").contains("headerexport", Qt::CaseInsensitive)) { - writeExportPart(t); - } } -void SymbianMakefileGenerator::writeExportPart(QTextStream &t) -{ - QDir currentDir = QDir::current(); - t << "prj_exports" << endl; - - foreach(QString install, project->values("INSTALLS")) { - QString installDir = project->first(install + ".path"); - - // Export macros are the recommended way, but might not be used - // in all cases (such as Qt headers). We handle it either way, - // macros or not. - bool useLayerMacro = false; - if (installDir.startsWith("MW_LAYER_") || - installDir.startsWith("APP_LAYER_") || - installDir.startsWith("APP_LAYER_")) { - useLayerMacro = true; - } else { -#ifdef Q_OS_WIN - // If we are running on Windows, and the export target starts - // with a drive letter, we need to remove it, the build tools - // cannot handle drives in export paths - - if (installDir.length() > 2 && installDir[1] == ':') { - installDir.remove(0, 2); - } -#endif - installDir.replace("\\", "/"); - if (!installDir.endsWith("/")) { - installDir.append("/"); - } - } - - foreach(QString target, project->values(install + ".files")) { - // Handle glob targets (only in the current directory) - if (target.contains("*") || target.contains("?")) { - QDir globber = QDir::current(); - globber.setNameFilters(QStringList(target)); - foreach(QString globbedTarget, globber.entryList()) { - if (useLayerMacro) { - QFileInfo globbedInfo(globbedTarget); - t << globbedTarget << " " << installDir << - "(" << globbedInfo.fileName() << ")" << endl; - } else { - t << globbedTarget << " " << installDir << - globbedTarget << endl; - } - } - } else { - target = currentDir.relativeFilePath(target); - QFileInfo targetInfo(target); - - // Not possible to export whole directories, extension makefile needed for this - // Note that this check requires the file to be exported to exist in the qmake phase! - if (targetInfo.isFile()) { - if (useLayerMacro) { - t << target << " " << installDir << - "(" << targetInfo.fileName() << ")" << endl; - } else { - t << target << " " << installDir << - targetInfo.fileName() << endl; - } - } - } - } - } - t << endl; -} - -void SymbianMakefileGenerator::writeRegRssFile(QStringList &userItems) +void SymbianMakefileGenerator::writeRegRssFile(QMap &userItems) { QString filename(fixedTarget); filename.append("_reg.rss"); @@ -1448,6 +1531,8 @@ t << endl; t << "#include <" << fixedTarget << ".rsg>" << endl; t << "#include " << endl; + foreach(QString item, userItems[RSS_TAG_HEADER]) + t << item << endl; t << endl; t << "UID2 KUidAppRegistrationResourceFile" << endl; t << "UID3 " << uid3 << endl << endl; @@ -1455,16 +1540,51 @@ t << "\t{" << endl; t << "\tapp_file=\"" << fixedTarget << "\";" << endl; t << "\tlocalisable_resource_file=\"" RESOURCE_DIRECTORY_RESOURCE << fixedTarget << "\";" << endl; + + writeRegRssList(t, userItems[RSS_TAG_SERVICE_LIST], + QLatin1String(RSS_TAG_SERVICE_LIST), + QLatin1String("SERVICE_INFO")); + writeRegRssList(t, userItems[RSS_TAG_FILE_OWNERSHIP_LIST], + QLatin1String(RSS_TAG_FILE_OWNERSHIP_LIST), + QLatin1String("FILE_OWNERSHIP_INFO")); + writeRegRssList(t, userItems[RSS_TAG_DATATYPE_LIST], + QLatin1String(RSS_TAG_DATATYPE_LIST), + QLatin1String("DATATYPE")); t << endl; - foreach(QString item, userItems) - t << "\t" << item << endl; + foreach(QString item, userItems[RSS_TAG_DEFAULT]) + t << "\t" << item.replace("\n","\n\t") << endl; t << "\t}" << endl; + + foreach(QString item, userItems[RSS_TAG_FOOTER]) + t << item << endl; } else { PRINT_FILE_CREATE_ERROR(filename) } } +void SymbianMakefileGenerator::writeRegRssList(QTextStream &t, + QStringList &userList, + const QString &listTag, + const QString &listItem) +{ + int itemCount = userList.count(); + if (itemCount) { + t << "\t" << listTag << " ="<< endl; + t << "\t\t{" << endl; + foreach(QString item, userList) { + t << "\t\t" << listItem << endl; + t << "\t\t\t{" << endl; + t << "\t\t\t" << item.replace("\n","\n\t\t\t") << endl; + t << "\t\t\t}"; + if (--itemCount) + t << ","; + t << endl; + } + t << "\t\t}; "<< endl; + } +} + void SymbianMakefileGenerator::writeRssFile(QString &numberOfIcons, QString &iconFile) { QString filename(fixedTarget); @@ -1484,10 +1604,7 @@ t << "// ============================================================================" << endl; t << endl; t << "#include " << endl; - if (!project->values("SYMBIANTRANSLATIONS").isEmpty()) - t << "#include <" << fixedTarget << ".loc>" << endl; - else - t << "#include \"" << fixedTarget << ".loc\"" << endl; + t << "#include <" << translationFileName << ".loc>" << endl; t << endl; t << "RESOURCE LOCALISABLE_APP_INFO r_localisable_app_info" << endl; t << "\t{" << endl; @@ -1519,14 +1636,14 @@ void SymbianMakefileGenerator::writeLocFile(QStringList &symbianLangCodes) { - QString filename(fixedTarget); + QString filename(translationFileName); if (project->values("SYMBIANTRANSLATIONS").isEmpty()) { filename.append(".loc"); } else { if (!project->first("SYMBIANLOCFILESDIR").isEmpty()) { filename.insert(0,project->first("SYMBIANLOCFILESDIR")); } else { - filename.insert(0,"/epoc32/include/platform/app/loc/"); + filename.insert(0,"/epoc32/include/platform/mw/loc/"); } filename.append(".loc"); } @@ -1560,11 +1677,11 @@ t << "#endif" << endl; } else { t << "#if LANGUAGE_01" << endl; - t << "#include <" << "01/" << fixedTarget << "_01.loc>" << endl; + t << "#include <" << "01/" << translationFileName << "_01.loc>" << endl; foreach(QString lang, symbianLangCodes) { if (lang.localeAwareCompare("01") != 0) { t << "#elif LANGUAGE_" << lang << endl; - t << "#include <" << lang << "/" << fixedTarget << "_" << lang << ".loc>" << ">" << endl; + t << "#include <" << lang << "/" << translationFileName << "_" << lang << ".loc" << ">" << endl; } } t << "#endif" << endl; @@ -1576,13 +1693,14 @@ void SymbianMakefileGenerator::writeSymbianLocFile(QStringList &symbianLangCodes) { - QString filename(fixedTarget); + QString filename(translationFileName); foreach(QString lang, symbianLangCodes) { QString tsFilename(filename); QString language = qt2S60LangMapTable.key(lang, QString("en")); tsFilename.append("_"+language+".ts"); - tsFilename.insert(0,project->first("SYMBIANTRANSLATIONDIR")); + + tsFilename.insert(0,project->first("SYMBIANTRANSLATIONSRCDIR")); QString locFilename(filename); locFilename.append("_"+lang+".loc"); @@ -1590,7 +1708,7 @@ locFilename.insert(0,lang+"/"); locFilename.insert(0,project->first("SYMBIANLOCFILESDIR")); } else { - locFilename.insert(0,"/epoc32/include/platform/app/loc/"+lang+"/"); + locFilename.insert(0,"/epoc32/include/platform/mw/loc/"+lang+"/"); } QString shortCaption; @@ -1633,17 +1751,22 @@ } } } - if (shortCaption.isEmpty()) + if (shortCaption.isEmpty()){ fprintf(stderr, "Warning: STRING_r_short_caption not generated from file '%s'.\n", qPrintable(tsFilename)); - if (longCaption.isEmpty()) + fprintf(stderr, " : short caption generated from target name '#%s'.\n", qPrintable(fixedTarget)); + } + if (longCaption.isEmpty()){ fprintf(stderr, "Warning: STRING_r_caption not generated from file '%s'.\n", qPrintable(tsFilename)); + fprintf(stderr, " : caption generated from target name '#%s'.\n", qPrintable(fixedTarget)); + } if (xml.hasError()) fprintf(stderr, "ERROR: \"%s\" when parsing ts file\n", qPrintable(xml.errorString())); } else { fprintf(stderr, "Could not open ts file (%s)\n", qPrintable(tsFilename)); } } else { - fprintf(stderr, "ts file does not exist: (%s)\n", qPrintable(tsFilename)); + fprintf(stderr, "Warning: ts file does not exist: (%s)\n", qPrintable(tsFilename)); + fprintf(stderr, " : short and long caption generated from target name '#%s'.\n", qPrintable(fixedTarget)); } // generate language specific caption loc file @@ -1661,12 +1784,12 @@ if (!shortCaption.isEmpty()) { t << "#define STRING_r_short_caption \"" << shortCaption << "\"" << endl; } else { - t << "#define STRING_r_short_caption \"" << fixedTarget << "\"" << endl; + t << "#define STRING_r_short_caption \"" "#"<< fixedTarget << "\"" << endl; } if (!longCaption.isEmpty()) { t << "#define STRING_r_caption \"" << longCaption << "\"" << endl; } else { - t << "#define STRING_r_caption \"" << fixedTarget << "\"" << endl; + t << "#define STRING_r_caption \"" "#"<< fixedTarget << "\"" << endl; } ft.close(); } else { @@ -1675,7 +1798,9 @@ } } -void SymbianMakefileGenerator::readRssRules(QString &numberOfIcons, QString &iconFile, QStringList &userRssRules) +void SymbianMakefileGenerator::readRssRules(QString &numberOfIcons, + QString &iconFile, QMap &userRssRules) { for (QMap::iterator it = project->variables().begin(); it != project->variables().end(); ++it) { if (it.key().startsWith(RSS_RULES_BASE)) { @@ -1687,14 +1812,16 @@ QStringList newValues; QStringList values = it.value(); foreach(QString item, values) { - // If there is no stringlist defined for a rule, use rule name directly + // If there is no stringlist defined for a rule, use rule value directly // This is convenience for defining single line statements if (project->values(item).isEmpty()) { newValues << item; } else { + QStringList itemList; foreach(QString itemRow, project->values(item)) { - newValues << itemRow; + itemList << itemRow; } + newValues << itemList.join("\n"); } } // Verify thet there is exactly one value in RSS_TAG_NBROFICONS @@ -1715,6 +1842,14 @@ RSS_RULES_BASE, RSS_TAG_ICONFILE); continue; } + } else if (newKey == RSS_TAG_HEADER + || newKey == RSS_TAG_SERVICE_LIST + || newKey == RSS_TAG_FILE_OWNERSHIP_LIST + || newKey == RSS_TAG_DATATYPE_LIST + || newKey == RSS_TAG_FOOTER + || newKey == RSS_TAG_DEFAULT) { + userRssRules[newKey] = newValues; + continue; } else { fprintf(stderr, "Warning: Unsupported key:'%s%s'\n", RSS_RULES_BASE, newKey.toLatin1().constData()); @@ -1723,15 +1858,17 @@ } } + QStringList newValues; foreach(QString item, project->values(RSS_RULES)) { - // If there is no stringlist defined for a rule, use rule name directly - // This is convenience for defining single line mmp statements + // If there is no stringlist defined for a rule, use rule value directly + // This is convenience for defining single line statements if (project->values(item).isEmpty()) { - userRssRules << item; + newValues << item; } else { - userRssRules << project->values(item); + newValues << project->values(item); } } + userRssRules[RSS_TAG_DEFAULT] << newValues; // Validate that either both RSS_TAG_NBROFICONS and RSS_TAG_ICONFILE keys exist // or neither of them exist @@ -1747,7 +1884,7 @@ if (!numberOfIcons.isEmpty()) { bool ok; numberOfIcons = numberOfIcons.simplified(); - int tmp = numberOfIcons.toInt(&ok); + numberOfIcons.toInt(&ok); if (!ok) { numberOfIcons.clear(); iconFile.clear(); @@ -2041,9 +2178,14 @@ void SymbianMakefileGenerator::writeSisTargets(QTextStream &t) { - t << SIS_TARGET ": " RESTORE_BUILD_TARGET << endl; - QString siscommand = QString("\t$(if $(wildcard %1_template.%2),$(if $(wildcard %3)," \ - "$(MAKE) -s -f $(MAKEFILE) %4,$(MAKE) -s -f $(MAKEFILE) %5)," \ + t << "-include " MAKE_CACHE_NAME << endl; + t << endl; + + t << SIS_TARGET ":" << endl; + QString siscommand = QString::fromLatin1("\t$(if $(wildcard %1_template.%2),$(if $(wildcard %3)," \ + "$(MAKE) -s -f $(MAKEFILE) %4," \ + "$(if $(QT_SIS_TARGET),$(MAKE) -s -f $(MAKEFILE) %4," \ + "$(MAKE) -s -f $(MAKEFILE) %5))," \ "$(MAKE) -s -f $(MAKEFILE) %6)") .arg(fixedTarget) .arg("pkg") @@ -2056,24 +2198,69 @@ t << OK_SIS_TARGET ":" << endl; - QString pkgcommand = QString("\tcreatepackage.bat $(QT_SIS_OPTIONS) %1_template.%2 $(QT_SIS_TARGET) " \ + QString pkgcommand = QString::fromLatin1("\tcreatepackage.bat $(QT_SIS_OPTIONS) %1_template.%2 $(QT_SIS_TARGET) " \ "$(QT_SIS_CERTIFICATE) $(QT_SIS_KEY) $(QT_SIS_PASSPHRASE)") .arg(fixedTarget) .arg("pkg"); t << pkgcommand << endl; t << endl; + QString sisName = fixedTarget; + sisName += ".sis"; + + t << sisName << ":" << endl; + t << "\t$(MAKE) -s -f $(MAKEFILE) " SIS_TARGET << endl << endl; + + t << ROM_STUB_SIS_TARGET ":" << endl; + QString stubsiscommand = QString::fromLatin1("\t$(if $(wildcard %1_template.%2),$(if $(wildcard %3)," \ + "$(MAKE) -s -f $(MAKEFILE) %4," \ + "$(if $(QT_SIS_TARGET),$(MAKE) -s -f $(MAKEFILE) %4," \ + "$(MAKE) -s -f $(MAKEFILE) %5))," \ + "$(MAKE) -s -f $(MAKEFILE) %6)") + .arg(fixedTarget) + .arg("pkg") + .arg(MAKE_CACHE_NAME) + .arg(OK_ROM_STUB_SIS_TARGET) + .arg(FAIL_SIS_NOCACHE_TARGET) + .arg(FAIL_SIS_NOPKG_TARGET); + t << stubsiscommand << endl; + t << endl; + + t << OK_ROM_STUB_SIS_TARGET ":" << endl; + + QString stubpkgcommand = QString::fromLatin1("\tcreatepackage.bat -s $(QT_SIS_OPTIONS) %1_template.%2 $(QT_SIS_TARGET) " \ + "$(QT_SIS_CERTIFICATE) $(QT_SIS_KEY) $(QT_SIS_PASSPHRASE)") + .arg(fixedTarget) + .arg("pkg"); + t << stubpkgcommand << endl; + t << endl; + + t << INSTALLER_SIS_TARGET ": " << sisName << endl; + siscommand = QString::fromLatin1("\t$(if $(wildcard %1_installer.%2)," \ + "$(MAKE) -s -f $(MAKEFILE) %3," \ + "$(MAKE) -s -f $(MAKEFILE) %4)") + .arg(fixedTarget) + .arg("pkg") + .arg(OK_INSTALLER_SIS_TARGET) + .arg(FAIL_SIS_NOPKG_TARGET); + t << siscommand << endl; + t << endl; + + t << OK_INSTALLER_SIS_TARGET ": " << endl; + + pkgcommand = QString::fromLatin1("\tcreatepackage.bat $(QT_SIS_OPTIONS) %1_installer.%2 - " \ + "$(QT_SIS_CERTIFICATE) $(QT_SIS_KEY) $(QT_SIS_PASSPHRASE)") + .arg(fixedTarget) + .arg("pkg"); + t << pkgcommand << endl; + t << endl; + t << FAIL_SIS_NOPKG_TARGET ":" << endl; - t << "\t$(error PKG file does not exist, 'SIS' target is only supported for executables or projects with DEPLOYMENT statement)" << endl; + t << "\t$(error PKG file does not exist, '" SIS_TARGET "' and '" INSTALLER_SIS_TARGET "' target are only supported for executables or projects with DEPLOYMENT statement)" << endl; t << endl; t << FAIL_SIS_NOCACHE_TARGET ":" << endl; - t << "\t$(error Project has to be build before calling 'SIS' target)" << endl; - t << endl; - - - t << RESTORE_BUILD_TARGET ":" << endl; - t << "-include " MAKE_CACHE_NAME << endl; + t << "\t$(error Project has to be built or QT_SIS_TARGET environment variable has to be set before calling 'SIS' target)" << endl; t << endl; } @@ -2131,3 +2318,17 @@ t << "distclean: clean dodistclean" << endl; t << endl; } + +void SymbianMakefileGenerator::generateExecutionTargets(QTextStream& t, const QStringList& platforms) +{ + // create execution targets + if (targetType == TypeExe) { + if (platforms.contains("winscw")) { + t << "run:" << endl; + t << "\t-call " << epocRoot() << "epoc32/release/winscw/udeb/" << fixedTarget << ".exe " << "$(QT_RUN_OPTIONS)" << endl; + } + t << "runonphone: sis" << endl; + t << "\trunonphone $(QT_RUN_ON_PHONE_OPTIONS) --sis " << fixedTarget << ".sis " << fixedTarget << ".exe " << "$(QT_RUN_OPTIONS)" << endl; + t << endl; + } +}