Revision control
Copy as Markdown
# Copyright (C) 2025 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
# Collects the dynamic features for the target
function(_qt_internal_android_add_dynamic_feature_deployment target)
get_target_property(dynamic_features ${target} _qt_android_dynamic_features)
if(NOT dynamic_features)
return()
endif()
foreach(dynamic_feature IN LISTS dynamic_features)
get_target_property(is_imported ${dynamic_feature} IMPORTED)
if(is_imported)
message(FATAL_ERROR "Imported target ${dynamic_feature} can not be a"
" 'DYNAMIC_FEATURE'.")
endif()
get_target_property(type ${dynamic_feature} TYPE)
if(NOT type STREQUAL "SHARED_LIBRARY")
message(FATAL_ERROR "Cannot make ${dynamic_feature} 'DYNAMIC_FEATURE'."
" The target must be the 'SHARED_LIBRARY'.")
endif()
get_target_property(android_type ${dynamic_feature} _qt_android_target_type)
if(NOT android_type STREQUAL "" AND NOT android_type MATCHES "-NOTFOUND$"
AND NOT android_type STREQUAL "DYNAMIC_FEATURE")
message(FATAL_ERROR "Cannot make ${dynamic_feature} 'DYNAMIC_FEATURE',"
" it's already '${android_type}'. The target must be the plain 'SHARED_LIBRARY'.")
endif()
# Mark the target as DYNAMIC_FEATURE, since we used it in this role once.
set_target_properties(${dynamic_feature} PROPERTIES _qt_android_target_type DYNAMIC_FEATURE)
_qt_internal_set_android_dynamic_feature_gradle_defaults(${dynamic_feature})
_qt_internal_android_get_dynamic_feature_deployment_dir(dynamic_feature_deployment_dir
${target} ${dynamic_feature})
_qt_internal_android_generate_target_build_gradle(${dynamic_feature}
DEPLOYMENT_DIR "${dynamic_feature_deployment_dir}")
_qt_internal_android_generate_dynamic_feature_manifest(${target} ${dynamic_feature})
_qt_internal_android_copy_dynamic_feature(${target} ${dynamic_feature})
endforeach()
endfunction()
# Sets the default values of the gradle properties for the Android dynamic feature target.
function(_qt_internal_set_android_dynamic_feature_gradle_defaults target)
_qt_internal_android_java_dir(android_java_dir)
set(implementation_dependencies "project(':app')" "libs.androidx.core")
set_target_properties(${target} PROPERTIES
_qt_android_gradle_java_source_dirs "src;java"
_qt_android_gradle_aidl_source_dirs "src;aidl"
_qt_android_gradle_res_source_dirs "res"
_qt_android_gradle_resources_source_dirs "resources"
_qt_android_gradle_renderscript_source_dirs "src"
_qt_android_gradle_assets_source_dirs "assets"
_qt_android_gradle_jniLibs_source_dirs "libs"
_qt_android_manifest "AndroidManifest.xml"
_qt_android_gradle_implementation_dependencies "${implementation_dependencies}"
)
endfunction()
# Copies the dynamic feature library to the respective gradle build tree.
function(_qt_internal_android_copy_dynamic_feature target dynamic_feature)
if(NOT TARGET ${dynamic_feature})
message(FATAL_ERROR "${dynamic_feature} is not a target.")
endif()
_qt_internal_android_get_dynamic_feature_deployment_dir(dynamic_feature_deployment_dir
${target} ${dynamic_feature})
set(dynamic_feature_libs_dir "${dynamic_feature_deployment_dir}/libs/${CMAKE_ANDROID_ARCH_ABI}")
get_target_property(output_name ${dynamic_feature} OUTPUT_NAME)
if(NOT output_name)
get_target_property(suffix "${dynamic_feature}" SUFFIX)
set(output_name "lib${dynamic_feature}${suffix}")
endif()
set(output_file_path "${dynamic_feature_libs_dir}/${output_name}")
_qt_internal_copy_file_if_different_command(copy_command
"$<TARGET_FILE:${dynamic_feature}>"
"${output_file_path}"
)
add_custom_command(OUTPUT ${output_file_path}
COMMAND ${copy_command}
DEPENDS ${dynamic_feature}
COMMENT "Copying ${dynamic_feature} dynamic feature to ${target} deployment directory"
)
add_custom_target(${target}_deploy_dynamic_features DEPENDS "${output_file_path}")
_qt_internal_android_add_deploy_libraries_dependency(${target}
${target}_deploy_dynamic_features)
endfunction()
# Generates the feature name strings and copy them to the respective deployment directory.
function(_qt_internal_android_generate_dynamic_feature_names target)
get_target_property(dynamic_features ${target} _qt_android_dynamic_features)
if(NOT dynamic_features)
return()
endif()
# Collect the titles
string(JOIN "\n" content
"<?xml version=\"1.0\" encoding=\"utf-8\"?>"
"<resources>"
)
foreach(feature IN LISTS dynamic_features)
string(APPEND content "\n <string name=\"${feature}_title\">${feature}</string>")
endforeach()
string(APPEND content "\n</resources>")
_qt_internal_android_get_target_deployment_dir(deployment_dir ${target})
# TODO: androiddeployqt wipes the android build directory. Generate feature_names.xml target
# build dir and copy after androiddeployqt run. We should skip feature_names.xml copying when
# androiddeployqt is not involved into the deployment process anymore.
#
# set(output_file "${deployment_dir}/res/values/feature_names.xml")
set(output_file "$<TARGET_PROPERTY:${target},BINARY_DIR>/res/values/feature_names.xml")
_qt_internal_configure_file(GENERATE OUTPUT "${output_file}" CONTENT "${content}")
set(output_file_in_deployment_dir "${deployment_dir}/res/values/feature_names.xml")
add_custom_command(OUTPUT "${output_file_in_deployment_dir}"
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${output_file}"
"${output_file_in_deployment_dir}"
DEPENDS "${output_file}"
VERBATIM
)
add_custom_target(${target}_copy_feature_names
DEPENDS
"${output_file_in_deployment_dir}"
)
endfunction()
# Returns the dynamic feature deployment directory in the target build tree.
function(_qt_internal_android_get_dynamic_feature_deployment_dir out_var target dynamic_feature)
_qt_internal_android_get_target_android_build_dir(android_build_dir ${target})
set(${out_var} "${android_build_dir}/${dynamic_feature}" PARENT_SCOPE)
endfunction()
# Generates the AndroidManifest.xml file for the dynamic_feature.
function(_qt_internal_android_generate_dynamic_feature_manifest target dynamic_feature)
set(android_manifest_filename AndroidManifest.xml)
_qt_internal_android_get_dynamic_feature_deployment_dir(dynamic_feature_deployment_dir ${target}
${dynamic_feature})
_qt_internal_android_get_template_path(template_file ${target}
"dynamic_feature/${android_manifest_filename}")
set(output_file "${dynamic_feature_deployment_dir}/AndroidManifest.xml")
_qt_internal_configure_file(CONFIGURE OUTPUT "${output_file}" INPUT "${template_file}")
endfunction()