diff options
Diffstat (limited to 'qmake/generators/symbian/symmake_sbsv2.cpp')
-rw-r--r-- | qmake/generators/symbian/symmake_sbsv2.cpp | 408 |
1 files changed, 408 insertions, 0 deletions
diff --git a/qmake/generators/symbian/symmake_sbsv2.cpp b/qmake/generators/symbian/symmake_sbsv2.cpp new file mode 100644 index 0000000..2a15ee5 --- /dev/null +++ b/qmake/generators/symbian/symmake_sbsv2.cpp @@ -0,0 +1,408 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_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())) + generatedFiles << destInfo.absoluteFilePath(); + else + fprintf(stderr, "Error: Could not copy '%s' -> '%s'\n", qPrintable(item.absoluteFilePath()), qPrintable(destInfo.absoluteFilePath())); + } + } + flmExportDone = true; + } +} + +bool SymbianSbsv2MakefileGenerator::writeMkFile(const QString& wrapperFileName, bool deploymentOnly) +{ + // Can't use extension makefile with sbsv2 + Q_UNUSED(wrapperFileName); + Q_UNUSED(deploymentOnly); + return true; +} + +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 +#if !defined(Q_OS_WIN) + debugPlatforms.removeAll("winscw"); // Winscw is only for windows +#endif + + bool isSubdirs = getTargetExtension() == "subdirs"; + + 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 << "QMAKE = " << Option::fixPathToTargetOS(var("QMAKE_QMAKE")) << endl; + t << "DEL_FILE = " << var("QMAKE_DEL_FILE") << endl; + t << "DEL_DIR = " << var("QMAKE_DEL_DIR") << 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. + t << extraTargetsCache; + + if (!isSubdirs) { + t << extraCompilersCache; + } + + t << "dodistclean:" << endl; + foreach(QString item, project->values("SUBDIRS")) { + bool fromFile = false; + QString fixedItem; + if(!project->isEmpty(item + ".file")) { + fixedItem = project->first(item + ".file"); + fromFile = true; + } else if(!project->isEmpty(item + ".subdir")) { + fixedItem = project->first(item + ".subdir"); + fromFile = false; + } else { + fromFile = item.endsWith(Option::pro_ext); + fixedItem = item; + } + QFileInfo fi(fileInfo(fixedItem)); + if (!fromFile) { + t << "\t-$(MAKE) -f \"" << Option::fixPathToTargetOS(fi.absoluteFilePath() + "/Makefile") << "\" dodistclean" << endl; + } else { + QString itemName = fi.fileName(); + int extIndex = itemName.lastIndexOf(Option::pro_ext); + if (extIndex) + fixedItem = fi.absolutePath() + "/" + QString("Makefile.") + itemName.mid(0,extIndex); + t << "\t-$(MAKE) -f \"" << Option::fixPathToTargetOS(fixedItem) << "\" dodistclean" << endl; + } + + } + + generatedFiles << Option::fixPathToTargetOS(fileInfo(Option::output.fileName()).absoluteFilePath()); // bld.inf + generatedFiles << project->values("QMAKE_INTERNAL_PRL_FILE"); // Add generated prl files for cleanup + generatedFiles << project->values("QMAKE_DISTCLEAN"); // Add any additional files marked for distclean + QStringList fixedFiles; + QStringList fixedDirs; + foreach(QString item, generatedFiles) { + QString fixedItem = Option::fixPathToTargetOS(fileInfo(item).absoluteFilePath()); + if (!fixedFiles.contains(fixedItem)) { + fixedFiles << fixedItem; + } + } + foreach(QString item, generatedDirs) { + QString fixedItem = Option::fixPathToTargetOS(fileInfo(item).absoluteFilePath()); + if (!fixedDirs.contains(fixedItem)) { + fixedDirs << fixedItem; + } + } + generateCleanCommands(t, fixedFiles, "$(DEL_FILE)", "", "", ""); + generateCleanCommands(t, fixedDirs, "$(DEL_DIR)", "", "", ""); + t << endl; + + t << "distclean: clean dodistclean" << endl; + t << endl; + t << "clean: " << BLD_INF_FILENAME << endl; + t << "\t-$(SBS) reallyclean" << endl; + t << endl; + + // create execution target + if (debugPlatforms.contains("winscw") && getTargetExtension() == "exe") { + t << "run:" << endl; + t << "\t-call " << epocRoot() << "epoc32/release/winscw/udeb/" << removePathSeparators(escapeFilePath(fileFixify(project->first("TARGET"))).append(".exe")) << endl << endl; + } +} + +bool 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_ET_PARSED_TARGETS.") + item)) { + // Make sure targetpath is absolute + QString absoluteTarget = fileInfo(targetItem).absoluteFilePath(); + if (allPreDeps.contains(absoluteTarget)) { + QStringList deps = project->values(QLatin1String("QMAKE_ET_PARSED_DEPS.") + item + targetItem); + //QString depsItem = project->values(QLatin1String("QMAKE_ET_PARSED_DEPS.") + item + targetItem).join(" "); + QString commandItem = project->values(QLatin1String("QMAKE_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; + //t << "OPTION DEPS " << depsItem << 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; + +#if defined(Q_OS_WIN) + // 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 ); + + for (int i=0; i<depList.size(); ++i) { + t << "START EXTENSION qt/qmake_emulator_deployment" << endl; + QString fromItem = depList.at(i).from; + QString toItem = depList.at(i).to; + fromItem.replace("\\", "/"); + toItem.replace("\\", "/"); + t << "OPTION DEPLOY_SOURCE " << fromItem << endl; + t << "OPTION DEPLOY_TARGET " << toItem << endl; + t << "END" << endl; + } + + t << endl; +#endif + + // ### TODO: Linux emulator (platsim?) deployment + + // 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'.", 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 << "END" << endl; + } + + t << endl; + + return true; +} + +void SymbianSbsv2MakefileGenerator::writeBldInfMkFilePart(QTextStream& t, bool addDeploymentExtension) +{ + // We don't generate extension makefile in sbsb2 + Q_UNUSED(t); + Q_UNUSED(addDeploymentExtension); +} + |