diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp index 0c2dfd61f26dfd110155909ca74d5787e1ad96d6..9f754d61b858327e4eabc277a0db7c5aa0b70a0b 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp @@ -309,18 +309,68 @@ QString S60DeviceRunConfiguration::packageFileName() const return rc; } -QString S60DeviceRunConfiguration::localExecutableFileName() const +/* Grep a package file for the '.exe' file. Curently for use on Linux only + * as the '.pkg'-files on Windows do not contain drive letters, which is not + * handled here. \code +; Executable and default resource files +"./foo.exe" - "!:\sys\bin\foo.exe" +\endcode */ + +static inline QString executableFromPackageUnix(const QString &packageFileName) { - Qt4BuildConfiguration *qt4bc = qobject_cast<Qt4BuildConfiguration *>(target()->activeBuildConfiguration()); - S60Devices::Device device = S60Manager::instance()->deviceForQtVersion(qt4bc->qtVersion()); + QFile packageFile(packageFileName); + if (!packageFile.open(QIODevice::ReadOnly|QIODevice::Text)) + return QString(); + QRegExp pattern(QLatin1String("^\"(.*.exe)\" *- \"!:.*.exe\"$")); + QTC_ASSERT(pattern.isValid(), return QString()); + foreach(const QString &line, QString::fromLocal8Bit(packageFile.readAll()).split(QLatin1Char('\n'))) + if (pattern.exactMatch(line)) { + // Expand relative paths by package file paths + QString rc = pattern.cap(1); + if (rc.startsWith(QLatin1String("./"))) + rc.remove(0, 2); + const QFileInfo fi(rc); + if (fi.isAbsolute()) + return rc; + return QFileInfo(packageFileName).absolutePath() + QLatin1Char('/') + rc; + } + return QString(); +} - QString localExecutable = device.epocRoot; - localExecutable += QString::fromLatin1("/epoc32/release/%1/%2/%3.exe") - .arg(symbianPlatform()).arg(symbianTarget()).arg(targetName()); - qDebug() << localExecutable; +QString S60DeviceRunConfiguration::localExecutableFileName() const +{ + QString localExecutable; + switch (toolChainType()) { + case ToolChain::GCCE_GNUPOC: + case ToolChain::RVCT_ARMV5_GNUPOC: + localExecutable = executableFromPackageUnix(packageTemplateFileName()); + break; + default: { + const Qt4BuildConfiguration *qt4bc = qobject_cast<Qt4BuildConfiguration *>(target()->activeBuildConfiguration()); + const S60Devices::Device device = S60Manager::instance()->deviceForQtVersion(qt4bc->qtVersion()); + QTextStream(&localExecutable) << device.epocRoot << "/epoc32/release/" + << symbianPlatform() << '/' << symbianTarget() << '/' << targetName() + << ".exe"; + } + break; + } + if (debug) + qDebug() << "Local executable" << localExecutable; return QDir::toNativeSeparators(localExecutable); } +QString S60DeviceRunConfiguration::unsignedPackage() const +{ + const_cast<S60DeviceRunConfiguration *>(this)->updateTarget(); + return QDir::toNativeSeparators(m_baseFileName + QLatin1String("_unsigned.sis")); +} + +QString S60DeviceRunConfiguration::signedPackage() const +{ + const_cast<S60DeviceRunConfiguration *>(this)->updateTarget(); + return QDir::toNativeSeparators(m_baseFileName + QLatin1String(".sis")); +} + QStringList S60DeviceRunConfiguration::commandLineArguments() const { return m_commandLineArguments; @@ -364,9 +414,10 @@ void S60DeviceRunConfiguration::updateTarget() m_platform = QLatin1String("gcce"); break; case ToolChain::RVCT_ARMV5: + case ToolChain::RVCT_ARMV5_GNUPOC: m_platform = QLatin1String("armv5"); break; - default: // including ToolChain::RVCT_ARMV6_GNUPOC: + default: m_platform = QLatin1String("armv6"); break; } @@ -505,6 +556,8 @@ S60DeviceRunControlBase::S60DeviceRunControlBase(RunConfiguration *runConfigurat m_serialPortFriendlyName = SymbianUtils::SymbianDeviceManager::instance()->friendlyNameForPort(m_serialPortName); m_targetName = s60runConfig->targetName(); m_baseFileName = s60runConfig->basePackageFilePath(); + m_unsignedPackage = s60runConfig->unsignedPackage(); + m_signedPackage = s60runConfig->signedPackage(); m_commandLineArguments = s60runConfig->commandLineArguments(); m_symbianPlatform = s60runConfig->symbianPlatform(); m_symbianTarget = s60runConfig->symbianTarget(); @@ -524,8 +577,6 @@ S60DeviceRunControlBase::S60DeviceRunControlBase(RunConfiguration *runConfigurat m_makesisTool = toolchain->makeCommand(); m_toolsDirectory = device.epocRoot + QLatin1String("/epoc32/tools"); ProjectExplorer::Environment env = ProjectExplorer::Environment::systemEnvironment(); - env.set(QLatin1String("QT_SIS_CERTIFICATE"), signSisCertificate()); - env.set(QLatin1String("QT_SIS_KEY"), signSisKey()); toolchain->addToEnvironment(env); m_makesisProcess->setEnvironment(env.toStringList()); } @@ -549,7 +600,7 @@ S60DeviceRunControlBase::S60DeviceRunControlBase(RunConfiguration *runConfigurat m_packageFilePath = s60runConfig->packageFileName(); m_packageFile = QFileInfo(m_packageFilePath).fileName(); if (debug) - qDebug() << "S60DeviceRunControlBase" << m_targetName << ProjectExplorer::ToolChain::toolChainName(m_toolChain) + qDebug() << "S60DeviceRunControlBase::CT" << m_targetName << ProjectExplorer::ToolChain::toolChainName(m_toolChain) << m_serialPortName << m_workingDirectory; } @@ -566,6 +617,13 @@ void S60DeviceRunControlBase::setReleaseDeviceAfterLauncherFinish(bool v) m_releaseDeviceAfterLauncherFinish = v; } +// Format a message with command line +static inline QString msgRun(const QString &cmd, const QStringList &args) +{ + const QChar blank = QLatin1Char(' '); + return QDir::toNativeSeparators(cmd) + blank + args.join(QString(blank)); +} + void S60DeviceRunControlBase::start() { m_deployProgress = new QFutureInterface<void>; @@ -582,7 +640,7 @@ void S60DeviceRunControlBase::start() return; } - emit addToOutputWindow(this, tr("Creating %1.sisx ...").arg(QDir::toNativeSeparators(m_baseFileName))); + emit addToOutputWindow(this, tr("Creating %1 ...").arg(m_signedPackage)); emit addToOutputWindow(this, tr("Executable file: %1").arg(lsFile(m_executableFileName))); QString errorMessage; @@ -597,24 +655,27 @@ void S60DeviceRunControlBase::start() return; } + if (!createPackageFileFromTemplate(&errorMessage)) { + error(this, errorMessage); + emit finished(); + return; + } + QStringList makeSisArgs; switch (m_toolChain) { case ProjectExplorer::ToolChain::GCCE_GNUPOC: case ProjectExplorer::ToolChain::RVCT_ARMV5_GNUPOC: - makeSisArgs.push_back(QLatin1String("sis")); + makeSisArgs << QLatin1String("sis") + << QLatin1String("QT_SIS_OPTIONS=-i") + << (QLatin1String("QT_SIS_CERTIFICATE=") + signSisCertificate()) + << (QLatin1String("QT_SIS_KEY=") + signSisKey()); break; default: makeSisArgs.push_back(m_packageFile); - if (!createPackageFileFromTemplate(&errorMessage)) { - error(this, errorMessage); - emit finished(); - return; - } break; } - m_makesisProcess->setWorkingDirectory(m_workingDirectory); - emit addToOutputWindow(this, tr("%1 %2").arg(QDir::toNativeSeparators(m_makesisTool), m_packageFile)); + emit addToOutputWindow(this, msgRun(m_makesisTool, makeSisArgs)); if (debug) qDebug() << m_makesisTool << makeSisArgs << m_workingDirectory; m_makesisProcess->start(m_makesisTool, makeSisArgs, QIODevice::ReadOnly); @@ -662,6 +723,9 @@ void S60DeviceRunControlBase::readStandardOutput() bool S60DeviceRunControlBase::createPackageFileFromTemplate(QString *errorMessage) { + if (debug) + qDebug() << "Creating package file" << m_packageFilePath << " from " << m_packageTemplateFile + << m_symbianPlatform << m_symbianTarget; QFile packageTemplate(m_packageTemplateFile); if (!packageTemplate.open(QIODevice::ReadOnly)) { *errorMessage = tr("Could not read template package file '%1'").arg(QDir::toNativeSeparators(m_packageTemplateFile)); @@ -678,6 +742,8 @@ bool S60DeviceRunControlBase::createPackageFileFromTemplate(QString *errorMessag } packageFile.write(contents.toLocal8Bit()); packageFile.close(); + if (debug > 1) + qDebug() << contents; return true; } @@ -686,6 +752,24 @@ void S60DeviceRunControlBase::makesisProcessFailed() processFailed(m_makesisTool, m_makesisProcess->error()); } + +static inline bool renameFile(const QString &sourceName, const QString &targetName, + QString *errorMessage) +{ + QFile target(targetName); + if (target.exists() && !target.remove()) { + *errorMessage = S60DeviceRunControlBase::tr("Unable to remove existing file '%1': %2").arg(targetName, target.errorString()); + return false; + } + QFile source(sourceName); + if (!source.rename(targetName)) { + *errorMessage = S60DeviceRunControlBase::tr("Unable to rename file '%1' to '%2': %3") + .arg(sourceName, targetName, source.errorString()); + return false; + } + return true; +} + void S60DeviceRunControlBase::makesisProcessFinished() { if (m_makesisProcess->exitCode() != 0) { @@ -701,7 +785,17 @@ void S60DeviceRunControlBase::makesisProcessFinished() startDeployment(); break; default: - startSigning(); + // makesis.exe derives the sis file name from the package, + // it thus needs to renamed to '_unsigned.sis'. + QString errorMessage; + if (renameFile(m_signedPackage, m_unsignedPackage, &errorMessage)) { + startSigning(); + } else { + error(this, errorMessage); + stop(); + emit finished(); + return; + } break; } } @@ -722,18 +816,16 @@ QString S60DeviceRunControlBase::signSisCertificate() const void S60DeviceRunControlBase::startSigning() { - // Signis creates a signed package ('.sisx') from a '.sis' + // Signis creates a signed package ('.sis') from an 'unsigned.sis' // using certificate and key. QString signsisTool = m_toolsDirectory + QLatin1String("/signsis"); #ifdef Q_OS_WIN signsisTool += QLatin1String(".exe"); #endif - const QString sisFile = QFileInfo(m_baseFileName + QLatin1String(".sis")).fileName(); - const QString sisxFile = sisFile + QLatin1Char('x'); QStringList arguments; - arguments << sisFile << sisxFile << signSisCertificate() << signSisKey(); + arguments << m_unsignedPackage << m_signedPackage << signSisCertificate() << signSisKey(); m_signsisProcess->setWorkingDirectory(m_workingDirectory); - emit addToOutputWindow(this, tr("%1 %2").arg(QDir::toNativeSeparators(signsisTool), arguments.join(QString(QLatin1Char(' '))))); + emit addToOutputWindow(this, msgRun(signsisTool, arguments)); m_signsisProcess->start(signsisTool, arguments, QIODevice::ReadOnly); } @@ -783,13 +875,12 @@ void S60DeviceRunControlBase::startDeployment() //TODO sisx destination and file path user definable if (!m_commandLineArguments.isEmpty()) m_launcher->setCommandLineArgs(m_commandLineArguments); - const QString copySrc(m_baseFileName + QLatin1String(".sisx")); - const QString copyDst = QString::fromLatin1("C:\\Data\\%1.sisx").arg(QFileInfo(m_baseFileName).fileName()); + const QString copyDst = QString::fromLatin1("C:\\Data\\%1.sis").arg(QFileInfo(m_baseFileName).fileName()); const QString runFileName = QString::fromLatin1("C:\\sys\\bin\\%1.exe").arg(m_targetName); - m_launcher->setCopyFileName(copySrc, copyDst); + m_launcher->setCopyFileName(m_signedPackage, copyDst); m_launcher->setInstallFileName(copyDst); initLauncher(runFileName, m_launcher); - emit addToOutputWindow(this, tr("Package: %1\nDeploying application to '%2'...").arg(lsFile(copySrc), m_serialPortFriendlyName)); + emit addToOutputWindow(this, tr("Package: %1\nDeploying application to '%2'...").arg(lsFile(m_signedPackage), m_serialPortFriendlyName)); // Prompt the user to start up the Blue tooth connection const trk::PromptStartCommunicationResult src = S60RunConfigBluetoothStarter::startCommunication(m_launcher->trkDevice(), diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h index 4fa2a06ef4513cb7e1a062bc1a8ec1ae79cba303..abba4ee1c8051061939c98c7e4b744369366cba8 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h @@ -94,6 +94,8 @@ public: QString packageFileName() const; QString localExecutableFileName() const; + QString unsignedPackage() const; + QString signedPackage() const; QStringList commandLineArguments() const; void setCommandLineArguments(const QStringList &args); @@ -228,6 +230,8 @@ private: QString m_toolsDirectory; QString m_executableFileName; QString m_qtDir; + QString m_unsignedPackage; + QString m_signedPackage; bool m_useCustomSignature; QString m_customSignaturePath; QString m_customKeyPath; diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp index 2d23a7260d4fe9d71af4ed4f9ab709fea85bb33b..778b2e90d4960628398514f5489bdfcf45a0f64b 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.cpp @@ -70,7 +70,7 @@ S60DeviceRunConfigurationWidget::S60DeviceRunConfigurationWidget( m_serialPortsCombo(new QComboBox), m_nameLineEdit(new QLineEdit(m_runConfiguration->displayName())), m_argumentsLineEdit(new QLineEdit(m_runConfiguration->commandLineArguments().join(QString(QLatin1Char(' '))))), - m_sisxFileLabel(new QLabel), + m_sisFileLabel(new QLabel), m_deviceInfoButton(new QToolButton), m_deviceInfoDescriptionLabel(new QLabel(tr("Device:"))), m_deviceInfoLabel(new QLabel), @@ -97,7 +97,7 @@ S60DeviceRunConfigurationWidget::S60DeviceRunConfigurationWidget( nameLabel->setBuddy(m_nameLineEdit); formLayout->addRow(nameLabel, m_nameLineEdit); formLayout->addRow(tr("Arguments:"), m_argumentsLineEdit); - formLayout->addRow(tr("Install File:"), m_sisxFileLabel); + formLayout->addRow(tr("Install File:"), m_sisFileLabel); updateSerialDevices(); connect(SymbianUtils::SymbianDeviceManager::instance(), SIGNAL(updated()), @@ -236,8 +236,7 @@ void S60DeviceRunConfigurationWidget::argumentsEdited(const QString &text) void S60DeviceRunConfigurationWidget::updateTargetInformation() { - m_sisxFileLabel->setText(QDir::toNativeSeparators(m_runConfiguration->basePackageFilePath() - + QLatin1String(".sisx"))); + m_sisFileLabel->setText(m_runConfiguration->signedPackage()); } void S60DeviceRunConfigurationWidget::setSerialPort(int index) diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.h b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.h index c1b1841df8df8aa74fe41d6a8e439a4a7eb9d43e..edaa62663d3831e2acb9b8ea08179c825e9e6347 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.h +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfigurationwidget.h @@ -94,7 +94,7 @@ private: QComboBox *m_serialPortsCombo; QLineEdit *m_nameLineEdit; QLineEdit *m_argumentsLineEdit; - QLabel *m_sisxFileLabel; + QLabel *m_sisFileLabel; QToolButton *m_deviceInfoButton; QLabel *m_deviceInfoDescriptionLabel; QLabel *m_deviceInfoLabel;