qmake/generators/symbian/symmake.cpp
changeset 19 fcece45ef507
parent 18 2f34d5167611
child 22 79de32ba3296
equal deleted inserted replaced
18:2f34d5167611 19:fcece45ef507
    63 #define BLD_INF_RULES_BASE "BLD_INF_RULES."
    63 #define BLD_INF_RULES_BASE "BLD_INF_RULES."
    64 #define BLD_INF_TAG_PLATFORMS "prj_platforms"
    64 #define BLD_INF_TAG_PLATFORMS "prj_platforms"
    65 #define BLD_INF_TAG_MMPFILES "prj_mmpfiles"
    65 #define BLD_INF_TAG_MMPFILES "prj_mmpfiles"
    66 #define BLD_INF_TAG_TESTMMPFILES "prj_testmmpfiles"
    66 #define BLD_INF_TAG_TESTMMPFILES "prj_testmmpfiles"
    67 #define BLD_INF_TAG_EXTENSIONS "prj_extensions"
    67 #define BLD_INF_TAG_EXTENSIONS "prj_extensions"
    68 #define BLD_INF_TAG_EXPORTS "prj_exports"
    68 #define BLD_INF_TAG_TESTEXTENSIONS "prj_testextensions"
    69 
    69 
    70 #define RSS_RULES "RSS_RULES"
    70 #define RSS_RULES "RSS_RULES"
    71 #define RSS_RULES_BASE "RSS_RULES."
    71 #define RSS_RULES_BASE "RSS_RULES."
    72 #define RSS_TAG_NBROFICONS "number_of_icons"
    72 #define RSS_TAG_NBROFICONS "number_of_icons"
    73 #define RSS_TAG_ICONFILE "icon_file"
    73 #define RSS_TAG_ICONFILE "icon_file"
       
    74 #define RSS_TAG_HEADER "header"
       
    75 #define RSS_TAG_SERVICE_LIST "service_list"
       
    76 #define RSS_TAG_FILE_OWNERSHIP_LIST "file_ownership_list"
       
    77 #define RSS_TAG_DATATYPE_LIST "datatype_list"
       
    78 #define RSS_TAG_FOOTER "footer"
       
    79 #define RSS_TAG_DEFAULT "default_rules" // Same as just giving rules without tag
    74 
    80 
    75 #define MMP_TARGET "TARGET"
    81 #define MMP_TARGET "TARGET"
    76 #define MMP_TARGETTYPE "TARGETTYPE"
    82 #define MMP_TARGETTYPE "TARGETTYPE"
    77 #define MMP_SECUREID "SECUREID"
    83 #define MMP_SECUREID "SECUREID"
    78 #define MMP_OPTION_CW "OPTION CW"
    84 #define MMP_OPTION_CW "OPTION CW"
   147     QString resultPath = QDir::fromNativeSeparators(origPath);
   153     QString resultPath = QDir::fromNativeSeparators(origPath);
   148     if (resultPath.startsWith("/epoc32/", Qt::CaseInsensitive))
   154     if (resultPath.startsWith("/epoc32/", Qt::CaseInsensitive))
   149         resultPath = QDir::fromNativeSeparators(epocRoot()) + resultPath.mid(1);
   155         resultPath = QDir::fromNativeSeparators(epocRoot()) + resultPath.mid(1);
   150 
   156 
   151     QFileInfo fi(fileInfo(resultPath));
   157     QFileInfo fi(fileInfo(resultPath));
   152 	
   158 
   153     // Since origPath can be something given in HEADERS, we need to check if we are dealing
   159     // Since origPath can be something given in HEADERS, we need to check if we are dealing
   154     // with a file or a directory. In case the origPath doesn't yet exist, isFile() returns
   160     // with a file or a directory. In case the origPath doesn't yet exist, isFile() returns
   155     // false and we default to assuming it is a dir.
   161     // false and we default to assuming it is a dir.
   156     if (fi.isFile()) {
   162     if (fi.isFile()) {
   157         resultPath = fi.absolutePath();
   163         resultPath = fi.absolutePath();
   158     } else {
   164     } else {
   159        resultPath = fi.absoluteFilePath();
   165         resultPath = fi.absoluteFilePath();
   160     }
   166     }
   161 
   167 
   162     resultPath = QDir::cleanPath(resultPath);
   168     resultPath = QDir::cleanPath(resultPath);
   163 
   169 
   164     return resultPath;
   170     return resultPath;
   200 {
   206 {
   201     writeHeader(t);
   207     writeHeader(t);
   202 
   208 
   203     QString numberOfIcons;
   209     QString numberOfIcons;
   204     QString iconFile;
   210     QString iconFile;
   205     QStringList userRssRules;
   211     QMap<QString, QStringList> userRssRules;
   206     readRssRules(numberOfIcons, iconFile, userRssRules);
   212     readRssRules(numberOfIcons, iconFile, userRssRules);
   207 
   213 
   208     // Get the application translations and convert to symbian OS lang code, i.e. decical number
   214     // Get the application translations and convert to symbian OS lang code, i.e. decical number
   209     QStringList symbianLangCodes = symbianLangCodesFromTsFiles();
   215     QStringList symbianLangCodes = symbianLangCodesFromTsFiles();
   210 
   216 
   324         ";\n\n";
   330         ";\n\n";
   325     t << headerComment.arg(pkgFilename).arg(dateStr);
   331     t << headerComment.arg(pkgFilename).arg(dateStr);
   326     tw << headerComment.arg(wrapperPkgFilename).arg(dateStr);
   332     tw << headerComment.arg(wrapperPkgFilename).arg(dateStr);
   327 
   333 
   328     // Construct QStringList from pkg_prerules since we need search it before printed to file
   334     // Construct QStringList from pkg_prerules since we need search it before printed to file
       
   335     // Note: Though there can't be more than one language or header line, use stringlists
       
   336     // in case user wants comments to go with the rules.
   329     QStringList rawPkgPreRules;
   337     QStringList rawPkgPreRules;
       
   338     QStringList languageRules;
       
   339     QStringList headerRules;
   330     foreach(QString deploymentItem, project->values("DEPLOYMENT")) {
   340     foreach(QString deploymentItem, project->values("DEPLOYMENT")) {
   331         foreach(QString pkgrulesItem, project->values(deploymentItem + ".pkg_prerules")) {
   341         foreach(QString pkgrulesItem, project->values(deploymentItem + ".pkg_prerules")) {
   332             QStringList pkgrulesValue = project->values(pkgrulesItem);
   342             QStringList pkgrulesValue = project->values(pkgrulesItem);
   333             // If there is no stringlist defined for a rule, use rule name directly
   343             // If there is no stringlist defined for a rule, use rule name directly
   334             // This is convenience for defining single line mmp statements
   344             // This is convenience for defining single line mmp statements
   335             if (pkgrulesValue.isEmpty()) {
   345             if (pkgrulesValue.isEmpty()) {
   336                 rawPkgPreRules << pkgrulesItem;
   346                 if (pkgrulesItem.startsWith("&"))
       
   347                     languageRules << pkgrulesItem;
       
   348                 else if (pkgrulesItem.startsWith("#"))
       
   349                     headerRules << pkgrulesItem;
       
   350                 else
       
   351                     rawPkgPreRules << pkgrulesItem;
   337             } else {
   352             } else {
   338                 foreach(QString pkgrule, pkgrulesValue) {
   353                 if (containsStartWithItem('&', pkgrulesValue)) {
   339                     rawPkgPreRules << pkgrule;
   354                     foreach(QString pkgrule, pkgrulesValue) {
       
   355                         languageRules << pkgrule;
       
   356                     }
       
   357                 } else if (containsStartWithItem('#', pkgrulesValue)) {
       
   358                     foreach(QString pkgrule, pkgrulesValue) {
       
   359                         headerRules << pkgrule;
       
   360                     }
       
   361                 } else {
       
   362                     foreach(QString pkgrule, pkgrulesValue) {
       
   363                         rawPkgPreRules << pkgrule;
       
   364                     }
   340                 }
   365                 }
   341             }
   366             }
   342         }
   367         }
   343     }
   368     }
   344 
   369 
   345     // Apply some defaults if specific data does not exist in PKG pre-rules
   370     // Apply some defaults if specific data does not exist in PKG pre-rules
   346 
   371 
   347     if (!containsStartWithItem('&', rawPkgPreRules)) {
   372     if (languageRules.isEmpty()) {
   348         // language, (*** hardcoded to english atm, should be parsed from TRANSLATIONS)
   373         // language, (*** hardcoded to english atm, should be parsed from TRANSLATIONS)
   349         QString languageCode = "; Language\n&EN\n\n";
   374         languageRules << "; Language\n&EN\n\n";
   350         t << languageCode;
   375     } else if (headerRules.isEmpty()) {
   351         tw << languageCode;
       
   352     } else {
       
   353         // In case user defines langs, he must take care also about SIS header
   376         // In case user defines langs, he must take care also about SIS header
   354         if (!containsStartWithItem('#', rawPkgPreRules))
   377         fprintf(stderr, "Warning: If language is defined with DEPLOYMENT pkg_prerules, also the SIS header must be defined\n");
   355             fprintf(stderr, "Warning: If language is defined with DEPLOYMENT pkg_prerules, also the SIS header must be defined\n");
   378     }
   356     }
   379 
       
   380     t << languageRules.join("\n") << endl;
       
   381     tw << languageRules.join("\n") << endl;
   357 
   382 
   358     // name of application, UID and version
   383     // name of application, UID and version
   359     QString applicationVersion = project->first("VERSION").isEmpty() ? "1,0,0" : project->first("VERSION").replace('.', ',');
   384     QString applicationVersion = project->first("VERSION").isEmpty() ? "1,0,0" : project->first("VERSION").replace('.', ',');
   360     QString sisHeader = "; SIS header: name, uid, version\n#{\"%1\"},(%2),%3\n\n";
   385     QString sisHeader = "; SIS header: name, uid, version\n#{\"%1\"},(%2),%3\n\n";
   361     QString visualTarget = escapeFilePath(fileFixify(project->first("TARGET")));
   386     QString visualTarget = escapeFilePath(fileFixify(project->first("TARGET")));
   366         tw << sisHeader.arg(wrapperTarget).arg(installerSisHeader).arg(applicationVersion);
   391         tw << sisHeader.arg(wrapperTarget).arg(installerSisHeader).arg(applicationVersion);
   367     } else {
   392     } else {
   368         tw << installerSisHeader << endl;
   393         tw << installerSisHeader << endl;
   369     }
   394     }
   370 
   395 
   371     if (!containsStartWithItem('#', rawPkgPreRules)) {
   396     if (headerRules.isEmpty())
   372         t << sisHeader.arg(visualTarget).arg(uid3).arg(applicationVersion);
   397         t << sisHeader.arg(visualTarget).arg(uid3).arg(applicationVersion);
   373     }
   398     else
       
   399         t << headerRules.join("\n") << endl;
   374 
   400 
   375     // Localized vendor name
   401     // Localized vendor name
   376     QString vendorName;
   402     QString vendorName;
   377     if (!containsStartWithItem('%', rawPkgPreRules)) {
   403     if (!containsStartWithItem('%', rawPkgPreRules)) {
   378         vendorName += "; Localised Vendor name\n%{\"Vendor\"}\n\n";
   404         vendorName += "; Localised Vendor name\n%{\"Vendor\"}\n\n";
   458     }
   484     }
   459 
   485 
   460     // deploy any additional DEPLOYMENT  files
   486     // deploy any additional DEPLOYMENT  files
   461     QString remoteTestPath;
   487     QString remoteTestPath;
   462     remoteTestPath = QString("!:\\private\\%1").arg(privateDirUid);
   488     remoteTestPath = QString("!:\\private\\%1").arg(privateDirUid);
       
   489     QString zDir = epocRoot() + QLatin1String("epoc32/data/z");
   463 
   490 
   464     initProjectDeploySymbian(project, depList, remoteTestPath, true, "$(PLATFORM)", "$(TARGET)", generatedDirs, generatedFiles);
   491     initProjectDeploySymbian(project, depList, remoteTestPath, true, "$(PLATFORM)", "$(TARGET)", generatedDirs, generatedFiles);
   465     if (depList.size())
   492     if (depList.size())
   466         t << "; DEPLOYMENT" << endl;
   493         t << "; DEPLOYMENT" << endl;
   467     for (int i = 0; i < depList.size(); ++i)  {
   494     for (int i = 0; i < depList.size(); ++i)  {
   468         t << QString("\"%1\"    - \"%2\"")
   495         QString from = depList.at(i).from;
   469              .arg(QString(depList.at(i).from).replace('\\','/'))
   496         QString to = depList.at(i).to;
   470              .arg(depList.at(i).to) << endl;
   497 
       
   498         // Deploy anything not already deployed from under epoc32 instead from under
       
   499         // \epoc32\data\z\ to enable using pkg file without rebuilding
       
   500         // the project, which can be useful for some binary only distributions.
       
   501         if (!from.contains(QLatin1String("epoc32"), Qt::CaseInsensitive)) {
       
   502             from = to;
       
   503             if (from.size() > 1 && from.at(1) == QLatin1Char(':'))
       
   504                 from = from.mid(2);
       
   505             from.prepend(zDir);
       
   506         } else {
       
   507             if (from.size() > 1 && from.at(1) == QLatin1Char(':'))
       
   508                 from = from.mid(2);
       
   509         }
       
   510 
       
   511         t << QString("\"%1\"    - \"%2\"").arg(from.replace('\\','/')).arg(to) << endl;
   471     }
   512     }
   472     t << endl;
   513     t << endl;
   473 
   514 
   474     // PKG post-rules - these are added after actual file installations i.e. SIS package body
   515     // PKG post-rules - these are added after actual file installations i.e. SIS package body
   475     t << "; Manual PKG post-rules from PRO files" << endl;
   516     t << "; Manual PKG post-rules from PRO files" << endl;
   777     QStringList overridableMmpKeywords;
   818     QStringList overridableMmpKeywords;
   778     QStringList restrictableMmpKeywords;
   819     QStringList restrictableMmpKeywords;
   779     QStringList restrictedMmpKeywords;
   820     QStringList restrictedMmpKeywords;
   780     bool inResourceBlock = false;
   821     bool inResourceBlock = false;
   781 
   822 
   782     overridableMmpKeywords << QLatin1String(MMP_TARGETTYPE);
   823     overridableMmpKeywords << QLatin1String(MMP_TARGETTYPE) << QLatin1String(MMP_EPOCHEAPSIZE);
   783     restrictableMmpKeywords << QLatin1String(MMP_TARGET) << QLatin1String(MMP_SECUREID)
   824     restrictableMmpKeywords << QLatin1String(MMP_TARGET) << QLatin1String(MMP_SECUREID)
   784        << QLatin1String(MMP_OPTION_CW) << QLatin1String(MMP_OPTION_ARMCC)
   825        << QLatin1String(MMP_LINKEROPTION_CW) << QLatin1String(MMP_LINKEROPTION_ARMCC)
   785        << QLatin1String(MMP_OPTION_GCCE) << QLatin1String(MMP_LINKEROPTION_CW)
   826        << QLatin1String(MMP_LINKEROPTION_GCCE)
   786        << QLatin1String(MMP_LINKEROPTION_ARMCC) << QLatin1String(MMP_LINKEROPTION_GCCE)
       
   787        << QLatin1String(MMP_CAPABILITY) << QLatin1String(MMP_EPOCALLOWDLLDATA)
   827        << QLatin1String(MMP_CAPABILITY) << QLatin1String(MMP_EPOCALLOWDLLDATA)
   788        << QLatin1String(MMP_EPOCHEAPSIZE) << QLatin1String(MMP_EPOCSTACKSIZE)
   828        << QLatin1String(MMP_EPOCSTACKSIZE) << QLatin1String(MMP_UID)
   789        << QLatin1String(MMP_UID) << QLatin1String(MMP_VENDORID)
   829        << QLatin1String(MMP_VENDORID) << QLatin1String(MMP_VERSION);
   790        << QLatin1String(MMP_VERSION);
       
   791 
   830 
   792     foreach (QString item, project->values("MMP_RULES")) {
   831     foreach (QString item, project->values("MMP_RULES")) {
   793         if (project->values(item).isEmpty()) {
   832         if (project->values(item).isEmpty()) {
   794             handleMmpRulesOverrides(item, inResourceBlock, restrictedMmpKeywords,
   833             handleMmpRulesOverrides(item, inResourceBlock, restrictedMmpKeywords,
   795                                     restrictableMmpKeywords, overridableMmpKeywords);
   834                                     restrictableMmpKeywords, overridableMmpKeywords);
   959 
   998 
   960 
   999 
   961 void SymbianMakefileGenerator::writeMmpFileTargetPart(QTextStream& t)
  1000 void SymbianMakefileGenerator::writeMmpFileTargetPart(QTextStream& t)
   962 {
  1001 {
   963     bool skipTargetType = overriddenMmpKeywords.contains(MMP_TARGETTYPE);
  1002     bool skipTargetType = overriddenMmpKeywords.contains(MMP_TARGETTYPE);
       
  1003     bool skipEpocHeapSize = overriddenMmpKeywords.contains(MMP_EPOCHEAPSIZE);
   964 
  1004 
   965     if (targetType == TypeExe) {
  1005     if (targetType == TypeExe) {
   966         t << MMP_TARGET "\t\t" << fixedTarget << ".exe" << endl;
  1006         t << MMP_TARGET "\t\t" << fixedTarget << ".exe" << endl;
   967         if (!skipTargetType) {
  1007         if (!skipTargetType) {
   968             if (project->isActiveConfig("stdbinary"))
  1008             if (project->isActiveConfig("stdbinary"))
  1010 
  1050 
  1011     t << endl;
  1051     t << endl;
  1012 
  1052 
  1013     if (0 != project->first("TARGET.EPOCSTACKSIZE").size())
  1053     if (0 != project->first("TARGET.EPOCSTACKSIZE").size())
  1014         t << MMP_EPOCSTACKSIZE "\t\t" << project->first("TARGET.EPOCSTACKSIZE") << endl;
  1054         t << MMP_EPOCSTACKSIZE "\t\t" << project->first("TARGET.EPOCSTACKSIZE") << endl;
  1015     if (0 != project->values("TARGET.EPOCHEAPSIZE").size())
  1055     if (!skipEpocHeapSize && 0 != project->values("TARGET.EPOCHEAPSIZE").size())
  1016         t << MMP_EPOCHEAPSIZE "\t\t" << project->values("TARGET.EPOCHEAPSIZE").join(" ") << endl;
  1056         t << MMP_EPOCHEAPSIZE "\t\t" << project->values("TARGET.EPOCHEAPSIZE").join(" ") << endl;
  1017     if (0 != project->values("TARGET.EPOCALLOWDLLDATA").size())
  1057     if (0 != project->values("TARGET.EPOCALLOWDLLDATA").size())
  1018         t << MMP_EPOCALLOWDLLDATA << endl;
  1058         t << MMP_EPOCALLOWDLLDATA << endl;
  1019 
  1059 
  1020     if (targetType == TypePlugin && !project->isActiveConfig("stdbinary")) {
  1060     if (targetType == TypePlugin && !project->isActiveConfig("stdbinary")) {
  1238 
  1278 
  1239     if (!cw.isEmpty())
  1279     if (!cw.isEmpty())
  1240         t << MMP_OPTION_CW " " << cw <<  endl;
  1280         t << MMP_OPTION_CW " " << cw <<  endl;
  1241     if (!armcc.isEmpty())
  1281     if (!armcc.isEmpty())
  1242         t << MMP_OPTION_ARMCC " " << armcc <<  endl;
  1282         t << MMP_OPTION_ARMCC " " << armcc <<  endl;
       
  1283 
       
  1284     foreach(QString armccVersion, project->values("VERSION_FLAGS.ARMCC")) {
       
  1285         QStringList currentValues = project->values("QMAKE_CXXFLAGS." + armccVersion);
       
  1286         if (currentValues.size()) {
       
  1287             t << "#if defined(" << armccVersion << ")" << endl;
       
  1288             t << MMP_OPTION_ARMCC " " << currentValues.join(" ") <<  endl;
       
  1289             t << "#endif" << endl;
       
  1290         }
       
  1291     }
       
  1292 
  1243     if (!gcce.isEmpty())
  1293     if (!gcce.isEmpty())
  1244         t << MMP_OPTION_GCCE " " << gcce <<  endl;
  1294         t << MMP_OPTION_GCCE " " << gcce <<  endl;
  1245 
  1295 
  1246     if (!cwlink.isEmpty())
  1296     if (!cwlink.isEmpty())
  1247         t << MMP_LINKEROPTION_CW " " << cwlink <<  endl;
  1297         t << MMP_LINKEROPTION_CW " " << cwlink <<  endl;
  1349         } else if (!project->isEmpty(item + ".subdir")) {
  1399         } else if (!project->isEmpty(item + ".subdir")) {
  1350             fixedItem = project->first(item + ".subdir");
  1400             fixedItem = project->first(item + ".subdir");
  1351         } else {
  1401         } else {
  1352             fixedItem = item;
  1402             fixedItem = item;
  1353         }
  1403         }
       
  1404 
       
  1405         QString condition;
       
  1406         if (!project->isEmpty(item + ".condition"))
       
  1407             condition = project->first(item + ".condition");
  1354 
  1408 
  1355         QFileInfo subdir(fileInfo(fixedItem));
  1409         QFileInfo subdir(fileInfo(fixedItem));
  1356         QString relativePath = directory.relativeFilePath(fixedItem);
  1410         QString relativePath = directory.relativeFilePath(fixedItem);
  1357         QString subdirFileName = subdir.completeBaseName();
  1411         QString subdirFileName = subdir.completeBaseName();
  1358         QString fullProName = subdir.absoluteFilePath();;
  1412         QString fullProName = subdir.absoluteFilePath();;
  1378         QString uid = generate_uid(fullProName);
  1432         QString uid = generate_uid(fullProName);
  1379         QString bldinfDefine = QString("BLD_INF_") + subdirFileName + QString("_") + uid;
  1433         QString bldinfDefine = QString("BLD_INF_") + subdirFileName + QString("_") + uid;
  1380         bldinfDefine = bldinfDefine.toUpper();
  1434         bldinfDefine = bldinfDefine.toUpper();
  1381         removeSpecialCharacters(bldinfDefine);
  1435         removeSpecialCharacters(bldinfDefine);
  1382 
  1436 
       
  1437         if (!condition.isEmpty())
       
  1438             t << "#if defined(" << condition << ")" << endl;
       
  1439 
  1383         t << "#ifndef " << bldinfDefine << endl;
  1440         t << "#ifndef " << bldinfDefine << endl;
  1384         t << "\t#include \"" << bldinfFilename << "\"" << endl;
  1441         t << "\t#include \"" << bldinfFilename << "\"" << endl;
  1385         t << "#endif // " << bldinfDefine << endl;
  1442         t << "#endif" << endl;
       
  1443 
       
  1444         if (!condition.isEmpty())
       
  1445             t << "#endif" << endl;
       
  1446 
  1386     }
  1447     }
  1387 
  1448 
  1388     // Add supported project platforms
  1449     // Add supported project platforms
  1389 
  1450 
  1390     t << endl << BLD_INF_TAG_PLATFORMS << endl << endl;
  1451     t << endl << BLD_INF_TAG_PLATFORMS << endl << endl;
  1398     t << endl;
  1459     t << endl;
  1399 
  1460 
  1400     // Add project mmps and old style extension makefiles
  1461     // Add project mmps and old style extension makefiles
  1401 
  1462 
  1402     QString mmpTag;
  1463     QString mmpTag;
  1403     if (project->isActiveConfig("symbian_test"))
  1464     if (project->isActiveConfig(SYMBIAN_TEST_CONFIG))
  1404         mmpTag = QLatin1String(BLD_INF_TAG_TESTMMPFILES);
  1465         mmpTag = QLatin1String(BLD_INF_TAG_TESTMMPFILES);
  1405     else
  1466     else
  1406         mmpTag = QLatin1String(BLD_INF_TAG_MMPFILES);
  1467         mmpTag = QLatin1String(BLD_INF_TAG_MMPFILES);
  1407 
  1468 
  1408     t << endl << mmpTag << endl << endl;
  1469     t << endl << mmpTag << endl << endl;
  1421     userItems = userBldInfRules.value(mmpTag);
  1482     userItems = userBldInfRules.value(mmpTag);
  1422     foreach(QString item, userItems)
  1483     foreach(QString item, userItems)
  1423         t << item << endl;
  1484         t << item << endl;
  1424     userBldInfRules.remove(mmpTag);
  1485     userBldInfRules.remove(mmpTag);
  1425 
  1486 
  1426     t << endl << BLD_INF_TAG_EXTENSIONS << endl << endl;
  1487     QString extensionTag;
       
  1488     if (project->isActiveConfig(SYMBIAN_TEST_CONFIG))
       
  1489         extensionTag = QLatin1String(BLD_INF_TAG_TESTEXTENSIONS);
       
  1490     else
       
  1491         extensionTag = QLatin1String(BLD_INF_TAG_EXTENSIONS);
       
  1492 
       
  1493     t << endl << extensionTag << endl << endl;
  1427 
  1494 
  1428     // Generate extension rules
  1495     // Generate extension rules
  1429 
  1496 
  1430     writeBldInfExtensionRulesPart(t, iconFile);
  1497     writeBldInfExtensionRulesPart(t, iconFile);
  1431 
  1498 
  1432     userItems = userBldInfRules.value(BLD_INF_TAG_EXTENSIONS);
  1499     userItems = userBldInfRules.value(extensionTag);
  1433     foreach(QString item, userItems)
  1500     foreach(QString item, userItems)
  1434         t << item << endl;
  1501         t << item << endl;
  1435     userBldInfRules.remove(BLD_INF_TAG_EXTENSIONS);
  1502     userBldInfRules.remove(extensionTag);
  1436 
  1503 
  1437     // Add rest of the user defined content
  1504     // Add rest of the user defined content
  1438 
  1505 
  1439     for (QMap<QString, QStringList>::iterator it = userBldInfRules.begin(); it != userBldInfRules.end(); ++it) {
  1506     for (QMap<QString, QStringList>::iterator it = userBldInfRules.begin(); it != userBldInfRules.end(); ++it) {
  1440         t << endl << endl << it.key() << endl << endl;
  1507         t << endl << endl << it.key() << endl << endl;
  1441         userItems = it.value();
  1508         userItems = it.value();
  1442         foreach(QString item, userItems)
  1509         foreach(QString item, userItems)
  1443             t << item << endl;
  1510             t << item << endl;
  1444     }
  1511     }
  1445     if (project->values("CONFIG").contains("headerexport", Qt::CaseInsensitive)) {
  1512 }
  1446         writeExportPart(t);
  1513 
  1447     }
  1514 void SymbianMakefileGenerator::writeRegRssFile(QMap<QString, QStringList> &userItems)
  1448 }
       
  1449 
       
  1450 void SymbianMakefileGenerator::writeExportPart(QTextStream &t)
       
  1451 {
       
  1452     QDir currentDir = QDir::current();
       
  1453     t << "prj_exports" << endl;
       
  1454 
       
  1455     foreach(QString install, project->values("INSTALLS")) {
       
  1456         QString installDir = project->first(install + ".path");
       
  1457 
       
  1458         // Export macros are the recommended way, but might not be used
       
  1459         // in all cases (such as Qt headers). We handle it either way,
       
  1460         // macros or not. 
       
  1461         bool useLayerMacro = false;
       
  1462         if (installDir.startsWith("MW_LAYER_") ||
       
  1463             installDir.startsWith("APP_LAYER_") ||
       
  1464             installDir.startsWith("APP_LAYER_")) {
       
  1465             useLayerMacro = true;
       
  1466         } else {
       
  1467 #ifdef Q_OS_WIN
       
  1468             // If we are running on Windows, and the export target starts
       
  1469             // with a drive letter, we need to remove it, the build tools
       
  1470             // cannot handle drives in export paths
       
  1471 
       
  1472             if (installDir.length() > 2 && installDir[1] == ':') {
       
  1473                 installDir.remove(0, 2);
       
  1474             }
       
  1475 #endif
       
  1476             installDir.replace("\\", "/");
       
  1477             if (!installDir.endsWith("/")) {
       
  1478                 installDir.append("/");
       
  1479             }
       
  1480         }
       
  1481 
       
  1482         foreach(QString target, project->values(install + ".files")) {
       
  1483             // Handle glob targets (only in the current directory)
       
  1484             if (target.contains("*") || target.contains("?")) {
       
  1485                 QDir globber = QDir::current();
       
  1486                 globber.setNameFilters(QStringList(target));
       
  1487                 foreach(QString globbedTarget, globber.entryList()) {
       
  1488                     if (useLayerMacro) {
       
  1489                         QFileInfo globbedInfo(globbedTarget);
       
  1490                         t << globbedTarget << " " << installDir <<
       
  1491                             "(" << globbedInfo.fileName() << ")" << endl;
       
  1492                     } else {
       
  1493                         t << globbedTarget << " " << installDir << 
       
  1494                             globbedTarget << endl;
       
  1495                     }
       
  1496                 }
       
  1497             } else {
       
  1498                 target = currentDir.relativeFilePath(target);
       
  1499                 QFileInfo targetInfo(target);
       
  1500 
       
  1501                 // Not possible to export whole directories, extension makefile needed for this
       
  1502                 // Note that this check requires the file to be exported to exist in the qmake phase!
       
  1503                 if (targetInfo.isFile()) {
       
  1504                     if (useLayerMacro) {
       
  1505                         t << target << " " << installDir <<
       
  1506                             "(" << targetInfo.fileName() << ")" << endl;
       
  1507                     } else {
       
  1508                         t << target << " " << installDir <<
       
  1509                             targetInfo.fileName() << endl;
       
  1510                     }
       
  1511                 }
       
  1512             }
       
  1513         }
       
  1514     }
       
  1515     t << endl;
       
  1516 }
       
  1517 
       
  1518 void SymbianMakefileGenerator::writeRegRssFile(QStringList &userItems)
       
  1519 {
  1515 {
  1520     QString filename(fixedTarget);
  1516     QString filename(fixedTarget);
  1521     filename.append("_reg.rss");
  1517     filename.append("_reg.rss");
  1522     QFile ft(filename);
  1518     QFile ft(filename);
  1523     if (ft.open(QIODevice::WriteOnly)) {
  1519     if (ft.open(QIODevice::WriteOnly)) {
  1533         t << "// * user." << endl;
  1529         t << "// * user." << endl;
  1534         t << "// ============================================================================" << endl;
  1530         t << "// ============================================================================" << endl;
  1535         t << endl;
  1531         t << endl;
  1536         t << "#include <" << fixedTarget << ".rsg>" << endl;
  1532         t << "#include <" << fixedTarget << ".rsg>" << endl;
  1537         t << "#include <appinfo.rh>" << endl;
  1533         t << "#include <appinfo.rh>" << endl;
       
  1534         foreach(QString item, userItems[RSS_TAG_HEADER])
       
  1535             t << item << endl;
  1538         t << endl;
  1536         t << endl;
  1539         t << "UID2 KUidAppRegistrationResourceFile" << endl;
  1537         t << "UID2 KUidAppRegistrationResourceFile" << endl;
  1540         t << "UID3 " << uid3 << endl << endl;
  1538         t << "UID3 " << uid3 << endl << endl;
  1541         t << "RESOURCE APP_REGISTRATION_INFO" << endl;
  1539         t << "RESOURCE APP_REGISTRATION_INFO" << endl;
  1542         t << "\t{" << endl;
  1540         t << "\t{" << endl;
  1543         t << "\tapp_file=\"" << fixedTarget << "\";" << endl;
  1541         t << "\tapp_file=\"" << fixedTarget << "\";" << endl;
  1544         t << "\tlocalisable_resource_file=\"" RESOURCE_DIRECTORY_RESOURCE << fixedTarget << "\";" << endl;
  1542         t << "\tlocalisable_resource_file=\"" RESOURCE_DIRECTORY_RESOURCE << fixedTarget << "\";" << endl;
       
  1543 
       
  1544         writeRegRssList(t, userItems[RSS_TAG_SERVICE_LIST],
       
  1545                         QLatin1String(RSS_TAG_SERVICE_LIST),
       
  1546                         QLatin1String("SERVICE_INFO"));
       
  1547         writeRegRssList(t, userItems[RSS_TAG_FILE_OWNERSHIP_LIST],
       
  1548                         QLatin1String(RSS_TAG_FILE_OWNERSHIP_LIST),
       
  1549                         QLatin1String("FILE_OWNERSHIP_INFO"));
       
  1550         writeRegRssList(t, userItems[RSS_TAG_DATATYPE_LIST],
       
  1551                         QLatin1String(RSS_TAG_DATATYPE_LIST),
       
  1552                         QLatin1String("DATATYPE"));
  1545         t << endl;
  1553         t << endl;
  1546 
  1554 
  1547         foreach(QString item, userItems)
  1555         foreach(QString item, userItems[RSS_TAG_DEFAULT])
  1548             t << "\t" << item << endl;
  1556             t << "\t" << item.replace("\n","\n\t") << endl;
  1549         t << "\t}" << endl;
  1557         t << "\t}" << endl;
       
  1558 
       
  1559         foreach(QString item, userItems[RSS_TAG_FOOTER])
       
  1560             t << item << endl;
  1550     } else {
  1561     } else {
  1551         PRINT_FILE_CREATE_ERROR(filename)
  1562         PRINT_FILE_CREATE_ERROR(filename)
       
  1563     }
       
  1564 }
       
  1565 
       
  1566 void SymbianMakefileGenerator::writeRegRssList(QTextStream &t,
       
  1567                                                QStringList &userList,
       
  1568                                                const QString &listTag,
       
  1569                                                const QString &listItem)
       
  1570 {
       
  1571     int itemCount = userList.count();
       
  1572     if (itemCount) {
       
  1573         t << "\t" << listTag << " ="<< endl;
       
  1574         t << "\t\t{" << endl;
       
  1575         foreach(QString item, userList) {
       
  1576             t << "\t\t" << listItem << endl;
       
  1577             t << "\t\t\t{" << endl;
       
  1578             t << "\t\t\t" << item.replace("\n","\n\t\t\t") << endl;
       
  1579             t << "\t\t\t}";
       
  1580             if (--itemCount)
       
  1581                 t << ",";
       
  1582             t << endl;
       
  1583         }
       
  1584         t << "\t\t}; "<< endl;
  1552     }
  1585     }
  1553 }
  1586 }
  1554 
  1587 
  1555 void SymbianMakefileGenerator::writeRssFile(QString &numberOfIcons, QString &iconFile)
  1588 void SymbianMakefileGenerator::writeRssFile(QString &numberOfIcons, QString &iconFile)
  1556 {
  1589 {
  1684         // get captions from ts file
  1717         // get captions from ts file
  1685         QFile tsFile(tsFilename);
  1718         QFile tsFile(tsFilename);
  1686         if (tsFile.exists()) {
  1719         if (tsFile.exists()) {
  1687             if (tsFile.open(QIODevice::ReadOnly)) {
  1720             if (tsFile.open(QIODevice::ReadOnly)) {
  1688                 QString shortCaptionId = QLatin1String("txt_short_caption_");
  1721                 QString shortCaptionId = QLatin1String("txt_short_caption_");
  1689                 shortCaptionId.append(filename);
       
  1690                 QString longCaptionId = QLatin1String("txt_long_caption_");
  1722                 QString longCaptionId = QLatin1String("txt_long_caption_");
  1691                 longCaptionId.append(filename);
       
  1692                 QXmlStreamReader xml(&tsFile);
  1723                 QXmlStreamReader xml(&tsFile);
  1693                 while (!xml.atEnd()) {
  1724                 while (!xml.atEnd()) {
  1694                     xml.readNext();
  1725                     xml.readNext();
  1695                     if (xml.isStartElement() && xml.name() == "context") {
  1726                     if (xml.isStartElement() && xml.name() == "context") {
  1696                         while (!(xml.isEndElement() && xml.name() == "context") && !xml.atEnd()) {
  1727                         while (!(xml.isEndElement() && xml.name() == "context") && !xml.atEnd()) {
  1697                             xml.readNext();  
  1728                             xml.readNext();  
  1698                             if (xml.isStartElement() && xml.name() == "message" && 
  1729                             if (xml.isStartElement() && xml.name() == "message" && 
  1699                                 xml.attributes().value("numerus") == "no" && 
  1730                                 xml.attributes().value("numerus") == "no" && 
  1700                                 xml.attributes().value("id") == shortCaptionId) {
  1731                                 xml.attributes().value("id").toString().left(shortCaptionId.length()) == shortCaptionId) {
  1701                                 while (!(xml.isEndElement() && xml.name() == "message") && !xml.atEnd()) {
  1732                                 while (!(xml.isEndElement() && xml.name() == "message") && !xml.atEnd()) {
  1702                                     xml.readNext();
  1733                                     xml.readNext();
  1703                                     if (xml.isStartElement() && xml.name() == "translation") {
  1734                                     if (xml.isStartElement() && xml.name() == "translation") {
  1704                             		   shortCaption = xml.readElementText();
  1735                             		   shortCaption = xml.readElementText();
  1705                                     }
  1736                                     }
  1706                                 }
  1737                                 }
  1707                             }
  1738                             }
  1708                             if (xml.isStartElement() && xml.name() == "message" && 
  1739                             if (xml.isStartElement() && xml.name() == "message" && 
  1709                                 xml.attributes().value("numerus") == "no" && 
  1740                                 xml.attributes().value("numerus") == "no" && 
  1710                                 xml.attributes().value("id") == longCaptionId) {
  1741                                 xml.attributes().value("id").toString().left(longCaptionId.length()) == longCaptionId) {
  1711                                 while (!(xml.isEndElement() && xml.name() == "message") && !xml.atEnd()) {   
  1742                                 while (!(xml.isEndElement() && xml.name() == "message") && !xml.atEnd()) {   
  1712                                     xml.readNext();
  1743                                     xml.readNext();
  1713                                     if (xml.isStartElement() && xml.name() == "translation") {
  1744                                     if (xml.isStartElement() && xml.name() == "translation") {
  1714                                         longCaption = xml.readElementText();
  1745                                         longCaption = xml.readElementText();
  1715                                     }
  1746                                     }
  1717                             }
  1748                             }
  1718                         }
  1749                         }
  1719                     }         
  1750                     }         
  1720                 }
  1751                 }
  1721                 if (shortCaption.isEmpty()){
  1752                 if (shortCaption.isEmpty()){
  1722                     fprintf(stderr, "Warning: STRING_r_short_caption not generated from file '%s'.\n", qPrintable(tsFilename));
  1753                     fprintf(stderr, "Short caption generated from target name '#%s'.\n", qPrintable(fixedTarget));
  1723                     fprintf(stderr, "       : short caption generated from target name '#%s'.\n", qPrintable(fixedTarget));
       
  1724                   }
  1754                   }
  1725                 if (longCaption.isEmpty()){
  1755                 if (longCaption.isEmpty()){
  1726                     fprintf(stderr, "Warning: STRING_r_caption not generated from file '%s'.\n", qPrintable(tsFilename));
  1756                     fprintf(stderr, "Warning: STRING_r_caption not generated from file '%s'.\n", qPrintable(tsFilename));
  1727                     fprintf(stderr, "       : caption generated from target name '#%s'.\n", qPrintable(fixedTarget));
  1757                     fprintf(stderr, "       : caption generated from target name '#%s'.\n", qPrintable(fixedTarget));
  1728                   }
  1758                   }
  1763             PRINT_FILE_CREATE_ERROR(locFilename);	
  1793             PRINT_FILE_CREATE_ERROR(locFilename);	
  1764 	    }
  1794 	    }
  1765     }
  1795     }
  1766 }
  1796 }
  1767 
  1797 
  1768 void SymbianMakefileGenerator::readRssRules(QString &numberOfIcons, QString &iconFile, QStringList &userRssRules)
  1798 void SymbianMakefileGenerator::readRssRules(QString &numberOfIcons,
       
  1799                                             QString &iconFile, QMap<QString,
       
  1800                                             QStringList> &userRssRules)
  1769 {
  1801 {
  1770     for (QMap<QString, QStringList>::iterator it = project->variables().begin(); it != project->variables().end(); ++it) {
  1802     for (QMap<QString, QStringList>::iterator it = project->variables().begin(); it != project->variables().end(); ++it) {
  1771         if (it.key().startsWith(RSS_RULES_BASE)) {
  1803         if (it.key().startsWith(RSS_RULES_BASE)) {
  1772             QString newKey = it.key().mid(sizeof(RSS_RULES_BASE) - 1);
  1804             QString newKey = it.key().mid(sizeof(RSS_RULES_BASE) - 1);
  1773             if (newKey.isEmpty()) {
  1805             if (newKey.isEmpty()) {
  1775                 continue;
  1807                 continue;
  1776             }
  1808             }
  1777             QStringList newValues;
  1809             QStringList newValues;
  1778             QStringList values = it.value();
  1810             QStringList values = it.value();
  1779             foreach(QString item, values) {
  1811             foreach(QString item, values) {
  1780                 // If there is no stringlist defined for a rule, use rule name directly
  1812                 // If there is no stringlist defined for a rule, use rule value directly
  1781                 // This is convenience for defining single line statements
  1813                 // This is convenience for defining single line statements
  1782                 if (project->values(item).isEmpty()) {
  1814                 if (project->values(item).isEmpty()) {
  1783                     newValues << item;
  1815                     newValues << item;
  1784                 } else {
  1816                 } else {
       
  1817                     QStringList itemList;
  1785                     foreach(QString itemRow, project->values(item)) {
  1818                     foreach(QString itemRow, project->values(item)) {
  1786                         newValues << itemRow;
  1819                         itemList << itemRow;
  1787                     }
  1820                     }
       
  1821                     newValues << itemList.join("\n");
  1788                 }
  1822                 }
  1789             }
  1823             }
  1790             // Verify thet there is exactly one value in RSS_TAG_NBROFICONS
  1824             // Verify thet there is exactly one value in RSS_TAG_NBROFICONS
  1791             if (newKey == RSS_TAG_NBROFICONS) {
  1825             if (newKey == RSS_TAG_NBROFICONS) {
  1792                 if (newValues.count() == 1) {
  1826                 if (newValues.count() == 1) {
  1803                 } else {
  1837                 } else {
  1804                     fprintf(stderr, "Warning: There must be exactly one value in '%s%s'\n",
  1838                     fprintf(stderr, "Warning: There must be exactly one value in '%s%s'\n",
  1805                             RSS_RULES_BASE, RSS_TAG_ICONFILE);
  1839                             RSS_RULES_BASE, RSS_TAG_ICONFILE);
  1806                     continue;
  1840                     continue;
  1807                 }
  1841                 }
       
  1842             } else if (newKey == RSS_TAG_HEADER
       
  1843                        || newKey == RSS_TAG_SERVICE_LIST
       
  1844                        || newKey == RSS_TAG_FILE_OWNERSHIP_LIST
       
  1845                        || newKey == RSS_TAG_DATATYPE_LIST
       
  1846                        || newKey == RSS_TAG_FOOTER
       
  1847                        || newKey == RSS_TAG_DEFAULT) {
       
  1848                 userRssRules[newKey] = newValues;
       
  1849                 continue;
  1808             } else {
  1850             } else {
  1809                 fprintf(stderr, "Warning: Unsupported key:'%s%s'\n",
  1851                 fprintf(stderr, "Warning: Unsupported key:'%s%s'\n",
  1810                         RSS_RULES_BASE, newKey.toLatin1().constData());
  1852                         RSS_RULES_BASE, newKey.toLatin1().constData());
  1811                 continue;
  1853                 continue;
  1812             }
  1854             }
  1813         }
  1855         }
  1814     }
  1856     }
  1815 
  1857 
       
  1858     QStringList newValues;
  1816     foreach(QString item, project->values(RSS_RULES)) {
  1859     foreach(QString item, project->values(RSS_RULES)) {
  1817         // If there is no stringlist defined for a rule, use rule name directly
  1860         // If there is no stringlist defined for a rule, use rule value directly
  1818         // This is convenience for defining single line mmp statements
  1861         // This is convenience for defining single line statements
  1819         if (project->values(item).isEmpty()) {
  1862         if (project->values(item).isEmpty()) {
  1820             userRssRules << item;
  1863             newValues << item;
  1821         } else {
  1864         } else {
  1822             userRssRules << project->values(item);
  1865             newValues << project->values(item);
  1823         }
  1866         }
  1824     }
  1867     }
       
  1868     userRssRules[RSS_TAG_DEFAULT] << newValues;
  1825 
  1869 
  1826     // Validate that either both RSS_TAG_NBROFICONS and RSS_TAG_ICONFILE keys exist
  1870     // Validate that either both RSS_TAG_NBROFICONS and RSS_TAG_ICONFILE keys exist
  1827     // or neither of them exist
  1871     // or neither of them exist
  1828     if (!((numberOfIcons.isEmpty() && iconFile.isEmpty()) ||
  1872     if (!((numberOfIcons.isEmpty() && iconFile.isEmpty()) ||
  1829             (!numberOfIcons.isEmpty() && !iconFile.isEmpty()))) {
  1873             (!numberOfIcons.isEmpty() && !iconFile.isEmpty()))) {
  2279         if (platforms.contains("winscw")) {
  2323         if (platforms.contains("winscw")) {
  2280             t << "run:" << endl;
  2324             t << "run:" << endl;
  2281             t << "\t-call " << epocRoot() << "epoc32/release/winscw/udeb/" << fixedTarget << ".exe " << "$(QT_RUN_OPTIONS)" << endl;
  2325             t << "\t-call " << epocRoot() << "epoc32/release/winscw/udeb/" << fixedTarget << ".exe " << "$(QT_RUN_OPTIONS)" << endl;
  2282         }
  2326         }
  2283         t << "runonphone: sis" << endl;
  2327         t << "runonphone: sis" << endl;
  2284         t << "\trunonphone $(QT_RUN_ON_PHONE_OPTIONS) --sis " << fixedTarget << "_$(QT_SIS_TARGET).sis " << fixedTarget << ".exe " << "$(QT_RUN_OPTIONS)" << endl;
  2328         t << "\trunonphone $(QT_RUN_ON_PHONE_OPTIONS) --sis " << fixedTarget << ".sis " << fixedTarget << ".exe " << "$(QT_RUN_OPTIONS)" << endl;
  2285         t << endl;
  2329         t << endl;
  2286     }
  2330     }
  2287 }
  2331 }