qmake/generators/symbian/symmake_sbsv2.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/qmake/generators/symbian/symmake_sbsv2.cpp	Mon Jan 11 14:00:40 2010 +0000
@@ -0,0 +1,420 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the qmake application of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "symmake_sbsv2.h"
+#include "initprojectdeploy_symbian.h"
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qdir.h>
+#include <qdatetime.h>
+#include <qdebug.h>
+
+SymbianSbsv2MakefileGenerator::SymbianSbsv2MakefileGenerator() : SymbianMakefileGenerator() { }
+SymbianSbsv2MakefileGenerator::~SymbianSbsv2MakefileGenerator() { }
+
+#define FLM_DEST_DIR "epoc32/tools/makefile_templates/qt"
+#define FLM_SOURCE_DIR "/mkspecs/symbian-sbsv2/flm/qt"
+
+// Copies Qt FLMs to correct location under epocroot.
+// This is not done by configure as it is possible to change epocroot after configure.
+void SymbianSbsv2MakefileGenerator::exportFlm()
+{
+    static bool flmExportDone = false;
+
+    if (!flmExportDone) {
+        QDir sourceDir = QDir(QLibraryInfo::location(QLibraryInfo::PrefixPath) + FLM_SOURCE_DIR);
+        QFileInfoList sourceInfos = sourceDir.entryInfoList(QDir::Files);
+
+        QDir destDir(epocRoot() + FLM_DEST_DIR);
+        if (!destDir.exists()) {
+            if (destDir.mkpath(destDir.absolutePath()))
+                generatedDirs << destDir.absolutePath();
+        }
+
+        foreach(QFileInfo item, sourceInfos) {
+            QFileInfo destInfo = QFileInfo(destDir.absolutePath() + "/" + item.fileName());
+            if (!destInfo.exists() || destInfo.lastModified() < item.lastModified()) {
+                if (destInfo.exists())
+                    QFile::remove(destInfo.absoluteFilePath());
+                if (QFile::copy(item.absoluteFilePath(), destInfo.absoluteFilePath())) {
+                    if (Option::mkfile::listgen) {
+                        generatePrint(destInfo.absoluteFilePath());
+                    }
+                    generatedFiles << destInfo.absoluteFilePath();
+                }
+                else
+                    fprintf(stderr, "Error: Could not copy '%s' -> '%s'\n",
+                            qPrintable(item.absoluteFilePath()),
+                            qPrintable(destInfo.absoluteFilePath()));
+            }
+        }
+        flmExportDone = true;
+    }
+}
+
+void SymbianSbsv2MakefileGenerator::writeMkFile(const QString& wrapperFileName, bool deploymentOnly)
+{
+    // Can't use extension makefile with sbsv2
+    Q_UNUSED(wrapperFileName);
+    Q_UNUSED(deploymentOnly);
+}
+
+void SymbianSbsv2MakefileGenerator::writeWrapperMakefile(QFile& wrapperFile, bool isPrimaryMakefile)
+{
+    QStringList allPlatforms;
+    foreach(QString platform, project->values("SYMBIAN_PLATFORMS")) {
+        allPlatforms << platform.toLower();
+    }
+
+    QStringList debugPlatforms = allPlatforms;
+    QStringList releasePlatforms = allPlatforms;
+    releasePlatforms.removeAll("winscw"); // No release for emulator
+
+    QString testClause;
+    if (project->values("CONFIG").contains("symbian_test", Qt::CaseInsensitive))
+        testClause = QLatin1String(".test");
+    else
+        testClause = QLatin1String("");
+
+    QTextStream t(&wrapperFile);
+
+    t << "# ==============================================================================" << endl;
+    t << "# Generated by qmake (" << qmake_version() << ") (Qt " << QT_VERSION_STR << ") on: ";
+    t << QDateTime::currentDateTime().toString() << endl;
+    t << "# This file is generated by qmake and should not be modified by the" << endl;
+    t << "# user." << endl;
+    t << "#  Name        : " << wrapperFile.fileName() << endl;
+    t << "#  Description : Wrapper Makefile for calling Symbian build tools" << endl;
+    t << "#" << endl;
+    t << "# ==============================================================================" << "\n" << endl;
+    t << endl;
+    t << "MAKEFILE          = " << wrapperFile.fileName() << endl;
+    t << "QMAKE             = " << Option::fixPathToTargetOS(var("QMAKE_QMAKE")) << endl;
+    t << "DEL_FILE          = " << var("QMAKE_DEL_FILE") << endl;
+    t << "DEL_DIR           = " << var("QMAKE_DEL_DIR") << endl;
+    t << "MOVE              = " << var("QMAKE_MOVE") << endl;
+    t << "DEBUG_PLATFORMS   = " << debugPlatforms.join(" ") << endl;
+    t << "RELEASE_PLATFORMS = " << releasePlatforms.join(" ") << endl;
+    t << "MAKE              = make" << endl;
+    t << "SBS               = sbs" << endl;
+    t << endl;
+    t << "DEFINES" << '\t' << " = "
+        << varGlue("PRL_EXPORT_DEFINES","-D"," -D"," ")
+        << varGlue("QMAKE_COMPILER_DEFINES", "-D", "-D", " ")
+        << varGlue("DEFINES","-D"," -D","") << endl;
+
+    t << "INCPATH" << '\t' << " = ";
+
+    for (QMap<QString, QStringList>::iterator it = systeminclude.begin(); it != systeminclude.end(); ++it) {
+        QStringList values = it.value();
+        for (int i = 0; i < values.size(); ++i) {
+            t << " -I\"" << values.at(i) << "\" ";
+        }
+    }
+    t << endl;
+    t << "first: default" << endl;
+    if (debugPlatforms.contains("winscw"))
+        t << "default: debug-winscw";
+    else if (debugPlatforms.contains("armv5"))
+        t << "default: debug-armv5";
+    else if (debugPlatforms.size())
+        t << "default: debug-" << debugPlatforms.first();
+    else
+        t << "default: all";
+
+    t << endl;
+    if (!isPrimaryMakefile) {
+        t << "all:" << endl;
+    } else {
+        t << "all: debug release" << endl;
+        t << endl;
+        t << "qmake:" << endl;
+        t << "\t$(QMAKE) -spec symbian-sbsv2 -o \"" << fileInfo(Option::output.fileName()).fileName()
+          << "\" \"" << project->projectFile() << "\"" << endl;
+        t << endl;
+        t << BLD_INF_FILENAME ":" << endl;
+        t << "\t$(QMAKE)" << endl;
+        t << endl;
+
+        t << "debug: " << BLD_INF_FILENAME << endl;
+        foreach(QString item, debugPlatforms) {
+            t << "\t$(SBS) -c " << item << "_udeb" << testClause << endl;
+        }
+        t << endl;
+        t << "release: " << BLD_INF_FILENAME << endl;
+        foreach(QString item, releasePlatforms) {
+            t << "\t$(SBS) -c " << item << "_urel" << testClause << endl;
+        }
+        t << endl;
+
+        // For more specific builds, targets are in this form: build-platform, e.g. release-armv5
+        foreach(QString item, debugPlatforms) {
+            t << "debug-" << item << ": " << BLD_INF_FILENAME << endl;
+            t << "\t$(SBS) -c " << item << "_udeb" << testClause << endl;
+        }
+
+        foreach(QString item, releasePlatforms) {
+            t << "release-" << item << ": " << BLD_INF_FILENAME << endl;
+            t << "\t$(SBS) -c " << item << "_urel" << testClause << endl;
+        }
+
+        t << endl;
+        t << "export: " << BLD_INF_FILENAME << endl;
+        t << "\t$(SBS) export" << endl;
+        t << endl;
+
+        t << "cleanexport: " << BLD_INF_FILENAME << endl;
+        t << "\t$(SBS) cleanexport" << endl;
+        t << endl;
+
+    }
+
+    // Add all extra targets including extra compiler targest also to wrapper makefile,
+    // even though many of them may have already been added to bld.inf as FLMs.
+    // This is to enable use of targets like 'mocables', which call targets generated by extra compilers.
+    if (targetType != TypeSubdirs) {
+        t << extraTargetsCache;
+        t << extraCompilersCache;
+    } else {
+        QList<MakefileGenerator::SubTarget*> subtargets = findSubDirsSubTargets();
+        writeSubTargets(t, subtargets, SubTargetSkipDefaultVariables|SubTargetSkipDefaultTargets);
+        qDeleteAll(subtargets);
+    }
+
+    writeSisTargets(t);
+
+    generateDistcleanTargets(t);
+
+    t << "clean: " << BLD_INF_FILENAME << endl;
+    t << "\t-$(SBS) reallyclean" << endl;
+    t << endl;
+
+    // create execution target
+    if (debugPlatforms.contains("winscw") && targetType == TypeExe) {
+        t << "run:" << endl;
+        t << "\t-call " << epocRoot() << "epoc32/release/winscw/udeb/" << removePathSeparators(escapeFilePath(fileFixify(project->first("TARGET"))).append(".exe")) << endl << endl;
+    }
+}
+
+void SymbianSbsv2MakefileGenerator::writeBldInfExtensionRulesPart(QTextStream& t)
+{
+    // Makes sure we have needed FLMs in place.
+    exportFlm();
+
+    // Parse extra compilers data
+    QStringList defines;
+    QStringList incPath;
+
+    defines << varGlue("PRL_EXPORT_DEFINES","-D"," -D"," ")
+            << varGlue("QMAKE_COMPILER_DEFINES", "-D", "-D", " ")
+            << varGlue("DEFINES","-D"," -D","");
+    for (QMap<QString, QStringList>::iterator it = systeminclude.begin(); it != systeminclude.end(); ++it) {
+        QStringList values = it.value();
+        for (int i = 0; i < values.size(); ++i) {
+            incPath << QLatin1String(" -I\"") + values.at(i) + "\"";
+        }
+    }
+
+    // Write extra compilers and targets to initialize QMAKE_ET_* variables
+    // Cache results to avoid duplicate calls when creating wrapper makefile
+    QTextStream extraCompilerStream(&extraCompilersCache);
+    QTextStream extraTargetStream(&extraTargetsCache);
+    writeExtraCompilerTargets(extraCompilerStream);
+    writeExtraTargets(extraTargetStream);
+
+    // Figure out everything the target depends on as we don't want to run extra targets that
+    // are not necessary.
+    QStringList allPreDeps;
+    foreach(QString item, project->values("PRE_TARGETDEPS")) {
+        // Predeps get mangled in windows, so fix them to more sbsv2 friendly format
+#if defined(Q_OS_WIN)
+        if (item.mid(1, 1) == ":")
+            item = item.mid(0, 1).toUpper().append(item.mid(1)); // Fix drive to uppercase
+#endif
+        item.replace("\\", "/");
+        allPreDeps << escapeDependencyPath(item);
+    }
+
+    foreach (QString item, project->values("GENERATED_SOURCES")) {
+        allPreDeps.append(fileInfo(item).absoluteFilePath());
+    }
+
+    for (QMap<QString, QStringList>::iterator it = sources.begin(); it != sources.end(); ++it) {
+        QString currentSourcePath = it.key();
+        QStringList values = it.value();
+        for (int i = 0; i < values.size(); ++i) {
+            QString sourceFile = currentSourcePath + "/" + values.at(i);
+            QStringList deps = findDependencies(QDir::toNativeSeparators(sourceFile));
+            foreach(QString depItem, deps) {
+                appendIfnotExist(allPreDeps, fileInfo(depItem).absoluteFilePath());
+            }
+        }
+    }
+
+    // Write FLM rules for all extra targets and compilers that we depend on to build the target.
+    QStringList extraTargets;
+    extraTargets << project->values("QMAKE_EXTRA_TARGETS") <<  project->values("QMAKE_EXTRA_COMPILERS");
+    foreach(QString item, extraTargets) {
+        foreach(QString targetItem, project->values(QLatin1String("QMAKE_INTERNAL_ET_PARSED_TARGETS.") + item)) {
+            // Make sure targetpath is absolute
+            QString absoluteTarget = fileInfo(targetItem).absoluteFilePath();
+            if (allPreDeps.contains(absoluteTarget)) {
+                QStringList deps = project->values(QLatin1String("QMAKE_INTERNAL_ET_PARSED_DEPS.") + item + targetItem);
+                QString commandItem =  project->values(QLatin1String("QMAKE_INTERNAL_ET_PARSED_CMD.") + item + targetItem).join(" ");
+
+
+                // Make sure all deps paths are absolute
+                QString absoluteDeps;
+                foreach (QString depItem, deps) {
+                    if (!depItem.isEmpty()) {
+                        absoluteDeps.append(fileInfo(depItem).absoluteFilePath());
+                        absoluteDeps.append(" ");
+                    }
+                }
+
+                t << "START EXTENSION qt/qmake_extra_pre_targetdep" << endl;
+                t << "OPTION PREDEP_TARGET " << absoluteTarget << endl;
+                t << "OPTION DEPS " << absoluteDeps << endl;
+
+                if (commandItem.indexOf("$(INCPATH)") != -1)
+                    commandItem.replace("$(INCPATH)", incPath.join(" "));
+                if (commandItem.indexOf("$(DEFINES)") != -1)
+                    commandItem.replace("$(DEFINES)", defines.join(" "));
+
+                // Sbsv2 strips all backslashes (even doubles ones) from option parameters, so just replace them with slashes
+                // Problem: If some command actually needs backslashes for something else than dir separator, we are out of luck...
+                commandItem.replace("\\", "/");
+                t << "OPTION COMMAND " << commandItem << endl;
+                t << "END" << endl;
+            }
+        }
+    }
+
+    t << endl;
+
+    // Write winscw deployment rules
+    QString remoteTestPath = epocRoot() + QLatin1String("epoc32/winscw/c/private/") + privateDirUid;
+    DeploymentList depList;
+    initProjectDeploySymbian(project, depList, remoteTestPath, false, QLatin1String("winscw"), QLatin1String("udeb"), generatedDirs, generatedFiles);
+
+    //:QTP:QTPROD-92 Deployment of plugins requires WINSCW build before ARM build
+    t << "#if defined(WINSCW)" << endl;
+    //write WINSCW deployment
+    writeSbsDeploymentList(depList, t);
+    t << "#else" << endl;
+    //write ARMV5 deployment
+	remoteTestPath = epocRoot() + QLatin1String("epoc32/data/z/private/") + privateDirUid;
+    depList.clear();
+    generatedDirs.clear();
+    generatedFiles.clear();
+    initProjectDeploySymbian(project, depList, remoteTestPath, false, QLatin1String("armv5"), QLatin1String("urel"), generatedDirs, generatedFiles);
+    writeSbsDeploymentList(depList, t);
+    t << "#endif" << endl;
+    t << endl;
+
+    // Write post link rules
+    if (!project->isEmpty("QMAKE_POST_LINK")) {
+        t << "START EXTENSION qt/qmake_post_link" << endl;
+        t << "OPTION POST_LINK_CMD " << var("QMAKE_POST_LINK") << endl;
+        t << "OPTION LINK_TARGET " << removePathSeparators(escapeFilePath(fileFixify(project->first("TARGET"))).append(".").append(getTargetExtension())) << endl;
+        t << "END" << endl;
+        t << endl;
+    }
+
+    // Application icon generation
+    QStringList icons = project->values("ICON");
+    if (icons.size()) {
+        QString icon = icons.first();
+        if (icons.size() > 1)
+            fprintf(stderr, "Warning: Only first icon specified in ICON variable is used: '%s'.", qPrintable(icon));
+
+        t << "START EXTENSION s60/mifconv" << endl;
+
+        QFileInfo iconInfo = fileInfo(icon);
+        QString iconPath = iconInfo.path();
+        QString iconFile = iconInfo.baseName();
+
+        t << "OPTION SOURCES -c32 " << iconFile << endl;
+        t << "OPTION SOURCEDIR " << iconPath << endl;
+        t << "OPTION TARGETFILE " << uid3 << ".mif" << endl;
+        t << "OPTION SVGENCODINGVERSION 3" << endl; // Compatibility with S60 3.1 devices and up
+        t << "END" << endl;
+    }
+
+    // Generate temp dirs
+    QString tempDirs;
+    for (QMap<QString, QStringList>::iterator it = systeminclude.begin(); it != systeminclude.end(); ++it) {
+        QStringList values = it.value();
+        for (int i = 0; i < values.size(); ++i) {
+            QString value = values.at(i);
+            if (value.endsWith("/" QT_EXTRA_INCLUDE_DIR)) {
+                value = fileInfo(value).absoluteFilePath();
+                tempDirs.append(value);
+                tempDirs.append(" ");
+            }
+        }
+    }
+
+    if (tempDirs.size())
+        tempDirs.chop(1); // Remove final space
+
+    t << "START EXTENSION qt/qmake_generate_temp_dirs" << endl;
+    t << "OPTION DIRS " << tempDirs << endl;
+    t << "END" << endl;
+    t << endl;
+
+    /* :QTP:QTPROD-155: Don't write .make.cache during the compilation, it causes dependency problems in
+     * the parallel build clusters
+    t << "START EXTENSION qt/qmake_store_build" << endl;
+    t << "END" << endl;
+    t << endl;
+    */
+
+    t << endl;
+}
+
+void SymbianSbsv2MakefileGenerator::writeBldInfMkFilePart(QTextStream& t, bool addDeploymentExtension)
+{
+    // We don't generate extension makefile in sbsb2
+    Q_UNUSED(t);
+    Q_UNUSED(addDeploymentExtension);
+}