2012-04-18 20:30:57 +03:00
|
|
|
/**************************************************************************
|
|
|
|
|
**
|
2013-01-28 17:12:19 +01:00
|
|
|
** Copyright (c) 2013 BogDan Vatra <bog_dan_ro@yahoo.com>
|
2012-10-02 09:12:39 +02:00
|
|
|
** Contact: http://www.qt-project.org/legal
|
2012-04-18 20:30:57 +03:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** This file is part of Qt Creator.
|
2012-04-18 20:30:57 +03:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** Commercial License Usage
|
|
|
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
|
|
|
** accordance with the commercial license agreement provided with the
|
|
|
|
|
** Software or, alternatively, in accordance with the terms contained in
|
|
|
|
|
** a written agreement between you and Digia. For licensing terms and
|
|
|
|
|
** conditions see http://qt.digia.com/licensing. For further information
|
|
|
|
|
** use the contact form at http://qt.digia.com/contact-us.
|
2012-04-18 20:30:57 +03:00
|
|
|
**
|
|
|
|
|
** GNU Lesser General Public License Usage
|
2012-10-02 09:12:39 +02:00
|
|
|
** 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, Digia gives you certain additional
|
|
|
|
|
** rights. These rights are described in the Digia Qt LGPL Exception
|
2012-04-18 20:30:57 +03:00
|
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
****************************************************************************/
|
2012-04-18 20:30:57 +03:00
|
|
|
|
|
|
|
|
#include "androiddeploystep.h"
|
|
|
|
|
|
|
|
|
|
#include "androidconstants.h"
|
|
|
|
|
#include "androiddeploystepwidget.h"
|
|
|
|
|
#include "androidglobal.h"
|
|
|
|
|
#include "androidpackagecreationstep.h"
|
|
|
|
|
#include "androidrunconfiguration.h"
|
2012-04-24 15:49:09 +02:00
|
|
|
#include "androidmanager.h"
|
2013-01-25 16:49:22 +01:00
|
|
|
#include "androidtoolchain.h"
|
2013-09-10 19:19:31 +02:00
|
|
|
#include "androiddevicedialog.h"
|
2012-04-18 20:30:57 +03:00
|
|
|
|
2013-01-22 16:03:31 +01:00
|
|
|
#include <coreplugin/messagemanager.h>
|
2012-04-18 20:30:57 +03:00
|
|
|
#include <projectexplorer/buildconfiguration.h>
|
2013-08-30 17:28:36 +02:00
|
|
|
#include <projectexplorer/deployconfiguration.h>
|
2012-04-18 20:30:57 +03:00
|
|
|
#include <projectexplorer/projectexplorerconstants.h>
|
2013-08-30 17:28:36 +02:00
|
|
|
#include <projectexplorer/buildsteplist.h>
|
2012-04-18 20:30:57 +03:00
|
|
|
#include <projectexplorer/target.h>
|
2013-10-16 12:10:22 +02:00
|
|
|
#include <qt4projectmanager/qmakebuildconfiguration.h>
|
|
|
|
|
#include <qt4projectmanager/qmakeproject.h>
|
|
|
|
|
#include <qt4projectmanager/qmakenodes.h>
|
2012-04-18 20:30:57 +03:00
|
|
|
|
2012-09-03 18:31:44 +02:00
|
|
|
#include <qtsupport/qtkitinformation.h>
|
2012-04-18 20:30:57 +03:00
|
|
|
|
|
|
|
|
#include <QDir>
|
|
|
|
|
|
|
|
|
|
#define ASSERT_STATE(state) ASSERT_STATE_GENERIC(State, state, m_state)
|
|
|
|
|
|
2013-09-05 01:52:17 +02:00
|
|
|
using namespace Core;
|
2012-04-18 20:30:57 +03:00
|
|
|
using namespace ProjectExplorer;
|
2013-10-16 11:02:37 +02:00
|
|
|
using namespace QmakeProjectManager;
|
2012-04-18 20:30:57 +03:00
|
|
|
|
|
|
|
|
namespace Android {
|
|
|
|
|
namespace Internal {
|
|
|
|
|
|
2012-06-25 00:48:17 -07:00
|
|
|
static const char USE_LOCAL_QT_KEY[] = "Qt4ProjectManager.AndroidDeployStep.UseLocalQtLibs";
|
2013-01-22 16:03:31 +01:00
|
|
|
static const char DEPLOY_ACTION_KEY[] = "Qt4ProjectManager.AndroidDeployStep.DeployAction";
|
2012-06-25 00:48:17 -07:00
|
|
|
|
2013-09-05 01:52:17 +02:00
|
|
|
const Id AndroidDeployStep::Id("Qt4ProjectManager.AndroidDeployStep");
|
2012-04-18 20:30:57 +03:00
|
|
|
|
|
|
|
|
AndroidDeployStep::AndroidDeployStep(ProjectExplorer::BuildStepList *parent)
|
|
|
|
|
: BuildStep(parent, Id)
|
|
|
|
|
{
|
|
|
|
|
ctor();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AndroidDeployStep::AndroidDeployStep(ProjectExplorer::BuildStepList *parent,
|
|
|
|
|
AndroidDeployStep *other)
|
|
|
|
|
: BuildStep(parent, other)
|
|
|
|
|
{
|
|
|
|
|
ctor();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AndroidDeployStep::~AndroidDeployStep() { }
|
|
|
|
|
|
|
|
|
|
void AndroidDeployStep::ctor()
|
|
|
|
|
{
|
|
|
|
|
//: AndroidDeployStep default display name
|
|
|
|
|
setDefaultDisplayName(tr("Deploy to Android device"));
|
|
|
|
|
m_deployAction = NoDeploy;
|
2013-04-19 12:27:58 +02:00
|
|
|
|
2013-06-13 16:38:03 +02:00
|
|
|
QtSupport::BaseQtVersion *qt = QtSupport::QtKitInformation::qtVersion(target()->kit());
|
|
|
|
|
m_bundleQtAvailable = qt && qt->qtVersion() >= QtSupport::QtVersionNumber(5, 0, 0);
|
|
|
|
|
if (m_bundleQtAvailable)
|
|
|
|
|
m_deployAction = BundleLibraries;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
connect(ProjectExplorer::KitManager::instance(), SIGNAL(kitUpdated(ProjectExplorer::Kit*)),
|
2013-10-10 17:41:34 +02:00
|
|
|
this, SLOT(kitUpdated(ProjectExplorer::Kit*)));
|
2012-04-18 20:30:57 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool AndroidDeployStep::init()
|
|
|
|
|
{
|
2012-04-24 15:49:09 +02:00
|
|
|
m_packageName = AndroidManager::packageName(target());
|
2013-08-28 15:23:04 +02:00
|
|
|
m_deviceAPILevel = AndroidManager::minimumSDK(target());
|
2013-07-05 18:54:42 +02:00
|
|
|
m_targetArch = AndroidManager::targetArch(target());
|
2012-04-18 20:30:57 +03:00
|
|
|
|
2013-09-10 19:19:31 +02:00
|
|
|
AndroidDeviceInfo info = AndroidConfigurations::instance().showDeviceDialog(project(), m_deviceAPILevel, m_targetArch);
|
|
|
|
|
if (info.serialNumber.isEmpty()) // aborted
|
2012-04-18 20:30:57 +03:00
|
|
|
return false;
|
2013-09-10 19:19:31 +02:00
|
|
|
|
|
|
|
|
m_deviceAPILevel = info.sdk;
|
|
|
|
|
m_deviceSerialNumber = info.serialNumber;
|
|
|
|
|
|
|
|
|
|
if (info.type == AndroidDeviceInfo::Emulator)
|
|
|
|
|
m_avdName = m_deviceSerialNumber;
|
2012-04-18 20:30:57 +03:00
|
|
|
|
2012-09-03 18:31:44 +02:00
|
|
|
QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target()->kit());
|
2012-04-24 15:49:09 +02:00
|
|
|
if (!version)
|
2012-04-18 20:30:57 +03:00
|
|
|
return false;
|
2012-07-07 16:36:25 +03:00
|
|
|
|
|
|
|
|
const Qt4BuildConfiguration *bc = static_cast<Qt4BuildConfiguration *>(target()->activeBuildConfiguration());
|
|
|
|
|
if (!bc)
|
|
|
|
|
return false;
|
|
|
|
|
|
2013-08-30 17:28:36 +02:00
|
|
|
m_signPackage = false;
|
|
|
|
|
// find AndroidPackageCreationStep
|
|
|
|
|
foreach (BuildStep *step, target()->activeDeployConfiguration()->stepList()->steps()) {
|
|
|
|
|
if (AndroidPackageCreationStep *apcs = qobject_cast<AndroidPackageCreationStep *>(step)) {
|
|
|
|
|
m_signPackage = apcs->signPackage();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-04 21:46:15 -03:00
|
|
|
m_qtVersionSourcePath = version->qmakeProperty("QT_INSTALL_PREFIX");
|
2012-04-24 15:49:09 +02:00
|
|
|
m_androidDirPath = AndroidManager::dirPath(target());
|
|
|
|
|
m_apkPathDebug = AndroidManager::apkPath(target(), AndroidManager::DebugBuild).toString();
|
|
|
|
|
m_apkPathRelease = AndroidManager::apkPath(target(), AndroidManager::ReleaseBuildSigned).toString();
|
|
|
|
|
m_buildDirectory = static_cast<Qt4Project *>(target()->project())->rootQt4ProjectNode()->buildDir();
|
2012-04-18 20:30:57 +03:00
|
|
|
m_runDeployAction = m_deployAction;
|
2013-01-25 16:49:22 +01:00
|
|
|
ToolChain *tc = ToolChainKitInformation::toolChain(target()->kit());
|
|
|
|
|
if (!tc || tc->type() != QLatin1String(Constants::ANDROID_TOOLCHAIN_TYPE)) {
|
2013-02-12 15:34:00 +01:00
|
|
|
raiseError(tr("No Android toolchain selected."));
|
2013-01-25 16:49:22 +01:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
m_ndkToolChainVersion = static_cast<AndroidToolChain *>(tc)->ndkToolChainVersion();
|
2013-02-26 15:53:33 +01:00
|
|
|
|
2013-10-16 11:02:37 +02:00
|
|
|
QString arch = static_cast<Qt4Project *>(project())->rootQt4ProjectNode()->singleVariableValue(QmakeProjectManager::AndroidArchVar);
|
2013-02-26 15:53:33 +01:00
|
|
|
if (!arch.isEmpty())
|
|
|
|
|
m_libgnustl = AndroidManager::libGnuStl(arch, m_ndkToolChainVersion);
|
2012-04-18 20:30:57 +03:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AndroidDeployStep::run(QFutureInterface<bool> &fi)
|
|
|
|
|
{
|
|
|
|
|
fi.reportResult(deployPackage());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BuildStepConfigWidget *AndroidDeployStep::createConfigWidget()
|
|
|
|
|
{
|
|
|
|
|
return new AndroidDeployStepWidget(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AndroidDeployStep::AndroidDeployAction AndroidDeployStep::deployAction()
|
|
|
|
|
{
|
|
|
|
|
return m_deployAction;
|
|
|
|
|
}
|
|
|
|
|
|
2012-06-25 00:48:17 -07:00
|
|
|
bool AndroidDeployStep::fromMap(const QVariantMap &map)
|
|
|
|
|
{
|
2013-01-22 16:03:31 +01:00
|
|
|
m_deployAction = AndroidDeployAction(map.value(QLatin1String(DEPLOY_ACTION_KEY), NoDeploy).toInt());
|
2013-05-22 17:24:15 +02:00
|
|
|
QVariant useLocalQt = map.value(QLatin1String(USE_LOCAL_QT_KEY));
|
|
|
|
|
if (useLocalQt.isValid()) { // old settings
|
|
|
|
|
if (useLocalQt.toBool() && m_deployAction == NoDeploy)
|
|
|
|
|
m_deployAction = BundleLibraries;
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-22 16:03:31 +01:00
|
|
|
if (m_deployAction == InstallQASI)
|
|
|
|
|
m_deployAction = NoDeploy;
|
2013-06-13 16:38:03 +02:00
|
|
|
QtSupport::BaseQtVersion *qtVersion
|
|
|
|
|
= QtSupport::QtKitInformation::qtVersion(target()->kit());
|
|
|
|
|
if (m_deployAction == BundleLibraries)
|
|
|
|
|
if (!qtVersion || qtVersion->qtVersion() < QtSupport::QtVersionNumber(5, 0, 0))
|
|
|
|
|
m_deployAction = NoDeploy; // the kit changed to a non qt5 kit
|
|
|
|
|
|
|
|
|
|
m_bundleQtAvailable = qtVersion && qtVersion->qtVersion() >= QtSupport::QtVersionNumber(5, 0, 0);
|
|
|
|
|
|
2012-06-25 00:48:17 -07:00
|
|
|
return ProjectExplorer::BuildStep::fromMap(map);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QVariantMap AndroidDeployStep::toMap() const
|
|
|
|
|
{
|
|
|
|
|
QVariantMap map = ProjectExplorer::BuildStep::toMap();
|
2013-01-22 16:03:31 +01:00
|
|
|
map.insert(QLatin1String(DEPLOY_ACTION_KEY), m_deployAction);
|
2012-06-25 00:48:17 -07:00
|
|
|
return map;
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-13 16:38:03 +02:00
|
|
|
void AndroidDeployStep::kitUpdated(Kit *kit)
|
|
|
|
|
{
|
|
|
|
|
if (kit != target()->kit())
|
|
|
|
|
return;
|
|
|
|
|
QtSupport::BaseQtVersion *qtVersion
|
|
|
|
|
= QtSupport::QtKitInformation::qtVersion(target()->kit());
|
|
|
|
|
|
|
|
|
|
bool newBundleQtAvailable = qtVersion && qtVersion->qtVersion() >= QtSupport::QtVersionNumber(5, 0, 0);
|
|
|
|
|
if (m_bundleQtAvailable != newBundleQtAvailable) {
|
|
|
|
|
m_bundleQtAvailable = newBundleQtAvailable;
|
|
|
|
|
|
|
|
|
|
if (!m_bundleQtAvailable && m_deployAction == BundleLibraries)
|
|
|
|
|
m_deployAction = NoDeploy; // the kit changed to a non qt5 kit
|
|
|
|
|
|
|
|
|
|
emit deployOptionsChanged();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool AndroidDeployStep::bundleQtOptionAvailable()
|
|
|
|
|
{
|
|
|
|
|
return m_bundleQtAvailable;
|
|
|
|
|
}
|
|
|
|
|
|
2013-05-22 17:24:15 +02:00
|
|
|
void AndroidDeployStep::setDeployAction(AndroidDeployStep::AndroidDeployAction deploy)
|
2012-04-18 20:30:57 +03:00
|
|
|
{
|
2013-05-22 17:24:15 +02:00
|
|
|
m_deployAction = deploy;
|
|
|
|
|
|
2013-04-19 12:27:58 +02:00
|
|
|
AndroidManager::updateDeploymentSettings(target());
|
2012-04-18 20:30:57 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool AndroidDeployStep::runCommand(QProcess *buildProc,
|
|
|
|
|
const QString &program, const QStringList &arguments)
|
|
|
|
|
{
|
|
|
|
|
writeOutput(tr("Package deploy: Running command '%1 %2'.").arg(program).arg(arguments.join(QLatin1String(" "))), BuildStep::MessageOutput);
|
|
|
|
|
buildProc->start(program, arguments);
|
|
|
|
|
if (!buildProc->waitForStarted()) {
|
|
|
|
|
writeOutput(tr("Packaging error: Could not start command '%1 %2'. Reason: %3")
|
|
|
|
|
.arg(program).arg(arguments.join(QLatin1String(" "))).arg(buildProc->errorString()), BuildStep::ErrorMessageOutput);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2013-07-05 18:54:42 +02:00
|
|
|
if (!buildProc->waitForFinished(2 * 60 * 1000)
|
|
|
|
|
|| buildProc->error() != QProcess::UnknownError
|
2012-04-18 20:30:57 +03:00
|
|
|
|| buildProc->exitCode() != 0) {
|
|
|
|
|
QString mainMessage = tr("Packaging Error: Command '%1 %2' failed.")
|
|
|
|
|
.arg(program).arg(arguments.join(QLatin1String(" ")));
|
|
|
|
|
if (buildProc->error() != QProcess::UnknownError)
|
|
|
|
|
mainMessage += tr(" Reason: %1").arg(buildProc->errorString());
|
|
|
|
|
else
|
|
|
|
|
mainMessage += tr("Exit code: %1").arg(buildProc->exitCode());
|
|
|
|
|
writeOutput(mainMessage, BuildStep::ErrorMessageOutput);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AndroidDeployStep::handleBuildOutput()
|
|
|
|
|
{
|
|
|
|
|
QProcess *const buildProc = qobject_cast<QProcess *>(sender());
|
|
|
|
|
if (!buildProc)
|
|
|
|
|
return;
|
|
|
|
|
emit addOutput(QString::fromLocal8Bit(buildProc->readAllStandardOutput())
|
|
|
|
|
, BuildStep::NormalOutput);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AndroidDeployStep::handleBuildError()
|
|
|
|
|
{
|
|
|
|
|
QProcess *const buildProc = qobject_cast<QProcess *>(sender());
|
|
|
|
|
if (!buildProc)
|
|
|
|
|
return;
|
|
|
|
|
emit addOutput(QString::fromLocal8Bit(buildProc->readAllStandardError())
|
|
|
|
|
, BuildStep::ErrorOutput);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString AndroidDeployStep::deviceSerialNumber()
|
|
|
|
|
{
|
|
|
|
|
return m_deviceSerialNumber;
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-22 16:03:31 +01:00
|
|
|
unsigned int AndroidDeployStep::remoteModificationTime(const QString &fullDestination, QHash<QString, unsigned int> *cache)
|
2012-04-18 20:30:57 +03:00
|
|
|
{
|
2013-01-22 16:03:31 +01:00
|
|
|
QString destination = QFileInfo(fullDestination).absolutePath();
|
|
|
|
|
QProcess process;
|
|
|
|
|
QHash<QString, unsigned int>::const_iterator it = cache->find(fullDestination);
|
|
|
|
|
if (it != cache->constEnd())
|
|
|
|
|
return *it;
|
2013-02-24 18:04:36 +04:00
|
|
|
QStringList arguments = AndroidDeviceInfo::adbSelector(m_deviceSerialNumber);
|
|
|
|
|
arguments << QLatin1String("ls") << destination;
|
2013-01-22 16:03:31 +01:00
|
|
|
process.start(AndroidConfigurations::instance().adbToolPath().toString(), arguments);
|
|
|
|
|
process.waitForFinished(-1);
|
|
|
|
|
if (process.error() != QProcess::UnknownError
|
|
|
|
|
|| process.exitCode() != 0)
|
|
|
|
|
return -1;
|
|
|
|
|
QByteArray output = process.readAll();
|
|
|
|
|
output.replace("\r\n", "\n");
|
|
|
|
|
QList<QByteArray> lines = output.split('\n');
|
|
|
|
|
foreach (const QByteArray &line, lines) {
|
|
|
|
|
// do some checks if we got what we expected..
|
|
|
|
|
if (line.count() < (3 * 8 + 3))
|
|
|
|
|
continue;
|
|
|
|
|
if (line.at(8) != ' '
|
|
|
|
|
|| line.at(17) != ' '
|
|
|
|
|
|| line.at(26) != ' ')
|
|
|
|
|
continue;
|
|
|
|
|
bool ok;
|
|
|
|
|
int time = line.mid(18, 8).toUInt(&ok, 16);
|
|
|
|
|
if (!ok)
|
|
|
|
|
continue;
|
|
|
|
|
QString fileName = QString::fromLocal8Bit(line.mid(27));
|
|
|
|
|
cache->insert(destination + QLatin1Char('/') + fileName, time);
|
|
|
|
|
}
|
|
|
|
|
it = cache->find(fullDestination);
|
|
|
|
|
if (it != cache->constEnd())
|
|
|
|
|
return *it;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AndroidDeployStep::collectFiles(QList<DeployItem> *deployList, const QString &localPath, const QString &remotePath,
|
|
|
|
|
bool strip, const QStringList &filter)
|
|
|
|
|
{
|
|
|
|
|
QDirIterator libsIt(localPath, filter, QDir::NoFilter, QDirIterator::Subdirectories);
|
|
|
|
|
int pos = localPath.size();
|
2012-04-18 20:30:57 +03:00
|
|
|
while (libsIt.hasNext()) {
|
|
|
|
|
libsIt.next();
|
2013-01-22 16:03:31 +01:00
|
|
|
const QString destFile(remotePath + libsIt.filePath().mid(pos));
|
|
|
|
|
if (!libsIt.fileInfo().isDir()) {
|
|
|
|
|
deployList->append(DeployItem(libsIt.filePath(),
|
|
|
|
|
libsIt.fileInfo().lastModified().toTime_t(),
|
|
|
|
|
destFile, strip));
|
2012-04-18 20:30:57 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-22 16:03:31 +01:00
|
|
|
void AndroidDeployStep::fetchRemoteModificationTimes(QList<DeployItem> *deployList)
|
|
|
|
|
{
|
|
|
|
|
QHash<QString, unsigned int> cache;
|
|
|
|
|
for (int i = 0; i < deployList->count(); ++i) {
|
|
|
|
|
DeployItem &item = (*deployList)[i];
|
|
|
|
|
item.remoteTimeStamp
|
|
|
|
|
= remoteModificationTime(item.remoteFileName, &cache);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AndroidDeployStep::filterModificationTimes(QList<DeployItem> *deployList)
|
|
|
|
|
{
|
|
|
|
|
QList<DeployItem>::iterator it = deployList->begin();
|
|
|
|
|
while (it != deployList->end()) {
|
|
|
|
|
int index = it - deployList->begin();
|
|
|
|
|
Q_UNUSED(index);
|
|
|
|
|
if ((*it).localTimeStamp <= (*it).remoteTimeStamp)
|
|
|
|
|
it = deployList->erase(it);
|
|
|
|
|
else
|
|
|
|
|
++it;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AndroidDeployStep::copyFilesToTemp(QList<DeployItem> *deployList, const QString &tempDirectory, const QString &sourcePrefix)
|
|
|
|
|
{
|
|
|
|
|
QDir dir;
|
|
|
|
|
|
|
|
|
|
int pos = sourcePrefix.size();
|
|
|
|
|
for (int i = 0; i < deployList->count(); ++i) {
|
|
|
|
|
DeployItem &item = (*deployList)[i];
|
|
|
|
|
if (!item.needsStrip)
|
|
|
|
|
continue;
|
|
|
|
|
const QString destFile(tempDirectory + item.localFileName.mid(pos));
|
|
|
|
|
dir.mkpath(QFileInfo(destFile).absolutePath());
|
|
|
|
|
QFile::copy(item.localFileName, destFile);
|
|
|
|
|
item.localFileName = destFile;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-25 16:49:22 +01:00
|
|
|
void AndroidDeployStep::stripFiles(const QList<DeployItem> &deployList, Abi::Architecture architecture, const QString &ndkToolchainVersion)
|
2013-01-22 16:03:31 +01:00
|
|
|
{
|
|
|
|
|
QProcess stripProcess;
|
|
|
|
|
foreach (const DeployItem &item, deployList) {
|
2013-01-25 16:49:22 +01:00
|
|
|
stripProcess.start(AndroidConfigurations::instance().stripPath(architecture, ndkToolchainVersion).toString(),
|
2013-01-22 16:03:31 +01:00
|
|
|
QStringList()<<QLatin1String("--strip-unneeded") << item.localFileName);
|
|
|
|
|
stripProcess.waitForStarted();
|
|
|
|
|
if (!stripProcess.waitForFinished())
|
|
|
|
|
stripProcess.kill();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AndroidDeployStep::deployFiles(QProcess *process, const QList<DeployItem> &deployList)
|
|
|
|
|
{
|
|
|
|
|
foreach (const DeployItem &item, deployList) {
|
|
|
|
|
runCommand(process, AndroidConfigurations::instance().adbToolPath().toString(),
|
2013-02-24 18:04:36 +04:00
|
|
|
AndroidDeviceInfo::adbSelector(m_deviceSerialNumber)
|
2013-01-22 16:03:31 +01:00
|
|
|
<< QLatin1String("push") << item.localFileName
|
|
|
|
|
<< item.remoteFileName);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-18 20:30:57 +03:00
|
|
|
bool AndroidDeployStep::deployPackage()
|
|
|
|
|
{
|
2013-07-05 18:54:42 +02:00
|
|
|
if (!m_avdName.isEmpty()) {
|
2013-10-17 17:40:56 +02:00
|
|
|
if (!AndroidConfigurations::instance().findAvd(m_deviceAPILevel, m_targetArch)
|
|
|
|
|
&& !AndroidConfigurations::instance().startAVDAsync(m_avdName))
|
2013-07-05 18:54:42 +02:00
|
|
|
return false;
|
|
|
|
|
m_deviceSerialNumber = AndroidConfigurations::instance().waitForAvd(m_deviceAPILevel, m_targetArch);
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-18 20:30:57 +03:00
|
|
|
QProcess *const deployProc = new QProcess;
|
|
|
|
|
connect(deployProc, SIGNAL(readyReadStandardOutput()), this,
|
|
|
|
|
SLOT(handleBuildOutput()));
|
|
|
|
|
connect(deployProc, SIGNAL(readyReadStandardError()), this,
|
|
|
|
|
SLOT(handleBuildError()));
|
|
|
|
|
|
|
|
|
|
if (m_runDeployAction == DeployLocal) {
|
2012-09-28 16:13:16 +02:00
|
|
|
writeOutput(tr("Deploy Qt libraries. This may take some time, please wait."));
|
2012-04-18 20:30:57 +03:00
|
|
|
const QString tempPath = QDir::tempPath() + QLatin1String("/android_qt_libs_") + m_packageName;
|
|
|
|
|
AndroidPackageCreationStep::removeDirectory(tempPath);
|
2013-01-22 16:03:31 +01:00
|
|
|
|
|
|
|
|
const QString remoteRoot = QLatin1String("/data/local/tmp/qt");
|
|
|
|
|
QList<DeployItem> deployList;
|
|
|
|
|
collectFiles(&deployList,
|
|
|
|
|
m_qtVersionSourcePath + QLatin1String("/lib"),
|
|
|
|
|
remoteRoot + QLatin1String("/lib"),
|
|
|
|
|
true,
|
|
|
|
|
QStringList() << QLatin1String("*.so"));
|
2013-02-26 15:53:33 +01:00
|
|
|
|
|
|
|
|
// don't use the libgnustl_shared.so from the qt directory
|
|
|
|
|
for (int i = 0; i < deployList.count(); ++i) {
|
|
|
|
|
if (deployList.at(i).remoteFileName == QLatin1String("/data/local/tmp/qt/lib/libgnustl_shared.so")) {
|
|
|
|
|
deployList.removeAt(i);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// We want to deploy that *always*
|
|
|
|
|
// since even if the timestamps did not change, the toolchain might have changed
|
|
|
|
|
// leading to a different file
|
|
|
|
|
deployList.append(DeployItem(m_libgnustl,
|
|
|
|
|
QDateTime::currentDateTimeUtc().toTime_t(),
|
|
|
|
|
QLatin1String("/data/local/tmp/qt/lib/libgnustl_shared.so"), false));
|
|
|
|
|
|
2013-01-22 16:03:31 +01:00
|
|
|
collectFiles(&deployList,
|
|
|
|
|
m_qtVersionSourcePath + QLatin1String("/plugins"),
|
|
|
|
|
remoteRoot + QLatin1String("/plugins"),
|
|
|
|
|
true);
|
|
|
|
|
collectFiles(&deployList,
|
|
|
|
|
m_qtVersionSourcePath + QLatin1String("/imports"),
|
|
|
|
|
remoteRoot + QLatin1String("/imports"),
|
|
|
|
|
true);
|
|
|
|
|
collectFiles(&deployList,
|
|
|
|
|
m_qtVersionSourcePath + QLatin1String("/qml"),
|
|
|
|
|
remoteRoot + QLatin1String("/qml"),
|
|
|
|
|
true);
|
|
|
|
|
collectFiles(&deployList,
|
|
|
|
|
m_qtVersionSourcePath + QLatin1String("/jar"),
|
|
|
|
|
remoteRoot + QLatin1String("/jar"),
|
|
|
|
|
true);
|
|
|
|
|
|
|
|
|
|
fetchRemoteModificationTimes(&deployList);
|
|
|
|
|
filterModificationTimes(&deployList);
|
|
|
|
|
copyFilesToTemp(&deployList, tempPath, m_qtVersionSourcePath);
|
2013-01-25 16:49:22 +01:00
|
|
|
stripFiles(deployList, target()->activeRunConfiguration()->abi().architecture(), m_ndkToolChainVersion);
|
2013-01-22 16:03:31 +01:00
|
|
|
deployFiles(deployProc, deployList);
|
|
|
|
|
|
2012-04-18 20:30:57 +03:00
|
|
|
AndroidPackageCreationStep::removeDirectory(tempPath);
|
|
|
|
|
}
|
|
|
|
|
|
2012-04-24 15:49:09 +02:00
|
|
|
deployProc->setWorkingDirectory(m_androidDirPath.toString());
|
2012-04-18 20:30:57 +03:00
|
|
|
|
|
|
|
|
writeOutput(tr("Installing package onto %1.").arg(m_deviceSerialNumber));
|
2012-04-24 15:49:09 +02:00
|
|
|
runCommand(deployProc, AndroidConfigurations::instance().adbToolPath().toString(),
|
2013-02-24 18:04:36 +04:00
|
|
|
AndroidDeviceInfo::adbSelector(m_deviceSerialNumber) << QLatin1String("uninstall") << m_packageName);
|
2012-04-18 20:30:57 +03:00
|
|
|
QString package = m_apkPathDebug;
|
|
|
|
|
|
2013-08-30 17:28:36 +02:00
|
|
|
if (m_signPackage && QFile::exists(m_apkPathRelease))
|
2012-04-18 20:30:57 +03:00
|
|
|
package = m_apkPathRelease;
|
|
|
|
|
|
2012-04-24 15:49:09 +02:00
|
|
|
if (!runCommand(deployProc, AndroidConfigurations::instance().adbToolPath().toString(),
|
2013-02-24 18:04:36 +04:00
|
|
|
AndroidDeviceInfo::adbSelector(m_deviceSerialNumber) << QLatin1String("install") << package)) {
|
2012-09-28 16:13:16 +02:00
|
|
|
raiseError(tr("Package installation failed."));
|
2012-04-18 20:30:57 +03:00
|
|
|
disconnect(deployProc, 0, this, 0);
|
|
|
|
|
deployProc->deleteLater();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-28 16:13:16 +02:00
|
|
|
writeOutput(tr("Pulling files necessary for debugging."));
|
2012-04-24 15:49:09 +02:00
|
|
|
runCommand(deployProc, AndroidConfigurations::instance().adbToolPath().toString(),
|
2013-02-24 18:04:36 +04:00
|
|
|
AndroidDeviceInfo::adbSelector(m_deviceSerialNumber)
|
2012-04-18 20:30:57 +03:00
|
|
|
<< QLatin1String("pull") << QLatin1String("/system/bin/app_process")
|
|
|
|
|
<< QString::fromLatin1("%1/app_process").arg(m_buildDirectory));
|
2012-04-24 15:49:09 +02:00
|
|
|
runCommand(deployProc, AndroidConfigurations::instance().adbToolPath().toString(),
|
2013-02-24 18:04:36 +04:00
|
|
|
AndroidDeviceInfo::adbSelector(m_deviceSerialNumber) << QLatin1String("pull")
|
2012-04-18 20:30:57 +03:00
|
|
|
<< QLatin1String("/system/lib/libc.so")
|
|
|
|
|
<< QString::fromLatin1("%1/libc.so").arg(m_buildDirectory));
|
|
|
|
|
disconnect(deployProc, 0, this, 0);
|
|
|
|
|
deployProc->deleteLater();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AndroidDeployStep::raiseError(const QString &errorString)
|
|
|
|
|
{
|
|
|
|
|
emit addTask(Task(Task::Error, errorString, Utils::FileName::fromString(QString()), -1,
|
2013-08-19 15:35:14 +02:00
|
|
|
ProjectExplorer::Constants::TASK_CATEGORY_DEPLOYMENT));
|
2012-04-18 20:30:57 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AndroidDeployStep::writeOutput(const QString &text, OutputFormat format)
|
|
|
|
|
{
|
|
|
|
|
emit addOutput(text, format);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace Internal
|
2013-10-16 11:02:37 +02:00
|
|
|
} // namespace Android
|