Commit 381b04fa authored by BogDan Vatra's avatar BogDan Vatra Committed by Daniel Teske
Browse files

Android: Remove Necessitas support



Change-Id: I082acfad3b20d5e096fbb2ca3db775bb527eaf7a
Reviewed-by: default avatarBogDan Vatra <bogdan@kde.org>
parent c4451570
......@@ -17,12 +17,6 @@ HEADERS += \
androidtoolchain.h \
androidpackageinstallationstep.h \
androidpackageinstallationfactory.h \
androidpackagecreationstep.h \
androidpackagecreationfactory.h \
androidpackagecreationwidget.h \
androiddeploystep.h \
androiddeploystepwidget.h \
androiddeploystepfactory.h \
androiderrormessage.h \
androidglobal.h \
androidrunner.h \
......@@ -69,12 +63,6 @@ SOURCES += \
androidtoolchain.cpp \
androidpackageinstallationstep.cpp \
androidpackageinstallationfactory.cpp \
androidpackagecreationstep.cpp \
androidpackagecreationfactory.cpp \
androidpackagecreationwidget.cpp \
androiddeploystep.cpp \
androiddeploystepwidget.cpp \
androiddeploystepfactory.cpp \
androiderrormessage.cpp \
androidrunner.cpp \
androiddebugsupport.cpp \
......@@ -111,8 +99,6 @@ SOURCES += \
FORMS += \
androidsettingswidget.ui \
androidpackagecreationwidget.ui \
androiddeploystepwidget.ui \
addnewavddialog.ui \
androidcreatekeystorecertificate.ui \
androiddevicedialog.ui \
......
......@@ -39,13 +39,6 @@ QtcPlugin {
"androiddevicedialog.ui",
"androiddeployconfiguration.cpp",
"androiddeployconfiguration.h",
"androiddeploystep.cpp",
"androiddeploystep.h",
"androiddeploystepfactory.cpp",
"androiddeploystepfactory.h",
"androiddeploystepwidget.cpp",
"androiddeploystepwidget.h",
"androiddeploystepwidget.ui",
"androiddeployqtwidget.cpp",
"androiddeployqtwidget.h",
"androiddeployqtwidget.ui",
......@@ -70,13 +63,6 @@ QtcPlugin {
"androidmanifesteditorfactory.h",
"androidmanifesteditorwidget.cpp",
"androidmanifesteditorwidget.h",
"androidpackagecreationfactory.cpp",
"androidpackagecreationfactory.h",
"androidpackagecreationstep.cpp",
"androidpackagecreationstep.h",
"androidpackagecreationwidget.cpp",
"androidpackagecreationwidget.h",
"androidpackagecreationwidget.ui",
"androidpackageinstallationfactory.cpp",
"androidpackageinstallationfactory.h",
"androidpackageinstallationstep.cpp",
......
......@@ -844,7 +844,7 @@ QString AndroidConfig::bestNdkPlatformMatch(const QString &targetAPI) const
if (apiLevel <= target)
return QString::fromLatin1("android-%1").arg(apiLevel);
}
return QLatin1String("android-8");
return QLatin1String("android-9");
}
FileName AndroidConfig::sdkLocation() const
......
......@@ -29,7 +29,6 @@
#include "androiddebugsupport.h"
#include "androiddeploystep.h"
#include "androidglobal.h"
#include "androidrunner.h"
#include "androidmanager.h"
......
......@@ -29,9 +29,7 @@
#include "androiddeployconfiguration.h"
#include "androidconstants.h"
#include "androiddeploystep.h"
#include "androidpackageinstallationstep.h"
#include "androidpackagecreationstep.h"
#include "androiddeployqtstep.h"
#include "androidmanager.h"
......@@ -76,14 +74,8 @@ DeployConfiguration *AndroidDeployConfigurationFactory::create(Target *parent, C
{
AndroidDeployConfiguration *dc = new AndroidDeployConfiguration(parent, id);
if (id == ANDROID_DEPLOYCONFIGURATION_ID) {
dc->stepList()->insertStep(0, new AndroidPackageInstallationStep(AndroidPackageInstallationStep::ProjectDirectory, dc->stepList()));
dc->stepList()->insertStep(1, new AndroidPackageCreationStep(dc->stepList()));
dc->stepList()->insertStep(2, new AndroidDeployStep(dc->stepList()));
} else {
dc->stepList()->insertStep(0, new AndroidPackageInstallationStep(AndroidPackageInstallationStep::BuildDirectory, dc->stepList()));
dc->stepList()->insertStep(1, new AndroidDeployQtStep(dc->stepList()));
}
dc->stepList()->insertStep(0, new AndroidPackageInstallationStep(AndroidPackageInstallationStep::BuildDirectory, dc->stepList()));
dc->stepList()->insertStep(1, new AndroidDeployQtStep(dc->stepList()));
return dc;
}
......@@ -136,17 +128,13 @@ QList<Core::Id> AndroidDeployConfigurationFactory::availableCreationIds(Target *
QtSupport::BaseQtVersion *qt = QtSupport::QtKitInformation::qtVersion(parent->kit());
if (qt->type() != QLatin1String(Constants::ANDROIDQT))
return ids;
if (qt->qtVersion() < QtSupport::QtVersionNumber(5, 2, 0))
ids << Core::Id(ANDROID_DEPLOYCONFIGURATION_ID);
else
ids << Core::Id(ANDROID_DEPLOYCONFIGURATION2_ID);
ids << Core::Id(ANDROID_DEPLOYCONFIGURATION_ID);
return ids;
}
QString AndroidDeployConfigurationFactory::displayNameForId(Core::Id id) const
{
if (id.name().startsWith(ANDROID_DC_PREFIX)
|| id.name().startsWith(ANDROID_DC2_PREFIX))
if (id.name().startsWith(ANDROID_DC_PREFIX))
return tr("Deploy on Android");
return QString();
}
......
......@@ -35,12 +35,9 @@
namespace Android {
namespace Internal {
const char ANDROID_DEPLOYCONFIGURATION_ID[] = "Qt4ProjectManager.AndroidDeployConfiguration";
const char ANDROID_DC_PREFIX[] = "Qt4ProjectManager.AndroidDeployConfiguration.";
// Qt 5.2 has a new form of deployment
const char ANDROID_DEPLOYCONFIGURATION2_ID[] = "Qt4ProjectManager.AndroidDeployConfiguration2";
const char ANDROID_DC2_PREFIX[] = "Qt4ProjectManager.AndroidDeployConfiguration2.";
const char ANDROID_DEPLOYCONFIGURATION_ID[] = "Qt4ProjectManager.AndroidDeployConfiguration2";
const char ANDROID_DC_PREFIX[] = "Qt4ProjectManager.AndroidDeployConfiguration2.";
class AndroidDeployConfiguration : public ProjectExplorer::DeployConfiguration
{
......
......@@ -81,9 +81,6 @@ QList<Core::Id> AndroidDeployQtStepFactory::availableCreationIds(ProjectExplorer
return QList<Core::Id>();
if (parent->contains(AndroidDeployQtStep::Id))
return QList<Core::Id>();
QtSupport::BaseQtVersion *qtVersion = QtSupport::QtKitInformation::qtVersion(parent->target()->kit());
if (!qtVersion || qtVersion->qtVersion() < QtSupport::QtVersionNumber(5, 2, 0))
return QList<Core::Id>();
return QList<Core::Id>() << AndroidDeployQtStep::Id;
}
......
/**************************************************************************
**
** Copyright (c) 2014 BogDan Vatra <bog_dan_ro@yahoo.com>
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** 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.
**
** 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, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/
#include "androiddeploystep.h"
#include "androidconstants.h"
#include "androiddeploystepwidget.h"
#include "androidglobal.h"
#include "androidpackagecreationstep.h"
#include "androidrunconfiguration.h"
#include "androidmanager.h"
#include "androidtoolchain.h"
#include "androiddevicedialog.h"
#include <coreplugin/messagemanager.h>
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/deployconfiguration.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/buildsteplist.h>
#include <projectexplorer/target.h>
#include <qmakeprojectmanager/qmakebuildconfiguration.h>
#include <qmakeprojectmanager/qmakeproject.h>
#include <qmakeprojectmanager/qmakenodes.h>
#include <qtsupport/qtkitinformation.h>
#include <QDir>
#define ASSERT_STATE(state) ASSERT_STATE_GENERIC(State, state, m_state)
using namespace Core;
using namespace ProjectExplorer;
using namespace QmakeProjectManager;
namespace Android {
namespace Internal {
static const char USE_LOCAL_QT_KEY[] = "Qt4ProjectManager.AndroidDeployStep.UseLocalQtLibs";
static const char DEPLOY_ACTION_KEY[] = "Qt4ProjectManager.AndroidDeployStep.DeployAction";
const Id AndroidDeployStep::Id("Qt4ProjectManager.AndroidDeployStep");
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;
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*)),
this, SLOT(kitUpdated(ProjectExplorer::Kit*)));
}
bool AndroidDeployStep::init()
{
m_packageName = AndroidManager::packageName(target());
m_deviceAPILevel = AndroidManager::minimumSDK(target());
m_targetArch = AndroidManager::targetArch(target());
AndroidDeviceInfo info = AndroidConfigurations::showDeviceDialog(project(), m_deviceAPILevel, m_targetArch);
if (info.serialNumber.isEmpty()) // aborted
return false;
m_deviceAPILevel = info.sdk;
m_deviceSerialNumber = info.serialNumber;
if (info.type == AndroidDeviceInfo::Emulator)
m_avdName = m_deviceSerialNumber;
QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target()->kit());
if (!version)
return false;
const QmakeBuildConfiguration *bc = static_cast<QmakeBuildConfiguration *>(target()->activeBuildConfiguration());
if (!bc)
return false;
m_signPackage = false;
// find AndroidPackageCreationStep
foreach (BuildStep *step, target()->activeDeployConfiguration()->stepList()->steps()) {
if (AndroidPackageCreationStep *apcs = qobject_cast<AndroidPackageCreationStep *>(step)) {
m_signPackage = apcs->signPackage();
break;
}
}
m_qtVersionSourcePath = version->qmakeProperty("QT_INSTALL_PREFIX");
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<QmakeProject *>(target()->project())->rootQmakeProjectNode()->buildDir();
m_runDeployAction = m_deployAction;
ToolChain *tc = ToolChainKitInformation::toolChain(target()->kit());
if (!tc || tc->type() != QLatin1String(Constants::ANDROID_TOOLCHAIN_TYPE)) {
raiseError(tr("No Android toolchain selected."));
return false;
}
m_ndkToolChainVersion = static_cast<AndroidToolChain *>(tc)->ndkToolChainVersion();
QString arch = static_cast<QmakeProject *>(project())->rootQmakeProjectNode()->singleVariableValue(QmakeProjectManager::AndroidArchVar);
if (!arch.isEmpty())
m_libgnustl = AndroidManager::libGnuStl(arch, m_ndkToolChainVersion);
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;
}
bool AndroidDeployStep::fromMap(const QVariantMap &map)
{
m_deployAction = AndroidDeployAction(map.value(QLatin1String(DEPLOY_ACTION_KEY), NoDeploy).toInt());
QVariant useLocalQt = map.value(QLatin1String(USE_LOCAL_QT_KEY));
if (useLocalQt.isValid()) { // old settings
if (useLocalQt.toBool() && m_deployAction == NoDeploy)
m_deployAction = BundleLibraries;
}
if (m_deployAction == InstallQASI)
m_deployAction = NoDeploy;
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);
return ProjectExplorer::BuildStep::fromMap(map);
}
QVariantMap AndroidDeployStep::toMap() const
{
QVariantMap map = ProjectExplorer::BuildStep::toMap();
map.insert(QLatin1String(DEPLOY_ACTION_KEY), m_deployAction);
return map;
}
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;
}
void AndroidDeployStep::setDeployAction(AndroidDeployStep::AndroidDeployAction deploy)
{
m_deployAction = deploy;
AndroidManager::updateDeploymentSettings(target());
}
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;
}
if (!buildProc->waitForFinished(2 * 60 * 1000)
|| buildProc->error() != QProcess::UnknownError
|| buildProc->exitCode() != 0) {
QString mainMessage = tr("Packaging Error: Command '%1 %2' failed.")
.arg(program).arg(arguments.join(QLatin1String(" ")));
if (buildProc->error() != QProcess::UnknownError)
mainMessage += QLatin1Char(' ') + 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;
}
unsigned int AndroidDeployStep::remoteModificationTime(const QString &fullDestination, QHash<QString, unsigned int> *cache)
{
QString destination = QFileInfo(fullDestination).absolutePath();
QProcess process;
QHash<QString, unsigned int>::const_iterator it = cache->find(fullDestination);
if (it != cache->constEnd())
return *it;
QStringList arguments = AndroidDeviceInfo::adbSelector(m_deviceSerialNumber);
arguments << QLatin1String("ls") << destination;
process.start(AndroidConfigurations::currentConfig().adbToolPath().toString(), arguments);
if (!process.waitForFinished(10000)
|| process.exitCode() != 0)
return 0;
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();
while (libsIt.hasNext()) {
libsIt.next();
const QString destFile(remotePath + libsIt.filePath().mid(pos));
if (!libsIt.fileInfo().isDir()) {
deployList->append(DeployItem(libsIt.filePath(),
libsIt.fileInfo().lastModified().toTime_t(),
destFile, strip));
}
}
}
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;
}
}
void AndroidDeployStep::stripFiles(const QList<DeployItem> &deployList, Abi::Architecture architecture, const QString &ndkToolchainVersion)
{
QProcess stripProcess;
foreach (const DeployItem &item, deployList) {
stripProcess.start(AndroidConfigurations::currentConfig().stripPath(architecture, ndkToolchainVersion).toString(),
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::currentConfig().adbToolPath().toString(),
AndroidDeviceInfo::adbSelector(m_deviceSerialNumber)
<< QLatin1String("push") << item.localFileName
<< item.remoteFileName);
}
}
bool AndroidDeployStep::deployPackage()
{
if (!m_avdName.isEmpty()) {
if (AndroidConfigurations::currentConfig().findAvd(m_deviceAPILevel, m_targetArch).isEmpty()
&& !AndroidConfigurations::currentConfig().startAVDAsync(m_avdName))
return false;
m_deviceSerialNumber = AndroidConfigurations::currentConfig().waitForAvd(m_deviceAPILevel, m_targetArch);
}
QProcess *const deployProc = new QProcess;
connect(deployProc, SIGNAL(readyReadStandardOutput()), this,
SLOT(handleBuildOutput()));
connect(deployProc, SIGNAL(readyReadStandardError()), this,
SLOT(handleBuildError()));
if (m_runDeployAction == DeployLocal) {
writeOutput(tr("Deploy Qt libraries. This may take some time, please wait."));
const QString tempPath = QDir::tempPath() + QLatin1String("/android_qt_libs_") + m_packageName;
AndroidPackageCreationStep::removeDirectory(tempPath);
const QString remoteRoot = QLatin1String("/data/local/tmp/qt");
QList<DeployItem> deployList;
collectFiles(&deployList,
m_qtVersionSourcePath + QLatin1String("/lib"),
remoteRoot + QLatin1String("/lib"),
true,
QStringList() << QLatin1String("*.so"));
// 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));
collectFiles(&deployList,
m_qtVersionSourcePath + QLatin1String("/plugins"),
remoteRoot + QLatin1String("/plugins"),
true);
collectFiles(&deployList,