summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSoheil Armin <soheil.armin@qt.io>2024-03-27 01:26:22 +0200
committerTinja Paavoseppä <tinja.paavoseppa@qt.io>2024-05-15 12:34:08 +0300
commit79f3fe70407932450e36e9a69046bbe923b8e445 (patch)
tree8e7a07e8ccdccdf891cb9a81929fa4a8aa90edbb
parente59f3100615e5ca52530f284a98d01627b826fae (diff)
Android: Add facilities to build AAR packages
This adds new aar target, as we do with apk targets, and an option to androiddeployqt, --build-aar, which builds an AAR instead of APK. AndroidManifest.xml of an AAR does not include application or activity nodes, so we add an AAR specific manifest. Also the plugin type in build.gradle will be com.android.library when choosing to build an AAR. Task-number: QTBUG-116955 Task-number: QTBUG-65567 Change-Id: Id33ac236f44038a8411ebfecdcc4e404c976e277 Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
-rw-r--r--src/android/CMakeLists.txt1
-rw-r--r--src/android/templates_aar/AndroidManifest.xml9
-rw-r--r--src/android/templates_aar/CMakeLists.txt24
-rw-r--r--src/corelib/Qt6AndroidMacros.cmake46
-rw-r--r--src/tools/androiddeployqt/main.cpp46
5 files changed, 124 insertions, 2 deletions
diff --git a/src/android/CMakeLists.txt b/src/android/CMakeLists.txt
index 045076c8d3..007430598e 100644
--- a/src/android/CMakeLists.txt
+++ b/src/android/CMakeLists.txt
@@ -8,5 +8,6 @@ if (ANDROID)
add_subdirectory(jar)
add_subdirectory(java)
add_subdirectory(templates)
+ add_subdirectory(templates_aar)
endif()
diff --git a/src/android/templates_aar/AndroidManifest.xml b/src/android/templates_aar/AndroidManifest.xml
new file mode 100644
index 0000000000..9c9e91e650
--- /dev/null
+++ b/src/android/templates_aar/AndroidManifest.xml
@@ -0,0 +1,9 @@
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ package="org.qtproject.example"
+ android:versionCode="-- %%INSERT_VERSION_CODE%% --"
+ android:versionName="-- %%INSERT_VERSION_NAME%% --">
+ <!-- %%INSERT_PERMISSIONS -->
+ <!-- %%INSERT_FEATURES -->
+</manifest>
diff --git a/src/android/templates_aar/CMakeLists.txt b/src/android/templates_aar/CMakeLists.txt
new file mode 100644
index 0000000000..07c421fbab
--- /dev/null
+++ b/src/android/templates_aar/CMakeLists.txt
@@ -0,0 +1,24 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+# Android aar specific template files
+
+set(templates_aar_files
+ "${CMAKE_CURRENT_SOURCE_DIR}/AndroidManifest.xml")
+
+add_custom_target(Qt${QtBase_VERSION_MAJOR}AndroidAarTemplates
+ SOURCES
+ ${templates_aar_files}
+)
+
+qt_path_join(destination ${QT_INSTALL_DIR} ${INSTALL_DATADIR} "src/android/templates_aar")
+
+qt_copy_or_install(FILES ${templates_aar_files}
+ DESTINATION "${destination}")
+
+if(NOT QT_WILL_INSTALL)
+ qt_internal_copy_at_build_time(TARGET Qt${QtBase_VERSION_MAJOR}AndroidAarTemplates
+ FILES ${templates_aar_files}
+ DESTINATION ${destination}
+ )
+endif()
diff --git a/src/corelib/Qt6AndroidMacros.cmake b/src/corelib/Qt6AndroidMacros.cmake
index 6218df1947..96b24ee680 100644
--- a/src/corelib/Qt6AndroidMacros.cmake
+++ b/src/corelib/Qt6AndroidMacros.cmake
@@ -381,6 +381,9 @@ function(qt6_android_add_apk_target target)
if(TARGET aab)
add_dependencies(aab ${target}_make_aab)
endif()
+ if(TARGET aar)
+ add_dependencies(aar ${target}_make_aar)
+ endif()
if(TARGET apk)
add_dependencies(apk ${target}_make_apk)
_qt_internal_create_global_apk_all_target_if_needed()
@@ -418,8 +421,10 @@ function(qt6_android_add_apk_target target)
endif()
set(apk_file_name "${target}.apk")
+ set(aar_file_name "${target}.aar")
set(dep_file_name "${target}.d")
set(apk_final_file_path "${apk_final_dir}/${apk_file_name}")
+ set(aar_final_file_path "${apk_final_dir}/${aar_file_name}")
set(dep_file_path "${apk_final_dir}/${dep_file_name}")
set(target_file_copy_relative_path
"libs/${CMAKE_ANDROID_ARCH_ABI}/$<TARGET_FILE_NAME:${target}>")
@@ -523,10 +528,33 @@ function(qt6_android_add_apk_target target)
VERBATIM
${uses_terminal}
)
+
+ # Add custom command that creates the aar and triggers rebuild if files listed in
+ # ${dep_file_path} are changed.
+ add_custom_command(OUTPUT "${aar_final_file_path}"
+ COMMAND ${CMAKE_COMMAND}
+ -E copy "$<TARGET_FILE:${target}>"
+ "${apk_final_dir}/${target_file_copy_relative_path}"
+ COMMAND "${deployment_tool}"
+ --input "${deployment_file}"
+ --output "${apk_final_dir}"
+ --apk "${aar_final_file_path}"
+ --depfile "${dep_file_path}"
+ --builddir "${relative_to_dir}"
+ --build-aar
+ ${extra_args}
+ COMMENT "Creating AAR for ${target}"
+ DEPENDS "${target}" "${deployment_file}" ${extra_deps}
+ DEPFILE "${dep_file_path}"
+ VERBATIM
+ ${uses_terminal}
+ )
cmake_policy(POP)
# Create a ${target}_make_apk target to trigger the apk build.
add_custom_target(${target}_make_apk DEPENDS "${apk_final_file_path}")
+ # Create a ${target}_make_aar target to trigger the aar build.
+ add_custom_target(${target}_make_aar DEPENDS "${aar_final_file_path}")
else()
add_custom_target(${target}_make_apk
DEPENDS ${target}_prepare_apk_dir
@@ -540,6 +568,19 @@ function(qt6_android_add_apk_target target)
VERBATIM
${uses_terminal}
)
+
+ add_custom_target(${target}_make_aar
+ DEPENDS ${target}_prepare_apk_dir
+ COMMAND ${deployment_tool}
+ --input ${deployment_file}
+ --output ${apk_final_dir}
+ --apk ${aar_final_file_path}
+ --build-aar
+ ${extra_args}
+ COMMENT "Creating AAR for ${target}"
+ VERBATIM
+ ${uses_terminal}
+ )
endif()
# Add target triggering AAB creation. Since the _make_aab target is not added to the ALL
@@ -638,6 +679,11 @@ function(_qt_internal_create_global_android_targets)
# It will trigger building all the apk build targets that are added as part of the project.
# Allow opting out.
_qt_internal_create_global_android_targets_impl(aab)
+
+ # Create a top-level "aar" target for convenience, so that users can call 'ninja aar'.
+ # It will trigger building all the aar build targets that are added as part of the project.
+ # Allow opting out.
+ _qt_internal_create_global_android_targets_impl(aar)
endfunction()
# The function collects all known non-imported shared libraries that are created in the build tree.
diff --git a/src/tools/androiddeployqt/main.cpp b/src/tools/androiddeployqt/main.cpp
index cbe6336c97..c2af8d381c 100644
--- a/src/tools/androiddeployqt/main.cpp
+++ b/src/tools/androiddeployqt/main.cpp
@@ -105,6 +105,7 @@ struct Options
, installApk(false)
, uninstallApk(false)
, qmlImportScannerBinaryPath()
+ , buildAar(false)
{}
enum DeploymentMechanism
@@ -240,6 +241,7 @@ struct Options
// Override qml import scanner path
QString qmlImportScannerBinaryPath;
bool qmlSkipImportScanning = false;
+ bool buildAar;
};
static const QHash<QByteArray, QByteArray> elfArchitectures = {
@@ -526,6 +528,8 @@ Options parseOptions()
options.protectedAuthenticationPath = true;
} else if (argument.compare("--aux-mode"_L1, Qt::CaseInsensitive) == 0) {
options.auxMode = true;
+ } else if (argument.compare("--build-aar"_L1, Qt::CaseInsensitive) == 0) {
+ options.buildAar = true;
} else if (argument.compare("--qml-importscanner-binary"_L1, Qt::CaseInsensitive) == 0) {
options.qmlImportScannerBinaryPath = arguments.at(++i).trimmed();
} else if (argument.compare("--no-rcc-bundle-cleanup"_L1,
@@ -537,6 +541,23 @@ Options parseOptions()
}
}
+ if (options.buildAar) {
+ if (options.installApk || options.uninstallApk) {
+ fprintf(stderr, "Warning: Skipping %s, AAR packages are not installable.\n",
+ options.uninstallApk ? "--reinstall" : "--install");
+ options.installApk = false;
+ options.uninstallApk = false;
+ }
+ if (options.buildAAB) {
+ fprintf(stderr, "Warning: Skipping -aab as --build-aar is present.\n");
+ options.buildAAB = false;
+ }
+ if (!options.keyStore.isEmpty()) {
+ fprintf(stderr, "Warning: Skipping --sign, signing AAR packages is not supported.\n");
+ options.keyStore.clear();
+ }
+ }
+
if (options.buildDirectory.isEmpty() && !options.depFilePath.isEmpty())
options.helpRequested = true;
@@ -644,6 +665,9 @@ Optional arguments:
--apk <path/where/to/copy/the/apk>: Path where to copy the built apk.
+ --build-aar: Build an AAR package. This option skips --aab, --install,
+ --reinstall, and --sign options if they are provided.
+
--qml-importscanner-binary <path/to/qmlimportscanner>: Override the
default qmlimportscanner binary path. By default the
qmlimportscanner binary is located using the Qt directory
@@ -1434,6 +1458,9 @@ bool copyAndroidTemplate(const Options &options)
if (!copyAndroidTemplate(options, "/src/android/templates"_L1))
return false;
+ if (options.buildAar)
+ return copyAndroidTemplate(options, "/src/android/templates_aar"_L1);
+
return true;
}
@@ -2850,7 +2877,9 @@ bool buildAndroidProject(const Options &options)
abiList.append(it.key());
}
gradleProperties["qtTargetAbiList"] = abiList.toLocal8Bit();// armeabi-v7a or arm64-v8a or ...
- gradleProperties["qtGradlePluginType"] = "com.android.application";
+ gradleProperties["qtGradlePluginType"] = options.buildAar
+ ? "com.android.library"
+ : "com.android.application";
if (!mergeGradleProperties(gradlePropertiesPath, gradleProperties))
return false;
@@ -2938,6 +2967,7 @@ bool uninstallApk(const Options &options)
enum PackageType {
AAB,
+ AAR,
UnsignedAPK,
SignedAPK
};
@@ -2945,7 +2975,14 @@ enum PackageType {
QString packagePath(const Options &options, PackageType pt)
{
QString path(options.outputDirectory);
- path += "/build/outputs/%1/"_L1.arg(pt >= UnsignedAPK ? QStringLiteral("apk") : QStringLiteral("bundle"));
+ // The package type is always AAR if option.buildAar has been set
+ if (options.buildAar)
+ pt = AAR;
+ static QHash<PackageType, QString> packageTypeToPath{ { AAB, QStringLiteral("bundle") },
+ { AAR, QStringLiteral("aar") },
+ { UnsignedAPK, QStringLiteral("apk") },
+ { SignedAPK, QStringLiteral("apk") } };
+ path += "/build/outputs/%1/"_L1.arg(packageTypeToPath[pt]);
QString buildType(options.releasePackage ? "release/"_L1 : "debug/"_L1);
if (QDir(path + buildType).exists())
path += buildType;
@@ -2956,6 +2993,9 @@ QString packagePath(const Options &options, PackageType pt)
if (pt == UnsignedAPK)
path += "un"_L1;
path += "signed.apk"_L1;
+ } else if (pt == AAR){
+ path.chop(1);
+ path += ".aar"_L1;
} else {
path.chop(1);
path += ".aab"_L1;
@@ -2966,6 +3006,8 @@ QString packagePath(const Options &options, PackageType pt)
if (pt == SignedAPK)
path += "-signed"_L1;
path += ".apk"_L1;
+ } else if (pt == AAR){
+ path += ".aar"_L1;
} else {
path += ".aab"_L1;
}