Revision control
++ # Copyright (C) 2025 The Qt Company Ltd.
++ # SPDX-License-Identifier: BSD-3-Clause
++
++ # Generates the generator expression that converts the 'target'
++ # QT_ANDROID_PERMISSIONS property to the specific 'type'.
++ #
++ # It's expected that each element in QT_ANDROID_PERMISSIONS list has specific
++ # format:
++ # <name>\;<permission>\\\;<extra1>\;<value>\\\;<extra2>\;<value>
++ #
++ # Synopsis
++ # _qt_internal_android_convert_permissions(out_var target <JSON|XML>)
++ #
++ # Arguments
++ #
++ # `out_var`
++ # The name of the variable where the resulting generator expression is
++ # stored.
++ #
++ # `target`
++ # The name of the target.
++ #
++ # `JSON`
++ # Generate JSON array known by androiddeployqt.
++ #
++ # `XML`
++ # Generate XML content compatible with AndroidManifest.xml.
++ #
++ # `DEPENDENCIESXML`
++ # Generate XML content compatible with <module>-android-dependencies.xml.
++ # This format doesn't produce generator expression, so it should be used in
++ # the scope finalizer.
++ function(_qt_internal_android_convert_permissions out_var target type)
++ if(type STREQUAL "DEPENDENCIESXML")
++ set(output "")
++ get_target_property(permissions ${target} QT_ANDROID_PERMISSIONS)
++ if(NOT permissions)
++ return()
++ endif()
++ foreach(permission IN LISTS permissions)
++ list(JOIN permission "=\"" permission)
++ list(LENGTH permission permission_length)
++ if(permission_length LESS 1)
++ message(FATAL_ERROR "Invalid QT_ANDROID_PERMISSIONS format for target"
++ " ${target}: ${arg_PERMISSIONS}")
++ endif()
++
++ list(GET permission 0 permission_name)
++ string(APPEND output "<permission ${permission_name}\"")
++
++ math(EXPR permission_length "${permission_length} - 1")
++ set(extras_string "")
++ if(permission_length GREATER_EQUAL 1)
++ set(attributes "")
++ foreach(i RANGE 1 ${permission_length})
++ list(GET permission ${i} permission_attribute)
++ list(APPEND attributes "android:${permission_attribute}'")
++ endforeach()
++ list(JOIN attributes " " attributes)
++ string(REPLACE "\"" "'" attributes "${attributes}")
++ set(extras_string " extras=\"${attributes}\"")
++ endif()
++ string(APPEND output "${extras_string}/>\n")
++ endforeach()
++ set(${out_var} "${output}" PARENT_SCOPE)
++ return()
++ endif()
++
++ set(permissions_property "$<TARGET_PROPERTY:${target},QT_ANDROID_PERMISSIONS>")
++ set(permissions_genex "$<$<BOOL:${permissions_property}>:")
++ if(type STREQUAL "JSON")
++ set(pref "{ \"")
++ set(post "\" }")
++ set(indent "\n ")
++ string(APPEND permissions_genex
++ " \"permissions\": [${indent}$<JOIN:"
++ "$<JOIN:"
++ "${pref}$<JOIN:"
++ "${permissions_property},"
++ "${post}$<COMMA>${indent}${pref}"
++ ">${post},"
++ "\": \""
++ ">,"
++ "\"$<COMMA> \""
++ ">\n ]$<COMMA>\n"
++ )
++ elseif(type STREQUAL "XML")
++ set(pref "<uses-permission android:")
++ set(post "' /$<ANGLE-R>")
++ string(APPEND permissions_genex
++ "$<JOIN:"
++ "$<JOIN:"
++ "${pref}$<JOIN:"
++ "${permissions_property},"
++ "${post}\n ${pref}"
++ ">${post},"
++ "='"
++ ">,"
++ "' \n android:"
++ ">"
++ )
++ else()
++ message(FATAL_ERROR "Invalid type ${type}. Supported types: JSON, XML")
++ endif()
++ string(APPEND permissions_genex ">")
++
++ set(${out_var} "${permissions_genex}" PARENT_SCOPE)
++ endfunction()
++
++ # Add the specific Android permission to the target. The permission is stored
++ # in the QT_ANDROID_PERMISSIONS property(the property is not a public API)
++ # and has the following format:
++ # <name>\;<permission>\\\;<extra1>\;<value>\\\;<extra2>\;<value>
++ #
++ # Synopsis
++ # _qt_internal_add_android_permission(target NAME <permission>
++ # ATTRIBUTES <extra1> <value1>
++ # [<extra2> <value2>]...
++ # )
++ #
++ # Arguments
++ #
++ # `target`
++ # The Android target.
++ #
++ # `NAME`
++ # The permission name. E.g. 'android.permission.CAMERA'.
++ #
++ # `ATTRIBUTES`
++ # Extra permission attribute key-value pairs.
++ # for details.
++ function(_qt_internal_add_android_permission target)
++ if(NOT TARGET ${target})
++ message(FATAL_ERROR "Empty or invalid target for adding Android permission: (${target})")
++ endif()
++
++ cmake_parse_arguments(arg "" "NAME" "ATTRIBUTES" ${ARGN})
++
++ if(NOT arg_NAME)
++ message(FATAL_ERROR "NAME for adding Android permission cannot be empty (${target})")
++ endif()
++
++ set(permission_entry "name\;${arg_NAME}")
++ if(arg_ATTRIBUTES)
++ # Permission with additional attributes
++ list(LENGTH arg_ATTRIBUTES attributes_len)
++ math(EXPR attributes_modulus "${attributes_len} % 2")
++ if(NOT (attributes_len GREATER 1 AND attributes_modulus EQUAL 0))
++ message(FATAL_ERROR "Android permission: ${arg_NAME} attributes: ${arg_ATTRIBUTES}"
++ " must be name-value pairs (for example: minSdkVersion 30)")
++ endif()
++ # Combine name-value pairs
++ set(index 0)
++ while(index LESS attributes_len)
++ list(GET arg_ATTRIBUTES ${index} name)
++ math(EXPR index "${index} + 1")
++ list(GET arg_ATTRIBUTES ${index} value)
++ string(APPEND permission_entry "\\\;${name}\;${value}")
++ math(EXPR index "${index} + 1")
++ endwhile()
++ endif()
++
++ # Append the permission to the target's property
++ set_property(TARGET ${target} APPEND PROPERTY QT_ANDROID_PERMISSIONS "${permission_entry}")
++ endfunction()
++
++ # Merges QT_ANDROID_PERMISSIONS from each SOURCE_TARGETS source into target's own property.
++ #
++ # Synopsis
++ # _qt_internal_android_collect_permissions(target
++ # SOURCE_TARGETS <source> [<source>...])
++ function(_qt_internal_android_collect_permissions target)
++ cmake_parse_arguments(PARSE_ARGV 1 arg "" "" "SOURCE_TARGETS")
++ if(NOT arg_SOURCE_TARGETS)
++ return()
++ endif()
++
++ get_target_property(existing ${target} QT_ANDROID_PERMISSIONS)
++
++ set(new_entries "")
++ foreach(src_target IN LISTS arg_SOURCE_TARGETS)
++ if(NOT TARGET "${src_target}")
++ continue()
++ endif()
++ get_target_property(src_permissions "${src_target}" QT_ANDROID_PERMISSIONS)
++ if(NOT src_permissions)
++ continue()
++ endif()
++ foreach(entry IN LISTS src_permissions)
++ if("${entry}" IN_LIST existing OR "${entry}" IN_LIST new_entries)
++ continue()
++ endif()
++ string(REPLACE ";" [[\;]] entry_escaped "${entry}")
++ if(new_entries)
++ string(APPEND new_entries ";${entry_escaped}")
++ else()
++ set(new_entries "${entry_escaped}")
++ endif()
++ endforeach()
++ endforeach()
++
++ if(new_entries)
++ set_property(TARGET ${target} APPEND PROPERTY QT_ANDROID_PERMISSIONS "${new_entries}")
++ endif()
++ endfunction()