Android: Add proper QBS support

Now we can use QtCreator to build, deploy, run & debug QBS projects.

[ChangeLog][Android][QBS] Add Android support for QBS projects.

Fixes: QTCREATORBUG-15573
Fixes: QTCREATORBUG-19880
Fixes: QTCREATORBUG-22182
Change-Id: I08b153a44dcf7ca178689c1c30fa2201c4cc0dbb
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
BogDan Vatra
2019-04-03 18:10:35 +02:00
committed by BogDan Vatra
parent f8202239d6
commit 57c48630a8
10 changed files with 251 additions and 134 deletions

View File

@@ -1015,6 +1015,18 @@ static QVariant findOrRegisterDebugger(ToolChain *tc)
void AndroidConfigurations::updateAutomaticKitList()
{
const QList<Kit *> androidKits = Utils::filtered(KitManager::kits(), [](Kit *k) {
Core::Id deviceTypeId = DeviceTypeKitAspect::deviceTypeId(k);
return deviceTypeId == Core::Id(Constants::ANDROID_DEVICE_TYPE);
});
for (auto k: androidKits) {
if (k->value(Constants::ANDROID_KIT_NDK).isNull() || k->value(Constants::ANDROID_KIT_SDK).isNull()) {
k->setValueSilently(Constants::ANDROID_KIT_NDK, currentConfig().ndkLocation().toString());
k->setValue(Constants::ANDROID_KIT_SDK, currentConfig().sdkLocation().toString());
}
}
const QList<Kit *> existingKits = Utils::filtered(KitManager::kits(), [](Kit *k) {
Core::Id deviceTypeId = DeviceTypeKitAspect::deviceTypeId(k);
if (k->isAutoDetected() && !k->isSdkProvided()
@@ -1090,6 +1102,8 @@ void AndroidConfigurations::updateAutomaticKitList()
k->setUnexpandedDisplayName(tr("Android for %1 (Clang %2)")
.arg(static_cast<const AndroidQtVersion *>(qt)->targetArch())
.arg(qt->displayName()));
k->setValueSilently(Constants::ANDROID_KIT_NDK, currentConfig().ndkLocation().toString());
k->setValueSilently(Constants::ANDROID_KIT_SDK, currentConfig().sdkLocation().toString());
};
if (existingKit)

View File

@@ -63,11 +63,13 @@ const char ANDROID_MANIFEST_MIME_TYPE[] = "application/vnd.google.android.androi
const char ANDROID_MANIFEST_EDITOR_ID[] = "Android.AndroidManifestEditor.Id";
const char ANDROID_MANIFEST_EDITOR_CONTEXT[] = "Android.AndroidManifestEditor.Id";
const char ANDROID_KIT_NDK[] = "Android.NDK";
const char ANDROID_KIT_SDK[] = "Android.SDK";
const char ANDROID_BUILDDIRECTORY[] = "android-build";
const char JAVA_EDITOR_ID[] = "java.editor";
const char JAVA_MIMETYPE[] = "text/x-java";
const char ANDROID_ARCHITECTURE[] = "Android.Architecture";
const char ANDROID_DEPLOY_SETTINGS_FILE[] = "AndroidDeploySettingsFile";
const char ANDROID_PACKAGE_SOURCE_DIR[] = "AndroidPackageSourceDir";
const char ANDROID_EXTRA_LIBS[] = "AndroidExtraLibs";
@@ -78,9 +80,12 @@ const char ANDROID_BUILD_APK_ID[] = "Android.BuildApkStep";
const char AndroidPackageSourceDir[] = "AndroidPackageSourceDir"; // QString
const char AndroidDeploySettingsFile[] = "AndroidDeploySettingsFile"; // QString
const char AndroidExtraLibs[] = "AndroidExtraLibs"; // QStringList
// REMOVE ME
const char AndroidArch[] = "AndroidArch"; // QString
const char AndroidSoLibPath[] = "AndroidSoLibPath"; // QStringList
const char AndroidTargets[] = "AndroidTargets"; // QStringList
const char AndroidApk[] = "Android.APK"; // QStringList
const char AndroidManifest[] = "Android.Manifest"; // QStringList
const char AndroidNdkPlatform[] = "AndroidNdkPlatform"; //QString
const char NdkLocation[] = "NdkLocation"; // FileName

View File

@@ -172,6 +172,8 @@ void AndroidDebugSupport::start()
QStringList extraLibs = getExtraLibs(node);
solibSearchPath.append(qtSoPaths(qtVersion));
solibSearchPath.append(uniquePaths(extraLibs));
solibSearchPath.append(target->activeBuildConfiguration()->buildDirectory().toString());
solibSearchPath.removeDuplicates();
setSolibSearchPath(solibSearchPath);
qCDebug(androidDebugSupportLog) << "SoLibSearchPath: "<<solibSearchPath;
setSymbolFile(target->activeBuildConfiguration()->buildDirectory().toString()

View File

@@ -186,11 +186,6 @@ bool AndroidDeployQtStep::init()
QTC_ASSERT(deployQtLive || bc, return false);
auto androidBuildApkStep = AndroidBuildApkStep::findInBuild(bc);
if (!androidBuildApkStep && !deployQtLive) {
emit addOutput(tr("Cannot find the android build step."), OutputFormat::Stderr);
return false;
}
int minTargetApi = AndroidManager::minimumSDK(target());
qCDebug(deployStepLog) << "Target architecture:" << m_targetArch
<< "Min target API" << minTargetApi;
@@ -236,49 +231,57 @@ bool AndroidDeployQtStep::init()
version->qtVersion() >= QtSupport::QtVersionNumber(5, 4, 0);
if (m_useAndroiddeployqt) {
m_command = version->qmakeProperty("QT_HOST_BINS");
if (m_command.isEmpty()) {
emit addOutput(tr("Cannot find the androiddeployqt tool."), OutputFormat::Stderr);
return false;
}
qCDebug(deployStepLog) << "Using androiddeployqt";
if (!m_command.endsWith(QLatin1Char('/')))
m_command += QLatin1Char('/');
m_command += Utils::HostOsInfo::withExecutableSuffix(QLatin1String("androiddeployqt"));
const ProjectNode *node = target()->project()->findNodeForBuildKey(rc->buildKey());
m_apkPath = Utils::FileName::fromString(node->data(Constants::AndroidApk).toString());
if (!m_apkPath.isEmpty()) {
m_manifestName = Utils::FileName::fromString(node->data(Constants::AndroidManifest).toString());
m_command = AndroidConfigurations::currentConfig().adbToolPath().toString();
AndroidManager::setManifestPath(target(), m_manifestName);
} else {
QString jsonFile;
if (node)
jsonFile = node->data(Constants::AndroidDeploySettingsFile).toString();
if (jsonFile.isEmpty()) {
emit addOutput(tr("Cannot find the androiddeploy Json file."), OutputFormat::Stderr);
return false;
} m_command = version->qmakeProperty("QT_HOST_BINS");
if (m_command.isEmpty()) {
emit addOutput(tr("Cannot find the androiddeployqt tool."), OutputFormat::Stderr);
return false;
}
qCDebug(deployStepLog) << "Using androiddeployqt";
if (!m_command.endsWith(QLatin1Char('/')))
m_command += QLatin1Char('/');
m_command += Utils::HostOsInfo::withExecutableSuffix(QLatin1String("androiddeployqt"));
m_workingDirectory = bc->buildDirectory().appendPath(QLatin1String(Constants::ANDROID_BUILDDIRECTORY)).toString();
m_workingDirectory = bc->buildDirectory().appendPath(QLatin1String(Constants::ANDROID_BUILDDIRECTORY)).toString();
Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("--verbose"));
Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("--output"));
Utils::QtcProcess::addArg(&m_androiddeployqtArgs, m_workingDirectory);
Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("--no-build"));
Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("--input"));
Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("--verbose"));
Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("--output"));
Utils::QtcProcess::addArg(&m_androiddeployqtArgs, m_workingDirectory);
Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("--no-build"));
Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("--input"));
QString jsonFile;
if (const ProjectNode *node = target()->project()->findNodeForBuildKey(rc->buildKey()))
jsonFile = node->data(Constants::AndroidDeploySettingsFile).toString();
if (jsonFile.isEmpty()) {
emit addOutput(tr("Cannot find the androiddeploy Json file."), OutputFormat::Stderr);
return false;
}
Utils::QtcProcess::addArg(&m_androiddeployqtArgs, jsonFile);
if (androidBuildApkStep && androidBuildApkStep->useMinistro()) {
qCDebug(deployStepLog) << "Using ministro";
Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("--deployment"));
Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("ministro"));
}
Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("--gradle"));
Utils::QtcProcess::addArg(&m_androiddeployqtArgs, jsonFile);
if (androidBuildApkStep && androidBuildApkStep->useMinistro()) {
qCDebug(deployStepLog) << "Using ministro";
Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("--deployment"));
Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("ministro"));
}
if (androidBuildApkStep && androidBuildApkStep->signPackage()) {
// The androiddeployqt tool is not really written to do stand-alone installations.
// This hack forces it to use the correct filename for the apk file when installing
// as a temporary fix until androiddeployqt gets the support. Since the --sign is
// only used to get the correct file name of the apk, its parameters are ignored.
Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("--sign"));
Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("foo"));
Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("bar"));
Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("--gradle"));
if (androidBuildApkStep && androidBuildApkStep->signPackage()) {
// The androiddeployqt tool is not really written to do stand-alone installations.
// This hack forces it to use the correct filename for the apk file when installing
// as a temporary fix until androiddeployqt gets the support. Since the --sign is
// only used to get the correct file name of the apk, its parameters are ignored.
Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("--sign"));
Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("foo"));
Utils::QtcProcess::addArg(&m_androiddeployqtArgs, QLatin1String("bar"));
}
}
} else {
m_uninstallPreviousPackageRun = true;
@@ -301,7 +304,7 @@ bool AndroidDeployQtStep::init()
AndroidDeployQtStep::DeployErrorCode AndroidDeployQtStep::runDeploy()
{
QString args;
if (m_useAndroiddeployqt) {
if (m_useAndroiddeployqt && m_apkPath.isEmpty()) {
args = m_androiddeployqtArgs;
if (m_uninstallPreviousPackageRun)
Utils::QtcProcess::addArg(&args, QLatin1String("--install"));

View File

@@ -332,9 +332,17 @@ Utils::FileName AndroidManager::manifestSourcePath(ProjectExplorer::Target *targ
Utils::FileName AndroidManager::manifestPath(ProjectExplorer::Target *target)
{
QVariant manifest = target->namedSettings(AndroidManifestName);
if (manifest.isValid())
return manifest.value<FileName>();
return dirPath(target).appendPath(AndroidManifestName);
}
void AndroidManager::setManifestPath(Target *target, const FileName &path)
{
target->setNamedSettings(AndroidManifestName, QVariant::fromValue(path));
}
Utils::FileName AndroidManager::defaultPropertiesPath(ProjectExplorer::Target *target)
{
return dirPath(target).appendPath(AndroidDefaultPropertiesName);

View File

@@ -91,6 +91,7 @@ public:
static Utils::FileName dirPath(const ProjectExplorer::Target *target);
static Utils::FileName manifestPath(ProjectExplorer::Target *target);
static void setManifestPath(ProjectExplorer::Target *target, const Utils::FileName &path);
static Utils::FileName manifestSourcePath(ProjectExplorer::Target *target);
static Utils::FileName defaultPropertiesPath(ProjectExplorer::Target *target);
static Utils::FileName apkPath(const ProjectExplorer::Target *target);