From d6b10f37c4dab1dcc073712ae66aa23c12777fc8 Mon Sep 17 00:00:00 2001 From: Alexey Edelev Date: Fri, 17 Dec 2021 13:02:04 +0100 Subject: Replace ANDROID_ABI argument with the QT_ANDROID_ABI target property This change tries to make the API more user friendly and prevent wrong use of multi-abi API. ANDROID_ABI argument of qt6_add_executable was position-depend and needed to be placed after the executable 'sources'. Using the target property we solve this problem and provide more consistent and common way to enable multi-abi build for the single target. This meanwhile also requires to execute multi-abi build configuration in the finalizer, since the property might be set at any point. Also the priority of the QT_ANDROID_ABI target property now is higher than the priority of the QT_ANDROID_BUILD_ALL_ABIS variable. So target will only build packages with the ABIs specified in QT_ANDROID_ABI property if both are set. Task-number: QTBUG-88841 Change-Id: I3515297ed267974498913c59619433dc234ec217 Reviewed-by: Joerg Bornemann (cherry picked from commit f90221d8cd2fdc8d4bf2105f0821ee30395443c7) Reviewed-by: Qt Cherry-pick Bot --- cmake/QtAndroidHelpers.cmake | 9 ++++ cmake/QtExecutableHelpers.cmake | 1 + src/corelib/Qt6AndroidMacros.cmake | 108 +++++++++++++++++++++++++++++++++++++ src/corelib/Qt6CoreMacros.cmake | 108 ++----------------------------------- 4 files changed, 122 insertions(+), 104 deletions(-) diff --git a/cmake/QtAndroidHelpers.cmake b/cmake/QtAndroidHelpers.cmake index 24233ac622..49c384f698 100644 --- a/cmake/QtAndroidHelpers.cmake +++ b/cmake/QtAndroidHelpers.cmake @@ -75,6 +75,15 @@ define_property(TARGET "Qt Module android feature list." ) +define_property(TARGET + PROPERTY + QT_ANDROID_ABIS + BRIEF_DOCS + "List of ABIs that the target packages are built with." + FULL_DOCS + "List of ABIs that the target packages are built with." +) + function(qt_internal_android_dependencies_content target file_content_out) get_target_property(arg_JAR_DEPENDENCIES ${target} QT_ANDROID_JAR_DEPENDENCIES) get_target_property(arg_BUNDLED_JAR_DEPENDENCIES ${target} QT_ANDROID_BUNDLED_JAR_DEPENDENCIES) diff --git a/cmake/QtExecutableHelpers.cmake b/cmake/QtExecutableHelpers.cmake index 3d0933942a..a7f7678e9e 100644 --- a/cmake/QtExecutableHelpers.cmake +++ b/cmake/QtExecutableHelpers.cmake @@ -21,6 +21,7 @@ function(qt_internal_add_executable name) _qt_internal_create_executable(${name}) if (ANDROID) + _qt_internal_configure_android_multiabi_target("${name}") qt_android_generate_deployment_settings("${name}") qt_android_add_apk_target("${name}") endif() diff --git a/src/corelib/Qt6AndroidMacros.cmake b/src/corelib/Qt6AndroidMacros.cmake index 3db5ce2132..d61f0e070d 100644 --- a/src/corelib/Qt6AndroidMacros.cmake +++ b/src/corelib/Qt6AndroidMacros.cmake @@ -795,3 +795,111 @@ function(_qt_internal_collect_default_android_abis) "Build project using the list of autodetected Qt for Android ABIs" ) endfunction() + +# The function configures external projects for ABIs that target packages need to build with. +# Each target adds build step to the external project that is linked to the +# qt_internal_android_${abi}-${target}_build target in the primary ABI build tree. +function(_qt_internal_configure_android_multiabi_target target) + # Functionality is only applicable for the primary ABI + if(QT_IS_ANDROID_MULTI_ABI_EXTERNAL_PROJECT) + return() + endif() + + get_target_property(target_abis ${target} QT_ANDROID_ABIS) + if(target_abis) + # Use target-specific Qt for Android ABIs. + set(android_abis ${target_abis}) + elseif(QT_ANDROID_BUILD_ALL_ABIS) + # Use autodetected Qt for Android ABIs. + set(android_abis ${QT_DEFAULT_ANDROID_ABIS}) + elseif(QT_ANDROID_ABIS) + # Use project-wide Qt for Android ABIs. + set(android_abis ${QT_ANDROID_ABIS}) + else() + # User have an empty list of Qt for Android ABIs. + message(FATAL_ERROR + "The list of Android ABIs is empty, when building ${target}.\n" + "You have the following options to select ABIs for a target:\n" + " - Set the QT_ANDROID_ABIS variable before calling qt6_add_executable\n" + " - Set the ANDROID_ABIS property for ${target}\n" + " - Set QT_ANDROID_BUILD_ALL_ABIS flag to try building with\n" + " the list of autodetected Qt for Android:\n ${QT_DEFAULT_ANDROID_ABIS}" + ) + endif() + + set(missing_qt_abi_toolchains "") + # Create external projects for each android ABI except the main one. + list(REMOVE_ITEM android_abis "${CMAKE_ANDROID_ARCH_ABI}") + include(ExternalProject) + foreach(abi IN ITEMS ${android_abis}) + if(NOT "${abi}" IN_LIST QT_DEFAULT_ANDROID_ABIS) + list(APPEND missing_qt_abi_toolchains ${abi}) + list(REMOVE_ITEM android_abis "${abi}") + continue() + endif() + + get_cmake_property(is_multi_config GENERATOR_IS_MULTI_CONFIG) + if(is_multi_config) + list(JOIN CMAKE_CONFIGURATION_TYPES "$" escaped_configuration_types) + set(config_arg "-DCMAKE_CONFIGURATION_TYPES=${escaped_configuration_types}") + else() + set(config_arg "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}") + endif() + set(android_abi_build_dir "${CMAKE_BINARY_DIR}/android_abi_builds/${abi}") + get_property(abi_external_projects GLOBAL + PROPERTY _qt_internal_abi_external_projects) + if(NOT abi_external_projects + OR NOT "qt_internal_android_${abi}" IN_LIST abi_external_projects) + _qt_internal_get_android_abi_path(qt_abi_path ${abi}) + set(qt_abi_toolchain_path + "${qt_abi_path}/lib/cmake/${QT_CMAKE_EXPORT_NAMESPACE}/qt.toolchain.cmake") + ExternalProject_Add("qt_internal_android_${abi}" + SOURCE_DIR "${CMAKE_SOURCE_DIR}" + BINARY_DIR "${android_abi_build_dir}" + CMAKE_ARGS "-DCMAKE_TOOLCHAIN_FILE=${qt_abi_toolchain_path}" + "-DQT_IS_ANDROID_MULTI_ABI_EXTERNAL_PROJECT=ON" + "-DQT_INTERNAL_ANDROID_MULTI_ABI_BINARY_DIR=${CMAKE_BINARY_DIR}" + "${config_arg}" + EXCLUDE_FROM_ALL TRUE + STETPS_TARGETS + BUILD_COMMAND "" # avoid top-level build of external project + ) + set_property(GLOBAL APPEND PROPERTY + _qt_internal_abi_external_projects "qt_internal_android_${abi}") + endif() + ExternalProject_Add_Step("qt_internal_android_${abi}" + "${target}_build" + DEPENDEES configure + # TODO: Remove this when the step will depend on DEPFILE generated by + # androiddeployqt for the ${target}. + ALWAYS TRUE + COMMAND "${CMAKE_COMMAND}" + "--build" "${android_abi_build_dir}" + "--config" "$" + "--target" "qt_internal_${target}_copy_apk_dependencies" + ) + ExternalProject_Add_StepTargets("qt_internal_android_${abi}" + "${target}_build") + add_dependencies(${target} "qt_internal_android_${abi}-${target}_build") + endforeach() + + if(missing_qt_abi_toolchains) + list(JOIN missing_qt_abi_toolchains ", " missing_qt_abi_toolchains_string) + message(FATAL_ERROR "Cannot find toolchain files for the manually specified Android" + " ABIs: ${missing_qt_abi_toolchains_string}" + "\nNote that you also may manually specify the path to the required Qt for" + " Android ABI using QT_PATH_ANDROID_ABI_ CMake variable.\n") + endif() + + list(JOIN android_abis ", " android_abis_string) + if(android_abis_string) + set(android_abis_string "${CMAKE_ANDROID_ARCH_ABI}(default), ${android_abis_string}") + else() + set(android_abis_string "${CMAKE_ANDROID_ARCH_ABI}(default)") + endif() + if(NOT QT_NO_ANDROID_ABI_STATUS_MESSAGE) + message(STATUS "Configuring '${target}' for the following Android ABIs:" + " ${android_abis_string}") + endif() + set_target_properties(${target} PROPERTIES _qt_android_abis "${android_abis}") +endfunction() diff --git a/src/corelib/Qt6CoreMacros.cmake b/src/corelib/Qt6CoreMacros.cmake index 1949ca7066..afaa416349 100644 --- a/src/corelib/Qt6CoreMacros.cmake +++ b/src/corelib/Qt6CoreMacros.cmake @@ -542,10 +542,9 @@ function(qt6_add_executable target) endfunction() function(_qt_internal_create_executable target) - cmake_parse_arguments(arg "" "" "ANDROID_ABIS" ${ARGN}) if(ANDROID) - list(REMOVE_ITEM arg_UNPARSED_ARGUMENTS "WIN32" "MACOSX_BUNDLE") - add_library("${target}" MODULE ${arg_UNPARSED_ARGUMENTS}) + list(REMOVE_ITEM ARGN "WIN32" "MACOSX_BUNDLE") + add_library("${target}" MODULE ${ARGN}) # On our qmake builds we do don't compile the executables with # visibility=hidden. Not having this flag set will cause the # executable to have main() hidden and can then no longer be loaded @@ -556,108 +555,8 @@ function(_qt_internal_create_executable target) set_property(TARGET "${target}" PROPERTY OBJCXX_VISIBILITY_PRESET default) qt6_android_apply_arch_suffix("${target}") set_property(TARGET "${target}" PROPERTY _qt_is_android_executable TRUE) - # Build per-abi binaries for android - if(NOT QT_IS_ANDROID_MULTI_ABI_EXTERNAL_PROJECT) - if(QT_ANDROID_BUILD_ALL_ABIS) - # Use autodetected Qt for Android ABIs. - set(android_abis ${QT_DEFAULT_ANDROID_ABIS}) - elseif(arg_ANDROID_ABIS) - # Use target-specific Qt for Android ABIs. - set(android_abis ${arg_ANDROID_ABIS}) - elseif(QT_ANDROID_ABIS) - # Use project-wide Qt for Android ABIs. - set(android_abis ${QT_ANDROID_ABIS}) - else() - # User have an empty list of Qt for Android ABIs. - message(FATAL_ERROR - "The list of Android ABIs is empty, when building ${target}.\n" - "You have the following options to select ABIs for a target:\n" - " - Set the QT_ANDROID_ABIS variable before calling qt6_add_executable\n" - " - Add the ANDROID_ABIS parameter to the qt6_add_executable call\n" - " - Set QT_ANDROID_BUILD_ALL_ABIS flag to try building with\n" - " the list of autodetected Qt for Android:\n ${QT_DEFAULT_ANDROID_ABIS}" - ) - endif() - - set(missing_qt_abi_toolchains "") - # Create external projects for each android ABI except the main one. - list(REMOVE_ITEM android_abis "${CMAKE_ANDROID_ARCH_ABI}") - include(ExternalProject) - foreach(abi IN ITEMS ${android_abis}) - if(NOT "${abi}" IN_LIST QT_DEFAULT_ANDROID_ABIS) - list(APPEND missing_qt_abi_toolchains ${abi}) - list(REMOVE_ITEM android_abis "${abi}") - continue() - endif() - - get_cmake_property(is_multi_config GENERATOR_IS_MULTI_CONFIG) - if(is_multi_config) - list(JOIN CMAKE_CONFIGURATION_TYPES "$" escaped_configuration_types) - set(config_arg "-DCMAKE_CONFIGURATION_TYPES=${escaped_configuration_types}") - else() - set(config_arg "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}") - endif() - set(android_abi_build_dir "${CMAKE_BINARY_DIR}/android_abi_builds/${abi}") - get_property(abi_external_projects GLOBAL - PROPERTY _qt_internal_abi_external_projects) - if(NOT abi_external_projects - OR NOT "qt_internal_android_${abi}" IN_LIST abi_external_projects) - _qt_internal_get_android_abi_path(qt_abi_path ${abi}) - set(qt_abi_toolchain_path - "${qt_abi_path}/lib/cmake/${QT_CMAKE_EXPORT_NAMESPACE}/qt.toolchain.cmake") - ExternalProject_Add("qt_internal_android_${abi}" - SOURCE_DIR "${CMAKE_SOURCE_DIR}" - BINARY_DIR "${android_abi_build_dir}" - CMAKE_ARGS "-DCMAKE_TOOLCHAIN_FILE=${qt_abi_toolchain_path}" - "-DQT_IS_ANDROID_MULTI_ABI_EXTERNAL_PROJECT=ON" - "-DQT_INTERNAL_ANDROID_MULTI_ABI_BINARY_DIR=${CMAKE_BINARY_DIR}" - "${config_arg}" - EXCLUDE_FROM_ALL TRUE - STETPS_TARGETS - BUILD_COMMAND "" # avoid top-level build of external project - ) - set_property(GLOBAL APPEND PROPERTY - _qt_internal_abi_external_projects "qt_internal_android_${abi}") - endif() - ExternalProject_Add_Step("qt_internal_android_${abi}" - "${target}_build" - DEPENDEES configure - # TODO: Remove this when the step will depend on DEPFILE generated by - # androiddeployqt for the ${target}. - ALWAYS TRUE - COMMAND "${CMAKE_COMMAND}" - "--build" "${android_abi_build_dir}" - "--config" "$" - "--target" "qt_internal_${target}_copy_apk_dependencies" - ) - ExternalProject_Add_StepTargets("qt_internal_android_${abi}" - "${target}_build") - add_dependencies(${target} "qt_internal_android_${abi}-${target}_build") - endforeach() - - if(missing_qt_abi_toolchains) - list(JOIN missing_qt_abi_toolchains ", " missing_qt_abi_toolchains_string) - message(FATAL_ERROR "Cannot find toolchain files for the manually specified Android" - " ABIs: ${missing_qt_abi_toolchains_string}" - "\nSkipping these ABIs." - "\nNote that you also may manually specify the path to the required Qt for" - " Android ABI using QT_PATH_ANDROID_ABI_ CMake variable.\n") - endif() - - list(JOIN android_abis ", " android_abis_string) - if(android_abis_string) - set(android_abis_string "${CMAKE_ANDROID_ARCH_ABI}(default), ${android_abis_string}") - else() - set(android_abis_string "${CMAKE_ANDROID_ARCH_ABI}(default)") - endif() - if(NOT QT_NO_ANDROID_ABI_STATUS_MESSAGE) - message(STATUS "Configuring '${target}' for the following Android ABIs:" - " ${android_abis_string}") - endif() - set_target_properties(${target} PROPERTIES _qt_android_abis "${android_abis}") - endif() else() - add_executable("${target}" ${arg_UNPARSED_ARGUMENTS}) + add_executable("${target}" ${ARGN}) endif() _qt_internal_set_up_static_runtime_library("${target}") @@ -719,6 +618,7 @@ function(_qt_internal_finalize_executable target) endif() if(ANDROID) + _qt_internal_configure_android_multiabi_target("${target}") qt6_android_generate_deployment_settings("${target}") qt6_android_add_apk_target("${target}") endif() -- cgit v1.2.3