Android: Read NDK and api versions from modules/Core.json

Qt 6.5+ writes the NDK version that was used for building Qt into
modules/Core.json. With this change, Qt Creator, now reads this version
and (if present) prefers it over the respective NDK version defined by
Qt Creator's own sdk_definition.json.

The order of preference for an NDK version being required and used for a
Qt version is now:

1) NDK that was manually set as "Default"
2) NDK defined by Qt's modules/Core.json
3) NDK version defined for a Qt version by sdk_definition.json
4) Default/fallback NDK version defined by sdk_definition.json

Task-number: QTCREATORBUG-28629
Change-Id: I2a0a9b3a1719139dc937d468e1dd3643289510a1
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
This commit is contained in:
Alessandro Portale
2023-01-09 13:59:45 +01:00
parent 06c4df37b9
commit b73d6f3be8
4 changed files with 139 additions and 0 deletions

View File

@@ -953,6 +953,16 @@ bool AndroidConfig::sdkToolsOk() const
QStringList AndroidConfig::essentialsFromQtVersion(const QtVersion &version) const
{
if (auto androidQtVersion = dynamic_cast<const AndroidQtVersion *>(&version)) {
bool ok;
const AndroidQtVersion::BuiltWith bw = androidQtVersion->builtWith(&ok);
if (ok) {
const QString ndkPackage = ndkPackageMarker() + bw.ndkVersion.toString();
return QStringList(ndkPackage)
+ packagesWithoutNdks(m_defaultSdkDepends.essentialPackages);
}
}
QVersionNumber qtVersion = version.qtVersion();
for (const SdkForQtVersions &item : m_specificQtVersions)
if (item.containsVersion(qtVersion))
@@ -973,6 +983,13 @@ static FilePath ndkSubPath(const SdkForQtVersions &packages)
FilePath AndroidConfig::ndkSubPathFromQtVersion(const QtVersion &version) const
{
if (auto androidQtVersion = dynamic_cast<const AndroidQtVersion *>(&version)) {
bool ok;
const AndroidQtVersion::BuiltWith bw = androidQtVersion->builtWith(&ok);
if (ok)
return FilePath::fromString(NdksSubDir) / bw.ndkVersion.toString();
}
for (const SdkForQtVersions &item : m_specificQtVersions)
if (item.containsVersion(version.qtVersion()))
return ndkSubPath(item);

View File

@@ -27,6 +27,8 @@ private slots:
void testAndroidSdkManagerProgressParser();
void testAndroidConfigAvailableNdkPlatforms_data();
void testAndroidConfigAvailableNdkPlatforms();
void testAndroidQtVersionParseBuiltWith_data();
void testAndroidQtVersionParseBuiltWith();
#endif // WITH_TESTS
};

View File

@@ -9,6 +9,7 @@
#include <utils/algorithm.h>
#include <utils/environment.h>
#include <utils/fileutils.h>
#include <utils/hostosinfo.h>
#include <qtsupport/qtkitinformation.h>
@@ -26,8 +27,15 @@
#include <proparser/profileevaluator.h>
#include <QJsonDocument>
#include <QJsonObject>
#include <QRegularExpression>
#ifdef WITH_TESTS
# include <QTest>
# include "androidplugin.h"
#endif // WITH_TESTS
using namespace ProjectExplorer;
namespace Android {
@@ -137,6 +145,22 @@ Utils::FilePath AndroidQtVersion::androidDeploymentSettings(const Target *target
.arg(displayName));
}
AndroidQtVersion::BuiltWith AndroidQtVersion::builtWith(bool *ok) const
{
const Utils::FilePath coreModuleJson = qmakeFilePath().parentDir().parentDir()
// version.prefix() not yet set when this is called
/ "modules/Core.json";
if (coreModuleJson.exists()) {
Utils::FileReader reader;
if (reader.fetch(coreModuleJson))
return parseBuiltWith(reader.data(), ok);
}
if (ok)
*ok = false;
return {};
}
static int versionFromPlatformString(const QString &string, bool *ok = nullptr)
{
static const QRegularExpression regex("android-(\\d+)");
@@ -146,6 +170,32 @@ static int versionFromPlatformString(const QString &string, bool *ok = nullptr)
return match.hasMatch() ? match.captured(1).toInt(ok) : -1;
}
AndroidQtVersion::BuiltWith AndroidQtVersion::parseBuiltWith(const QByteArray &modulesCoreJsonData,
bool *ok)
{
bool validPlatformString = false;
AndroidQtVersion::BuiltWith result;
const QJsonObject jsonObject = QJsonDocument::fromJson(modulesCoreJsonData).object();
if (const QJsonValue builtWith = jsonObject.value("built_with"); !builtWith.isUndefined()) {
if (const QJsonValue android = builtWith["android"]; !android.isUndefined()) {
if (const QJsonValue apiVersion = android["api_version"]; !apiVersion.isUndefined()) {
const QString apiVersionString = apiVersion.toString();
const int v = versionFromPlatformString(apiVersionString, &validPlatformString);
if (validPlatformString)
result.apiVersion = v;
}
if (const QJsonValue ndk = android["ndk"]; !ndk.isUndefined()) {
if (const QJsonValue version = ndk["version"]; !version.isUndefined())
result.ndkVersion = QVersionNumber::fromString(version.toString());
}
}
}
if (ok)
*ok = validPlatformString && !result.ndkVersion.isNull();
return result;
}
void AndroidQtVersion::parseMkSpec(ProFileEvaluator *evaluator) const
{
m_androidAbis = evaluator->values("ALL_ANDROID_ABIS");
@@ -187,5 +237,68 @@ AndroidQtVersionFactory::AndroidQtVersionFactory()
});
}
#ifdef WITH_TESTS
void AndroidPlugin::testAndroidQtVersionParseBuiltWith_data()
{
QTest::addColumn<QString>("modulesCoreJson");
QTest::addColumn<bool>("hasInfo");
QTest::addColumn<QVersionNumber>("ndkVersion");
QTest::addColumn<int>("apiVersion");
QTest::newRow("Android Qt 6.4")
<< R"({
"module_name": "Core",
"version": "6.4.1",
"built_with": {
"compiler_id": "Clang",
"compiler_target": "x86_64-none-linux-android23",
"compiler_version": "12.0.8",
"cross_compiled": true,
"target_system": "Android"
}
})"
<< false
<< QVersionNumber()
<< -1;
QTest::newRow("Android Qt 6.5")
<< R"({
"module_name": "Core",
"version": "6.5.0",
"built_with": {
"android": {
"api_version": "android-31",
"ndk": {
"version": "25.1.8937393"
}
},
"compiler_id": "Clang",
"compiler_target": "i686-none-linux-android23",
"compiler_version": "14.0.6",
"cross_compiled": true,
"target_system": "Android"
}
})"
<< true
<< QVersionNumber(25, 1, 8937393)
<< 31;
}
void AndroidPlugin::testAndroidQtVersionParseBuiltWith()
{
QFETCH(QString, modulesCoreJson);
QFETCH(bool, hasInfo);
QFETCH(int, apiVersion);
QFETCH(QVersionNumber, ndkVersion);
bool ok = false;
const AndroidQtVersion::BuiltWith bw =
AndroidQtVersion::parseBuiltWith(modulesCoreJson.toUtf8(), &ok);
QCOMPARE(ok, hasInfo);
QCOMPARE(bw.apiVersion, apiVersion);
QCOMPARE(bw.ndkVersion, ndkVersion);
}
#endif // WITH_TESTS
} // Internal
} // Android

View File

@@ -34,6 +34,13 @@ public:
static Utils::FilePath androidDeploymentSettings(const ProjectExplorer::Target *target);
struct BuiltWith {
int apiVersion = -1;
QVersionNumber ndkVersion;
};
static BuiltWith parseBuiltWith(const QByteArray &modulesCoreJsonData, bool *ok = nullptr);
BuiltWith builtWith(bool *ok = nullptr) const;
protected:
void parseMkSpec(ProFileEvaluator *) const override;
private: