--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/qmake/generators/symbian/initprojectdeploy_symbian.cpp Mon Jan 11 14:00:40 2010 +0000
@@ -0,0 +1,410 @@
+/****************************************************************************
+**
+** 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 "initprojectdeploy_symbian.h"
+#include <QDirIterator>
+#include <project.h>
+#include <qxmlstream.h>
+#include <qsettings.h>
+#include <qdebug.h>
+
+#define PLUGIN_STUB_DIR "qmakepluginstubs"
+#define SYSBIN_DIR "\\sys\\bin"
+
+#define SUFFIX_DLL "dll"
+#define SUFFIX_EXE "exe"
+#define SUFFIX_QTPLUGIN "qtplugin"
+
+static void fixEpocRootStr(QString& path)
+{
+ path.replace("\\", "/");
+
+ /* :QTP:QTPROD-154: Raptor needs the drive letter
+ if (path.size() > 1 && path[1] == QChar(':')) {
+ path = path.mid(2);
+ }
+ */
+
+ if (!path.size() || path[path.size()-1] != QChar('/')) {
+ path += QChar('/');
+ }
+}
+
+#define SYMBIAN_SDKS_KEY "HKEY_LOCAL_MACHINE\\Software\\Symbian\\EPOC SDKs"
+
+static QString epocRootStr;
+
+QString epocRoot()
+{
+ if (!epocRootStr.isEmpty()) {
+ return epocRootStr;
+ }
+
+ // First, check the env variable
+ epocRootStr = qgetenv("EPOCROOT");
+
+ if (epocRootStr.isEmpty()) {
+ // No EPOCROOT set, check the default device
+ // First check EPOCDEVICE env variable
+ QString defaultDevice = qgetenv("EPOCDEVICE");
+
+ // Check the windows registry via QSettings for devices.xml path
+ QSettings settings(SYMBIAN_SDKS_KEY, QSettings::NativeFormat);
+ QString devicesXmlPath = settings.value("CommonPath").toString();
+
+ if (!devicesXmlPath.isEmpty()) {
+ // Parse xml for correct device
+ devicesXmlPath += "/devices.xml";
+ QFile devicesFile(devicesXmlPath);
+ if (devicesFile.open(QIODevice::ReadOnly)) {
+ QXmlStreamReader xml(&devicesFile);
+ while (!xml.atEnd()) {
+ xml.readNext();
+ if (xml.isStartElement() && xml.name() == "devices") {
+ if (xml.attributes().value("version") == "1.0") {
+ // Look for correct device
+ while (!(xml.isEndElement() && xml.name() == "devices") && !xml.atEnd()) {
+ xml.readNext();
+ if (xml.isStartElement() && xml.name() == "device") {
+ if ((defaultDevice.isEmpty() && xml.attributes().value("default") == "yes") ||
+ (!defaultDevice.isEmpty() && (xml.attributes().value("id").toString() + QString(":") + xml.attributes().value("name").toString()) == defaultDevice)) {
+ // Found the correct device
+ while (!(xml.isEndElement() && xml.name() == "device") && !xml.atEnd()) {
+ xml.readNext();
+ if (xml.isStartElement() && xml.name() == "epocroot") {
+ epocRootStr = xml.readElementText();
+ fixEpocRootStr(epocRootStr);
+ return epocRootStr;
+ }
+ }
+ xml.raiseError("No epocroot element found");
+ }
+ }
+ }
+ } else {
+ xml.raiseError("Invalid 'devices' element version");
+ }
+ }
+ }
+ if (xml.hasError()) {
+ fprintf(stderr, "ERROR: \"%s\" when parsing devices.xml\n", qPrintable(xml.errorString()));
+ }
+ } else {
+ fprintf(stderr, "Could not open devices.xml (%s)\n", qPrintable(devicesXmlPath));
+ }
+ } else {
+ fprintf(stderr, "Could not retrieve " SYMBIAN_SDKS_KEY " setting\n");
+ }
+
+ fprintf(stderr, "Failed to determine epoc root.\n");
+ if (!defaultDevice.isEmpty())
+ fprintf(stderr, "The device indicated by EPOCDEVICE environment variable (%s) could not be found.\n", qPrintable(defaultDevice));
+ fprintf(stderr, "Either set EPOCROOT or EPOCDEVICE environment variable to a valid value, or provide a default Symbian device.\n");
+
+ // No valid device found; set epocroot to "/"
+ epocRootStr = QLatin1String("/");
+ }
+
+ fixEpocRootStr(epocRootStr);
+ return epocRootStr;
+}
+
+
+static bool isPlugin(const QFileInfo& info, const QString& devicePath)
+{
+ // Libraries are plugins if deployment path is something else than
+ // SYSBIN_DIR with or without drive letter
+ if (0 == info.suffix().compare(QLatin1String(SUFFIX_DLL), Qt::CaseInsensitive) &&
+ (devicePath.size() < 8 ||
+ (0 != devicePath.compare(QLatin1String(SYSBIN_DIR), Qt::CaseInsensitive) &&
+ 0 != devicePath.mid(1).compare(QLatin1String(":" SYSBIN_DIR), Qt::CaseInsensitive)))) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+static bool isBinary(const QFileInfo& info)
+{
+ if (0 == info.suffix().compare(QLatin1String(SUFFIX_DLL), Qt::CaseInsensitive) ||
+ 0 == info.suffix().compare(QLatin1String(SUFFIX_EXE), Qt::CaseInsensitive)) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+static void createPluginStub(const QFileInfo& info,
+ const QString& devicePath,
+ DeploymentList &deploymentList,
+ QStringList& generatedDirs,
+ QStringList& generatedFiles)
+{
+ QDir().mkpath(QLatin1String(PLUGIN_STUB_DIR "\\"));
+ if (!generatedDirs.contains(PLUGIN_STUB_DIR))
+ generatedDirs << PLUGIN_STUB_DIR;
+ // Plugin stubs must have different name from the actual plugins, because
+ // the toolchain for creating ROM images cannot handle non-binary .dll files properly.
+ QFile stubFile(QLatin1String(PLUGIN_STUB_DIR "\\") + info.completeBaseName() + "." SUFFIX_QTPLUGIN);
+ if (stubFile.open(QIODevice::WriteOnly)) {
+ if (!generatedFiles.contains(stubFile.fileName()))
+ generatedFiles << stubFile.fileName();
+ QTextStream t(&stubFile);
+ // Add note to stub so that people will not wonder what it is.
+ // Creation date is added to make new stub to deploy always to
+ // force plugin cache miss when loading plugins.
+ t << "This file is a Qt plugin stub file. The real Qt plugin is located in " SYSBIN_DIR ". Created:" << QDateTime::currentDateTime().toString(Qt::ISODate) << "\n";
+ } else {
+ fprintf(stderr, "cannot deploy \"%s\" because of plugin stub file creation failed\n", info.fileName().toLatin1().constData());
+ }
+ QFileInfo stubInfo(stubFile);
+ deploymentList.append(CopyItem(Option::fixPathToLocalOS(stubInfo.absoluteFilePath()),
+ Option::fixPathToLocalOS(devicePath + "\\" + stubInfo.fileName())));
+}
+
+QString generate_uid(const QString& target)
+{
+ static QMap<QString, QString> targetToUid;
+
+ QString tmp = targetToUid[target];
+
+ if (!tmp.isEmpty()) {
+ return tmp;
+ }
+
+ unsigned long hash = 5381;
+ int c;
+
+ for (int i = 0; i < target.size(); ++i) {
+ c = target.at(i).toAscii();
+ hash ^= c + ((c - i) << i % 20) + ((c + i) << (i + 5) % 20) + ((c - 2 * i) << (i + 10) % 20) + ((c + 2 * i) << (i + 15) % 20);
+ }
+
+ tmp.setNum(hash, 16);
+ for (int i = tmp.size(); i < 8; ++i)
+ tmp.prepend("0");
+
+ targetToUid[target] = tmp;
+
+ return tmp;
+}
+
+// UIDs starting with 0xE are test UIDs in symbian
+QString generate_test_uid(const QString& target)
+{
+ QString tmp = generate_uid(target);
+ tmp.replace(0, 1, "E");
+ tmp.prepend("0x");
+
+ return tmp;
+}
+
+
+void initProjectDeploySymbian(QMakeProject* project,
+ DeploymentList &deploymentList,
+ const QString &testPath,
+ bool deployBinaries,
+ const QString &platform,
+ const QString &build,
+ QStringList& generatedDirs,
+ QStringList& generatedFiles)
+{
+ QString targetPath = project->values("deploy.path").join(" ");
+ if (targetPath.isEmpty())
+ targetPath = testPath;
+ if (targetPath.endsWith("/") || targetPath.endsWith("\\"))
+ targetPath = targetPath.mid(0, targetPath.size() - 1);
+
+ bool targetPathHasDriveLetter = false;
+ if (targetPath.size() > 1) {
+ targetPathHasDriveLetter = targetPath.at(1) == QLatin1Char(':');
+ }
+ QString deploymentDrive = targetPathHasDriveLetter ? targetPath.left(2) : QLatin1String("c:");
+
+ foreach(QString item, project->values("DEPLOYMENT")) {
+ QString devicePath = project->first(item + ".path");
+ if (!deployBinaries
+ && !devicePath.isEmpty()
+ && (0 == devicePath.compare(project->values("APP_RESOURCE_DIR").join(""), Qt::CaseInsensitive)
+ || 0 == devicePath.compare(project->values("REG_RESOURCE_IMPORT_DIR").join(""), Qt::CaseInsensitive))) {
+ // Do not deploy resources in emulator builds, as that seems to cause conflicts
+ // If there is ever a real need to deploy pre-built resources for emulator,
+ // BLD_INF_RULES.prj_exports can be used as a workaround.
+ continue;
+ }
+
+ bool devicePathHasDriveLetter = false;
+ if (devicePath.size() > 1) {
+ devicePathHasDriveLetter = devicePath.at(1) == QLatin1Char(':');
+ }
+
+ if (devicePath.isEmpty() || devicePath == QLatin1String(".")) {
+ devicePath = targetPath;
+ }
+ // check if item.path is relative (! either / or \)
+ else if (!(devicePath.at(0) == QLatin1Char('/')
+ || devicePath.at(0) == QLatin1Char('\\')
+ || devicePathHasDriveLetter)) {
+ // create output path
+ devicePath = Option::fixPathToLocalOS(QDir::cleanPath(targetPath + QLatin1Char('\\') + devicePath));
+ } else {
+ if (0 == platform.compare(QLatin1String("winscw"), Qt::CaseInsensitive)) {
+ if (devicePathHasDriveLetter) {
+ devicePath = epocRoot() + "epoc32\\winscw\\" + devicePath.remove(1, 1);
+ } else {
+ devicePath = epocRoot() + "epoc32\\winscw\\c" + devicePath;
+ }
+ } else {
+ // Drive letter needed if targetpath contains one and it is not already in
+ //:QTP:QTPROD-92 Deployment of plugins requires WINSCW build before ARM build
+ if (targetPathHasDriveLetter && !devicePathHasDriveLetter) {
+ //temporary fix for Raptor building for plugins
+ if (devicePath.indexOf("plugins", Qt::CaseInsensitive) != -1) {
+ devicePath = deploymentDrive + "\\epoc32\\data\\z" + devicePath;
+ } else {
+ devicePath = deploymentDrive + devicePath;
+ }
+ } else {
+ devicePath = epocRoot() + "epoc32\\data\\z" + devicePath;
+ }
+ }
+ }
+
+ devicePath.replace(QLatin1String("/"), QLatin1String("\\"));
+
+ if (!deployBinaries &&
+ 0 == devicePath.right(8).compare(QLatin1String(SYSBIN_DIR), Qt::CaseInsensitive)) {
+ // Skip deploying to SYSBIN_DIR for anything but binary deployments
+ // Note: Deploying pre-built binaries also follow this rule, so emulator builds
+ // will not get those deployed. Since there is no way to differentiate currently
+ // between pre-built binaries for emulator and HW anyway, this is not a major issue.
+ continue;
+ }
+
+ foreach(QString source, project->values(item + ".sources")) {
+ source = Option::fixPathToLocalOS(source);
+ QString nameFilter;
+ QFileInfo info(source);
+ QString searchPath;
+ bool dirSearch = false;
+
+ if (info.isDir()) {
+ nameFilter = QLatin1String("*");
+ searchPath = info.absoluteFilePath();
+ dirSearch = true;
+ } else {
+ if (info.exists() || source.indexOf('*') != -1) {
+ nameFilter = source.split('\\').last();
+ searchPath = info.absolutePath();
+ } else {
+ // Entry was not found. That is ok if it is a binary, since those do not necessarily yet exist.
+ // Dlls need to be processed even when not deploying binaries for the stubs
+ if (isBinary(info)) {
+ if (deployBinaries) {
+ // Executables and libraries are deployed to \sys\bin
+ QFileInfo releasePath(epocRoot() + "epoc32\\release\\" + platform + "\\" + build + "\\");
+ if(devicePathHasDriveLetter) {
+ deploymentList.append(CopyItem(Option::fixPathToLocalOS(releasePath.absolutePath() + "\\" + info.fileName(), false, true),
+ Option::fixPathToLocalOS(devicePath.left(2) + QLatin1String(SYSBIN_DIR "\\") + info.fileName())));
+ } else {
+ deploymentList.append(CopyItem(Option::fixPathToLocalOS(releasePath.absolutePath() + "\\" + info.fileName(), false, true),
+ Option::fixPathToLocalOS(deploymentDrive + QLatin1String(SYSBIN_DIR "\\") + info.fileName())));
+ }
+ }
+ if (isPlugin(info, devicePath)) {
+ createPluginStub(info, devicePath, deploymentList, generatedDirs, generatedFiles);
+ continue;
+ }
+ } else {
+ // Generate deployment even if file doesn't exist, as this may be the case
+ // when generating .pkg files.
+ deploymentList.append(CopyItem(Option::fixPathToLocalOS(info.absoluteFilePath()),
+ Option::fixPathToLocalOS(devicePath + "\\" + info.fileName())));
+ continue;
+ }
+ }
+ }
+
+ int pathSize = info.absolutePath().size();
+ QDirIterator iterator(searchPath, QStringList() << nameFilter
+ , QDir::Files | QDir::NoDotAndDotDot | QDir::NoSymLinks
+ , dirSearch ? QDirIterator::Subdirectories : QDirIterator::NoIteratorFlags);
+
+ while (iterator.hasNext()) {
+ iterator.next();
+ QFileInfo iteratorInfo(iterator.filePath());
+ QString absoluteItemPath = Option::fixPathToLocalOS(iteratorInfo.absolutePath());
+ int diffSize = absoluteItemPath.size() - pathSize;
+
+ if (!iteratorInfo.isDir()) {
+ if (isPlugin(iterator.fileInfo(), devicePath)) {
+ // This deploys pre-built plugins. Other pre-built binaries will deploy normally,
+ // as they have SYSBIN_DIR target path.
+ if (deployBinaries) {
+ deploymentList.append(CopyItem(Option::fixPathToLocalOS(absoluteItemPath + "\\" + iterator.fileName()),
+ Option::fixPathToLocalOS(deploymentDrive + QLatin1String(SYSBIN_DIR "\\") + iterator.fileName())));
+ }
+ createPluginStub(info, devicePath + "\\" + absoluteItemPath.right(diffSize), deploymentList, generatedDirs, generatedFiles);
+ continue;
+ } else {
+ deploymentList.append(CopyItem(Option::fixPathToLocalOS(absoluteItemPath + "\\" + iterator.fileName()),
+ Option::fixPathToLocalOS(devicePath + "\\" + absoluteItemPath.right(diffSize) + "\\" + iterator.fileName())));
+ }
+ }
+ }
+ }
+ }
+}
+
+//:QTP:QTPROD-92 Deployment of plugins requires WINSCW build before ARM build
+void writeSbsDeploymentList(const DeploymentList& depList, QTextStream& t)
+{
+ 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;
+ }
+}