forked from qt-creator/qt-creator
Symbian/Linux: Enable building with makefile-based system.
- Autodetect SDK by environment variable EPOCROOT and qt directory below. - Environment::appendOrSet/prependOrSet: Avoid duplicate entries - Rename toolchain enumeration value - Adapt S60ToolChainMixin to new GnuPoc setup, provide routines for all required variables. - RVCTToolChain: Make RVCT detection smarter (Check for RVCT<v1><v2>BIN variable). Set all required variables in case of RVCTToolChain/GnuPoc - QtVersionManager: Detect toolchain and Qt version properly, make S60 device run config accept toolchain. - Modify S60DeviceRunControl to execute 'make sis' - Modify S60Devices::detectQt...() to check for Qt installed into SDK first and symlink as fallback.
This commit is contained in:
@@ -123,14 +123,15 @@ void Environment::appendOrSet(const QString &key, const QString &value, const QS
|
||||
#else
|
||||
const QString &_key = key;
|
||||
#endif
|
||||
QMap<QString, QString>::const_iterator it = m_values.constFind(key);
|
||||
if (it == m_values.constEnd()) {
|
||||
QMap<QString, QString>::iterator it = m_values.find(key);
|
||||
if (it == m_values.end()) {
|
||||
m_values.insert(_key, value);
|
||||
} else {
|
||||
QString tmp = *it + sep + value;
|
||||
m_values.insert(_key, tmp);
|
||||
// Append unless it is already there
|
||||
const QString toAppend = sep + value;
|
||||
if (!it.value().endsWith(toAppend))
|
||||
it.value().append(toAppend);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Environment::prependOrSet(const QString&key, const QString &value, const QString &sep)
|
||||
@@ -140,12 +141,14 @@ void Environment::prependOrSet(const QString&key, const QString &value, const QS
|
||||
#else
|
||||
const QString &_key = key;
|
||||
#endif
|
||||
QMap<QString, QString>::const_iterator it = m_values.constFind(key);
|
||||
if (it == m_values.constEnd()) {
|
||||
QMap<QString, QString>::iterator it = m_values.find(key);
|
||||
if (it == m_values.end()) {
|
||||
m_values.insert(_key, value);
|
||||
} else {
|
||||
QString tmp = value + sep + *it;
|
||||
m_values.insert(_key, tmp);
|
||||
// Prepend unless it is already there
|
||||
const QString toPrepend = value + sep;
|
||||
if (!it.value().startsWith(toPrepend))
|
||||
it.value().prepend(toPrepend);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@ QString ToolChain::toolChainName(ToolChainType tc)
|
||||
return QCoreApplication::translate("ToolChain", "GCCE");
|
||||
case GCCE_GNUPOC:
|
||||
return QCoreApplication::translate("ToolChain", "GCCE/GnuPoc");
|
||||
case RVCT_ARMV6_GNUPOC:
|
||||
case RVCT_ARMV5_GNUPOC:
|
||||
return QCoreApplication::translate("ToolChain", "RVCT (ARMV6)/GnuPoc");
|
||||
case RVCT_ARMV5:
|
||||
return QCoreApplication::translate("ToolChain", "RVCT (ARMV5)");
|
||||
|
||||
@@ -86,7 +86,7 @@ public:
|
||||
RVCT_ARMV6 = 8,
|
||||
GCC_MAEMO = 9,
|
||||
GCCE_GNUPOC = 10,
|
||||
RVCT_ARMV6_GNUPOC = 11,
|
||||
RVCT_ARMV5_GNUPOC = 11,
|
||||
LAST_VALID = 11,
|
||||
OTHER = 200,
|
||||
UNKNOWN = 201,
|
||||
|
||||
@@ -30,11 +30,19 @@
|
||||
#include "rvcttoolchain.h"
|
||||
#include "rvctparser.h"
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QtCore/QProcess>
|
||||
#include <QtCore/QProcessEnvironment>
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QFileInfo>
|
||||
#include <QtCore/QDir>
|
||||
|
||||
using namespace ProjectExplorer;
|
||||
using namespace Qt4ProjectManager::Internal;
|
||||
|
||||
static const char rvctBinaryC[] = "armcc";
|
||||
|
||||
RVCTToolChain::RVCTToolChain(const S60Devices::Device &device, ToolChain::ToolChainType type) :
|
||||
m_mixin(device),
|
||||
m_type(type),
|
||||
@@ -45,6 +53,54 @@ RVCTToolChain::RVCTToolChain(const S60Devices::Device &device, ToolChain::ToolCh
|
||||
{
|
||||
}
|
||||
|
||||
// Return the environment variable indicating the RVCT version
|
||||
// 'RVCT<major><minor>BIN'
|
||||
QByteArray RVCTToolChain::rvctBinEnvironmentVariable()
|
||||
{
|
||||
static QByteArray binVar;
|
||||
// Grep the environment list
|
||||
if (binVar.isEmpty()) {
|
||||
const QRegExp regex(QLatin1String("^(RVCT\\d\\dBIN)=.*$"));
|
||||
QTC_ASSERT(regex.isValid(), return QByteArray());
|
||||
foreach(const QString &v, QProcessEnvironment::systemEnvironment().toStringList()) {
|
||||
if (regex.exactMatch(v)) {
|
||||
binVar = regex.cap(1).toLocal8Bit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return binVar;
|
||||
}
|
||||
|
||||
// Return binary path as pointed to by RVCT<X><X>BIN
|
||||
QString RVCTToolChain::rvctBinPath()
|
||||
{
|
||||
static QString binPath;
|
||||
if (binPath.isEmpty()) {
|
||||
const QByteArray binVar = rvctBinEnvironmentVariable();
|
||||
if (!binVar.isEmpty()) {
|
||||
const QByteArray binPathB = qgetenv(binVar);
|
||||
if (!binPathB.isEmpty()) {
|
||||
const QFileInfo fi(QString::fromLocal8Bit(binPathB));
|
||||
if (fi.isDir())
|
||||
binPath = fi.absoluteFilePath();
|
||||
}
|
||||
}
|
||||
}
|
||||
return binPath;
|
||||
}
|
||||
|
||||
// Return binary expanded by path or resort to PATH
|
||||
QString RVCTToolChain::rvctBinary()
|
||||
{
|
||||
QString executable = QLatin1String(rvctBinaryC);
|
||||
#ifdef Q_OS_WIN
|
||||
executable += QLatin1String(".exe");
|
||||
#endif
|
||||
const QString binPath = rvctBinPath();
|
||||
return binPath.isEmpty() ? executable : (binPath + QLatin1Char('/') + executable);
|
||||
}
|
||||
|
||||
ToolChain::ToolChainType RVCTToolChain::type() const
|
||||
{
|
||||
return m_type;
|
||||
@@ -54,6 +110,7 @@ void RVCTToolChain::updateVersion()
|
||||
{
|
||||
if (m_versionUpToDate)
|
||||
return;
|
||||
|
||||
m_versionUpToDate = true;
|
||||
m_major = 0;
|
||||
m_minor = 0;
|
||||
@@ -62,13 +119,19 @@ void RVCTToolChain::updateVersion()
|
||||
ProjectExplorer::Environment env = ProjectExplorer::Environment::systemEnvironment();
|
||||
addToEnvironment(env);
|
||||
armcc.setEnvironment(env.toStringList());
|
||||
armcc.start("armcc", QStringList());
|
||||
const QString binary = rvctBinary();
|
||||
armcc.start(rvctBinary(), QStringList());
|
||||
if (!armcc.waitForStarted()) {
|
||||
qWarning("Unable to run rvct binary '%s' when trying to determine version.", qPrintable(binary));
|
||||
return;
|
||||
}
|
||||
armcc.closeWriteChannel();
|
||||
armcc.waitForFinished();
|
||||
QString versionLine = armcc.readAllStandardOutput();
|
||||
versionLine += armcc.readAllStandardError();
|
||||
QRegExp versionRegExp("RVCT(\\d*)\\.(\\d*).*\\[Build.(\\d*)\\]",
|
||||
QString versionLine = QString::fromLocal8Bit(armcc.readAllStandardOutput());
|
||||
versionLine += QString::fromLocal8Bit(armcc.readAllStandardError());
|
||||
const QRegExp versionRegExp(QLatin1String("RVCT(\\d*)\\.(\\d*).*\\[Build.(\\d*)\\]"),
|
||||
Qt::CaseInsensitive);
|
||||
QTC_ASSERT(versionRegExp.isValid(), return);
|
||||
if (versionRegExp.indexIn(versionLine) != -1) {
|
||||
m_major = versionRegExp.cap(1).toInt();
|
||||
m_minor = versionRegExp.cap(2).toInt();
|
||||
@@ -113,8 +176,8 @@ QList<HeaderPath> RVCTToolChain::systemHeaderPaths()
|
||||
if (!rvctInclude.isEmpty())
|
||||
m_systemHeaderPaths.append(HeaderPath(rvctInclude, HeaderPath::GlobalHeaderPath));
|
||||
switch (m_type) {
|
||||
case ProjectExplorer::ToolChain::RVCT_ARMV6_GNUPOC:
|
||||
m_systemHeaderPaths += m_mixin.gnuPocHeaderPaths();
|
||||
case ProjectExplorer::ToolChain::RVCT_ARMV5_GNUPOC:
|
||||
m_systemHeaderPaths += m_mixin.gnuPocRvctHeaderPaths(m_major, m_minor);
|
||||
break;
|
||||
default:
|
||||
m_systemHeaderPaths += m_mixin.epocHeaderPaths();
|
||||
@@ -124,11 +187,66 @@ QList<HeaderPath> RVCTToolChain::systemHeaderPaths()
|
||||
return m_systemHeaderPaths;
|
||||
}
|
||||
|
||||
static inline QStringList headerPathToStringList(const QList<ProjectExplorer::HeaderPath> &hl)
|
||||
{
|
||||
QStringList rc;
|
||||
foreach(const ProjectExplorer::HeaderPath &hp, hl)
|
||||
rc.push_back(hp.path());
|
||||
return rc;
|
||||
}
|
||||
|
||||
// Expand an RVCT variable, such as RVCT22BIN, by some new values
|
||||
void RVCTToolChain::addToRVCTPathVariable(const QString &postfix, const QStringList &values,
|
||||
ProjectExplorer::Environment &env) const
|
||||
{
|
||||
// get old values
|
||||
const QChar separator = QLatin1Char(',');
|
||||
const QString variable = QString::fromLatin1("RVCT%1%2%3").arg(m_major).arg(m_minor).arg(postfix);
|
||||
const QString oldValueS = env.value(variable);
|
||||
const QStringList oldValue = oldValueS.isEmpty() ? QStringList() : oldValueS.split(separator);
|
||||
// merge new values
|
||||
QStringList newValue = oldValue;
|
||||
foreach(const QString &v, values) {
|
||||
const QString normalized = QDir::toNativeSeparators(v);
|
||||
if (!newValue.contains(normalized))
|
||||
newValue.push_back(normalized);
|
||||
}
|
||||
if (newValue != oldValue)
|
||||
env.set(variable, newValue.join(QString(separator)));
|
||||
}
|
||||
|
||||
// Figure out lib path via
|
||||
QStringList RVCTToolChain::libPaths()
|
||||
{
|
||||
const QByteArray binLocation = qgetenv(rvctBinEnvironmentVariable());
|
||||
if (binLocation.isEmpty())
|
||||
return QStringList();
|
||||
const QString pathRoot = QFileInfo(QString::fromLocal8Bit(binLocation)).path();
|
||||
QStringList rc;
|
||||
rc.push_back(pathRoot + QLatin1String("/lib"));
|
||||
rc.push_back(pathRoot + QLatin1String("/lib/armlib"));
|
||||
return rc;
|
||||
}
|
||||
|
||||
void RVCTToolChain::addToEnvironment(ProjectExplorer::Environment &env)
|
||||
{
|
||||
updateVersion();
|
||||
switch (m_type) {
|
||||
case ProjectExplorer::ToolChain::RVCT_ARMV6_GNUPOC:
|
||||
case ProjectExplorer::ToolChain::RVCT_ARMV5_GNUPOC: {
|
||||
m_mixin.addGnuPocToEnvironment(&env);
|
||||
// setup RVCT22INC, LIB
|
||||
addToRVCTPathVariable(QLatin1String("INC"),
|
||||
headerPathToStringList(m_mixin.gnuPocRvctHeaderPaths(m_major, m_minor)),
|
||||
env);
|
||||
addToRVCTPathVariable(QLatin1String("LIB"),
|
||||
libPaths() + m_mixin.gnuPocRvctLibPaths(5, true),
|
||||
env);
|
||||
// Add rvct to path and set locale to 'C'
|
||||
const QString binPath = rvctBinPath();
|
||||
if (!binPath.isEmpty())
|
||||
env.prependOrSetPath(binPath);
|
||||
env.set(QLatin1String("LANG"), QString(QLatin1Char('C')));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
m_mixin.addEpocToEnvironment(&env);
|
||||
|
||||
@@ -49,10 +49,19 @@ public:
|
||||
QString makeCommand() const;
|
||||
ProjectExplorer::IOutputParser *outputParser() const;
|
||||
|
||||
// Return the environment variable indicating the RVCT version
|
||||
// 'RVCT<major><minor>BIN' and its setting
|
||||
static QByteArray rvctBinEnvironmentVariable();
|
||||
static QString rvctBinPath();
|
||||
static QString rvctBinary();
|
||||
|
||||
protected:
|
||||
bool equals(ToolChain *other) const;
|
||||
|
||||
private:
|
||||
void addToRVCTPathVariable(const QString &postfix, const QStringList &values,
|
||||
ProjectExplorer::Environment &env) const;
|
||||
static QStringList libPaths();
|
||||
void updateVersion();
|
||||
|
||||
const S60ToolChainMixin m_mixin;
|
||||
|
||||
@@ -179,9 +179,18 @@ ProjectExplorer::ToolChain::ToolChainType S60DeviceRunConfiguration::toolChainTy
|
||||
|
||||
bool S60DeviceRunConfiguration::isEnabled(ProjectExplorer::BuildConfiguration *configuration) const
|
||||
{
|
||||
Qt4BuildConfiguration *qt4bc = static_cast<Qt4BuildConfiguration *>(configuration);
|
||||
const ToolChain::ToolChainType type = qt4bc->toolChainType();
|
||||
return type == ToolChain::GCCE || type == ToolChain::RVCT_ARMV5 || type == ToolChain::RVCT_ARMV6;
|
||||
const Qt4BuildConfiguration *qt4bc = static_cast<const Qt4BuildConfiguration *>(configuration);
|
||||
switch (qt4bc->toolChainType()) {
|
||||
case ToolChain::GCCE:
|
||||
case ToolChain::RVCT_ARMV5:
|
||||
case ToolChain::RVCT_ARMV6:
|
||||
case ToolChain::GCCE_GNUPOC:
|
||||
case ToolChain::RVCT_ARMV5_GNUPOC:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QWidget *S60DeviceRunConfiguration::configurationWidget()
|
||||
@@ -468,8 +477,8 @@ RunConfiguration *S60DeviceRunConfigurationFactory::clone(Target *parent, RunCon
|
||||
S60DeviceRunControlBase::S60DeviceRunControlBase(RunConfiguration *runConfiguration) :
|
||||
RunControl(runConfiguration),
|
||||
m_toolChain(ProjectExplorer::ToolChain::INVALID),
|
||||
m_makesis(new QProcess(this)),
|
||||
m_signsis(0),
|
||||
m_makesisProcess(new QProcess(this)),
|
||||
m_signsisProcess(0),
|
||||
m_releaseDeviceAfterLauncherFinish(false),
|
||||
m_handleDeviceRemoval(true),
|
||||
m_launcher(0)
|
||||
@@ -477,13 +486,13 @@ S60DeviceRunControlBase::S60DeviceRunControlBase(RunConfiguration *runConfigurat
|
||||
// connect for automatically reporting the "finished deploy" state to the progress manager
|
||||
connect(this, SIGNAL(finished()), this, SLOT(reportDeployFinished()));
|
||||
|
||||
connect(m_makesis, SIGNAL(readyReadStandardError()),
|
||||
connect(m_makesisProcess, SIGNAL(readyReadStandardError()),
|
||||
this, SLOT(readStandardError()));
|
||||
connect(m_makesis, SIGNAL(readyReadStandardOutput()),
|
||||
connect(m_makesisProcess, SIGNAL(readyReadStandardOutput()),
|
||||
this, SLOT(readStandardOutput()));
|
||||
connect(m_makesis, SIGNAL(error(QProcess::ProcessError)),
|
||||
connect(m_makesisProcess, SIGNAL(error(QProcess::ProcessError)),
|
||||
this, SLOT(makesisProcessFailed()));
|
||||
connect(m_makesis, SIGNAL(finished(int,QProcess::ExitStatus)),
|
||||
connect(m_makesisProcess, SIGNAL(finished(int,QProcess::ExitStatus)),
|
||||
this, SLOT(makesisProcessFinished()));
|
||||
|
||||
S60DeviceRunConfiguration *s60runConfig = qobject_cast<S60DeviceRunConfiguration *>(runConfiguration);
|
||||
@@ -509,28 +518,30 @@ S60DeviceRunControlBase::S60DeviceRunControlBase(RunConfiguration *runConfigurat
|
||||
const S60Devices::Device device = S60Manager::instance()->deviceForQtVersion(activeBuildConf->qtVersion());
|
||||
switch (m_toolChain) {
|
||||
case ProjectExplorer::ToolChain::GCCE_GNUPOC:
|
||||
case ProjectExplorer::ToolChain::RVCT_ARMV6_GNUPOC: {
|
||||
case ProjectExplorer::ToolChain::RVCT_ARMV5_GNUPOC: {
|
||||
// 'sis' is a make target here. Set up with correct environment
|
||||
ProjectExplorer::ToolChain *toolchain = activeBuildConf->toolChain();
|
||||
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_makesis->setEnvironment(env.toStringList());
|
||||
m_makesisProcess->setEnvironment(env.toStringList());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
m_toolsDirectory = device.toolsRoot + QLatin1String("/epoc32/tools");
|
||||
m_makesisTool = m_toolsDirectory + "/makesis.exe";
|
||||
// Set up signing packages
|
||||
m_signsis = new QProcess(this);
|
||||
connect(m_signsis, SIGNAL(readyReadStandardError()),
|
||||
m_signsisProcess = new QProcess(this);
|
||||
connect(m_signsisProcess, SIGNAL(readyReadStandardError()),
|
||||
this, SLOT(readStandardError()));
|
||||
connect(m_signsis, SIGNAL(readyReadStandardOutput()),
|
||||
connect(m_signsisProcess, SIGNAL(readyReadStandardOutput()),
|
||||
this, SLOT(readStandardOutput()));
|
||||
connect(m_signsis, SIGNAL(error(QProcess::ProcessError)),
|
||||
connect(m_signsisProcess, SIGNAL(error(QProcess::ProcessError)),
|
||||
this, SLOT(signsisProcessFailed()));
|
||||
connect(m_signsis, SIGNAL(finished(int,QProcess::ExitStatus)),
|
||||
connect(m_signsisProcess, SIGNAL(finished(int,QProcess::ExitStatus)),
|
||||
this, SLOT(signsisProcessFinished()));
|
||||
break;
|
||||
}
|
||||
@@ -589,7 +600,7 @@ void S60DeviceRunControlBase::start()
|
||||
QStringList makeSisArgs;
|
||||
switch (m_toolChain) {
|
||||
case ProjectExplorer::ToolChain::GCCE_GNUPOC:
|
||||
case ProjectExplorer::ToolChain::RVCT_ARMV6_GNUPOC:
|
||||
case ProjectExplorer::ToolChain::RVCT_ARMV5_GNUPOC:
|
||||
makeSisArgs.push_back(QLatin1String("sis"));
|
||||
break;
|
||||
default:
|
||||
@@ -602,11 +613,11 @@ void S60DeviceRunControlBase::start()
|
||||
break;
|
||||
}
|
||||
|
||||
m_makesis->setWorkingDirectory(m_workingDirectory);
|
||||
m_makesisProcess->setWorkingDirectory(m_workingDirectory);
|
||||
emit addToOutputWindow(this, tr("%1 %2").arg(QDir::toNativeSeparators(m_makesisTool), m_packageFile));
|
||||
if (debug)
|
||||
qDebug() << m_makesisTool << makeSisArgs << m_workingDirectory;
|
||||
m_makesis->start(m_makesisTool, makeSisArgs, QIODevice::ReadOnly);
|
||||
m_makesisProcess->start(m_makesisTool, makeSisArgs, QIODevice::ReadOnly);
|
||||
}
|
||||
|
||||
static inline void stopProcess(QProcess *p)
|
||||
@@ -622,17 +633,17 @@ static inline void stopProcess(QProcess *p)
|
||||
|
||||
void S60DeviceRunControlBase::stop()
|
||||
{
|
||||
if (m_makesis)
|
||||
stopProcess(m_makesis);
|
||||
if (m_signsis)
|
||||
stopProcess(m_signsis);
|
||||
if (m_makesisProcess)
|
||||
stopProcess(m_makesisProcess);
|
||||
if (m_signsisProcess)
|
||||
stopProcess(m_signsisProcess);
|
||||
if (m_launcher)
|
||||
m_launcher->terminate();
|
||||
}
|
||||
|
||||
bool S60DeviceRunControlBase::isRunning() const
|
||||
{
|
||||
return m_makesis->state() != QProcess::NotRunning;
|
||||
return m_makesisProcess->state() != QProcess::NotRunning;
|
||||
}
|
||||
|
||||
void S60DeviceRunControlBase::readStandardError()
|
||||
@@ -672,12 +683,12 @@ bool S60DeviceRunControlBase::createPackageFileFromTemplate(QString *errorMessag
|
||||
|
||||
void S60DeviceRunControlBase::makesisProcessFailed()
|
||||
{
|
||||
processFailed(m_makesisTool, m_makesis->error());
|
||||
processFailed(m_makesisTool, m_makesisProcess->error());
|
||||
}
|
||||
|
||||
void S60DeviceRunControlBase::makesisProcessFinished()
|
||||
{
|
||||
if (m_makesis->exitCode() != 0) {
|
||||
if (m_makesisProcess->exitCode() != 0) {
|
||||
error(this, tr("An error occurred while creating the package."));
|
||||
stop();
|
||||
emit finished();
|
||||
@@ -686,7 +697,7 @@ void S60DeviceRunControlBase::makesisProcessFinished()
|
||||
m_deployProgress->setProgressValue(PROGRESS_PACKAGECREATED);
|
||||
switch (m_toolChain) {
|
||||
case ProjectExplorer::ToolChain::GCCE_GNUPOC:
|
||||
case ProjectExplorer::ToolChain::RVCT_ARMV6_GNUPOC:
|
||||
case ProjectExplorer::ToolChain::RVCT_ARMV5_GNUPOC:
|
||||
startDeployment();
|
||||
break;
|
||||
default:
|
||||
@@ -695,32 +706,45 @@ void S60DeviceRunControlBase::makesisProcessFinished()
|
||||
}
|
||||
}
|
||||
|
||||
QString S60DeviceRunControlBase::signSisKey() const
|
||||
{
|
||||
const QString key = m_useCustomSignature ? m_customKeyPath:
|
||||
m_qtDir + QLatin1String("/src/s60installs/selfsigned.key");
|
||||
return QDir::toNativeSeparators(key);
|
||||
}
|
||||
|
||||
QString S60DeviceRunControlBase::signSisCertificate() const
|
||||
{
|
||||
const QString cert = m_useCustomSignature ? m_customSignaturePath :
|
||||
m_qtDir + QLatin1String("/src/s60installs/selfsigned.cer");
|
||||
return QDir::toNativeSeparators(cert);
|
||||
}
|
||||
|
||||
void S60DeviceRunControlBase::startSigning()
|
||||
{
|
||||
QString signsisTool = m_toolsDirectory + QLatin1String("/signsis.exe");
|
||||
QString sisFile = QFileInfo(m_baseFileName + QLatin1String(".sis")).fileName();
|
||||
QString sisxFile = QFileInfo(m_baseFileName + QLatin1String(".sisx")).fileName();
|
||||
QString signature = (m_useCustomSignature ? m_customSignaturePath
|
||||
: m_qtDir + QLatin1String("/src/s60installs/selfsigned.cer"));
|
||||
QString key = (m_useCustomSignature ? m_customKeyPath
|
||||
: m_qtDir + QLatin1String("/src/s60installs/selfsigned.key"));
|
||||
// Signis creates a signed package ('.sisx') from a '.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 << QDir::toNativeSeparators(signature)
|
||||
<< QDir::toNativeSeparators(key);
|
||||
m_signsis->setWorkingDirectory(m_workingDirectory);
|
||||
arguments << sisFile << sisxFile << signSisCertificate() << signSisKey();
|
||||
m_signsisProcess->setWorkingDirectory(m_workingDirectory);
|
||||
emit addToOutputWindow(this, tr("%1 %2").arg(QDir::toNativeSeparators(signsisTool), arguments.join(QString(QLatin1Char(' ')))));
|
||||
m_signsis->start(signsisTool, arguments, QIODevice::ReadOnly);
|
||||
m_signsisProcess->start(signsisTool, arguments, QIODevice::ReadOnly);
|
||||
}
|
||||
|
||||
void S60DeviceRunControlBase::signsisProcessFailed()
|
||||
{
|
||||
processFailed("signsis.exe", m_signsis->error());
|
||||
processFailed("signsis.exe", m_signsisProcess->error());
|
||||
}
|
||||
|
||||
void S60DeviceRunControlBase::signsisProcessFinished()
|
||||
{
|
||||
if (m_signsis->exitCode() != 0) {
|
||||
if (m_signsisProcess->exitCode() != 0) {
|
||||
error(this, tr("An error occurred while creating the package."));
|
||||
stop();
|
||||
emit finished();
|
||||
|
||||
@@ -156,7 +156,7 @@ public:
|
||||
/* S60DeviceRunControlBase: Builds the package and starts launcher
|
||||
* to deploy. Subclasses can configure the launcher to run or start a debugger.
|
||||
* Building the package comprises for:
|
||||
* GnuPoc: run 'make sis'
|
||||
* GnuPoc: run 'make sis' with environment variables for signing set
|
||||
* Other: run the makesis.exe tool, run signsis */
|
||||
|
||||
class S60DeviceRunControlBase : public ProjectExplorer::RunControl
|
||||
@@ -211,6 +211,8 @@ private:
|
||||
bool createPackageFileFromTemplate(QString *errorMessage);
|
||||
void startSigning();
|
||||
void startDeployment();
|
||||
QString signSisKey() const;
|
||||
QString signSisCertificate() const;
|
||||
|
||||
ProjectExplorer::ToolChain::ToolChainType m_toolChain;
|
||||
QString m_serialPortName;
|
||||
@@ -229,8 +231,8 @@ private:
|
||||
bool m_useCustomSignature;
|
||||
QString m_customSignaturePath;
|
||||
QString m_customKeyPath;
|
||||
QProcess *m_makesis;
|
||||
QProcess *m_signsis;
|
||||
QProcess *m_makesisProcess;
|
||||
QProcess *m_signsisProcess;
|
||||
QString m_makesisTool;
|
||||
QString m_packageFile;
|
||||
bool m_releaseDeviceAfterLauncherFinish;
|
||||
|
||||
@@ -85,7 +85,7 @@ S60Devices::S60Devices(QObject *parent)
|
||||
}
|
||||
|
||||
// GNU-Poc stuff
|
||||
static const char *gnuPocRootC = "GNUPOC_ROOT";
|
||||
static const char *epocRootC = "EPOCROOT";
|
||||
|
||||
static inline QString msgEnvVarNotSet(const char *var)
|
||||
{
|
||||
@@ -100,28 +100,22 @@ static inline QString msgEnvVarDirNotExist(const QString &dir, const char *var)
|
||||
bool S60Devices::readLinux()
|
||||
{
|
||||
// Detect GNUPOC_ROOT/EPOC ROOT
|
||||
const QByteArray gnuPocRootA = qgetenv(gnuPocRootC);
|
||||
if (gnuPocRootA.isEmpty()) {
|
||||
m_errorString = msgEnvVarNotSet(gnuPocRootC);
|
||||
const QByteArray epocRootA = qgetenv(epocRootC);
|
||||
if (epocRootA.isEmpty()) {
|
||||
m_errorString = msgEnvVarNotSet(epocRootC);
|
||||
return false;
|
||||
}
|
||||
|
||||
const QDir gnuPocRootDir(QString::fromLocal8Bit(gnuPocRootA));
|
||||
if (!gnuPocRootDir.exists()) {
|
||||
m_errorString = msgEnvVarDirNotExist(gnuPocRootDir.absolutePath(), gnuPocRootC);
|
||||
const QDir epocRootDir(QString::fromLocal8Bit(epocRootA));
|
||||
if (!epocRootDir.exists()) {
|
||||
m_errorString = msgEnvVarDirNotExist(epocRootDir.absolutePath(), epocRootC);
|
||||
return false;
|
||||
}
|
||||
|
||||
const QDir epocDir(gnuPocRootDir.absolutePath() + QLatin1String("/symbian-sdks/5.0"));
|
||||
if (!epocDir.exists()) {
|
||||
m_errorString = QString::fromLatin1("EPOC could not be found at %1.").arg(epocDir.absolutePath());
|
||||
return false;
|
||||
}
|
||||
// Check Qt
|
||||
Device device;
|
||||
device.id = device.name = QLatin1String("GnuPoc");
|
||||
device.epocRoot = epocDir.absolutePath();
|
||||
device.toolsRoot = gnuPocRootDir.absolutePath();
|
||||
device.toolsRoot = device.epocRoot = epocRootDir.absolutePath();
|
||||
device.isDefault = true;
|
||||
m_devices.push_back(device);
|
||||
return true;
|
||||
@@ -233,39 +227,72 @@ bool S60Devices::readWin()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool S60Devices::detectQtForDevices()
|
||||
// Detect a Qt version that is installed into a Symbian SDK
|
||||
static QString detect_SDK_installedQt(const QString &epocRoot)
|
||||
{
|
||||
const QString coreLibDllFileName = epocRoot + QLatin1String("/epoc32/release/winscw/udeb/QtCore.dll");
|
||||
QFile coreLibDllFile(coreLibDllFileName);
|
||||
if (!coreLibDllFile.exists() || !coreLibDllFile.open(QIODevice::ReadOnly))
|
||||
return false;
|
||||
|
||||
// Do not normalize these backslashes since they are in ARM binaries:
|
||||
const QByteArray indicator("\\src\\corelib\\kernel\\qobject.h");
|
||||
const int indicatorlength = indicator.size();
|
||||
for (int i = 0; i < m_devices.size(); ++i) {
|
||||
if (!m_devices.at(i).qt.isEmpty())
|
||||
continue;
|
||||
QFile qtDll(QString("%1/epoc32/release/winscw/udeb/QtCore.dll").arg(m_devices.at(i).epocRoot));
|
||||
if (!qtDll.exists() || !qtDll.open(QIODevice::ReadOnly)) {
|
||||
m_devices[i].qt.clear();
|
||||
continue;
|
||||
}
|
||||
QByteArray buffer;
|
||||
const int chunkSize = 10000;
|
||||
|
||||
int index = -1;
|
||||
while (!qtDll.atEnd()) {
|
||||
buffer = qtDll.read(10000);
|
||||
QByteArray buffer;
|
||||
while (true) {
|
||||
buffer = coreLibDllFile.read(chunkSize);
|
||||
index = buffer.indexOf(indicator);
|
||||
if (index >= 0)
|
||||
break;
|
||||
if (!qtDll.atEnd())
|
||||
qtDll.seek(qtDll.pos()-indicatorlength);
|
||||
if (buffer.size() < chunkSize || coreLibDllFile.atEnd())
|
||||
return QString();
|
||||
coreLibDllFile.seek(coreLibDllFile.pos() - indicatorlength);
|
||||
}
|
||||
coreLibDllFile.close();
|
||||
|
||||
int lastIndex = index;
|
||||
while (index >= 0 && buffer.at(index))
|
||||
--index;
|
||||
if (index < 0) { // this is untested
|
||||
} else {
|
||||
if (index < 0)
|
||||
return QString();
|
||||
|
||||
index += 2; // the 0 and another byte for some reason
|
||||
m_devices[i].qt = QDir(buffer.mid(index, lastIndex-index)).absolutePath();
|
||||
return QDir(QString::fromLatin1(buffer.mid(index, lastIndex-index))).absolutePath();
|
||||
}
|
||||
|
||||
// GnuPoc: Detect a Qt version that is symlinked/below an SDK
|
||||
// TODO: Find a proper way of doing that
|
||||
static QString detectGnuPocQt(const QString &epocRoot)
|
||||
{
|
||||
const QFileInfo fi(epocRoot + QLatin1String("/qt"));
|
||||
if (!fi.exists())
|
||||
return QString();
|
||||
if (fi.isSymLink())
|
||||
return QFileInfo(fi.symLinkTarget()).absoluteFilePath();
|
||||
return fi.absoluteFilePath();
|
||||
}
|
||||
|
||||
bool S60Devices::detectQtForDevices()
|
||||
{
|
||||
bool changed = false;
|
||||
const int deviceCount = m_devices.size();
|
||||
for (int i = 0; i < deviceCount; ++i) {
|
||||
Device &device = m_devices[i];
|
||||
if (device.qt.isEmpty()) {
|
||||
device.qt = detect_SDK_installedQt(device.epocRoot);
|
||||
if (device.qt.isEmpty())
|
||||
device.qt = detectGnuPocQt(device.epocRoot);
|
||||
if (device.qt.isEmpty()) {
|
||||
qWarning("Unable to detect Qt version for '%s'.", qPrintable(device.epocRoot));
|
||||
} else {
|
||||
changed = true;
|
||||
}
|
||||
qtDll.close();
|
||||
}
|
||||
}
|
||||
if (changed)
|
||||
emit qtVersionsChanged();
|
||||
return true;
|
||||
}
|
||||
@@ -389,15 +416,49 @@ void S60ToolChainMixin::addEpocToEnvironment(ProjectExplorer::Environment *env)
|
||||
env->set(QLatin1String("EPOCROOT"), QDir::toNativeSeparators(epocRootPath));
|
||||
}
|
||||
|
||||
static const char *gnuPocHeaderPathsC[] = {
|
||||
"epoc32/include", "epoc32/include/variant", "epoc32/include/stdapis",
|
||||
"epoc32/include/stdapis/stlport" };
|
||||
|
||||
QList<ProjectExplorer::HeaderPath> S60ToolChainMixin::gnuPocHeaderPaths() const
|
||||
{
|
||||
return QList<ProjectExplorer::HeaderPath>(); // TODO:
|
||||
QList<ProjectExplorer::HeaderPath> rc;
|
||||
const QString root = m_device.epocRoot + QLatin1Char('/');
|
||||
const int count = sizeof(gnuPocHeaderPathsC)/sizeof(const char *);
|
||||
for (int i = 0; i < count; i++)
|
||||
rc.push_back(ProjectExplorer::HeaderPath(root + QLatin1String(gnuPocHeaderPathsC[i]),
|
||||
ProjectExplorer::HeaderPath::GlobalHeaderPath));
|
||||
return rc;
|
||||
}
|
||||
|
||||
QStringList S60ToolChainMixin::gnuPocRvctLibPaths(int armver, bool debug) const
|
||||
{
|
||||
QStringList rc;
|
||||
QString root;
|
||||
QTextStream(&root) << m_device.epocRoot << "epoc32/release/armv" << armver << '/';
|
||||
rc.push_back(root + QLatin1String("lib"));
|
||||
rc.push_back(root + (debug ? QLatin1String("udeb") : QLatin1String("urel")));
|
||||
return rc;
|
||||
}
|
||||
|
||||
QList<ProjectExplorer::HeaderPath> S60ToolChainMixin::gnuPocRvctHeaderPaths(int major, int minor) const
|
||||
{
|
||||
// Additional header for rvct
|
||||
QList<ProjectExplorer::HeaderPath> rc = gnuPocHeaderPaths();
|
||||
QString rvctHeader;
|
||||
QTextStream(&rvctHeader) << m_device.epocRoot << "/epoc32/include/rvct" << major << '_' << minor;
|
||||
rc.push_back(ProjectExplorer::HeaderPath(rvctHeader, ProjectExplorer::HeaderPath::GlobalHeaderPath));
|
||||
return rc;
|
||||
}
|
||||
|
||||
void S60ToolChainMixin::addGnuPocToEnvironment(ProjectExplorer::Environment *env) const
|
||||
{
|
||||
env->prependOrSetPath(QDir::toNativeSeparators(m_device.toolsRoot + QLatin1String("/bin")));
|
||||
env->set(QLatin1String("EPOCROOT"), QDir::toNativeSeparators(S60Devices::cleanedRootPath(m_device.epocRoot)));
|
||||
env->prependOrSetPath(QDir::toNativeSeparators(m_device.toolsRoot + QLatin1String("/epoc32/tools")));
|
||||
const QString epocRootVar = QLatin1String("EPOCROOT");
|
||||
// No trailing slash is required here, so, do not perform path cleaning.
|
||||
// The variable also should be set since it is currently used for autodetection.
|
||||
if (env->find(epocRootVar) == env->constEnd())
|
||||
env->set(epocRootVar, m_device.epocRoot);
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug db, const S60Devices::Device &d)
|
||||
|
||||
@@ -95,6 +95,8 @@ public:
|
||||
|
||||
// GnuPoc
|
||||
QList<ProjectExplorer::HeaderPath> gnuPocHeaderPaths() const;
|
||||
QList<ProjectExplorer::HeaderPath> gnuPocRvctHeaderPaths(int major, int minor) const;
|
||||
QStringList gnuPocRvctLibPaths(int armver, bool debug) const;
|
||||
void addGnuPocToEnvironment(ProjectExplorer::Environment *env) const;
|
||||
|
||||
bool equals(const S60ToolChainMixin &rhs) const;
|
||||
|
||||
@@ -32,8 +32,10 @@
|
||||
|
||||
#include <qt4projectmanager/qt4projectmanagerconstants.h>
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
#include <QtCore/QDir>
|
||||
#include <QtDebug>
|
||||
#include <QtCore/QtDebug>
|
||||
|
||||
using namespace Qt4ProjectManager;
|
||||
using namespace Qt4ProjectManager::Internal;
|
||||
@@ -56,7 +58,7 @@ S60DevicesWidget::~S60DevicesWidget()
|
||||
void S60DevicesWidget::updateDevices()
|
||||
{
|
||||
m_devices->read();
|
||||
Q_ASSERT(m_devices->detectQtForDevices());
|
||||
QTC_ASSERT(m_devices->detectQtForDevices(), return);
|
||||
updateDevicesList();
|
||||
}
|
||||
|
||||
|
||||
@@ -138,6 +138,11 @@ S60Manager::~S60Manager()
|
||||
}
|
||||
}
|
||||
|
||||
bool S60Manager::hasRvctCompiler()
|
||||
{
|
||||
return !RVCTToolChain::rvctBinEnvironmentVariable().isEmpty();
|
||||
}
|
||||
|
||||
void S60Manager::addAutoReleasedObject(QObject *o)
|
||||
{
|
||||
ExtensionSystem::PluginManager::instance()->addObject(o);
|
||||
|
||||
@@ -60,6 +60,8 @@ public:
|
||||
S60Devices::Device deviceForQtVersion(const Qt4ProjectManager::QtVersion *version) const;
|
||||
QString deviceIdFromDetectionSource(const QString &autoDetectionSource) const;
|
||||
|
||||
static bool hasRvctCompiler();
|
||||
|
||||
private slots:
|
||||
void updateQtVersions();
|
||||
|
||||
|
||||
@@ -305,13 +305,13 @@ QString Qt4BuildConfiguration::defaultMakeTarget() const
|
||||
|
||||
switch (tc->type()) {
|
||||
case ToolChain::GCCE:
|
||||
case ToolChain::GCCE_GNUPOC:
|
||||
return symbianMakeTarget(buildConfig, QLatin1String("gcce"));
|
||||
case ToolChain::RVCT_ARMV5:
|
||||
return symbianMakeTarget(buildConfig, QLatin1String("armv5"));
|
||||
case ToolChain::RVCT_ARMV6:
|
||||
case ToolChain::RVCT_ARMV6_GNUPOC:
|
||||
return symbianMakeTarget(buildConfig, QLatin1String("armv6"));
|
||||
case ToolChain::RVCT_ARMV5_GNUPOC:
|
||||
case ToolChain::GCCE_GNUPOC:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ bool Qt4RunConfiguration::isEnabled(ProjectExplorer::BuildConfiguration *configu
|
||||
switch (type) {
|
||||
case ToolChain::MSVC: case ToolChain::WINCE:
|
||||
case ToolChain::GCC: case ToolChain::MinGW:
|
||||
case ToolChain::GCCE_GNUPOC: case ToolChain::RVCT_ARMV6_GNUPOC:
|
||||
case ToolChain::GCCE_GNUPOC: case ToolChain::RVCT_ARMV5_GNUPOC:
|
||||
case ToolChain::OTHER: case ToolChain::UNKNOWN:
|
||||
case ToolChain::INVALID:
|
||||
enabled = true;
|
||||
|
||||
@@ -1231,12 +1231,13 @@ void QtVersion::updateToolChainAndMkspec() const
|
||||
m_toolChains << ToolChainPtr(ProjectExplorer::ToolChain::createWinCEToolChain(msvcVersion(), wincePlatformName));
|
||||
m_targetIds.insert(DESKTOP_TARGET_ID);
|
||||
} else if (makefileGenerator == QLatin1String("SYMBIAN_ABLD") ||
|
||||
makefileGenerator == QLatin1String("SYMBIAN_SBSV2")) {
|
||||
makefileGenerator == QLatin1String("SYMBIAN_SBSV2") ||
|
||||
makefileGenerator == QLatin1String("SYMBIAN_UNIX")) {
|
||||
if (S60Manager *s60mgr = S60Manager::instance()) {
|
||||
# ifdef Q_OS_WIN
|
||||
m_targetIds.insert(QLatin1String(S60_DEVICE_TARGET_ID));
|
||||
m_toolChains << ToolChainPtr(s60mgr->createGCCEToolChain(this));
|
||||
if (!qgetenv("RVCT22BIN").isEmpty())
|
||||
if (S60Manager::hasRvctCompiler())
|
||||
m_toolChains << ToolChainPtr(s60mgr->createRVCTToolChain(this, ProjectExplorer::ToolChain::RVCT_ARMV5))
|
||||
<< ToolChainPtr(s60mgr->createRVCTToolChain(this, ProjectExplorer::ToolChain::RVCT_ARMV6));
|
||||
if (!mwcDirectory().isEmpty()) {
|
||||
@@ -1244,8 +1245,9 @@ void QtVersion::updateToolChainAndMkspec() const
|
||||
m_targetIds.insert(QLatin1String(S60_EMULATOR_TARGET_ID));
|
||||
}
|
||||
# else
|
||||
m_toolChains << ToolChainPtr(s60mgr->createGCCE_GnuPocToolChain(this))
|
||||
<< ToolChainPtr(s60mgr->createRVCTToolChain(this, ProjectExplorer::ToolChain::RVCT_ARMV6_GNUPOC));
|
||||
if (S60Manager::hasRvctCompiler())
|
||||
m_toolChains << ToolChainPtr(s60mgr->createRVCTToolChain(this, ProjectExplorer::ToolChain::RVCT_ARMV5_GNUPOC));
|
||||
m_toolChains << ToolChainPtr(s60mgr->createGCCE_GnuPocToolChain(this));
|
||||
m_targetIds.insert(QLatin1String(S60_DEVICE_TARGET_ID));
|
||||
# endif
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user