summaryrefslogtreecommitdiffstats
path: root/src/tools/androiddeployqt/main.cpp
diff options
context:
space:
mode:
authorAlexey Edelev <alexey.edelev@qt.io>2023-02-01 17:53:58 +0000
committerAlexey Edelev <alexey.edelev@qt.io>2023-02-02 19:03:36 +0100
commit871f7a05db4b152387c563be519cf3426a9b249e (patch)
tree6fd677280ab1c23bc545e95af72a07e6012e28fa /src/tools/androiddeployqt/main.cpp
parentfd65f709748a7026428cc3a8828784cbb8421a03 (diff)
Revert "Revert "Add support for MultiABI with custom install dir of the android-build""
This reverts commit d7e8d5bb1b5a9c4b21a3d824780c672eaf4e56b1. Reason for revert: Found a working solution for the issue. Change-Id: Ia720cc63ece9dfb1a24067cdd9c3d79d4edbe3be Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io> Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
Diffstat (limited to 'src/tools/androiddeployqt/main.cpp')
-rw-r--r--src/tools/androiddeployqt/main.cpp164
1 files changed, 139 insertions, 25 deletions
diff --git a/src/tools/androiddeployqt/main.cpp b/src/tools/androiddeployqt/main.cpp
index 787c2f405c..75a2ddd4d5 100644
--- a/src/tools/androiddeployqt/main.cpp
+++ b/src/tools/androiddeployqt/main.cpp
@@ -70,10 +70,18 @@ struct QtDependency
struct QtInstallDirectoryWithTriple
{
- QtInstallDirectoryWithTriple(const QString &dir = QString(), const QString &t = QString()) :
- qtInstallDirectory(dir), triple(t), enabled(false) {}
+ QtInstallDirectoryWithTriple(const QString &dir = QString(),
+ const QString &t = QString(),
+ const QHash<QString, QString> &dirs = QHash<QString, QString>()
+ ) :
+ qtInstallDirectory(dir),
+ qtDirectories(dirs),
+ triple(t),
+ enabled(false)
+ {}
QString qtInstallDirectory;
+ QHash<QString, QString> qtDirectories;
QString triple;
bool enabled;
};
@@ -128,6 +136,12 @@ struct Options
// Build paths
QString qtInstallDirectory;
+ QHash<QString, QString> qtDirectories;
+ QString qtDataDirectory;
+ QString qtLibsDirectory;
+ QString qtLibExecsDirectory;
+ QString qtPluginsDirectory;
+ QString qtQmlDirectory;
QString qtHostDirectory;
std::vector<QString> extraPrefixDirs;
// Unlike 'extraPrefixDirs', the 'extraLibraryDirs' key doesn't expect the 'lib' subfolder
@@ -198,10 +212,17 @@ struct Options
QString installLocation;
// Per architecture collected information
- void setCurrentQtArchitecture(const QString &arch, const QString &directory)
+ void setCurrentQtArchitecture(const QString &arch,
+ const QString &directory,
+ const QHash<QString, QString> &directories)
{
currentArchitecture = arch;
qtInstallDirectory = directory;
+ qtDataDirectory = directories["qtDataDirectory"_L1];
+ qtLibsDirectory = directories["qtLibsDirectory"_L1];
+ qtLibExecsDirectory = directories["qtLibExecsDirectory"_L1];
+ qtPluginsDirectory = directories["qtPluginsDirectory"_L1];
+ qtQmlDirectory = directories["qtQmlDirectory"_L1];
}
typedef QPair<QString, QString> BundledFile;
QHash<QString, QList<BundledFile>> bundledFiles;
@@ -815,6 +836,66 @@ bool parseCmakeBoolean(const QJsonValue &value)
|| stringValue.toInt() > 0);
}
+bool readInputFileDirectory(Options *options, QJsonObject &jsonObject, const QString keyName)
+{
+ const QJsonValue qtDirectory = jsonObject.value(keyName);
+ if (qtDirectory.isUndefined()) {
+ for (auto it = options->architectures.constBegin(); it != options->architectures.constEnd(); ++it) {
+ if (keyName == "qtDataDirectory"_L1) {
+ options->architectures[it.key()].qtDirectories[keyName] = it.value().qtInstallDirectory;
+ break;
+ } else if (keyName == "qtLibsDirectory"_L1) {
+ options->architectures[it.key()].qtDirectories[keyName] = "lib"_L1;
+ break;
+ } else if (keyName == "qtLibExecsDirectory"_L1) {
+ options->architectures[it.key()].qtDirectories[keyName] = defaultLibexecDir();
+ break;
+ } else if (keyName == "qtPluginsDirectory"_L1) {
+ options->architectures[it.key()].qtDirectories[keyName] = "plugins"_L1;
+ break;
+ } else if (keyName == "qtQmlDirectory"_L1) {
+ options->architectures[it.key()].qtDirectories[keyName] = "qml"_L1;
+ break;
+ }
+ }
+ return true;
+ }
+
+ if (qtDirectory.isObject()) {
+ const QJsonObject object = qtDirectory.toObject();
+ for (auto it = object.constBegin(); it != object.constEnd(); ++it) {
+ if (it.value().isUndefined()) {
+ fprintf(stderr,
+ "Invalid '%s' record in deployment settings: %s\n",
+ qPrintable(keyName),
+ qPrintable(it.value().toString()));
+ return false;
+ }
+ if (it.value().isNull())
+ continue;
+ if (!options->architectures.contains(it.key())) {
+ fprintf(stderr, "Architecture %s unknown (%s).", qPrintable(it.key()),
+ qPrintable(options->architectures.keys().join(u',')));
+ return false;
+ }
+ options->architectures[it.key()].qtDirectories[keyName] = it.value().toString();
+ }
+ } else if (qtDirectory.isString()) {
+ // Format for Qt < 6 or when using the tool with Qt >= 6 but in single arch.
+ // We assume Qt > 5.14 where all architectures are in the same directory.
+ const QString directory = qtDirectory.toString();
+ options->architectures["arm64-v8a"_L1].qtDirectories[keyName] = directory;
+ options->architectures["armeabi-v7a"_L1].qtDirectories[keyName] = directory;
+ options->architectures["x86"_L1].qtDirectories[keyName] = directory;
+ options->architectures["x86_64"_L1].qtDirectories[keyName] = directory;
+ } else {
+ fprintf(stderr, "Invalid format for %s in json file %s.\n",
+ qPrintable(keyName), qPrintable(options->inputFileName));
+ return false;
+ }
+ return true;
+}
+
bool readInputFile(Options *options)
{
QFile file(options->inputFileName);
@@ -871,7 +952,8 @@ bool readInputFile(Options *options)
const QJsonObject object = qtInstallDirectory.toObject();
for (auto it = object.constBegin(); it != object.constEnd(); ++it) {
if (it.value().isUndefined()) {
- fprintf(stderr, "Invalid architecture: %s\n",
+ fprintf(stderr,
+ "Invalid 'qt' record in deployment settings: %s\n",
qPrintable(it.value().toString()));
return false;
}
@@ -899,6 +981,14 @@ bool readInputFile(Options *options)
return false;
}
}
+
+ if (!readInputFileDirectory(options, jsonObject, "qtDataDirectory"_L1) ||
+ !readInputFileDirectory(options, jsonObject, "qtLibsDirectory"_L1) ||
+ !readInputFileDirectory(options, jsonObject, "qtLibExecsDirectory"_L1) ||
+ !readInputFileDirectory(options, jsonObject, "qtPluginsDirectory"_L1) ||
+ !readInputFileDirectory(options, jsonObject, "qtQmlDirectory"_L1))
+ return false;
+
{
const QJsonValue qtHostDirectory = jsonObject.value("qtHostDir"_L1);
if (!qtHostDirectory.isUndefined()) {
@@ -1220,13 +1310,15 @@ void cleanAndroidFiles(const Options &options)
if (!options.androidSourceDirectory.isEmpty())
cleanTopFolders(options, QDir(options.androidSourceDirectory), options.outputDirectory);
- cleanTopFolders(options, QDir(options.qtInstallDirectory + "/src/android/templates"_L1),
+ cleanTopFolders(options,
+ QDir(options.qtInstallDirectory + u'/' +
+ options.qtDataDirectory + "/src/android/templates"_L1),
options.outputDirectory);
}
bool copyAndroidTemplate(const Options &options, const QString &androidTemplate, const QString &outDirPrefix = QString())
{
- QDir sourceDirectory(options.qtInstallDirectory + androidTemplate);
+ QDir sourceDirectory(options.qtInstallDirectory + u'/' + options.qtDataDirectory + androidTemplate);
if (!sourceDirectory.exists()) {
fprintf(stderr, "Cannot find template directory %s\n", qPrintable(sourceDirectory.absolutePath()));
return false;
@@ -1244,7 +1336,8 @@ bool copyAndroidTemplate(const Options &options, const QString &androidTemplate,
bool copyGradleTemplate(const Options &options)
{
- QDir sourceDirectory(options.qtInstallDirectory + "/src/3rdparty/gradle"_L1);
+ QDir sourceDirectory(options.qtInstallDirectory + u'/' +
+ options.qtDataDirectory + "/src/3rdparty/gradle"_L1);
if (!sourceDirectory.exists()) {
fprintf(stderr, "Cannot find template directory %s\n", qPrintable(sourceDirectory.absolutePath()));
return false;
@@ -1369,7 +1462,8 @@ bool copyAndroidExtraResources(Options *options)
}
QDir resourceDir(extraResource);
- QString assetsDir = options->outputDirectory + "/assets/"_L1 + resourceDir.dirName() + u'/';
+ QString assetsDir = options->outputDirectory + "/assets/"_L1 +
+ resourceDir.dirName() + u'/';
QString libsDir = options->outputDirectory + "/libs/"_L1 + options->currentArchitecture + u'/';
const QStringList files = allFilesInside(resourceDir, resourceDir);
@@ -1706,6 +1800,21 @@ static QString absoluteFilePath(const Options *options, const QString &relativeF
if (QFile::exists(path))
return path;
}
+
+ if (relativeFileName.endsWith("-android-dependencies.xml"_L1)) {
+ return options->qtInstallDirectory + u'/' + options->qtLibsDirectory +
+ u'/' + relativeFileName;
+ }
+
+ if (relativeFileName.startsWith("jar/"_L1)) {
+ return options->qtInstallDirectory + u'/' + options->qtDataDirectory +
+ u'/' + relativeFileName;
+ }
+
+ if (relativeFileName.startsWith("lib/"_L1)) {
+ return options->qtInstallDirectory + u'/' + options->qtLibsDirectory +
+ u'/' + relativeFileName.mid(sizeof("lib/") - 1);
+ }
return options->qtInstallDirectory + u'/' + relativeFileName;
}
@@ -1739,8 +1848,9 @@ QList<QtDependency> findFilesRecursively(const Options &options, const QString &
if (info.exists())
return findFilesRecursively(options, info, prefix + u'/');
}
- QFileInfo info(options.qtInstallDirectory + u'/' + fileName);
- return findFilesRecursively(options, info, options.qtInstallDirectory + u'/');
+ QFileInfo info(options.qtInstallDirectory + "/"_L1 + fileName);
+ QFileInfo rootPath(options.qtInstallDirectory + "/"_L1);
+ return findFilesRecursively(options, info, rootPath.absolutePath() + u'/');
}
bool readAndroidDependencyXml(Options *options,
@@ -1748,7 +1858,7 @@ bool readAndroidDependencyXml(Options *options,
QSet<QString> *usedDependencies,
QSet<QString> *remainingDependencies)
{
- QString androidDependencyName = absoluteFilePath(options, "/lib/%1-android-dependencies.xml"_L1.arg(moduleName));
+ QString androidDependencyName = absoluteFilePath(options, "%1-android-dependencies.xml"_L1.arg(moduleName));
QFile androidDependencyFile(androidDependencyName);
if (androidDependencyFile.exists()) {
@@ -1774,6 +1884,7 @@ bool readAndroidDependencyXml(Options *options,
QString file = reader.attributes().value("file"_L1).toString();
const QList<QtDependency> fileNames = findFilesRecursively(*options, file);
+
for (const QtDependency &fileName : fileNames) {
if (usedDependencies->contains(fileName.absolutePath))
continue;
@@ -1951,8 +2062,8 @@ bool scanImports(Options *options, QSet<QString> *usedDependencies)
if (!options->qmlImportScannerBinaryPath.isEmpty()) {
qmlImportScanner = options->qmlImportScannerBinaryPath;
} else {
- qmlImportScanner = execSuffixAppended(options->qtInstallDirectory + u'/'
- + defaultLibexecDir() + "/qmlimportscanner"_L1);
+ qmlImportScanner = execSuffixAppended(options->qtLibExecsDirectory +
+ "/qmlimportscanner"_L1);
}
QStringList importPaths;
@@ -1961,7 +2072,7 @@ bool scanImports(Options *options, QSet<QString> *usedDependencies)
// lacks a qml directory. We don't want to pass it as an import path if it doesn't exist
// because it will cause qmlimportscanner to fail.
// This also covers the case when only qtbase is installed in a regular Qt build.
- const QString mainImportPath = options->qtInstallDirectory + "/qml"_L1;
+ const QString mainImportPath = options->qtInstallDirectory + u'/' + options->qtQmlDirectory;
if (QFile::exists(mainImportPath))
importPaths += shellQuote(mainImportPath);
@@ -2215,8 +2326,7 @@ bool createRcc(const Options &options)
if (!options.rccBinaryPath.isEmpty()) {
rcc = options.rccBinaryPath;
} else {
- rcc = execSuffixAppended(options.qtInstallDirectory + u'/' + defaultLibexecDir() +
- "/rcc"_L1);
+ rcc = execSuffixAppended(options.qtLibExecsDirectory + "/rcc"_L1);
}
if (!QFile::exists(rcc)) {
@@ -2409,12 +2519,8 @@ bool copyQtFiles(Options *options)
QString destinationFileName;
bool isSharedLibrary = qtDependency.relativePath.endsWith(".so"_L1);
if (isSharedLibrary) {
- QString garbledFileName;
- if (QDir::fromNativeSeparators(qtDependency.relativePath).startsWith("lib/"_L1)) {
- garbledFileName = qtDependency.relativePath.mid(sizeof("lib/") - 1);
- } else {
- garbledFileName = qtDependency.relativePath.mid(qtDependency.relativePath.lastIndexOf(u'/') + 1);
- }
+ QString garbledFileName = qtDependency.relativePath.mid(
+ qtDependency.relativePath.lastIndexOf(u'/') + 1);
destinationFileName = libsDirectory + options->currentArchitecture + u'/' + garbledFileName;
} else if (QDir::fromNativeSeparators(qtDependency.relativePath).startsWith("jar/"_L1)) {
destinationFileName = libsDirectory + qtDependency.relativePath.mid(sizeof("jar/") - 1);
@@ -2615,11 +2721,17 @@ bool buildAndroidProject(const Options &options)
gradleProperties["android.bundle.enableUncompressedNativeLibs"] = "false";
gradleProperties["buildDir"] = "build";
- gradleProperties["qtAndroidDir"] = (options.qtInstallDirectory + "/src/android/java"_L1).toUtf8();
+ gradleProperties["qtAndroidDir"] =
+ (options.qtInstallDirectory + u'/' + options.qtDataDirectory +
+ "/src/android/java"_L1)
+ .toUtf8();
// The following property "qt5AndroidDir" is only for compatibility.
// Projects using a custom build.gradle file may use this variable.
// ### Qt7: Remove the following line
- gradleProperties["qt5AndroidDir"] = (options.qtInstallDirectory + "/src/android/java"_L1).toUtf8();
+ gradleProperties["qt5AndroidDir"] =
+ (options.qtInstallDirectory + u'/' + options.qtDataDirectory +
+ "/src/android/java"_L1)
+ .toUtf8();
gradleProperties["androidCompileSdkVersion"] = options.androidPlatform.split(u'-').last().toLocal8Bit();
gradleProperties["qtMinSdkVersion"] = options.minSdkVersion;
gradleProperties["qtTargetSdkVersion"] = options.targetSdkVersion;
@@ -3131,7 +3243,9 @@ int main(int argc, char *argv[])
for (auto it = options.architectures.constBegin(); it != options.architectures.constEnd(); ++it) {
if (!it->enabled)
continue;
- options.setCurrentQtArchitecture(it.key(), it.value().qtInstallDirectory);
+ options.setCurrentQtArchitecture(it.key(),
+ it.value().qtInstallDirectory,
+ it.value().qtDirectories);
// All architectures have a copy of the gradle files but only one set needs to be copied.
if (!androidTemplatetCopied && options.build && !options.auxMode && !options.copyDependenciesOnly) {