forked from qt-creator/qt-creator
Android: Fix Sdk manager system environment
Android native tools fail if JAVA_HOME environment variable is not defined Task-number: QTCREATORBUG-19072 Change-Id: I3db910b34d9bdd9ebc9ba052b5300ecf5ef3ce15 Reviewed-by: BogDan Vatra <bogdan@kdab.com>
This commit is contained in:
@@ -56,6 +56,7 @@
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/runextensions.h>
|
||||
#include <utils/synchronousprocess.h>
|
||||
#include <utils/environment.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDirIterator>
|
||||
@@ -1070,6 +1071,19 @@ bool AndroidConfigurations::force32bitEmulator()
|
||||
return m_instance->m_force32bit;
|
||||
}
|
||||
|
||||
QProcessEnvironment AndroidConfigurations::toolsEnvironment(const AndroidConfig &config)
|
||||
{
|
||||
Environment env = Environment::systemEnvironment();
|
||||
Utils::FileName jdkLocation = config.openJDKLocation();
|
||||
if (!jdkLocation.isEmpty()) {
|
||||
env.set("JAVA_HOME", jdkLocation.toUserOutput());
|
||||
Utils::FileName binPath = jdkLocation;
|
||||
binPath.appendPath("bin");
|
||||
env.prependOrSetPath(binPath.toUserOutput());
|
||||
}
|
||||
return env.toProcessEnvironment();
|
||||
}
|
||||
|
||||
/**
|
||||
* Workaround for '????????????' serial numbers
|
||||
* @return ("-d") for buggy devices, ("-s", <serial no>) for normal
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <projectexplorer/toolchain.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QProcessEnvironment>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QVector>
|
||||
@@ -204,6 +205,7 @@ public:
|
||||
static void removeOldToolChains();
|
||||
static void updateAutomaticKitList();
|
||||
static bool force32bitEmulator();
|
||||
static QProcessEnvironment toolsEnvironment(const AndroidConfig &config);
|
||||
|
||||
signals:
|
||||
void updated();
|
||||
|
||||
@@ -129,13 +129,14 @@ void watcherDeleter(QFutureWatcher<void> *watcher)
|
||||
Runs the \c sdkmanger tool with arguments \a args. Returns \c true if the command is
|
||||
successfully executed. Output is copied into \a output. The function blocks the calling thread.
|
||||
*/
|
||||
static bool sdkManagerCommand(const Utils::FileName &toolPath, const QStringList &args,
|
||||
static bool sdkManagerCommand(const AndroidConfig &config, const QStringList &args,
|
||||
QString *output, int timeout = sdkManagerCmdTimeoutS)
|
||||
{
|
||||
SynchronousProcess proc;
|
||||
proc.setProcessEnvironment(AndroidConfigurations::toolsEnvironment(config));
|
||||
proc.setTimeoutS(timeout);
|
||||
proc.setTimeOutMessageBoxEnabled(true);
|
||||
SynchronousProcessResponse response = proc.run(toolPath.toString(), args);
|
||||
SynchronousProcessResponse response = proc.run(config.sdkManagerToolPath().toString(), args);
|
||||
if (output)
|
||||
*output = response.allOutput();
|
||||
return response.result == SynchronousProcessResponse::Finished;
|
||||
@@ -147,13 +148,14 @@ static bool sdkManagerCommand(const Utils::FileName &toolPath, const QStringList
|
||||
to cancel signal emmitted by \a sdkManager and kill the commands. The command is also killed
|
||||
after the lapse of \a timeout seconds. The function blocks the calling thread.
|
||||
*/
|
||||
static void sdkManagerCommand(const Utils::FileName &toolPath, const QStringList &args,
|
||||
static void sdkManagerCommand(const AndroidConfig &config, const QStringList &args,
|
||||
AndroidSdkManager &sdkManager, SdkCmdFutureInterface &fi,
|
||||
AndroidSdkManager::OperationOutput &output, double progressQuota,
|
||||
bool interruptible = true, int timeout = sdkManagerOperationTimeoutS)
|
||||
{
|
||||
int offset = fi.progressValue();
|
||||
SynchronousProcess proc;
|
||||
proc.setProcessEnvironment(AndroidConfigurations::toolsEnvironment(config));
|
||||
bool assertionFound = false;
|
||||
proc.setStdErrBufferedSignalsEnabled(true);
|
||||
proc.setStdOutBufferedSignalsEnabled(true);
|
||||
@@ -173,7 +175,7 @@ static void sdkManagerCommand(const Utils::FileName &toolPath, const QStringList
|
||||
QObject::connect(&sdkManager, &AndroidSdkManager::cancelActiveOperations,
|
||||
&proc, &SynchronousProcess::terminate);
|
||||
}
|
||||
SynchronousProcessResponse response = proc.run(toolPath.toString(), args);
|
||||
SynchronousProcessResponse response = proc.run(config.sdkManagerToolPath().toString(), args);
|
||||
if (assertionFound) {
|
||||
output.success = false;
|
||||
output.stdOutput = response.stdOut();
|
||||
@@ -769,7 +771,7 @@ void AndroidSdkManagerPrivate::reloadSdkPackages()
|
||||
QString packageListing;
|
||||
QStringList args({"--list", "--verbose"});
|
||||
args << m_config.sdkManagerToolArgs();
|
||||
if (sdkManagerCommand(m_config.sdkManagerToolPath(), args, &packageListing)) {
|
||||
if (sdkManagerCommand(m_config, args, &packageListing)) {
|
||||
SdkManagerOutputParser parser(m_allPackages);
|
||||
parser.parsePackageListing(packageListing);
|
||||
}
|
||||
@@ -797,7 +799,7 @@ void AndroidSdkManagerPrivate::updateInstalled(SdkCmdFutureInterface &fi)
|
||||
QStringList args("--update");
|
||||
args << m_config.sdkManagerToolArgs();
|
||||
if (!fi.isCanceled())
|
||||
sdkManagerCommand(m_config.sdkManagerToolPath(), args, m_sdkManager, fi, result, 100);
|
||||
sdkManagerCommand(m_config, args, m_sdkManager, fi, result, 100);
|
||||
else
|
||||
qCDebug(sdkManagerLog) << "Update: Operation cancelled before start";
|
||||
|
||||
@@ -826,12 +828,10 @@ void AndroidSdkManagerPrivate::update(SdkCmdFutureInterface &fi, const QStringLi
|
||||
result.stdOutput = QString("%1 %2").arg(isInstall ? installTag : uninstallTag)
|
||||
.arg(packagePath);
|
||||
fi.reportResult(result);
|
||||
if (fi.isCanceled()) {
|
||||
if (fi.isCanceled())
|
||||
qCDebug(sdkManagerLog) << args << "Update: Operation cancelled before start";
|
||||
} else {
|
||||
sdkManagerCommand(m_config.sdkManagerToolPath(), args, m_sdkManager, fi, result,
|
||||
progressQuota, isInstall);
|
||||
}
|
||||
else
|
||||
sdkManagerCommand(m_config, args, m_sdkManager, fi, result, progressQuota, isInstall);
|
||||
currentProgress += progressQuota;
|
||||
fi.setProgressValue(currentProgress);
|
||||
if (result.stdError.isEmpty() && !result.success)
|
||||
@@ -869,7 +869,7 @@ void AndroidSdkManagerPrivate::checkPendingLicense(SdkCmdFutureInterface &fi)
|
||||
result.type = AndroidSdkManager::LicenseCheck;
|
||||
QStringList args("--licenses");
|
||||
if (!fi.isCanceled())
|
||||
sdkManagerCommand(m_config.sdkManagerToolPath(), args, m_sdkManager, fi, result, 100.0);
|
||||
sdkManagerCommand(m_config, args, m_sdkManager, fi, result, 100.0);
|
||||
else
|
||||
qCDebug(sdkManagerLog) << "Update: Operation cancelled before start";
|
||||
|
||||
@@ -884,6 +884,7 @@ void AndroidSdkManagerPrivate::getPendingLicense(SdkCmdFutureInterface &fi)
|
||||
AndroidSdkManager::OperationOutput result;
|
||||
result.type = AndroidSdkManager::LicenseWorkflow;
|
||||
QtcProcess licenseCommand;
|
||||
licenseCommand.setProcessEnvironment(AndroidConfigurations::toolsEnvironment(m_config));
|
||||
bool reviewingLicenses = false;
|
||||
licenseCommand.setCommand(m_config.sdkManagerToolPath().toString(), {"--licenses"});
|
||||
if (Utils::HostOsInfo::isWindowsHost())
|
||||
@@ -987,7 +988,7 @@ void AndroidSdkManagerPrivate::parseCommonArguments(QFutureInterface<QString> &f
|
||||
{
|
||||
QString argumentDetails;
|
||||
QString output;
|
||||
sdkManagerCommand(m_config.sdkManagerToolPath(), QStringList("--help"), &output);
|
||||
sdkManagerCommand(m_config, QStringList("--help"), &output);
|
||||
bool foundTag = false;
|
||||
for (const QString& line : output.split('\n')) {
|
||||
if (fi.isCanceled())
|
||||
|
||||
@@ -58,11 +58,11 @@ public:
|
||||
output.
|
||||
*/
|
||||
static bool androidToolCommand(Utils::FileName toolPath, const QStringList &args,
|
||||
const Environment &environment, QString *output)
|
||||
const QProcessEnvironment &environment, QString *output)
|
||||
{
|
||||
QString androidToolPath = toolPath.toString();
|
||||
SynchronousProcess proc;
|
||||
proc.setProcessEnvironment(environment.toProcessEnvironment());
|
||||
proc.setProcessEnvironment(environment);
|
||||
SynchronousProcessResponse response = proc.runBlocking(androidToolPath, args);
|
||||
if (response.result == SynchronousProcessResponse::Finished) {
|
||||
if (output)
|
||||
@@ -103,7 +103,7 @@ SdkPlatformList AndroidToolManager::availableSdkPlatforms(bool *ok) const
|
||||
SdkPlatformList list;
|
||||
QString targetListing;
|
||||
if (androidToolCommand(m_config.androidToolPath(), QStringList({"list", "target"}),
|
||||
androidToolEnvironment(), &targetListing)) {
|
||||
AndroidConfigurations::toolsEnvironment(m_config), &targetListing)) {
|
||||
m_parser->parseTargetListing(targetListing, m_config.sdkLocation(), list);
|
||||
success = true;
|
||||
} else {
|
||||
@@ -124,14 +124,15 @@ void AndroidToolManager::launchAvdManager() const
|
||||
QFuture<CreateAvdInfo> AndroidToolManager::createAvd(CreateAvdInfo info) const
|
||||
{
|
||||
return Utils::runAsync(&AndroidToolManager::createAvdImpl, info,
|
||||
m_config.androidToolPath(), androidToolEnvironment());
|
||||
m_config.androidToolPath(),
|
||||
AndroidConfigurations::toolsEnvironment(m_config));
|
||||
}
|
||||
|
||||
bool AndroidToolManager::removeAvd(const QString &name) const
|
||||
{
|
||||
SynchronousProcess proc;
|
||||
proc.setTimeoutS(5);
|
||||
proc.setProcessEnvironment(androidToolEnvironment().toProcessEnvironment());
|
||||
proc.setProcessEnvironment(AndroidConfigurations::toolsEnvironment(m_config));
|
||||
SynchronousProcessResponse response
|
||||
= proc.runBlocking(m_config.androidToolPath().toString(),
|
||||
QStringList({"delete", "avd", "-n", name}));
|
||||
@@ -142,27 +143,14 @@ QFuture<AndroidDeviceInfoList> AndroidToolManager::androidVirtualDevicesFuture()
|
||||
{
|
||||
return Utils::runAsync(&AndroidToolManager::androidVirtualDevices,
|
||||
m_config.androidToolPath(), m_config.sdkLocation(),
|
||||
androidToolEnvironment());
|
||||
}
|
||||
|
||||
Environment AndroidToolManager::androidToolEnvironment() const
|
||||
{
|
||||
Environment env = Environment::systemEnvironment();
|
||||
Utils::FileName jdkLocation = m_config.openJDKLocation();
|
||||
if (!jdkLocation.isEmpty()) {
|
||||
env.set(QLatin1String("JAVA_HOME"), jdkLocation.toUserOutput());
|
||||
Utils::FileName binPath = jdkLocation;
|
||||
binPath.appendPath(QLatin1String("bin"));
|
||||
env.prependOrSetPath(binPath.toUserOutput());
|
||||
}
|
||||
return env;
|
||||
AndroidConfigurations::toolsEnvironment(m_config));
|
||||
}
|
||||
|
||||
CreateAvdInfo AndroidToolManager::createAvdImpl(CreateAvdInfo info, FileName androidToolPath,
|
||||
Environment env)
|
||||
QProcessEnvironment env)
|
||||
{
|
||||
QProcess proc;
|
||||
proc.setProcessEnvironment(env.toProcessEnvironment());
|
||||
proc.setProcessEnvironment(env);
|
||||
QStringList arguments;
|
||||
arguments << QLatin1String("create") << QLatin1String("avd")
|
||||
<< QLatin1String("-t") << AndroidConfig::apiLevelNameFor(info.sdkPlatform)
|
||||
@@ -212,11 +200,11 @@ CreateAvdInfo AndroidToolManager::createAvdImpl(CreateAvdInfo info, FileName and
|
||||
|
||||
AndroidDeviceInfoList AndroidToolManager::androidVirtualDevices(const Utils::FileName &androidTool,
|
||||
const FileName &sdkLocationPath,
|
||||
const Environment &environment)
|
||||
const QProcessEnvironment &env)
|
||||
{
|
||||
AndroidDeviceInfoList devices;
|
||||
QString output;
|
||||
if (!androidToolCommand(androidTool, QStringList({"list", "avd"}), environment, &output))
|
||||
if (!androidToolCommand(androidTool, QStringList({"list", "avd"}), env, &output))
|
||||
return devices;
|
||||
|
||||
QStringList avds = output.split('\n');
|
||||
|
||||
@@ -57,12 +57,11 @@ public:
|
||||
|
||||
// Helper methods
|
||||
private:
|
||||
Utils::Environment androidToolEnvironment() const;
|
||||
static CreateAvdInfo createAvdImpl(CreateAvdInfo info, Utils::FileName androidToolPath,
|
||||
Utils::Environment env);
|
||||
QProcessEnvironment env);
|
||||
static AndroidDeviceInfoList androidVirtualDevices(const Utils::FileName &androidTool,
|
||||
const Utils::FileName &sdkLlocationPath,
|
||||
const Utils::Environment &environment);
|
||||
const QProcessEnvironment &env);
|
||||
private:
|
||||
const AndroidConfig &m_config;
|
||||
std::unique_ptr<AndroidToolOutputParser> m_parser;
|
||||
|
||||
Reference in New Issue
Block a user