forked from qt-creator/qt-creator
Android: fix some issues with jdk path detection
* There were two functions to detect jdk path, unified them. * First try to find jdk 1.8, if not found, look for newer versions. SDK Tools version 26.x needs jdk 1.8 however, the new cmdline-tools can work with the newest jdk, so the UI will warn the user if the selected jdk cannot run sdkmanager potentially because of the jdk version. Change-Id: Iee2c378598c26e8a9a8245262110ac20322a2d2b Reviewed-by: Alessandro Portale <alessandro.portale@qt.io>
This commit is contained in:
@@ -105,7 +105,8 @@ const char macOsKey[] = "mac";
|
||||
|
||||
|
||||
namespace {
|
||||
const char jdkSettingsPath[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit";
|
||||
const char jdk8SettingsPath[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\Java Development Kit";
|
||||
const char jdkLatestSettingsPath[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\JDK\\";
|
||||
|
||||
const QLatin1String SettingsGroup("AndroidConfigurations");
|
||||
const QLatin1String SDKLocationKey("SDKLocation");
|
||||
@@ -1476,103 +1477,77 @@ AndroidConfigurations::AndroidConfigurations()
|
||||
|
||||
AndroidConfigurations::~AndroidConfigurations() = default;
|
||||
|
||||
static FilePath javaHomeForJavac(const FilePath &location)
|
||||
FilePath AndroidConfig::getJdkPath()
|
||||
{
|
||||
QFileInfo fileInfo = location.toFileInfo();
|
||||
int tries = 5;
|
||||
while (tries > 0) {
|
||||
QDir dir = fileInfo.dir();
|
||||
dir.cdUp();
|
||||
if (QFileInfo::exists(dir.filePath(QLatin1String("lib/tools.jar"))))
|
||||
return FilePath::fromString(dir.path());
|
||||
if (fileInfo.isSymLink())
|
||||
fileInfo.setFile(fileInfo.symLinkTarget());
|
||||
FilePath jdkHome;
|
||||
|
||||
if (HostOsInfo::isWindowsHost()) {
|
||||
QStringList allVersions;
|
||||
std::unique_ptr<QSettings> settings(
|
||||
new QSettings(jdk8SettingsPath, QSettings::NativeFormat));
|
||||
allVersions = settings->childGroups();
|
||||
#ifdef Q_OS_WIN
|
||||
if (allVersions.isEmpty()) {
|
||||
settings.reset(new QSettings(jdk8SettingsPath, QSettings::Registry64Format));
|
||||
allVersions = settings->childGroups();
|
||||
}
|
||||
#endif // Q_OS_WIN
|
||||
|
||||
// If no jdk 1.8 can be found, look for jdk versions above 1.8
|
||||
// Android section would warn if sdkmanager cannot run with newer jdk versions
|
||||
if (allVersions.isEmpty()) {
|
||||
settings.reset(new QSettings(jdkLatestSettingsPath, QSettings::NativeFormat));
|
||||
allVersions = settings->childGroups();
|
||||
#ifdef Q_OS_WIN
|
||||
if (allVersions.isEmpty()) {
|
||||
settings.reset(new QSettings(jdkLatestSettingsPath, QSettings::Registry64Format));
|
||||
allVersions = settings->childGroups();
|
||||
}
|
||||
#endif // Q_OS_WIN
|
||||
}
|
||||
|
||||
for (const QString &version : allVersions) {
|
||||
settings->beginGroup(version);
|
||||
jdkHome = FilePath::fromUserInput(settings->value("JavaHome").toString());
|
||||
settings->endGroup();
|
||||
if (version.startsWith("1.8")) {
|
||||
if (!jdkHome.exists())
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
QStringList args;
|
||||
if (HostOsInfo::isMacHost())
|
||||
args << "-c"
|
||||
<< "/usr/libexec/java_home";
|
||||
else
|
||||
break;
|
||||
--tries;
|
||||
args << "-c"
|
||||
<< "readlink -f $(which java)";
|
||||
|
||||
QProcess findJdkPathProc;
|
||||
findJdkPathProc.start("sh", args);
|
||||
findJdkPathProc.waitForFinished();
|
||||
QByteArray jdkPath = findJdkPathProc.readAllStandardOutput().trimmed();
|
||||
|
||||
if (HostOsInfo::isMacHost()) {
|
||||
jdkHome = FilePath::fromUtf8(jdkPath);
|
||||
} else {
|
||||
jdkPath.replace("bin/java", ""); // For OpenJDK 11
|
||||
jdkPath.replace("jre/bin/java", "");
|
||||
jdkHome = FilePath::fromUtf8(jdkPath);
|
||||
}
|
||||
}
|
||||
return FilePath();
|
||||
|
||||
return jdkHome;
|
||||
}
|
||||
|
||||
void AndroidConfigurations::load()
|
||||
{
|
||||
bool saveSettings = false;
|
||||
QSettings *settings = Core::ICore::settings();
|
||||
settings->beginGroup(SettingsGroup);
|
||||
m_config.load(*settings);
|
||||
|
||||
if (m_config.openJDKLocation().isEmpty()) {
|
||||
if (HostOsInfo::isLinuxHost()) {
|
||||
Environment env = Environment::systemEnvironment();
|
||||
FilePath location = env.searchInPath(QLatin1String("javac"));
|
||||
QFileInfo fi = location.toFileInfo();
|
||||
if (fi.exists() && fi.isExecutable() && !fi.isDir()) {
|
||||
m_config.setOpenJDKLocation(javaHomeForJavac(location));
|
||||
saveSettings = true;
|
||||
}
|
||||
} else if (HostOsInfo::isMacHost()) {
|
||||
QFileInfo javaHomeExec(QLatin1String("/usr/libexec/java_home"));
|
||||
if (javaHomeExec.isExecutable() && !javaHomeExec.isDir()) {
|
||||
SynchronousProcess proc;
|
||||
proc.setTimeoutS(2);
|
||||
proc.setProcessChannelMode(QProcess::MergedChannels);
|
||||
SynchronousProcessResponse response =
|
||||
proc.runBlocking({javaHomeExec.absoluteFilePath(), {}});
|
||||
if (response.result == SynchronousProcessResponse::Finished) {
|
||||
const QString &javaHome = response.allOutput().trimmed();
|
||||
if (!javaHome.isEmpty() && QFileInfo::exists(javaHome))
|
||||
m_config.setOpenJDKLocation(FilePath::fromString(javaHome));
|
||||
}
|
||||
}
|
||||
} else if (HostOsInfo::isWindowsHost()) {
|
||||
QStringList allVersions;
|
||||
std::unique_ptr<QSettings> settings(new QSettings(jdkSettingsPath,
|
||||
QSettings::NativeFormat));
|
||||
allVersions = settings->childGroups();
|
||||
#ifdef Q_OS_WIN
|
||||
if (allVersions.isEmpty()) {
|
||||
settings.reset(new QSettings(jdkSettingsPath, QSettings::Registry64Format));
|
||||
allVersions = settings->childGroups();
|
||||
}
|
||||
#endif // Q_OS_WIN
|
||||
|
||||
QString javaHome;
|
||||
int major = -1;
|
||||
int minor = -1;
|
||||
foreach (const QString &version, allVersions) {
|
||||
QStringList parts = version.split(QLatin1Char('.'));
|
||||
if (parts.size() != 2) // not interested in 1.7.0_u21
|
||||
continue;
|
||||
bool okMajor, okMinor;
|
||||
int tmpMajor = parts.at(0).toInt(&okMajor);
|
||||
int tmpMinor = parts.at(1).toInt(&okMinor);
|
||||
if (!okMajor || !okMinor)
|
||||
continue;
|
||||
if (tmpMajor > major
|
||||
|| (tmpMajor == major
|
||||
&& tmpMinor > minor)) {
|
||||
settings->beginGroup(version);
|
||||
QString tmpJavaHome = settings->value(QLatin1String("JavaHome")).toString();
|
||||
settings->endGroup();
|
||||
if (!QFileInfo::exists(tmpJavaHome))
|
||||
continue;
|
||||
|
||||
major = tmpMajor;
|
||||
minor = tmpMinor;
|
||||
javaHome = tmpJavaHome;
|
||||
}
|
||||
}
|
||||
if (!javaHome.isEmpty()) {
|
||||
m_config.setOpenJDKLocation(FilePath::fromString(javaHome));
|
||||
saveSettings = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
settings->endGroup();
|
||||
|
||||
if (saveSettings)
|
||||
save();
|
||||
}
|
||||
|
||||
void AndroidConfigurations::updateAndroidDevice()
|
||||
|
@@ -196,6 +196,7 @@ public:
|
||||
Utils::FilePath openSslLocation() const;
|
||||
void setOpenSslLocation(const Utils::FilePath &openSslLocation);
|
||||
|
||||
static Utils::FilePath getJdkPath();
|
||||
|
||||
private:
|
||||
static QString getDeviceProperty(const Utils::FilePath &adbToolPath,
|
||||
|
@@ -242,7 +242,7 @@ private:
|
||||
mutable QReadWriteLock m_licenseInputLock;
|
||||
|
||||
public:
|
||||
bool m_packageListingSuccessful = true;
|
||||
bool m_packageListingSuccessful = false;
|
||||
};
|
||||
|
||||
/*!
|
||||
@@ -908,6 +908,7 @@ void AndroidSdkManagerPrivate::reloadSdkPackages()
|
||||
clearPackages();
|
||||
|
||||
lastSdkManagerPath = m_config.sdkManagerToolPath();
|
||||
m_packageListingSuccessful = false;
|
||||
|
||||
if (m_config.sdkToolsVersion().isNull()) {
|
||||
// Configuration has invalid sdk path or corrupt installation.
|
||||
|
@@ -103,7 +103,6 @@ private:
|
||||
void apply() final { AndroidConfigurations::setConfig(m_androidConfig); }
|
||||
|
||||
void validateJdk();
|
||||
FilePath findJdkInCommonPaths() const;
|
||||
void validateNdk();
|
||||
void updateNdkList();
|
||||
void onSdkPathChanged();
|
||||
@@ -155,8 +154,7 @@ private:
|
||||
|
||||
enum JavaValidation {
|
||||
JavaPathExistsRow,
|
||||
JavaJdkValidRow,
|
||||
JavaJdkValidVersionRow
|
||||
JavaJdkValidRow
|
||||
};
|
||||
|
||||
enum AndroidValidation {
|
||||
@@ -395,7 +393,6 @@ AndroidSettingsWidget::AndroidSettingsWidget()
|
||||
QMap<int, QString> javaValidationPoints;
|
||||
javaValidationPoints[JavaPathExistsRow] = tr("JDK path exists.");
|
||||
javaValidationPoints[JavaJdkValidRow] = tr("JDK path is a valid JDK root folder.");
|
||||
javaValidationPoints[JavaJdkValidVersionRow] = tr("Working JDK version (8) detected.");
|
||||
m_javaSummary = new SummaryWidget(javaValidationPoints, tr("Java Settings are OK."),
|
||||
tr("Java settings have errors."), m_ui.javaDetailsWidget);
|
||||
|
||||
@@ -405,7 +402,7 @@ AndroidSettingsWidget::AndroidSettingsWidget()
|
||||
androidValidationPoints[SdkToolsInstalledRow] = tr("SDK tools installed.");
|
||||
androidValidationPoints[PlatformToolsInstalledRow] = tr("Platform tools installed.");
|
||||
androidValidationPoints[SdkManagerSuccessfulRow] = tr(
|
||||
"SDK manager runs (requires exactly Java 1.8).");
|
||||
"SDK manager runs (SDK Tools versions <= 26.x require exactly Java 1.8).");
|
||||
androidValidationPoints[AllEssentialsInstalledRow] = tr(
|
||||
"All essential packages installed for all installed Qt versions.");
|
||||
androidValidationPoints[BuildToolsInstalledRow] = tr("Build tools installed.");
|
||||
@@ -433,7 +430,7 @@ AndroidSettingsWidget::AndroidSettingsWidget()
|
||||
this, &AndroidSettingsWidget::validateJdk);
|
||||
FilePath currentJdkPath = m_androidConfig.openJDKLocation();
|
||||
if (currentJdkPath.isEmpty())
|
||||
currentJdkPath = findJdkInCommonPaths();
|
||||
currentJdkPath = AndroidConfig::getJdkPath();
|
||||
m_ui.OpenJDKLocationPathChooser->setFilePath(currentJdkPath);
|
||||
m_ui.OpenJDKLocationPathChooser->setPromptDialogTitle(tr("Select JDK Path"));
|
||||
|
||||
@@ -584,24 +581,6 @@ void AndroidSettingsWidget::validateJdk()
|
||||
const FilePath bin = m_androidConfig.openJDKLocation().pathAppended("bin/javac" QTC_HOST_EXE_SUFFIX);
|
||||
m_javaSummary->setPointValid(JavaJdkValidRow, jdkPathExists && bin.exists());
|
||||
|
||||
bool jdkVersionCorrect = false;
|
||||
SynchronousProcess javacProcess;
|
||||
const int timeoutS = 5;
|
||||
javacProcess.setTimeoutS(timeoutS);
|
||||
const CommandLine cmd(bin, {"-version"});
|
||||
SynchronousProcessResponse response = javacProcess.runBlocking(cmd);
|
||||
if (response.result == SynchronousProcessResponse::Finished) {
|
||||
QString output = response.stdOut(); // JDK 14 uses stdOut for this output.
|
||||
if (output.isEmpty())
|
||||
output = response.stdErr(); // JDK 8 uses stdErr for this output.
|
||||
if (output.startsWith("javac ")) {
|
||||
const QVersionNumber javacVersion = QVersionNumber::fromString(output.mid(6));
|
||||
if (QVersionNumber(1, 8).isPrefixOf(javacVersion))
|
||||
jdkVersionCorrect = true;
|
||||
}
|
||||
}
|
||||
m_javaSummary->setPointValid(JavaJdkValidVersionRow, jdkVersionCorrect);
|
||||
|
||||
updateUI();
|
||||
}
|
||||
|
||||
@@ -620,53 +599,6 @@ void AndroidSettingsWidget::validateOpenSsl()
|
||||
updateUI();
|
||||
}
|
||||
|
||||
FilePath AndroidSettingsWidget::findJdkInCommonPaths() const
|
||||
{
|
||||
QString jdkFromEnvVar = QString::fromLocal8Bit(getenv("JAVA_HOME"));
|
||||
if (!jdkFromEnvVar.isEmpty())
|
||||
return FilePath::fromUserInput(jdkFromEnvVar);
|
||||
|
||||
if (HostOsInfo::isWindowsHost()) {
|
||||
QString jdkRegisteryPath = "HKEY_LOCAL_MACHINE\\SOFTWARE\\JavaSoft\\JDK\\";
|
||||
QSettings jdkSettings(jdkRegisteryPath, QSettings::NativeFormat);
|
||||
|
||||
QStringList jdkVersions = jdkSettings.childGroups();
|
||||
FilePath jdkHome;
|
||||
|
||||
for (const QString &version : jdkVersions) {
|
||||
jdkSettings.beginGroup(version);
|
||||
jdkHome = FilePath::fromUserInput(jdkSettings.value("JavaHome").toString());
|
||||
jdkSettings.endGroup();
|
||||
if (version.startsWith("1.8"))
|
||||
return jdkHome;
|
||||
}
|
||||
|
||||
return jdkHome;
|
||||
}
|
||||
|
||||
QProcess findJdkPathProc;
|
||||
|
||||
QString cmd;
|
||||
QStringList args;
|
||||
|
||||
if (HostOsInfo::isMacHost()) {
|
||||
cmd = "sh";
|
||||
args << "-c" << "/usr/libexec/java_home";
|
||||
} else {
|
||||
cmd = "sh";
|
||||
args << "-c" << "readlink -f $(which java)";
|
||||
}
|
||||
|
||||
findJdkPathProc.start(cmd, args);
|
||||
findJdkPathProc.waitForFinished();
|
||||
QByteArray jdkPath = findJdkPathProc.readAllStandardOutput().trimmed();
|
||||
|
||||
if (HostOsInfo::isMacHost())
|
||||
return FilePath::fromUtf8(jdkPath);
|
||||
else
|
||||
return FilePath::fromUtf8(jdkPath.replace("jre/bin/java", ""));
|
||||
}
|
||||
|
||||
void AndroidSettingsWidget::validateNdk()
|
||||
{
|
||||
const QListWidgetItem *currentItem = m_ui.ndkListWidget->currentItem();
|
||||
|
Reference in New Issue
Block a user