qmake/generators/symbian/symmake_sbsv2.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the qmake application of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "symmake_sbsv2.h"
       
    43 #include "initprojectdeploy_symbian.h"
       
    44 
       
    45 #include <qstring.h>
       
    46 #include <qstringlist.h>
       
    47 #include <qdir.h>
       
    48 #include <qdatetime.h>
       
    49 #include <qdebug.h>
       
    50 
       
    51 SymbianSbsv2MakefileGenerator::SymbianSbsv2MakefileGenerator() : SymbianMakefileGenerator() { }
       
    52 SymbianSbsv2MakefileGenerator::~SymbianSbsv2MakefileGenerator() { }
       
    53 
       
    54 #define FLM_DEST_DIR "epoc32/tools/makefile_templates/qt"
       
    55 #define FLM_SOURCE_DIR "/mkspecs/symbian-sbsv2/flm/qt"
       
    56 
       
    57 // Copies Qt FLMs to correct location under epocroot.
       
    58 // This is not done by configure as it is possible to change epocroot after configure.
       
    59 void SymbianSbsv2MakefileGenerator::exportFlm()
       
    60 {
       
    61     static bool flmExportDone = false;
       
    62 
       
    63     if (!flmExportDone) {
       
    64         QDir sourceDir = QDir(QLibraryInfo::location(QLibraryInfo::PrefixPath) + FLM_SOURCE_DIR);
       
    65         QFileInfoList sourceInfos = sourceDir.entryInfoList(QDir::Files);
       
    66 
       
    67         QDir destDir(epocRoot() + FLM_DEST_DIR);
       
    68         if (!destDir.exists()) {
       
    69             if (destDir.mkpath(destDir.absolutePath()))
       
    70                 generatedDirs << destDir.absolutePath();
       
    71         }
       
    72 
       
    73         foreach(QFileInfo item, sourceInfos) {
       
    74             QFileInfo destInfo = QFileInfo(destDir.absolutePath() + "/" + item.fileName());
       
    75             if (!destInfo.exists() || destInfo.lastModified() < item.lastModified()) {
       
    76                 if (destInfo.exists())
       
    77                     QFile::remove(destInfo.absoluteFilePath());
       
    78                 if (QFile::copy(item.absoluteFilePath(), destInfo.absoluteFilePath())) {
       
    79                     if (Option::mkfile::listgen) {
       
    80                         generatePrint(destInfo.absoluteFilePath());
       
    81                     }
       
    82                     generatedFiles << destInfo.absoluteFilePath();
       
    83                 }
       
    84                 else
       
    85                     fprintf(stderr, "Error: Could not copy '%s' -> '%s'\n",
       
    86                             qPrintable(item.absoluteFilePath()),
       
    87                             qPrintable(destInfo.absoluteFilePath()));
       
    88             }
       
    89         }
       
    90         flmExportDone = true;
       
    91     }
       
    92 }
       
    93 
       
    94 void SymbianSbsv2MakefileGenerator::writeMkFile(const QString& wrapperFileName, bool deploymentOnly)
       
    95 {
       
    96     // Can't use extension makefile with sbsv2
       
    97     Q_UNUSED(wrapperFileName);
       
    98     Q_UNUSED(deploymentOnly);
       
    99 }
       
   100 
       
   101 void SymbianSbsv2MakefileGenerator::writeWrapperMakefile(QFile& wrapperFile, bool isPrimaryMakefile)
       
   102 {
       
   103     QStringList allPlatforms;
       
   104     foreach(QString platform, project->values("SYMBIAN_PLATFORMS")) {
       
   105         allPlatforms << platform.toLower();
       
   106     }
       
   107 
       
   108     QStringList debugPlatforms = allPlatforms;
       
   109     QStringList releasePlatforms = allPlatforms;
       
   110     releasePlatforms.removeAll("winscw"); // No release for emulator
       
   111 
       
   112     QString testClause;
       
   113     if (project->values("CONFIG").contains("symbian_test", Qt::CaseInsensitive))
       
   114         testClause = QLatin1String(".test");
       
   115     else
       
   116         testClause = QLatin1String("");
       
   117 
       
   118     QTextStream t(&wrapperFile);
       
   119 
       
   120     t << "# ==============================================================================" << endl;
       
   121     t << "# Generated by qmake (" << qmake_version() << ") (Qt " << QT_VERSION_STR << ") on: ";
       
   122     t << QDateTime::currentDateTime().toString() << endl;
       
   123     t << "# This file is generated by qmake and should not be modified by the" << endl;
       
   124     t << "# user." << endl;
       
   125     t << "#  Name        : " << wrapperFile.fileName() << endl;
       
   126     t << "#  Description : Wrapper Makefile for calling Symbian build tools" << endl;
       
   127     t << "#" << endl;
       
   128     t << "# ==============================================================================" << "\n" << endl;
       
   129     t << endl;
       
   130     t << "MAKEFILE          = " << wrapperFile.fileName() << endl;
       
   131     t << "QMAKE             = " << Option::fixPathToTargetOS(var("QMAKE_QMAKE")) << endl;
       
   132     t << "DEL_FILE          = " << var("QMAKE_DEL_FILE") << endl;
       
   133     t << "DEL_DIR           = " << var("QMAKE_DEL_DIR") << endl;
       
   134     t << "MOVE              = " << var("QMAKE_MOVE") << endl;
       
   135     t << "DEBUG_PLATFORMS   = " << debugPlatforms.join(" ") << endl;
       
   136     t << "RELEASE_PLATFORMS = " << releasePlatforms.join(" ") << endl;
       
   137     t << "MAKE              = make" << endl;
       
   138     t << "SBS               = sbs" << endl;
       
   139     t << endl;
       
   140     t << "DEFINES" << '\t' << " = "
       
   141         << varGlue("PRL_EXPORT_DEFINES","-D"," -D"," ")
       
   142         << varGlue("QMAKE_COMPILER_DEFINES", "-D", "-D", " ")
       
   143         << varGlue("DEFINES","-D"," -D","") << endl;
       
   144 
       
   145     t << "INCPATH" << '\t' << " = ";
       
   146 
       
   147     for (QMap<QString, QStringList>::iterator it = systeminclude.begin(); it != systeminclude.end(); ++it) {
       
   148         QStringList values = it.value();
       
   149         for (int i = 0; i < values.size(); ++i) {
       
   150             t << " -I\"" << values.at(i) << "\" ";
       
   151         }
       
   152     }
       
   153     t << endl;
       
   154     t << "first: default" << endl;
       
   155     if (debugPlatforms.contains("winscw"))
       
   156         t << "default: debug-winscw";
       
   157     else if (debugPlatforms.contains("armv5"))
       
   158         t << "default: debug-armv5";
       
   159     else if (debugPlatforms.size())
       
   160         t << "default: debug-" << debugPlatforms.first();
       
   161     else
       
   162         t << "default: all";
       
   163 
       
   164     t << endl;
       
   165     if (!isPrimaryMakefile) {
       
   166         t << "all:" << endl;
       
   167     } else {
       
   168         t << "all: debug release" << endl;
       
   169         t << endl;
       
   170         t << "qmake:" << endl;
       
   171         t << "\t$(QMAKE) -spec symbian-sbsv2 -o \"" << fileInfo(Option::output.fileName()).fileName()
       
   172           << "\" \"" << project->projectFile() << "\"" << endl;
       
   173         t << endl;
       
   174         t << BLD_INF_FILENAME ":" << endl;
       
   175         t << "\t$(QMAKE)" << endl;
       
   176         t << endl;
       
   177 
       
   178         t << "debug: " << BLD_INF_FILENAME << endl;
       
   179         foreach(QString item, debugPlatforms) {
       
   180             t << "\t$(SBS) -c " << item << "_udeb" << testClause << endl;
       
   181         }
       
   182         t << endl;
       
   183         t << "release: " << BLD_INF_FILENAME << endl;
       
   184         foreach(QString item, releasePlatforms) {
       
   185             t << "\t$(SBS) -c " << item << "_urel" << testClause << endl;
       
   186         }
       
   187         t << endl;
       
   188 
       
   189         // For more specific builds, targets are in this form: build-platform, e.g. release-armv5
       
   190         foreach(QString item, debugPlatforms) {
       
   191             t << "debug-" << item << ": " << BLD_INF_FILENAME << endl;
       
   192             t << "\t$(SBS) -c " << item << "_udeb" << testClause << endl;
       
   193         }
       
   194 
       
   195         foreach(QString item, releasePlatforms) {
       
   196             t << "release-" << item << ": " << BLD_INF_FILENAME << endl;
       
   197             t << "\t$(SBS) -c " << item << "_urel" << testClause << endl;
       
   198         }
       
   199 
       
   200         t << endl;
       
   201         t << "export: " << BLD_INF_FILENAME << endl;
       
   202         t << "\t$(SBS) export" << endl;
       
   203         t << endl;
       
   204 
       
   205         t << "cleanexport: " << BLD_INF_FILENAME << endl;
       
   206         t << "\t$(SBS) cleanexport" << endl;
       
   207         t << endl;
       
   208 
       
   209     }
       
   210 
       
   211     // Add all extra targets including extra compiler targest also to wrapper makefile,
       
   212     // even though many of them may have already been added to bld.inf as FLMs.
       
   213     // This is to enable use of targets like 'mocables', which call targets generated by extra compilers.
       
   214     if (targetType != TypeSubdirs) {
       
   215         t << extraTargetsCache;
       
   216         t << extraCompilersCache;
       
   217     } else {
       
   218         QList<MakefileGenerator::SubTarget*> subtargets = findSubDirsSubTargets();
       
   219         writeSubTargets(t, subtargets, SubTargetSkipDefaultVariables|SubTargetSkipDefaultTargets);
       
   220         qDeleteAll(subtargets);
       
   221     }
       
   222 
       
   223     writeSisTargets(t);
       
   224 
       
   225     generateDistcleanTargets(t);
       
   226 
       
   227     t << "clean: " << BLD_INF_FILENAME << endl;
       
   228     t << "\t-$(SBS) reallyclean" << endl;
       
   229     t << endl;
       
   230 
       
   231     // create execution target
       
   232     if (debugPlatforms.contains("winscw") && targetType == TypeExe) {
       
   233         t << "run:" << endl;
       
   234         t << "\t-call " << epocRoot() << "epoc32/release/winscw/udeb/" << removePathSeparators(escapeFilePath(fileFixify(project->first("TARGET"))).append(".exe")) << endl << endl;
       
   235     }
       
   236 }
       
   237 
       
   238 void SymbianSbsv2MakefileGenerator::writeBldInfExtensionRulesPart(QTextStream& t)
       
   239 {
       
   240     // Makes sure we have needed FLMs in place.
       
   241     exportFlm();
       
   242 
       
   243     // Parse extra compilers data
       
   244     QStringList defines;
       
   245     QStringList incPath;
       
   246 
       
   247     defines << varGlue("PRL_EXPORT_DEFINES","-D"," -D"," ")
       
   248             << varGlue("QMAKE_COMPILER_DEFINES", "-D", "-D", " ")
       
   249             << varGlue("DEFINES","-D"," -D","");
       
   250     for (QMap<QString, QStringList>::iterator it = systeminclude.begin(); it != systeminclude.end(); ++it) {
       
   251         QStringList values = it.value();
       
   252         for (int i = 0; i < values.size(); ++i) {
       
   253             incPath << QLatin1String(" -I\"") + values.at(i) + "\"";
       
   254         }
       
   255     }
       
   256 
       
   257     // Write extra compilers and targets to initialize QMAKE_ET_* variables
       
   258     // Cache results to avoid duplicate calls when creating wrapper makefile
       
   259     QTextStream extraCompilerStream(&extraCompilersCache);
       
   260     QTextStream extraTargetStream(&extraTargetsCache);
       
   261     writeExtraCompilerTargets(extraCompilerStream);
       
   262     writeExtraTargets(extraTargetStream);
       
   263 
       
   264     // Figure out everything the target depends on as we don't want to run extra targets that
       
   265     // are not necessary.
       
   266     QStringList allPreDeps;
       
   267     foreach(QString item, project->values("PRE_TARGETDEPS")) {
       
   268         // Predeps get mangled in windows, so fix them to more sbsv2 friendly format
       
   269 #if defined(Q_OS_WIN)
       
   270         if (item.mid(1, 1) == ":")
       
   271             item = item.mid(0, 1).toUpper().append(item.mid(1)); // Fix drive to uppercase
       
   272 #endif
       
   273         item.replace("\\", "/");
       
   274         allPreDeps << escapeDependencyPath(item);
       
   275     }
       
   276 
       
   277     foreach (QString item, project->values("GENERATED_SOURCES")) {
       
   278         allPreDeps.append(fileInfo(item).absoluteFilePath());
       
   279     }
       
   280 
       
   281     for (QMap<QString, QStringList>::iterator it = sources.begin(); it != sources.end(); ++it) {
       
   282         QString currentSourcePath = it.key();
       
   283         QStringList values = it.value();
       
   284         for (int i = 0; i < values.size(); ++i) {
       
   285             QString sourceFile = currentSourcePath + "/" + values.at(i);
       
   286             QStringList deps = findDependencies(QDir::toNativeSeparators(sourceFile));
       
   287             foreach(QString depItem, deps) {
       
   288                 appendIfnotExist(allPreDeps, fileInfo(depItem).absoluteFilePath());
       
   289             }
       
   290         }
       
   291     }
       
   292 
       
   293     // Write FLM rules for all extra targets and compilers that we depend on to build the target.
       
   294     QStringList extraTargets;
       
   295     extraTargets << project->values("QMAKE_EXTRA_TARGETS") <<  project->values("QMAKE_EXTRA_COMPILERS");
       
   296     foreach(QString item, extraTargets) {
       
   297         foreach(QString targetItem, project->values(QLatin1String("QMAKE_INTERNAL_ET_PARSED_TARGETS.") + item)) {
       
   298             // Make sure targetpath is absolute
       
   299             QString absoluteTarget = fileInfo(targetItem).absoluteFilePath();
       
   300             if (allPreDeps.contains(absoluteTarget)) {
       
   301                 QStringList deps = project->values(QLatin1String("QMAKE_INTERNAL_ET_PARSED_DEPS.") + item + targetItem);
       
   302                 QString commandItem =  project->values(QLatin1String("QMAKE_INTERNAL_ET_PARSED_CMD.") + item + targetItem).join(" ");
       
   303 
       
   304 
       
   305                 // Make sure all deps paths are absolute
       
   306                 QString absoluteDeps;
       
   307                 foreach (QString depItem, deps) {
       
   308                     if (!depItem.isEmpty()) {
       
   309                         absoluteDeps.append(fileInfo(depItem).absoluteFilePath());
       
   310                         absoluteDeps.append(" ");
       
   311                     }
       
   312                 }
       
   313 
       
   314                 t << "START EXTENSION qt/qmake_extra_pre_targetdep" << endl;
       
   315                 t << "OPTION PREDEP_TARGET " << absoluteTarget << endl;
       
   316                 t << "OPTION DEPS " << absoluteDeps << endl;
       
   317 
       
   318                 if (commandItem.indexOf("$(INCPATH)") != -1)
       
   319                     commandItem.replace("$(INCPATH)", incPath.join(" "));
       
   320                 if (commandItem.indexOf("$(DEFINES)") != -1)
       
   321                     commandItem.replace("$(DEFINES)", defines.join(" "));
       
   322 
       
   323                 // Sbsv2 strips all backslashes (even doubles ones) from option parameters, so just replace them with slashes
       
   324                 // Problem: If some command actually needs backslashes for something else than dir separator, we are out of luck...
       
   325                 commandItem.replace("\\", "/");
       
   326                 t << "OPTION COMMAND " << commandItem << endl;
       
   327                 t << "END" << endl;
       
   328             }
       
   329         }
       
   330     }
       
   331 
       
   332     t << endl;
       
   333 
       
   334     // Write winscw deployment rules
       
   335     QString remoteTestPath = epocRoot() + QLatin1String("epoc32/winscw/c/private/") + privateDirUid;
       
   336     DeploymentList depList;
       
   337     initProjectDeploySymbian(project, depList, remoteTestPath, false, QLatin1String("winscw"), QLatin1String("udeb"), generatedDirs, generatedFiles);
       
   338 
       
   339     //:QTP:QTPROD-92 Deployment of plugins requires WINSCW build before ARM build
       
   340     t << "#if defined(WINSCW)" << endl;
       
   341     //write WINSCW deployment
       
   342     writeSbsDeploymentList(depList, t);
       
   343     t << "#else" << endl;
       
   344     //write ARMV5 deployment
       
   345 	remoteTestPath = epocRoot() + QLatin1String("epoc32/data/z/private/") + privateDirUid;
       
   346     depList.clear();
       
   347     generatedDirs.clear();
       
   348     generatedFiles.clear();
       
   349     initProjectDeploySymbian(project, depList, remoteTestPath, false, QLatin1String("armv5"), QLatin1String("urel"), generatedDirs, generatedFiles);
       
   350     writeSbsDeploymentList(depList, t);
       
   351     t << "#endif" << endl;
       
   352     t << endl;
       
   353 
       
   354     // Write post link rules
       
   355     if (!project->isEmpty("QMAKE_POST_LINK")) {
       
   356         t << "START EXTENSION qt/qmake_post_link" << endl;
       
   357         t << "OPTION POST_LINK_CMD " << var("QMAKE_POST_LINK") << endl;
       
   358         t << "OPTION LINK_TARGET " << removePathSeparators(escapeFilePath(fileFixify(project->first("TARGET"))).append(".").append(getTargetExtension())) << endl;
       
   359         t << "END" << endl;
       
   360         t << endl;
       
   361     }
       
   362 
       
   363     // Application icon generation
       
   364     QStringList icons = project->values("ICON");
       
   365     if (icons.size()) {
       
   366         QString icon = icons.first();
       
   367         if (icons.size() > 1)
       
   368             fprintf(stderr, "Warning: Only first icon specified in ICON variable is used: '%s'.", qPrintable(icon));
       
   369 
       
   370         t << "START EXTENSION s60/mifconv" << endl;
       
   371 
       
   372         QFileInfo iconInfo = fileInfo(icon);
       
   373         QString iconPath = iconInfo.path();
       
   374         QString iconFile = iconInfo.baseName();
       
   375 
       
   376         t << "OPTION SOURCES -c32 " << iconFile << endl;
       
   377         t << "OPTION SOURCEDIR " << iconPath << endl;
       
   378         t << "OPTION TARGETFILE " << uid3 << ".mif" << endl;
       
   379         t << "OPTION SVGENCODINGVERSION 3" << endl; // Compatibility with S60 3.1 devices and up
       
   380         t << "END" << endl;
       
   381     }
       
   382 
       
   383     // Generate temp dirs
       
   384     QString tempDirs;
       
   385     for (QMap<QString, QStringList>::iterator it = systeminclude.begin(); it != systeminclude.end(); ++it) {
       
   386         QStringList values = it.value();
       
   387         for (int i = 0; i < values.size(); ++i) {
       
   388             QString value = values.at(i);
       
   389             if (value.endsWith("/" QT_EXTRA_INCLUDE_DIR)) {
       
   390                 value = fileInfo(value).absoluteFilePath();
       
   391                 tempDirs.append(value);
       
   392                 tempDirs.append(" ");
       
   393             }
       
   394         }
       
   395     }
       
   396 
       
   397     if (tempDirs.size())
       
   398         tempDirs.chop(1); // Remove final space
       
   399 
       
   400     t << "START EXTENSION qt/qmake_generate_temp_dirs" << endl;
       
   401     t << "OPTION DIRS " << tempDirs << endl;
       
   402     t << "END" << endl;
       
   403     t << endl;
       
   404 
       
   405     /* :QTP:QTPROD-155: Don't write .make.cache during the compilation, it causes dependency problems in
       
   406      * the parallel build clusters
       
   407     t << "START EXTENSION qt/qmake_store_build" << endl;
       
   408     t << "END" << endl;
       
   409     t << endl;
       
   410     */
       
   411 
       
   412     t << endl;
       
   413 }
       
   414 
       
   415 void SymbianSbsv2MakefileGenerator::writeBldInfMkFilePart(QTextStream& t, bool addDeploymentExtension)
       
   416 {
       
   417     // We don't generate extension makefile in sbsb2
       
   418     Q_UNUSED(t);
       
   419     Q_UNUSED(addDeploymentExtension);
       
   420 }