diff options
author | Soheil Armin <soheil.armin@qt.io> | 2024-03-27 01:26:22 +0200 |
---|---|---|
committer | Tinja Paavoseppä <tinja.paavoseppa@qt.io> | 2024-05-15 12:34:08 +0300 |
commit | 79f3fe70407932450e36e9a69046bbe923b8e445 (patch) | |
tree | 8e7a07e8ccdccdf891cb9a81929fa4a8aa90edbb | |
parent | e59f3100615e5ca52530f284a98d01627b826fae (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.txt | 1 | ||||
-rw-r--r-- | src/android/templates_aar/AndroidManifest.xml | 9 | ||||
-rw-r--r-- | src/android/templates_aar/CMakeLists.txt | 24 | ||||
-rw-r--r-- | src/corelib/Qt6AndroidMacros.cmake | 46 | ||||
-rw-r--r-- | src/tools/androiddeployqt/main.cpp | 46 |
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; } |