diff --git a/cmake/QtBuild.cmake b/cmake/QtBuild.cmake
index 3ee54f5d5a4..0852d8ed2fe 100644
--- a/cmake/QtBuild.cmake
+++ b/cmake/QtBuild.cmake
@@ -1293,6 +1293,14 @@ set(QT_CMAKE_EXPORT_NAMESPACE ${QT_CMAKE_EXPORT_NAMESPACE})")
PUBLIC_HEADER DESTINATION ${INSTALL_INCLUDEDIR}/${module}
PRIVATE_HEADER DESTINATION ${INSTALL_INCLUDEDIR}/${module}/${PROJECT_VERSION}/${module}/private
)
+
+ if (ANDROID)
+ # Record install library location so it can be accessed by
+ # qt_android_dependencies without having to specify it again.
+ set_target_properties(${target} PROPERTIES
+ QT_ANDROID_MODULE_INSTALL_DIR ${INSTALL_LIBDIR})
+ endif()
+
qt_install(EXPORT ${export_name}
NAMESPACE ${QT_CMAKE_EXPORT_NAMESPACE}::
DESTINATION ${config_install_dir})
diff --git a/cmake/QtBuildInternals/QtBuildInternalsAndroid.cmake b/cmake/QtBuildInternals/QtBuildInternalsAndroid.cmake
new file mode 100644
index 00000000000..4677c9dcae4
--- /dev/null
+++ b/cmake/QtBuildInternals/QtBuildInternalsAndroid.cmake
@@ -0,0 +1,206 @@
+#
+# Android specific functions/macros/properties required for building Qt Modules
+#
+
+define_property(TARGET
+ PROPERTY
+ QT_ANDROID_MODULE_INSTALL_DIR
+ BRIEF_DOCS
+ "Recorded install location for a Qt Module."
+ FULL_DOCS
+ "Recorded install location for a Qt Module. Used by qt_android_dependencies()."
+)
+
+
+define_property(TARGET
+ PROPERTY
+ QT_ANDROID_JAR_DEPENDENCIES
+ BRIEF_DOCS
+ "Qt Module Jar dependencies list."
+ FULL_DOCS
+ "Qt Module Jar dependencies list."
+)
+
+define_property(TARGET
+ PROPERTY
+ QT_ANDROID_BUNDLED_JAR_DEPENDENCIES
+ BRIEF_DOCS
+ "Qt Module Jars that should be bundled with it during packing."
+ FULL_DOCS
+ "Qt Module Jars that should be bundled with it during packing."
+)
+
+define_property(TARGET
+ PROPERTY
+ QT_ANDROID_LIB_DEPENDENCIES
+ BRIEF_DOCS
+ "Qt Module C++ libraries that should be bundled with it during packing."
+ FULL_DOCS
+ "Qt Module C++ libraries that should be bundled with it during packing."
+)
+
+define_property(TARGET
+ PROPERTY
+ QT_ANDROID_LIB_DEPENDENCY_REPLACEMENTS
+ BRIEF_DOCS
+ "Qt Module C++ libraries that can replace libraries declared with the QT_ANDROID_LIB_DEPENDENCIES property."
+ FULL_DOCS
+ "Qt Module C++ libraries that can replace libraries declared with the QT_ANDROID_LIB_DEPENDENCIES property."
+)
+
+define_property(TARGET
+ PROPERTY
+ QT_ANDROID_BUNDLED_FILES
+ BRIEF_DOCS
+ "Qt Module files that need to be bundled during packing."
+ FULL_DOCS
+ "Qt Module files that need to be bundled during packing."
+)
+
+define_property(TARGET
+ PROPERTY
+ QT_ANDROID_PERMISSIONS
+ BRIEF_DOCS
+ "Qt Module android permission list."
+ FULL_DOCS
+ "Qt Module android permission list."
+)
+# Generate Qt Module -android-dependencies.xml required by the
+# androiddeploytoolqt to successfully copy all the plugins and other dependent
+# items into tha APK
+function(qt_android_dependencies target)
+
+ get_target_property(arg_JAR_DEPENDENCIES ${target} QT_ANDROID_JAR_DEPENDENCIES)
+ get_target_property(arg_BUNDLED_JAR_DEPENDENCIES ${target} QT_ANDROID_BUNDLED_JAR_DEPENDENCIES)
+ get_target_property(arg_LIB_DEPENDENCIES ${target} QT_ANDROID_LIB_DEPENDENCIES)
+ get_target_property(arg_LIB_DEPENDENCY_REPLACEMENTS ${target} QT_ANDROID_LIB_DEPENDENCY_REPLACEMENTS)
+ get_target_property(arg_PERMISSIONS ${target} QT_ANDROID_PERMISSIONS)
+ get_target_property(module_plugins ${target} MODULE_PLUGIN_TYPES)
+
+ if ((NOT module_plugins)
+ AND (NOT arg_JAR_DEPENDENCIES)
+ AND (NOT arg_LIB_DEPENDENCY_REPLACEMENTS)
+ AND (NOT arg_LIB_DEPENDENCIES)
+ AND (NOT arg_BUNDLED_JAR_DEPENDENCIES)
+ AND (NOT arg_PERMISSIONS))
+ # None of the values were set, so there's nothing to do
+ return()
+ endif()
+
+
+ get_target_property(target_output_name ${target} OUTPUT_NAME)
+ if (NOT target_output_name)
+ set(target_name ${target})
+ else()
+ set(target_name ${target_output_name})
+ endif()
+
+ # mimic qmake's section and string splitting from
+ # mkspecs/feature/qt_android_deps.prf
+ macro(section string delimiter first second)
+ string(FIND ${string} ${delimiter} delimiter_location)
+ if (NOT ${delimiter_location} EQUAL -1)
+ string(SUBSTRING ${string} 0 ${delimiter_location} ${first})
+ math(EXPR delimiter_location "${delimiter_location} + 1")
+ string(SUBSTRING ${string} ${delimiter_location} -1 ${second})
+ else()
+ set(${first} ${string})
+ set(${second} "")
+ endif()
+ endmacro()
+
+ get_target_property(target_bin_dir ${target} BINARY_DIR)
+ set(dependency_file "${target_bin_dir}/${target_name}-android-dependencies.xml")
+
+ file(WRITE ${dependency_file} "\n")
+ file(APPEND ${dependency_file} "\n")
+
+ # Jar Dependencies
+ if(arg_JAR_DEPENDENCIES)
+ foreach(jar_dependency IN LISTS arg_JAR_DEPENDENCIES)
+ section(${jar_dependency} ":" jar_file init_class)
+ if (init_class)
+ set(init_class "initClass=\"${init_class}\"")
+ endif()
+ file(TO_NATIVE_PATH ${jar_file} jar_file_native)
+ file(APPEND ${dependency_file} "\n")
+ endforeach()
+ endif()
+
+ # Bundled Jar Dependencies
+ if(arg_BUNDLED_JAR_DEPENDENCIES)
+ foreach(jar_bundle IN LISTS arg_BUNDLED_JAR_DEPENDENCIES)
+ section(${jar_bundle} ":" bundle_file init_calss)
+ if (init_class)
+ set(init_class "initClass=\"${init_class}\"")
+ endif()
+ file(TO_NATIVE_PATH ${jar_bundle} jar_bundle_native)
+ file(APPEND ${dependency_file} "\n")
+ endforeach()
+ endif()
+
+ # Lib Dependencies
+ if(arg_LIB_DEPENDENCIES)
+ foreach(lib IN LISTS arg_LIB_DEPENDENCIES)
+ section(${lib} ":" lib_file lib_extends)
+ if (lib_extends)
+ set(lib_extends "extends=\"${lib_extends}\"")
+ endif()
+ file(TO_NATIVE_PATH ${lib_file} lib_file_native)
+ file(APPEND ${dependency_file} "\n")
+ endforeach()
+ endif()
+
+ # Lib Dependencies Replacements
+ if(arg_LIB_DEPENDENCY_REPLACEMENTS)
+ foreach(lib IN LISTS arg_LIB_DEPENDENCY_REPLACEMENTS)
+ section(${lib} ":" lib_file lib_replacement)
+ if (lib_replacement)
+ file(TO_NATIVE_PATH ${lib_replacement} lib_replacement_native)
+ set(lib_replacement "replaces=\"${lib_replacement_native}\"")
+ endif()
+ file(TO_NATIVE_PATH ${lib_file} lib_file_native)
+ file(APPEND ${dependency_file} "\n")
+ endforeach()
+ endif()
+
+
+ # Bundled files
+ if(arg_BUNDLED_FILES)
+ foreach(file IN LISTS arg_BUNDLED_FILES)
+ file(TO_NATIVE_PATH ${lib_file} file_native)
+ file(APPEND ${dependency_file} "\n")
+ endforeach()
+ endif()
+
+ # Module plugins
+ if(module_plugins)
+ foreach(plugin IN LISTS module_plugins)
+ file(APPEND ${dependency_file} "\n")
+ endforeach()
+ endif()
+
+ # Android Permissions
+ if(arg_PERMISSIONS)
+ foreach(permission IN LISTS arg_PERMISSIONS)
+ file(APPEND ${dependency_file} "\n")
+ endforeach()
+ endif()
+
+ file(APPEND ${dependency_file} "")
+ file(APPEND ${dependency_file} "\n")
+
+ get_target_property(target_install_dir ${target} QT_ANDROID_MODULE_INSTALL_DIR)
+ if (NOT target_install_dir)
+ message(SEND_ERROR "qt_android_dependencies: Target ${target} is either not a Qt Module or has no recorded install location")
+ return()
+ endif()
+
+ # Copy file into install directory, required by the androiddeployqt tool.
+ qt_install(FILES
+ ${dependency_file}
+ DESTINATION
+ ${target_install_dir}
+ COMPONENT
+ Devel)
+endfunction()
diff --git a/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake b/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake
index 8a6c2cb7338..590885c44d1 100644
--- a/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake
+++ b/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake
@@ -142,3 +142,7 @@ macro(qt_examples_build_end)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ${BACKUP_CMAKE_FIND_ROOT_PATH_MODE_PACKAGE})
endmacro()
+
+if (ANDROID)
+ include(QtBuildInternals/QtBuildInternalsAndroid)
+endif()
diff --git a/cmake/QtPlatformAndroid.cmake b/cmake/QtPlatformAndroid.cmake
index 70768947a06..bc7e0aa862f 100644
--- a/cmake/QtPlatformAndroid.cmake
+++ b/cmake/QtPlatformAndroid.cmake
@@ -74,7 +74,7 @@ if (NOT QT_ANDROID_SDK_BUILD_TOOLS_VERSION)
list(SORT android_build_tools)
list(REVERSE android_build_tools)
list(GET android_build_tools 0 android_build_tools_latest)
- set(qt_QT_ANDROID_SDK_BUILD_TOOLS_VERSION ${android_build_tools_latest})
+ set(QT_ANDROID_SDK_BUILD_TOOLS_VERSION ${android_build_tools_latest})
endif()
# Ensure we are using the shared version of libc++
diff --git a/cmake/QtPostProcess.cmake b/cmake/QtPostProcess.cmake
index 568719d4f0b..53b89f22f10 100644
--- a/cmake/QtPostProcess.cmake
+++ b/cmake/QtPostProcess.cmake
@@ -276,6 +276,18 @@ function(qt_generate_build_internals_extra_cmake_code)
endif()
endfunction()
+# For every Qt module check if there any android dependencies that require
+# processing.
+function(qt_modules_process_android_dependencies)
+ foreach (target ${QT_KNOWN_MODULES})
+ qt_android_dependencies(${target})
+ endforeach()
+endfunction()
+
qt_internal_create_depends_files()
qt_generate_build_internals_extra_cmake_code()
qt_internal_create_plugins_files()
+
+if (ANDROID)
+ qt_modules_process_android_dependencies()
+endif()
diff --git a/src/corelib/.prev_CMakeLists.txt b/src/corelib/.prev_CMakeLists.txt
index d6726e9336a..f1000e6301a 100644
--- a/src/corelib/.prev_CMakeLists.txt
+++ b/src/corelib/.prev_CMakeLists.txt
@@ -241,10 +241,19 @@ add_qt_simd_part(Core SIMD mips_dsp
+if(ANDROID)
+ set_property(TARGET Core APPEND PROPERTY QT_ANDROID_BUNDLED_JAR_DEPENDENCIES
+ jar/QtAndroid.jar
+ )
+ set_property(TARGET Core APPEND PROPERTY QT_ANDROID_LIB_DEPENDENCIES
+ plugins/platforms/android/libqtforandroid.so
+ )
+ set_property(TARGET Core APPEND PROPERTY QT_ANDROID_PERMISSIONS
+ android.permission.INTERNET android.permission.WRITE_EXTERNAL_STORAGE
+ )
+endif()
+
#### Keys ignored in scope 1:.:.:corelib.pro::
-# ANDROID_BUNDLED_JAR_DEPENDENCIES = "jar/QtAndroid.jar"
-# ANDROID_LIB_DEPENDENCIES = "plugins/platforms/android/libqtforandroid.so"
-# ANDROID_PERMISSIONS = "android.permission.INTERNET" "android.permission.WRITE_EXTERNAL_STORAGE"
# CMAKE_DISABLED_FEATURES = "$$joinQT_DISABLED_FEATURES,"$$escape_expand(\\n) ""
# CMAKE_HOST_DATA_DIR = "$$cmakeRelativePath$$[QT_HOST_DATA/src],$$[QT_INSTALL_PREFIX]"
# CMAKE_INSTALL_DATA_DIR = "$$cmakeRelativePath$$[QT_HOST_DATA],$$[QT_INSTALL_PREFIX]"
diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt
index da8eb4eea55..4d23f0f8929 100644
--- a/src/corelib/CMakeLists.txt
+++ b/src/corelib/CMakeLists.txt
@@ -323,10 +323,19 @@ add_qt_simd_part(Core SIMD mips_dsp
+if(ANDROID)
+ set_property(TARGET Core APPEND PROPERTY QT_ANDROID_BUNDLED_JAR_DEPENDENCIES
+ jar/QtAndroid.jar
+ )
+ set_property(TARGET Core APPEND PROPERTY QT_ANDROID_LIB_DEPENDENCIES
+ plugins/platforms/android/libqtforandroid.so
+ )
+ set_property(TARGET Core APPEND PROPERTY QT_ANDROID_PERMISSIONS
+ android.permission.INTERNET android.permission.WRITE_EXTERNAL_STORAGE
+ )
+endif()
+
#### Keys ignored in scope 1:.:.:corelib.pro::
-# ANDROID_BUNDLED_JAR_DEPENDENCIES = "jar/QtAndroid.jar"
-# ANDROID_LIB_DEPENDENCIES = "plugins/platforms/android/libqtforandroid.so"
-# ANDROID_PERMISSIONS = "android.permission.INTERNET" "android.permission.WRITE_EXTERNAL_STORAGE"
# CMAKE_DISABLED_FEATURES = "$$joinQT_DISABLED_FEATURES,"$$escape_expand(\\n) ""
# CMAKE_HOST_DATA_DIR = "$$cmakeRelativePath$$[QT_HOST_DATA/src],$$[QT_INSTALL_PREFIX]"
# CMAKE_INSTALL_DATA_DIR = "$$cmakeRelativePath$$[QT_HOST_DATA],$$[QT_INSTALL_PREFIX]"
diff --git a/src/corelib/Qt6CoreMacros.cmake b/src/corelib/Qt6CoreMacros.cmake
index 738816ee4e9..d82a65e4a6a 100644
--- a/src/corelib/Qt6CoreMacros.cmake
+++ b/src/corelib/Qt6CoreMacros.cmake
@@ -399,6 +399,11 @@ function(add_qt_gui_executable target)
if(ANDROID)
qt_android_generate_deployment_settings("${target}")
+ # 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
+ # through dlopen()
+ target_compile_options(${target} PRIVATE -fvisibility=default)
endif()
endfunction()
diff --git a/src/network/.prev_CMakeLists.txt b/src/network/.prev_CMakeLists.txt
index b1ba59e7be9..e5756e291d2 100644
--- a/src/network/.prev_CMakeLists.txt
+++ b/src/network/.prev_CMakeLists.txt
@@ -76,10 +76,19 @@ extend_target(Network CONDITION MSVC AND (TEST_architecture_arch STREQUAL "i386"
"/BASE:0x64000000"
)
+if(ANDROID AND (QT_FEATURE_bearermanagement))
+ set_property(TARGET Network APPEND PROPERTY QT_ANDROID_BUNDLED_JAR_DEPENDENCIES
+ jar/QtAndroidBearer.jar
+ )
+ set_property(TARGET Network APPEND PROPERTY QT_ANDROID_LIB_DEPENDENCIES
+ plugins/bearer/libqandroidbearer.so
+ )
+ set_property(TARGET Network APPEND PROPERTY QT_ANDROID_PERMISSIONS
+ android.permission.ACCESS_NETWORK_STATE
+ )
+endif()
+
#### Keys ignored in scope 3:.:.:network.pro:QT_FEATURE_bearermanagement:
-# ANDROID_BUNDLED_JAR_DEPENDENCIES = "jar/QtAndroidBearer.jar"
-# ANDROID_LIB_DEPENDENCIES = "plugins/bearer/libqandroidbearer.so"
-# ANDROID_PERMISSIONS = "android.permission.ACCESS_NETWORK_STATE"
# MODULE_PLUGIN_TYPES = "bearer"
extend_target(Network CONDITION QT_FEATURE_ftp
diff --git a/src/network/CMakeLists.txt b/src/network/CMakeLists.txt
index 7a6bf8f9e9d..3148c007043 100644
--- a/src/network/CMakeLists.txt
+++ b/src/network/CMakeLists.txt
@@ -76,10 +76,19 @@ extend_target(Network CONDITION MSVC AND (TEST_architecture_arch STREQUAL "i386"
"/BASE:0x64000000"
)
+if(ANDROID AND (QT_FEATURE_bearermanagement))
+ set_property(TARGET Network APPEND PROPERTY QT_ANDROID_BUNDLED_JAR_DEPENDENCIES
+ jar/QtAndroidBearer.jar
+ )
+ set_property(TARGET Network APPEND PROPERTY QT_ANDROID_LIB_DEPENDENCIES
+ plugins/bearer/libqandroidbearer.so
+ )
+ set_property(TARGET Network APPEND PROPERTY QT_ANDROID_PERMISSIONS
+ android.permission.ACCESS_NETWORK_STATE
+ )
+endif()
+
#### Keys ignored in scope 3:.:.:network.pro:QT_FEATURE_bearermanagement:
-# ANDROID_BUNDLED_JAR_DEPENDENCIES = "jar/QtAndroidBearer.jar"
-# ANDROID_LIB_DEPENDENCIES = "plugins/bearer/libqandroidbearer.so"
-# ANDROID_PERMISSIONS = "android.permission.ACCESS_NETWORK_STATE"
# MODULE_PLUGIN_TYPES = "bearer"
extend_target(Network CONDITION QT_FEATURE_ftp
diff --git a/util/cmake/pro2cmake.py b/util/cmake/pro2cmake.py
index 28724b1fc05..96e2bacae9a 100755
--- a/util/cmake/pro2cmake.py
+++ b/util/cmake/pro2cmake.py
@@ -1536,6 +1536,32 @@ def write_simd_part(cm_fh: typing.IO[str], target: str, scope: Scope, indent: in
header = 'add_qt_simd_part({} SIMD {}\n'.format(target, simd),
footer = ')\n\n')
+def write_android_part(cm_fh: typing.IO[str], target: str, scope:Scope, indent: int = 0):
+ keys = [ 'ANDROID_BUNDLED_JAR_DEPENDENCIES'
+ , 'ANDROID_LIB_DEPENDENCIES'
+ , 'ANDROID_JAR_DEPENDENCIES'
+ , 'ANDROID_LIB_DEPENDENCY_REPLACEMENTS'
+ , 'ANDROID_BUNDLED_FILES'
+ , 'ANDROID_PERMISSIONS' ]
+
+ has_no_values = True
+ for key in keys:
+ value = scope.get(key)
+ if len(value) != 0:
+ if has_no_values:
+ if scope.condition:
+ cm_fh.write('\n{}if(ANDROID AND ({}))\n'.format(spaces(indent), scope.condition))
+ else:
+ cm_fh.write('\n{}if(ANDROID)\n'.format(spaces(indent)))
+ indent += 1
+ has_no_values = False
+ cm_fh.write('{}set_property(TARGET {} APPEND PROPERTY QT_{}\n'.format(spaces(indent), target, key))
+ write_list(cm_fh, value, '', indent + 1)
+ cm_fh.write('{})\n'.format(spaces(indent)))
+ indent -= 1
+
+ if not has_no_values:
+ cm_fh.write('{}endif()\n'.format(spaces(indent)))
def write_main_part(cm_fh: typing.IO[str], name: str, typename: str,
cmake_function: str, scope: Scope, *,
@@ -1577,6 +1603,8 @@ def write_main_part(cm_fh: typing.IO[str], name: str, typename: str,
write_simd_part(cm_fh, name, scope, indent)
+ write_android_part(cm_fh, name, scopes[0], indent)
+
ignored_keys_report = write_ignored_keys(scopes[0], spaces(indent))
if ignored_keys_report:
cm_fh.write(ignored_keys_report)
@@ -1590,12 +1618,12 @@ def write_main_part(cm_fh: typing.IO[str], name: str, typename: str,
for c in scopes[1:]:
c.reset_visited_keys()
+ write_android_part(cm_fh, name, c, indent=indent)
write_extend_target(cm_fh, name, c, indent=indent)
ignored_keys_report = write_ignored_keys(c, spaces(indent))
if ignored_keys_report:
cm_fh.write(ignored_keys_report)
-
def write_module(cm_fh: typing.IO[str], scope: Scope, *,
indent: int = 0) -> None:
module_name = scope.TARGET