980 lines
41 KiB
CMake
980 lines
41 KiB
CMake
# Generate deployment tool json
|
|
|
|
# Locate newest Android sdk build tools revision
|
|
function(_qt_internal_android_get_sdk_build_tools_revision out_var)
|
|
if (NOT QT_ANDROID_SDK_BUILD_TOOLS_REVISION)
|
|
file(GLOB android_build_tools
|
|
LIST_DIRECTORIES true
|
|
RELATIVE "${ANDROID_SDK_ROOT}/build-tools"
|
|
"${ANDROID_SDK_ROOT}/build-tools/*")
|
|
if (NOT android_build_tools)
|
|
message(FATAL_ERROR "Could not locate Android SDK build tools under \"${ANDROID_SDK_ROOT}/build-tools\"")
|
|
endif()
|
|
list(SORT android_build_tools)
|
|
list(REVERSE android_build_tools)
|
|
list(GET android_build_tools 0 android_build_tools_latest)
|
|
endif()
|
|
set(${out_var} "${android_build_tools_latest}" PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
# The function appends to the 'out_var' a 'json_property' that contains the 'tool' path. If 'tool'
|
|
# target or its IMPORTED_LOCATION are not found the function displays warning, but is not failing
|
|
# at the project configuring phase.
|
|
function(_qt_internal_add_tool_to_android_deployment_settings out_var tool json_property target)
|
|
unset(tool_binary_path)
|
|
__qt_internal_get_tool_imported_location(tool_binary_path ${tool})
|
|
if("${tool_binary_path}" STREQUAL "")
|
|
# Fallback search for the tool in host bin and host libexec directories
|
|
find_program(tool_binary_path
|
|
NAMES ${tool} ${tool}.exe
|
|
PATHS
|
|
"${QT_HOST_PATH}/${QT6_HOST_INFO_BINDIR}"
|
|
"${QT_HOST_PATH}/${QT6_HOST_INFO_LIBEXECDIR}"
|
|
NO_DEFAULT_PATH
|
|
)
|
|
if(NOT tool_binary_path)
|
|
message(WARNING "Unable to locate ${tool}. Android package deployment of ${target}"
|
|
" target can be incomplete. Make sure the host Qt has ${tool} installed.")
|
|
return()
|
|
endif()
|
|
endif()
|
|
|
|
file(TO_CMAKE_PATH "${tool_binary_path}" tool_binary_path)
|
|
string(APPEND ${out_var}
|
|
" \"${json_property}\" : \"${tool_binary_path}\",\n")
|
|
|
|
set(${out_var} "${${out_var}}" PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
# Generate the deployment settings json file for a cmake target.
|
|
function(qt6_android_generate_deployment_settings target)
|
|
# Information extracted from mkspecs/features/android/android_deployment_settings.prf
|
|
if (NOT TARGET ${target})
|
|
message(FATAL_ERROR "${target} is not a cmake target")
|
|
endif()
|
|
|
|
# When parsing JSON file format backslashes and follow up symbols are regarded as special
|
|
# characters. This puts Windows path format into a trouble.
|
|
# _qt_internal_android_format_deployment_paths converts sensitive paths to the CMake format
|
|
# that is supported by JSON as well. The function should be called as many times as
|
|
# qt6_android_generate_deployment_settings, because users may change properties that contain
|
|
# paths in between the calls.
|
|
_qt_internal_android_format_deployment_paths(${target})
|
|
|
|
# Avoid calling the function body twice because of 'file(GENERATE'.
|
|
get_target_property(is_called ${target} _qt_is_android_generate_deployment_settings_called)
|
|
if(is_called)
|
|
return()
|
|
endif()
|
|
set_target_properties(${target} PROPERTIES
|
|
_qt_is_android_generate_deployment_settings_called TRUE
|
|
)
|
|
|
|
get_target_property(target_type ${target} TYPE)
|
|
|
|
if (NOT "${target_type}" STREQUAL "MODULE_LIBRARY")
|
|
message(SEND_ERROR "QT_ANDROID_GENERATE_DEPLOYMENT_SETTINGS only works on Module targets")
|
|
return()
|
|
endif()
|
|
|
|
get_target_property(target_source_dir ${target} SOURCE_DIR)
|
|
get_target_property(target_binary_dir ${target} BINARY_DIR)
|
|
get_target_property(target_output_name ${target} OUTPUT_NAME)
|
|
if (NOT target_output_name)
|
|
set(target_output_name ${target})
|
|
endif()
|
|
|
|
# QtCreator requires the file name of deployment settings has no config related suffixes
|
|
# to run androiddeployqt correctly. If we use multi-config generator for the first config
|
|
# in a list avoid adding any configuration-specific suffixes.
|
|
get_cmake_property(is_multi_config GENERATOR_IS_MULTI_CONFIG)
|
|
if(is_multi_config)
|
|
list(GET CMAKE_CONFIGURATION_TYPES 0 first_config_type)
|
|
set(config_suffix "$<$<NOT:$<CONFIG:${first_config_type}>>:-$<CONFIG>>")
|
|
endif()
|
|
set(deploy_file
|
|
"${target_binary_dir}/android-${target_output_name}-deployment-settings${config_suffix}.json")
|
|
|
|
set(file_contents "{\n")
|
|
# content begin
|
|
string(APPEND file_contents
|
|
" \"description\": \"This file is generated by cmake to be read by androiddeployqt and should not be modified by hand.\",\n")
|
|
|
|
# Host Qt Android install path
|
|
if (NOT QT_BUILDING_QT OR QT_STANDALONE_TEST_PATH)
|
|
set(qt_path "${QT6_INSTALL_PREFIX}")
|
|
set(android_plugin_dir_path "${qt_path}/${QT6_INSTALL_PLUGINS}/platforms")
|
|
set(glob_expression "${android_plugin_dir_path}/*qtforandroid*${CMAKE_ANDROID_ARCH_ABI}.so")
|
|
file(GLOB plugin_dir_files LIST_DIRECTORIES FALSE "${glob_expression}")
|
|
if (NOT plugin_dir_files)
|
|
message(SEND_ERROR
|
|
"Detected Qt installation does not contain qtforandroid_${CMAKE_ANDROID_ARCH_ABI}.so in the following dir:\n"
|
|
"${android_plugin_dir_path}\n"
|
|
"This is most likely due to the installation not being a Qt for Android build. "
|
|
"Please recheck your build configuration.")
|
|
return()
|
|
else()
|
|
list(GET plugin_dir_files 0 android_platform_plugin_path)
|
|
message(STATUS "Found android platform plugin at: ${android_platform_plugin_path}")
|
|
endif()
|
|
endif()
|
|
|
|
set(abi_records "")
|
|
get_target_property(qt_android_abis ${target} _qt_android_abis)
|
|
if(NOT qt_android_abis)
|
|
set(qt_android_abis "")
|
|
endif()
|
|
foreach(abi IN LISTS qt_android_abis)
|
|
_qt_internal_get_android_abi_path(qt_abi_path ${abi})
|
|
file(TO_CMAKE_PATH "${qt_abi_path}" qt_android_install_dir_native)
|
|
list(APPEND abi_records "\"${abi}\": \"${qt_android_install_dir_native}\"")
|
|
endforeach()
|
|
|
|
# Required to build unit tests in developer build
|
|
if(QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX)
|
|
set(qt_android_install_dir "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}")
|
|
else()
|
|
set(qt_android_install_dir "${QT6_INSTALL_PREFIX}")
|
|
endif()
|
|
file(TO_CMAKE_PATH "${qt_android_install_dir}" qt_android_install_dir_native)
|
|
list(APPEND abi_records "\"${CMAKE_ANDROID_ARCH_ABI}\": \"${qt_android_install_dir_native}\"")
|
|
|
|
list(JOIN abi_records "," qt_android_install_dir_records)
|
|
set(qt_android_install_dir_records "{${qt_android_install_dir_records}}")
|
|
|
|
string(APPEND file_contents
|
|
" \"qt\": ${qt_android_install_dir_records},\n")
|
|
|
|
# Android SDK path
|
|
file(TO_CMAKE_PATH "${ANDROID_SDK_ROOT}" android_sdk_root_native)
|
|
string(APPEND file_contents
|
|
" \"sdk\": \"${android_sdk_root_native}\",\n")
|
|
|
|
# Android SDK Build Tools Revision
|
|
get_target_property(android_sdk_build_tools ${target} QT_ANDROID_SDK_BUILD_TOOLS_REVISION)
|
|
if (NOT android_sdk_build_tools)
|
|
_qt_internal_android_get_sdk_build_tools_revision(android_sdk_build_tools)
|
|
endif()
|
|
string(APPEND file_contents
|
|
" \"sdkBuildToolsRevision\": \"${android_sdk_build_tools}\",\n")
|
|
|
|
# Android NDK
|
|
file(TO_CMAKE_PATH "${CMAKE_ANDROID_NDK}" android_ndk_root_native)
|
|
string(APPEND file_contents
|
|
" \"ndk\": \"${android_ndk_root_native}\",\n")
|
|
|
|
# Setup LLVM toolchain
|
|
string(APPEND file_contents
|
|
" \"toolchain-prefix\": \"llvm\",\n")
|
|
string(APPEND file_contents
|
|
" \"tool-prefix\": \"llvm\",\n")
|
|
string(APPEND file_contents
|
|
" \"useLLVM\": true,\n")
|
|
|
|
# NDK Toolchain Version
|
|
string(APPEND file_contents
|
|
" \"toolchain-version\": \"${CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION}\",\n")
|
|
|
|
# NDK Host
|
|
string(APPEND file_contents
|
|
" \"ndk-host\": \"${ANDROID_NDK_HOST_SYSTEM_NAME}\",\n")
|
|
|
|
set(architecture_record_list "")
|
|
foreach(abi IN LISTS qt_android_abis CMAKE_ANDROID_ARCH_ABI)
|
|
if(abi STREQUAL "x86")
|
|
set(arch_value "i686-linux-android")
|
|
elseif(abi STREQUAL "x86_64")
|
|
set(arch_value "x86_64-linux-android")
|
|
elseif(abi STREQUAL "arm64-v8a")
|
|
set(arch_value "aarch64-linux-android")
|
|
elseif(abi)
|
|
set(arch_value "arm-linux-androideabi")
|
|
endif()
|
|
list(APPEND architecture_record_list "\"${abi}\":\"${arch_value}\"")
|
|
endforeach()
|
|
|
|
list(JOIN architecture_record_list "," architecture_records)
|
|
# Architecture
|
|
string(APPEND file_contents
|
|
" \"architectures\": { ${architecture_records} },\n")
|
|
|
|
# deployment dependencies
|
|
_qt_internal_add_android_deployment_multi_value_property(file_contents "dependencies"
|
|
${target} "QT_ANDROID_DEPLOYMENT_DEPENDENCIES" )
|
|
|
|
# Extra plugins
|
|
_qt_internal_add_android_deployment_multi_value_property(file_contents "android-extra-plugins"
|
|
${target} "QT_ANDROID_EXTRA_PLUGINS" )
|
|
|
|
# Extra libs
|
|
_qt_internal_add_android_deployment_multi_value_property(file_contents "android-extra-libs"
|
|
${target} "QT_ANDROID_EXTRA_LIBS" )
|
|
|
|
# package source dir
|
|
_qt_internal_add_android_deployment_property(file_contents "android-package-source-directory"
|
|
${target} "_qt_android_native_package_source_dir")
|
|
|
|
# version code
|
|
_qt_internal_add_android_deployment_property(file_contents "android-version-code"
|
|
${target} "QT_ANDROID_VERSION_CODE")
|
|
|
|
# version name
|
|
_qt_internal_add_android_deployment_property(file_contents "android-version-name"
|
|
${target} "QT_ANDROID_VERSION_NAME")
|
|
|
|
# minimum SDK version
|
|
_qt_internal_add_android_deployment_property(file_contents "android-min-sdk-version"
|
|
${target} "QT_ANDROID_MIN_SDK_VERSION")
|
|
|
|
# target SDK version
|
|
_qt_internal_add_android_deployment_property(file_contents "android-target-sdk-version"
|
|
${target} "QT_ANDROID_TARGET_SDK_VERSION")
|
|
|
|
# QML import paths
|
|
if(NOT "${QT_QML_OUTPUT_DIRECTORY}" STREQUAL "")
|
|
# Need to prepend the default qml module output directory to take precedence
|
|
# over other qml import paths. By default QT_QML_OUTPUT_DIRECTORY is set to
|
|
# ${CMAKE_BINARY_DIR}/android-qml for Android.
|
|
get_target_property(native_qml_import_paths "${target}" _qt_native_qml_import_paths)
|
|
list(PREPEND native_qml_import_paths "${QT_QML_OUTPUT_DIRECTORY}")
|
|
set_property(TARGET "${target}" PROPERTY
|
|
"_qt_native_qml_import_paths" "${native_qml_import_paths}")
|
|
endif()
|
|
_qt_internal_add_android_deployment_multi_value_property(file_contents "qml-import-paths"
|
|
${target} "_qt_native_qml_import_paths")
|
|
|
|
# QML root paths
|
|
file(TO_CMAKE_PATH "${target_source_dir}" native_target_source_dir)
|
|
set_property(TARGET ${target} APPEND PROPERTY
|
|
_qt_android_native_qml_root_paths "${native_target_source_dir}")
|
|
_qt_internal_add_android_deployment_list_property(file_contents "qml-root-path"
|
|
${target} "_qt_android_native_qml_root_paths")
|
|
|
|
# App binary
|
|
string(APPEND file_contents
|
|
" \"application-binary\": \"${target_output_name}\",\n")
|
|
|
|
# App command-line arguments
|
|
if (QT_ANDROID_APPLICATION_ARGUMENTS)
|
|
string(APPEND file_contents
|
|
" \"android-application-arguments\": \"${QT_ANDROID_APPLICATION_ARGUMENTS}\",\n")
|
|
endif()
|
|
|
|
# Override qmlimportscanner binary path
|
|
set(qml_importscanner_binary_path "${QT_HOST_PATH}/${QT6_HOST_INFO_LIBEXECDIR}/qmlimportscanner")
|
|
if (WIN32)
|
|
string(APPEND qml_importscanner_binary_path ".exe")
|
|
endif()
|
|
file(TO_CMAKE_PATH "${qml_importscanner_binary_path}" qml_importscanner_binary_path_native)
|
|
string(APPEND file_contents
|
|
" \"qml-importscanner-binary\" : \"${qml_importscanner_binary_path_native}\",\n")
|
|
|
|
# Override rcc binary path
|
|
_qt_internal_add_tool_to_android_deployment_settings(file_contents rcc "rcc-binary" "${target}")
|
|
|
|
# Extra prefix paths
|
|
foreach(prefix IN LISTS CMAKE_FIND_ROOT_PATH)
|
|
if (NOT "${prefix}" STREQUAL "${qt_android_install_dir_native}"
|
|
AND NOT "${prefix}" STREQUAL "${android_ndk_root_native}")
|
|
file(TO_CMAKE_PATH "${prefix}" prefix)
|
|
list(APPEND extra_prefix_list "\"${prefix}\"")
|
|
endif()
|
|
endforeach()
|
|
string (REPLACE ";" "," extra_prefix_list "${extra_prefix_list}")
|
|
string(APPEND file_contents
|
|
" \"extraPrefixDirs\" : [ ${extra_prefix_list} ],\n")
|
|
|
|
# Extra library paths that could be used as a dependency lookup path by androiddeployqt.
|
|
#
|
|
# Unlike 'extraPrefixDirs', the 'extraLibraryDirs' key doesn't expect the 'lib' subfolder
|
|
# when looking for dependencies.
|
|
# TODO: add a public target property accessible from user space
|
|
_qt_internal_add_android_deployment_list_property(file_contents "extraLibraryDirs"
|
|
${target} "_qt_android_extra_library_dirs"
|
|
_qt_internal_apk_dependencies "_qt_android_extra_library_dirs"
|
|
)
|
|
|
|
if(QT_FEATURE_zstd)
|
|
set(is_zstd_enabled "true")
|
|
else()
|
|
set(is_zstd_enabled "false")
|
|
endif()
|
|
string(APPEND file_contents
|
|
" \"zstdCompression\": ${is_zstd_enabled},\n")
|
|
|
|
# Last item in json file
|
|
|
|
# base location of stdlibc++, will be suffixed by androiddeploy qt
|
|
# Sysroot is set by Android toolchain file and is composed of ANDROID_TOOLCHAIN_ROOT.
|
|
set(android_ndk_stdlib_base_path "${CMAKE_SYSROOT}/usr/lib/")
|
|
string(APPEND file_contents
|
|
" \"stdcpp-path\": \"${android_ndk_stdlib_base_path}\"\n")
|
|
|
|
# content end
|
|
string(APPEND file_contents "}\n")
|
|
|
|
file(GENERATE OUTPUT ${deploy_file} CONTENT ${file_contents})
|
|
|
|
set_target_properties(${target}
|
|
PROPERTIES
|
|
QT_ANDROID_DEPLOYMENT_SETTINGS_FILE ${deploy_file}
|
|
)
|
|
endfunction()
|
|
|
|
if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
|
|
function(qt_android_generate_deployment_settings)
|
|
qt6_android_generate_deployment_settings(${ARGV})
|
|
endfunction()
|
|
endif()
|
|
|
|
function(qt6_android_apply_arch_suffix target)
|
|
get_target_property(target_type ${target} TYPE)
|
|
if (target_type STREQUAL "SHARED_LIBRARY" OR target_type STREQUAL "MODULE_LIBRARY")
|
|
set_property(TARGET "${target}" PROPERTY SUFFIX "_${CMAKE_ANDROID_ARCH_ABI}.so")
|
|
elseif (target_type STREQUAL "STATIC_LIBRARY")
|
|
set_property(TARGET "${target}" PROPERTY SUFFIX "_${CMAKE_ANDROID_ARCH_ABI}.a")
|
|
endif()
|
|
endfunction()
|
|
|
|
if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
|
|
function(qt_android_apply_arch_suffix)
|
|
qt6_android_apply_arch_suffix(${ARGV})
|
|
endfunction()
|
|
endif()
|
|
|
|
# Add custom target to package the APK
|
|
function(qt6_android_add_apk_target target)
|
|
get_target_property(deployment_file ${target} QT_ANDROID_DEPLOYMENT_SETTINGS_FILE)
|
|
if (NOT deployment_file)
|
|
message(FATAL_ERROR "Target ${target} is not a valid android executable target\n")
|
|
endif()
|
|
|
|
# Make global apk and aab targets depend on the current apk target.
|
|
if(TARGET aab)
|
|
add_dependencies(aab ${target}_make_aab)
|
|
endif()
|
|
if(TARGET apk)
|
|
add_dependencies(apk ${target}_make_apk)
|
|
_qt_internal_create_global_apk_all_target_if_needed()
|
|
endif()
|
|
|
|
set(deployment_tool "${QT_HOST_PATH}/${QT6_HOST_INFO_BINDIR}/androiddeployqt")
|
|
get_target_property(target_binary_dir ${target} BINARY_DIR)
|
|
set(apk_final_dir "${target_binary_dir}/android-build")
|
|
set(apk_file_name "${target}.apk")
|
|
set(dep_file_name "${target}.d")
|
|
set(apk_final_file_path "${apk_final_dir}/${apk_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}>")
|
|
|
|
set(extra_deps "")
|
|
|
|
# Plugins still might be added after creating the deployment targets.
|
|
if(NOT TARGET qt_internal_plugins)
|
|
add_custom_target(qt_internal_plugins)
|
|
endif()
|
|
# Before running androiddeployqt, we need to make sure all plugins are built.
|
|
list(APPEND extra_deps qt_internal_plugins)
|
|
|
|
# This target is used by Qt Creator's Android support and by the ${target}_make_apk target
|
|
# in case DEPFILEs are not supported.
|
|
# Also the target is used to copy the library that belongs to ${target} when building multi-abi
|
|
# apk to the abi-specific directory.
|
|
_qt_internal_copy_file_if_different_command(copy_command
|
|
"$<TARGET_FILE:${target}>"
|
|
"${apk_final_dir}/${target_file_copy_relative_path}"
|
|
)
|
|
add_custom_target(${target}_prepare_apk_dir ALL
|
|
DEPENDS ${target} ${extra_deps}
|
|
COMMAND ${copy_command}
|
|
COMMENT "Copying ${target} binary to apk folder"
|
|
)
|
|
|
|
set(extra_args "")
|
|
if(QT_INTERNAL_NO_ANDROID_RCC_BUNDLE_CLEANUP)
|
|
list(APPEND extra_args "--no-rcc-bundle-cleanup")
|
|
endif()
|
|
if(QT_ENABLE_VERBOSE_DEPLOYMENT)
|
|
list(APPEND extra_args "--verbose")
|
|
endif()
|
|
|
|
# The DEPFILE argument to add_custom_command is only available with Ninja or CMake>=3.20 and
|
|
# make.
|
|
set(has_depfile_support FALSE)
|
|
if(CMAKE_GENERATOR MATCHES "Ninja" OR
|
|
(CMAKE_VERSION VERSION_GREATER_EQUAL 3.20 AND CMAKE_GENERATOR MATCHES "Makefiles"))
|
|
set(has_depfile_support TRUE)
|
|
endif()
|
|
|
|
if(has_depfile_support)
|
|
cmake_policy(PUSH)
|
|
if(POLICY CMP0116)
|
|
# Without explicitly setting this policy to NEW, we get a warning
|
|
# even though we ensure there's actually no problem here.
|
|
# See https://gitlab.kitware.com/cmake/cmake/-/issues/21959
|
|
cmake_policy(SET CMP0116 NEW)
|
|
set(relative_to_dir ${CMAKE_CURRENT_BINARY_DIR})
|
|
else()
|
|
set(relative_to_dir ${CMAKE_BINARY_DIR})
|
|
endif()
|
|
|
|
# Add custom command that creates the apk and triggers rebuild if files listed in
|
|
# ${dep_file_path} are changed.
|
|
add_custom_command(OUTPUT "${apk_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 "${apk_final_file_path}"
|
|
--depfile "${dep_file_path}"
|
|
--builddir "${relative_to_dir}"
|
|
${extra_args}
|
|
COMMENT "Creating APK for ${target}"
|
|
DEPENDS "${target}" "${deployment_file}" ${extra_deps}
|
|
DEPFILE "${dep_file_path}"
|
|
)
|
|
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}")
|
|
else()
|
|
add_custom_target(${target}_make_apk
|
|
DEPENDS ${target}_prepare_apk_dir
|
|
COMMAND ${deployment_tool}
|
|
--input ${deployment_file}
|
|
--output ${apk_final_dir}
|
|
--apk ${apk_final_file_path}
|
|
${extra_args}
|
|
COMMENT "Creating APK for ${target}"
|
|
)
|
|
endif()
|
|
|
|
# Add target triggering AAB creation. Since the _make_aab target is not added to the ALL
|
|
# set, we may avoid dependency check for it and admit that the target is "always out
|
|
# of date".
|
|
add_custom_target(${target}_make_aab
|
|
DEPENDS ${target}_prepare_apk_dir
|
|
COMMAND ${deployment_tool}
|
|
--input ${deployment_file}
|
|
--output ${apk_final_dir}
|
|
--apk ${apk_final_file_path}
|
|
--aab
|
|
${extra_args}
|
|
COMMENT "Creating AAB for ${target}"
|
|
)
|
|
|
|
if(QT_IS_ANDROID_MULTI_ABI_EXTERNAL_PROJECT)
|
|
# When building per-ABI external projects we only need to copy ABI-specific libraries and
|
|
# resources to the "main" ABI android build folder.
|
|
|
|
if("${QT_INTERNAL_ANDROID_MULTI_ABI_BINARY_DIR}" STREQUAL "")
|
|
message(FATAL_ERROR "QT_INTERNAL_ANDROID_MULTI_ABI_BINARY_DIR is not set when building"
|
|
" ABI specific external project. This should not happen and might mean an issue"
|
|
" in Qt. Please report a bug with CMake traces attached.")
|
|
endif()
|
|
# Assume that external project mirrors build structure of the top-level ABI project and
|
|
# replace the build root when specifying the output directory of androiddeployqt.
|
|
file(RELATIVE_PATH androiddeployqt_output_path "${CMAKE_BINARY_DIR}" "${apk_final_dir}")
|
|
set(androiddeployqt_output_path
|
|
"${QT_INTERNAL_ANDROID_MULTI_ABI_BINARY_DIR}/${androiddeployqt_output_path}")
|
|
_qt_internal_copy_file_if_different_command(copy_command
|
|
"$<TARGET_FILE:${target}>"
|
|
"${androiddeployqt_output_path}/${target_file_copy_relative_path}"
|
|
)
|
|
if(has_depfile_support)
|
|
set(deploy_android_deps_dir "${apk_final_dir}/${target}_deploy_android")
|
|
set(timestamp_file "${deploy_android_deps_dir}/timestamp")
|
|
set(dep_file "${deploy_android_deps_dir}/${target}.d")
|
|
add_custom_command(OUTPUT "${timestamp_file}"
|
|
DEPENDS ${target} ${extra_deps}
|
|
COMMAND ${CMAKE_COMMAND} -E make_directory "${deploy_android_deps_dir}"
|
|
COMMAND ${CMAKE_COMMAND} -E touch "${timestamp_file}"
|
|
COMMAND ${copy_command}
|
|
COMMAND ${deployment_tool}
|
|
--input ${deployment_file}
|
|
--output ${androiddeployqt_output_path}
|
|
--copy-dependencies-only
|
|
${extra_args}
|
|
--depfile "${dep_file}"
|
|
--builddir "${CMAKE_BINARY_DIR}"
|
|
COMMENT "Resolving ${CMAKE_ANDROID_ARCH_ABI} dependencies for the ${target} APK"
|
|
DEPFILE "${dep_file}"
|
|
)
|
|
add_custom_target(qt_internal_${target}_copy_apk_dependencies
|
|
DEPENDS "${timestamp_file}")
|
|
else()
|
|
add_custom_target(qt_internal_${target}_copy_apk_dependencies
|
|
DEPENDS ${target} ${extra_deps}
|
|
COMMAND ${copy_command}
|
|
COMMAND ${deployment_tool}
|
|
--input ${deployment_file}
|
|
--output ${androiddeployqt_output_path}
|
|
--copy-dependencies-only
|
|
${extra_args}
|
|
COMMENT "Resolving ${CMAKE_ANDROID_ARCH_ABI} dependencies for the ${target} APK"
|
|
)
|
|
endif()
|
|
endif()
|
|
|
|
set_property(GLOBAL APPEND PROPERTY _qt_apk_targets ${target})
|
|
_qt_internal_collect_apk_dependencies_defer()
|
|
endfunction()
|
|
|
|
function(_qt_internal_create_global_android_targets)
|
|
macro(_qt_internal_create_global_android_targets_impl target)
|
|
string(TOUPPER "${target}" target_upper)
|
|
if(NOT QT_NO_GLOBAL_${target_upper}_TARGET)
|
|
if(NOT TARGET ${target})
|
|
add_custom_target(${target} COMMENT "Building all apks")
|
|
endif()
|
|
endif()
|
|
endmacro()
|
|
|
|
# Create a top-level "apk" target for convenience, so that users can call 'ninja apk'.
|
|
# 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(apk)
|
|
|
|
# Create a top-level "aab" target for convenience, so that users can call 'ninja aab'.
|
|
# 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)
|
|
endfunction()
|
|
|
|
# The function collects all known non-imported shared libraries that are created in the build tree.
|
|
# It uses the CMake DEFER CALL feature if the CMAKE_VERSION is greater
|
|
# than or equal to 3.18.
|
|
# Note: Users that use cmake version less that 3.18 need to call qt_finalize_project
|
|
# in the end of a project's top-level CMakeLists.txt.
|
|
function(_qt_internal_collect_apk_dependencies_defer)
|
|
# User opted-out the functionality
|
|
if(QT_NO_COLLECT_BUILD_TREE_APK_DEPS)
|
|
return()
|
|
endif()
|
|
|
|
get_property(is_called GLOBAL PROPERTY _qt_is_collect_apk_dependencies_defer_called)
|
|
if(is_called) # Already scheduled
|
|
return()
|
|
endif()
|
|
set_property(GLOBAL PROPERTY _qt_is_collect_apk_dependencies_defer_called TRUE)
|
|
|
|
if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.18")
|
|
cmake_language(EVAL CODE "cmake_language(DEFER DIRECTORY \"${CMAKE_SOURCE_DIR}\"
|
|
CALL _qt_internal_collect_apk_dependencies)")
|
|
else()
|
|
# User don't want to see the warning
|
|
if(NOT QT_NO_WARN_BUILD_TREE_APK_DEPS)
|
|
message(WARNING "CMake version you use is less than 3.18. APK dependencies, that are a"
|
|
" part of the project tree, might not be collected correctly."
|
|
" Please call qt_finalize_project in the end of a project's top-level"
|
|
" CMakeLists.txt file to make sure that all the APK dependencies are"
|
|
" collected correctly."
|
|
" You can pass -DQT_NO_WARN_BUILD_TREE_APK_DEPS=ON when configuring the project"
|
|
" to silence the warning.")
|
|
endif()
|
|
endif()
|
|
endfunction()
|
|
|
|
# The function collects shared libraries from the build system tree, that might be dependencies for
|
|
# the main apk targets.
|
|
function(_qt_internal_collect_apk_dependencies)
|
|
# User opted-out the functionality
|
|
if(QT_NO_COLLECT_BUILD_TREE_APK_DEPS)
|
|
return()
|
|
endif()
|
|
|
|
get_property(is_called GLOBAL PROPERTY _qt_is_collect_apk_dependencies_called)
|
|
if(is_called)
|
|
return()
|
|
endif()
|
|
set_property(GLOBAL PROPERTY _qt_is_collect_apk_dependencies_called TRUE)
|
|
|
|
get_property(apk_targets GLOBAL PROPERTY _qt_apk_targets)
|
|
|
|
_qt_internal_collect_buildsystem_shared_libraries(libs "${CMAKE_SOURCE_DIR}")
|
|
|
|
if(NOT TARGET qt_internal_plugins)
|
|
add_custom_target(qt_internal_plugins)
|
|
endif()
|
|
|
|
foreach(lib IN LISTS libs)
|
|
if(NOT lib IN_LIST apk_targets)
|
|
list(APPEND extra_library_dirs "$<TARGET_FILE_DIR:${lib}>")
|
|
get_target_property(target_type ${lib} TYPE)
|
|
# We collect all MODULE_LIBRARY targets since target APK may have implicit dependency
|
|
# to the plugin that will cause the runtime issue. Plugins that were added using
|
|
# qt6_add_plugin should be already added to the qt_internal_plugins dependency list,
|
|
# but it's ok to re-add them.
|
|
if(target_type STREQUAL "MODULE_LIBRARY")
|
|
add_dependencies(qt_internal_plugins ${lib})
|
|
endif()
|
|
endif()
|
|
endforeach()
|
|
|
|
if(NOT TARGET _qt_internal_apk_dependencies)
|
|
add_custom_target(_qt_internal_apk_dependencies)
|
|
endif()
|
|
set_target_properties(_qt_internal_apk_dependencies PROPERTIES
|
|
_qt_android_extra_library_dirs "${extra_library_dirs}"
|
|
)
|
|
endfunction()
|
|
|
|
# The function recursively goes through the project subfolders and collects targets that supposed to
|
|
# be shared libraries of any kind.
|
|
function(_qt_internal_collect_buildsystem_shared_libraries out_var subdir)
|
|
set(result "")
|
|
get_directory_property(buildsystem_targets DIRECTORY ${subdir} BUILDSYSTEM_TARGETS)
|
|
foreach(buildsystem_target IN LISTS buildsystem_targets)
|
|
if(buildsystem_target AND TARGET ${buildsystem_target})
|
|
get_target_property(target_type ${buildsystem_target} TYPE)
|
|
if(target_type STREQUAL "SHARED_LIBRARY" OR target_type STREQUAL "MODULE_LIBRARY")
|
|
list(APPEND result ${buildsystem_target})
|
|
endif()
|
|
endif()
|
|
endforeach()
|
|
|
|
get_directory_property(subdirs DIRECTORY "${subdir}" SUBDIRECTORIES)
|
|
foreach(dir IN LISTS subdirs)
|
|
_qt_internal_collect_buildsystem_shared_libraries(result_inner "${dir}")
|
|
endforeach()
|
|
list(APPEND result ${result_inner})
|
|
set(${out_var} "${result}" PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
# This function allows deciding whether apks should be built as part of the ALL target at first
|
|
# add_executable call point, rather than when the 'apk' target is created as part of the
|
|
# find_package(Core) call.
|
|
#
|
|
# It does so by creating a custom 'apk_all' target as an implementation detail.
|
|
#
|
|
# This is needed to ensure that the decision is made only when the value of QT_BUILDING_QT is
|
|
# available, which is defined in qt_repo_build() -> include(QtSetup), which is included after the
|
|
# execution of _qt_internal_create_global_apk_target.
|
|
function(_qt_internal_create_global_apk_all_target_if_needed)
|
|
if(TARGET apk AND NOT TARGET apk_all)
|
|
# Some Qt tests helper executables have their apk build process failing.
|
|
# qt_internal_add_executables that are excluded from ALL should also not have apks built
|
|
# for them.
|
|
# Don't build apks by default when doing a Qt build.
|
|
set(skip_add_to_all FALSE)
|
|
if(QT_BUILDING_QT)
|
|
set(skip_add_to_all TRUE)
|
|
endif()
|
|
|
|
option(QT_NO_GLOBAL_APK_TARGET_PART_OF_ALL
|
|
"Skip building apks as part of the default 'ALL' target" ${skip_add_to_all})
|
|
|
|
set(part_of_all "ALL")
|
|
if(QT_NO_GLOBAL_APK_TARGET_PART_OF_ALL)
|
|
set(part_of_all "")
|
|
endif()
|
|
|
|
add_custom_target(apk_all ${part_of_all})
|
|
add_dependencies(apk_all apk)
|
|
endif()
|
|
endfunction()
|
|
|
|
# The function converts the target property to a json record and appends it to the output
|
|
# variable.
|
|
function(_qt_internal_add_android_deployment_property out_var json_key target property)
|
|
set(property_genex "$<TARGET_PROPERTY:${target},${property}>")
|
|
string(APPEND ${out_var}
|
|
"$<$<BOOL:${property_genex}>:"
|
|
" \"${json_key}\": \"${property_genex}\"\,\n"
|
|
">"
|
|
)
|
|
|
|
set(${out_var} "${${out_var}}" PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
# The function converts the list properties of the targets to a json list record and appends it
|
|
# to the output variable.
|
|
# _qt_internal_add_android_deployment_list_property(out_var json_key [<target> <property>]...)
|
|
# The generated JSON object is the normal JSON array, e.g.:
|
|
# "qml-root-path": ["qml/root/path1","qml/root/path2"],
|
|
function(_qt_internal_add_android_deployment_list_property out_var json_key)
|
|
list(LENGTH ARGN argn_count)
|
|
math(EXPR is_odd "${argn_count} % 2")
|
|
if(is_odd)
|
|
message(FATAL_ERROR "Invalid argument count")
|
|
endif()
|
|
|
|
set(skip_next FALSE)
|
|
set(property_genex "")
|
|
math(EXPR last_index "${argn_count} - 1")
|
|
foreach(idx RANGE ${last_index})
|
|
if(skip_next)
|
|
set(skip_next FALSE)
|
|
continue()
|
|
endif()
|
|
set(skip_next TRUE)
|
|
|
|
math(EXPR property_idx "${idx} + 1")
|
|
list(GET ARGN ${idx} target)
|
|
list(GET ARGN ${property_idx} property)
|
|
|
|
# Add comma if we have at least one element from the previous iteration
|
|
if(property_genex)
|
|
set(add_comma_genex
|
|
"$<$<BOOL:${property_genex}>:$<COMMA>>"
|
|
)
|
|
endif()
|
|
|
|
set(property_genex
|
|
"$<TARGET_PROPERTY:${target},${property}>"
|
|
)
|
|
set(add_quote_genex
|
|
"$<$<BOOL:${property_genex}>:\">"
|
|
)
|
|
string(JOIN "" list_join_genex
|
|
"${list_join_genex}"
|
|
"${add_comma_genex}${add_quote_genex}"
|
|
"$<JOIN:"
|
|
"$<GENEX_EVAL:${property_genex}>,"
|
|
"\",\""
|
|
">"
|
|
"${add_quote_genex}"
|
|
)
|
|
endforeach()
|
|
|
|
string(APPEND ${out_var}
|
|
" \"${json_key}\" : [ ${list_join_genex} ],\n")
|
|
set(${out_var} "${${out_var}}" PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
# The function converts the target list property to a json multi-value string record and appends it
|
|
# to the output variable.
|
|
# The generated JSON object is a simple string with the list property items separated by commas,
|
|
# e.g:
|
|
# "android-extra-plugins": "plugin1,plugin2",
|
|
function(_qt_internal_add_android_deployment_multi_value_property out_var json_key target property)
|
|
set(property_genex
|
|
"$<TARGET_PROPERTY:${target},${property}>"
|
|
)
|
|
string(JOIN "" list_join_genex
|
|
"$<JOIN:"
|
|
"$<GENEX_EVAL:${property_genex}>,"
|
|
","
|
|
">"
|
|
)
|
|
string(APPEND ${out_var}
|
|
"$<$<BOOL:${property_genex}>:"
|
|
" \"${json_key}\" : \"${list_join_genex}\",\n"
|
|
">"
|
|
)
|
|
|
|
set(${out_var} "${${out_var}}" PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
# The function converts paths to the CMake format to make them acceptable for JSON.
|
|
# It doesn't overwrite public properties, but instead writes formatted values to internal
|
|
# properties.
|
|
function(_qt_internal_android_format_deployment_paths target)
|
|
_qt_internal_android_format_deployment_path_property(${target}
|
|
QT_QML_IMPORT_PATH _qt_native_qml_import_paths)
|
|
|
|
_qt_internal_android_format_deployment_path_property(${target}
|
|
QT_QML_ROOT_PATH _qt_android_native_qml_root_paths)
|
|
|
|
_qt_internal_android_format_deployment_path_property(${target}
|
|
QT_ANDROID_PACKAGE_SOURCE_DIR _qt_android_native_package_source_dir)
|
|
endfunction()
|
|
|
|
# The function converts the value of target property to JSON compatible path and writes the
|
|
# result to out_property. Property might be either single value, semicolon separated list or system
|
|
# path spec.
|
|
function(_qt_internal_android_format_deployment_path_property target property out_property)
|
|
get_target_property(_paths ${target} ${property})
|
|
if(_paths)
|
|
set(native_paths "")
|
|
foreach(_path IN LISTS _paths)
|
|
file(TO_CMAKE_PATH "${_path}" _path)
|
|
list(APPEND native_paths "${_path}")
|
|
endforeach()
|
|
set_target_properties(${target} PROPERTIES
|
|
${out_property} "${native_paths}")
|
|
endif()
|
|
endfunction()
|
|
|
|
if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
|
|
function(qt_android_add_apk_target)
|
|
qt6_android_add_apk_target(${ARGV})
|
|
endfunction()
|
|
endif()
|
|
|
|
# The function returns the installation path to Qt for Android for the specified ${abi}.
|
|
# By default function expects to find a layout as is installed by the Qt online installer:
|
|
# Qt_install_dir/Version/
|
|
# |__ gcc_64
|
|
# |__ android_arm64_v8a
|
|
# |__ android_armv7
|
|
# |__ android_x86
|
|
# |__ android_x86_64
|
|
function(_qt_internal_get_android_abi_path out_path abi)
|
|
if(DEFINED QT_PATH_ANDROID_ABI_${abi})
|
|
get_filename_component(${out_path} "${QT_PATH_ANDROID_ABI_${abi}}" ABSOLUTE)
|
|
else()
|
|
# Map the ABI value to the Qt for Android folder.
|
|
if (abi STREQUAL "x86")
|
|
set(abi_directory_suffix "${abi}")
|
|
elseif (abi STREQUAL "x86_64")
|
|
set(abi_directory_suffix "${abi}")
|
|
elseif (abi STREQUAL "arm64-v8a")
|
|
set(abi_directory_suffix "arm64_v8a")
|
|
else()
|
|
set(abi_directory_suffix "armv7")
|
|
endif()
|
|
|
|
get_filename_component(${out_path}
|
|
"${_qt_cmake_dir}/../../../android_${abi_directory_suffix}" ABSOLUTE)
|
|
endif()
|
|
set(${out_path} "${${out_path}}" PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
# The function collects list of existing Qt for Android using _qt_internal_get_android_abi_path
|
|
# and pre-defined set of known Android ABIs. The result is written to QT_DEFAULT_ANDROID_ABIS
|
|
# cache variable.
|
|
# Note that QT_DEFAULT_ANDROID_ABIS is not intended to be set outside the function and will be
|
|
# rewritten.
|
|
function(_qt_internal_collect_default_android_abis)
|
|
set(known_android_abis armeabi-v7a arm64-v8a x86 x86_64)
|
|
|
|
set(default_abis)
|
|
foreach(abi IN LISTS known_android_abis)
|
|
_qt_internal_get_android_abi_path(qt_abi_path ${abi})
|
|
# It's expected that Qt for Android contains ABI specific toolchain file.
|
|
if(EXISTS "${qt_abi_path}/lib/cmake/${QT_CMAKE_EXPORT_NAMESPACE}/qt.toolchain.cmake"
|
|
OR CMAKE_ANDROID_ARCH_ABI STREQUAL abi)
|
|
list(APPEND default_abis ${abi})
|
|
endif()
|
|
endforeach()
|
|
set(QT_DEFAULT_ANDROID_ABIS "${default_abis}" CACHE STRING
|
|
"The list of autodetected Qt for Android ABIs" FORCE
|
|
)
|
|
set(QT_ANDROID_ABIS "${CMAKE_ANDROID_ARCH_ABI}" CACHE STRING
|
|
"The list of Qt for Android ABIs used to build the project apk"
|
|
)
|
|
set(QT_ANDROID_BUILD_ALL_ABIS FALSE CACHE BOOL
|
|
"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 "$<SEMICOLON>" escaped_configuration_types)
|
|
set(config_arg "-DCMAKE_CONFIGURATION_TYPES=${escaped_configuration_types}")
|
|
else()
|
|
set(config_arg "-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}")
|
|
endif()
|
|
|
|
# The flag is needed when building qt standalone tests only to avoid building
|
|
# qt repo itself
|
|
if(QT_BUILD_STANDALONE_TESTS)
|
|
list(APPEND extra_cmake_args "-DQT_BUILD_STANDALONE_TESTS=ON")
|
|
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}"
|
|
"${extra_cmake_args}"
|
|
EXCLUDE_FROM_ALL TRUE
|
|
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
|
|
EXCLUDE_FROM_MAIN TRUE
|
|
COMMAND "${CMAKE_COMMAND}"
|
|
"--build" "${android_abi_build_dir}"
|
|
"--config" "$<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_<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()
|