summaryrefslogtreecommitdiff
path: root/src/plugins/qmakeprojectmanager/qmakeandroidbuildapkstep.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/qmakeprojectmanager/qmakeandroidbuildapkstep.cpp')
-rw-r--r--src/plugins/qmakeprojectmanager/qmakeandroidbuildapkstep.cpp293
1 files changed, 293 insertions, 0 deletions
diff --git a/src/plugins/qmakeprojectmanager/qmakeandroidbuildapkstep.cpp b/src/plugins/qmakeprojectmanager/qmakeandroidbuildapkstep.cpp
new file mode 100644
index 0000000000..1848a6536b
--- /dev/null
+++ b/src/plugins/qmakeprojectmanager/qmakeandroidbuildapkstep.cpp
@@ -0,0 +1,293 @@
+/**************************************************************************
+**
+** Copyright (c) 2014 BogDan Vatra <bog_dan_ro@yahoo.com>
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** 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 "qmakeandroidbuildapkstep.h"
+#include "qmakeandroidbuildapkwidget.h"
+#include "qmakenodes.h"
+#include "qmakeproject.h"
+
+#include <android/androidconfigurations.h>
+#include <android/androidconstants.h>
+#include <android/androidmanager.h>
+#include <android/androidqtsupport.h>
+
+#include <projectexplorer/buildconfiguration.h>
+#include <projectexplorer/buildsteplist.h>
+#include <projectexplorer/project.h>
+#include <projectexplorer/projectexplorer.h>
+#include <projectexplorer/target.h>
+
+#include <qtsupport/qtkitinformation.h>
+
+#include <utils/qtcprocess.h>
+
+#include <QHBoxLayout>
+
+using namespace Android;
+
+namespace QmakeProjectManager {
+namespace Internal {
+
+const Core::Id ANDROID_BUILD_APK_ID("QmakeProjectManager.AndroidBuildApkStep");
+const QLatin1String ProFilePathForInputFile("ProFilePathForInputFile");
+
+
+//////////////////
+// QmakeAndroidBuildApkStepFactory
+/////////////////
+
+QmakeAndroidBuildApkStepFactory::QmakeAndroidBuildApkStepFactory(QObject *parent)
+ : IBuildStepFactory(parent)
+{
+}
+
+QList<Core::Id> QmakeAndroidBuildApkStepFactory::availableCreationIds(ProjectExplorer::BuildStepList *parent) const
+{
+ if (parent->id() != ProjectExplorer::Constants::BUILDSTEPS_BUILD
+ || !canHandle(parent->target())
+ || parent->contains(ANDROID_BUILD_APK_ID)) {
+ return QList<Core::Id>();
+ }
+
+ return QList<Core::Id>() << ANDROID_BUILD_APK_ID;
+}
+
+QString QmakeAndroidBuildApkStepFactory::displayNameForId(const Core::Id id) const
+{
+ if (id == ANDROID_BUILD_APK_ID)
+ return tr("Build Android APK");
+ return QString();
+}
+
+bool QmakeAndroidBuildApkStepFactory::canCreate(ProjectExplorer::BuildStepList *parent, const Core::Id id) const
+{
+ return availableCreationIds(parent).contains(id);
+}
+
+ProjectExplorer::BuildStep *QmakeAndroidBuildApkStepFactory::create(ProjectExplorer::BuildStepList *parent, const Core::Id id)
+{
+ Q_ASSERT(canCreate(parent, id));
+ Q_UNUSED(id);
+ return new QmakeAndroidBuildApkStep(parent);
+}
+
+bool QmakeAndroidBuildApkStepFactory::canRestore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map) const
+{
+ return canCreate(parent, ProjectExplorer::idFromMap(map));
+}
+
+ProjectExplorer::BuildStep *QmakeAndroidBuildApkStepFactory::restore(ProjectExplorer::BuildStepList *parent, const QVariantMap &map)
+{
+ Q_ASSERT(canRestore(parent, map));
+ QmakeAndroidBuildApkStep * const step = new QmakeAndroidBuildApkStep(parent);
+ if (!step->fromMap(map)) {
+ delete step;
+ return 0;
+ }
+ return step;
+}
+
+bool QmakeAndroidBuildApkStepFactory::canClone(ProjectExplorer::BuildStepList *parent, ProjectExplorer::BuildStep *product) const
+{
+ return canCreate(parent, product->id());
+}
+
+ProjectExplorer::BuildStep *QmakeAndroidBuildApkStepFactory::clone(ProjectExplorer::BuildStepList *parent, ProjectExplorer::BuildStep *product)
+{
+ Q_ASSERT(canClone(parent, product));
+ return new QmakeAndroidBuildApkStep(parent, static_cast<QmakeAndroidBuildApkStep *>(product));
+}
+
+bool QmakeAndroidBuildApkStepFactory::canHandle(ProjectExplorer::Target *t) const
+{
+ return t->project()->supportsKit(t->kit())
+ && AndroidManager::supportsAndroid(t)
+ && qobject_cast<QmakeProject *>(t->project());
+}
+
+
+QmakeAndroidBuildApkStep::QmakeAndroidBuildApkStep(ProjectExplorer::BuildStepList *bc)
+ :Android::AndroidBuildApkStep(bc, ANDROID_BUILD_APK_ID)
+{
+ ctor();
+}
+
+QString QmakeAndroidBuildApkStep::proFilePathForInputFile() const
+{
+ return m_proFilePathForInputFile;
+}
+
+void QmakeAndroidBuildApkStep::setProFilePathForInputFile(const QString &path)
+{
+ m_proFilePathForInputFile = path;
+}
+
+QmakeAndroidBuildApkStep::QmakeAndroidBuildApkStep(ProjectExplorer::BuildStepList *bc, QmakeAndroidBuildApkStep *other)
+ : Android::AndroidBuildApkStep(bc, other),
+ m_proFilePathForInputFile(other->m_proFilePathForInputFile)
+{
+ ctor();
+}
+
+Utils::FileName QmakeAndroidBuildApkStep::androidPackageSourceDir() const
+{
+ QmakeProjectManager::QmakeProject *pro = static_cast<QmakeProjectManager::QmakeProject *>(project());
+ const QmakeProjectManager::QmakeProFileNode *node
+ = pro->rootQmakeProjectNode()->findProFileFor(m_proFilePathForInputFile);
+ if (!node)
+ return Utils::FileName();
+ return Utils::FileName::fromString(node->singleVariableValue(QmakeProjectManager::AndroidPackageSourceDir));
+}
+
+void QmakeAndroidBuildApkStep::ctor()
+{
+ connect(project(), SIGNAL(proFilesEvaluated()),
+ this, SLOT(updateInputFile()));
+}
+
+bool QmakeAndroidBuildApkStep::init()
+{
+ if (AndroidManager::checkForQt51Files(project()->projectDirectory()))
+ emit addOutput(tr("Found old folder \"android\" in source directory. Qt 5.2 does not use that folder by default."), ErrorOutput);
+
+ if (!Android::AndroidBuildApkStep::init())
+ return false;
+
+ QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(target()->kit());
+ if (!version)
+ return false;
+
+ QString command = version->qmakeProperty("QT_HOST_BINS");
+ if (!command.endsWith(QLatin1Char('/')))
+ command += QLatin1Char('/');
+ command += QLatin1String("androiddeployqt");
+ if (Utils::HostOsInfo::isWindowsHost())
+ command += QLatin1String(".exe");
+
+ QString deploymentMethod;
+ if (m_deployAction == MinistroDeployment)
+ deploymentMethod = QLatin1String("ministro");
+ else if (m_deployAction == DebugDeployment)
+ deploymentMethod = QLatin1String("debug");
+ else if (m_deployAction == BundleLibrariesDeployment)
+ deploymentMethod = QLatin1String("bundled");
+
+ ProjectExplorer::BuildConfiguration *bc = buildConfiguration();
+ QString outputDir = bc->buildDirectory().appendPath(QLatin1String(Constants::ANDROID_BUILDDIRECTORY)).toString();
+
+ const auto *pro = static_cast<QmakeProjectManager::QmakeProject *>(project());
+ const QmakeProjectManager::QmakeProFileNode *node = pro->rootQmakeProjectNode()->findProFileFor(m_proFilePathForInputFile);
+ if (!node) { // should never happen
+ emit addOutput(tr("Internal Error: Could not find .pro file."), BuildStep::ErrorMessageOutput);
+ return false;
+ }
+
+ QString inputFile = node->singleVariableValue(QmakeProjectManager::AndroidDeploySettingsFile);
+ if (inputFile.isEmpty()) { // should never happen
+ emit addOutput(tr("Internal Error: Unknown Android deployment JSON file location."), BuildStep::ErrorMessageOutput);
+ return false;
+ }
+
+ QStringList arguments;
+ arguments << QLatin1String("--input")
+ << inputFile
+ << QLatin1String("--output")
+ << outputDir
+ << QLatin1String("--deployment")
+ << deploymentMethod
+ << QLatin1String("--ant")
+ << AndroidConfigurations::currentConfig().antToolPath().toString()
+ << QLatin1String("--android-platform")
+ << AndroidManager::buildTargetSDK(target())
+ << QLatin1String("--jdk")
+ << AndroidConfigurations::currentConfig().openJDKLocation().toString();
+
+ if (m_verbose)
+ arguments << QLatin1String("--verbose");
+
+ if (m_signPackage) {
+ arguments << QLatin1String("--sign")
+ << m_keystorePath.toString()
+ << m_certificateAlias
+ << QLatin1String("--storepass")
+ << m_keystorePasswd;
+ if (!m_certificatePasswd.isEmpty())
+ arguments << QLatin1String("--keypass")
+ << m_certificatePasswd;
+ }
+
+ ProjectExplorer::ProcessParameters *pp = processParameters();
+ pp->setMacroExpander(bc->macroExpander());
+ pp->setWorkingDirectory(bc->buildDirectory().toString());
+ Utils::Environment env = bc->environment();
+ pp->setEnvironment(env);
+ pp->setCommand(command);
+ pp->setArguments(Utils::QtcProcess::joinArgs(arguments));
+ pp->resolveAll();
+
+ return true;
+}
+
+ProjectExplorer::BuildStepConfigWidget *QmakeAndroidBuildApkStep::createConfigWidget()
+{
+ return new QmakeAndroidBuildApkWidget(this);
+}
+
+bool QmakeAndroidBuildApkStep::fromMap(const QVariantMap &map)
+{
+ m_proFilePathForInputFile = map.value(ProFilePathForInputFile).toString();
+ return Android::AndroidBuildApkStep::fromMap(map);
+}
+
+QVariantMap QmakeAndroidBuildApkStep::toMap() const
+{
+ QVariantMap map = Android::AndroidBuildApkStep::toMap();
+ map.insert(ProFilePathForInputFile, m_proFilePathForInputFile);
+ return map;
+}
+
+void QmakeAndroidBuildApkStep::updateInputFile()
+{
+ QmakeProject *pro = static_cast<QmakeProject *>(project());
+ QList<QmakeProFileNode *> nodes = pro->applicationProFiles();
+
+ const QmakeProFileNode *node = pro->rootQmakeProjectNode()->findProFileFor(m_proFilePathForInputFile);
+ if (!nodes.contains(const_cast<QmakeProFileNode *>(node))) {
+ if (!nodes.isEmpty())
+ m_proFilePathForInputFile = nodes.first()->path();
+ else
+ m_proFilePathForInputFile.clear();
+ }
+
+ emit inputFileChanged();
+}
+
+} // namespace Internal
+} // namespace QmakeProjectManager