2024-11-28 13:33:46 +00:00
|
|
|
# Copyright (C) 2024 The Qt Company Ltd.
|
|
|
|
# SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
|
CMake: Workaround Android CMP0155 issue
If a user:
- targets Android
- sets cmake_minimum_required(3.29) in their project which implies
policy CMP0155 being set to NEW
- sets CMAKE_CXX_STANDARD >= 20
- uses Qt Creator's maintenance tool provider
- uses Qt Creator's default of ANDROID_USE_LEGACY_TOOLCHAIN_FILE=OFF
then they will hit an issue where the Threads package cannot be found
due to a CMake bug that causes all try_compile calls to fail, which
in turns causes the Qt6 package not being found.
Android and ANDROID_USE_LEGACY_TOOLCHAIN_FILE being OFF is relevant,
because in that case CMake fails to find the
CMAKE_CXX_COMPILER_CLANG_SCAN_DEPS tool, which is used during
try_compile builds.
CMP0155 set to NEW and CMAKE_CXX_STANDARD >= 20 is relevant,
because only in that case will CMake try to use the scan deps tool to
scan for modules during try_compile builds.
The maintenance tool provider is relevant in this case, because CMake
records the CMP0155 policy value at function definition time.
Normally without a dependency provider, the policy value at Threads
package lookup time would be OLD because each Qt6Config.cmake file
has a cmake_minimum_required(3.16..3.21) call which overrides any
other policy value.
But because the dependency provider function is defined before any of
Qt's code is loaded, it inherits the CMP0155 NEW from
cmake_minimum_required(3.29) of the user's project. That causes
all find_package lookups to use CMP0155=NEW, ignoring Qt's request.
This works by design from CMake's PoV, but causes unfortunate fallout
in this case.
Because we can't influence the recorded policy value of the provided
function from the outside in any way, the only thing we can do is
disable module scanning via CMAKE_CXX_SCAN_FOR_MODULES.
Work around the issue by setting CMAKE_CXX_SCAN_FOR_MODULES to OFF
inside Qt6Config.cmake, which will set it in the directory scope of
the find_package(Qt6) caller, affecting all try_compile calls there.
Do it only in the specific conditions mentioned above.
Allow opting out of the variable assignment by configuring with
-DQT_NO_SET_CMAKE_CXX_SCAN_FOR_MODULES_TO_OFF=ON
Doing this in Qt6Config.cmake allows working around the issue when
using older Creator versions that don't work around it themselves,
See https://gitlab.kitware.com/cmake/cmake/-/issues/27169
Pick-to: 6.8 6.9 6.10
Fixes: QTBUG-139439
Change-Id: Id171c88566c41b65b24c2f2a3874e3f3c0abc814
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
2025-08-28 14:48:37 +00:00
|
|
|
function(__qt_internal_workaround_android_cmp0155_issue)
|
|
|
|
# Work around upstream cmake issue: https://gitlab.kitware.com/cmake/cmake/-/issues/27169
|
|
|
|
if(ANDROID
|
|
|
|
AND CMAKE_VERSION VERSION_GREATER_EQUAL 3.29
|
|
|
|
AND NOT ANDROID_USE_LEGACY_TOOLCHAIN_FILE
|
|
|
|
AND NOT CMAKE_CXX_COMPILER_CLANG_SCAN_DEPS
|
|
|
|
AND NOT QT_NO_SET_CMAKE_CXX_SCAN_FOR_MODULES_TO_OFF
|
|
|
|
)
|
|
|
|
message(DEBUG
|
|
|
|
"Setting CMAKE_CXX_SCAN_FOR_MODULES to OFF in the Qt6 package directory scope to "
|
|
|
|
"avoid issues with not being able to find the Threads package when targeting Android with "
|
|
|
|
"cmake_minimum_required(3.29) and CMAKE_CXX_STANDARD >= 20."
|
|
|
|
)
|
|
|
|
set(CMAKE_CXX_SCAN_FOR_MODULES OFF PARENT_SCOPE)
|
|
|
|
endif()
|
|
|
|
endfunction()
|
|
|
|
|
2024-11-28 13:33:46 +00:00
|
|
|
function(_qt_internal_detect_latest_android_platform out_var)
|
|
|
|
# Locate the highest available platform
|
|
|
|
file(GLOB android_platforms
|
|
|
|
LIST_DIRECTORIES true
|
|
|
|
RELATIVE "${ANDROID_SDK_ROOT}/platforms"
|
|
|
|
"${ANDROID_SDK_ROOT}/platforms/*")
|
|
|
|
|
|
|
|
# If list is not empty
|
|
|
|
if(android_platforms)
|
2025-01-08 17:27:34 +00:00
|
|
|
_qt_internal_sort_android_platforms(android_platforms ${android_platforms})
|
2024-11-28 13:33:46 +00:00
|
|
|
list(REVERSE android_platforms)
|
|
|
|
list(GET android_platforms 0 android_platform_latest)
|
|
|
|
set(${out_var} "${android_platform_latest}" PARENT_SCOPE)
|
|
|
|
else()
|
|
|
|
set(${out_var} "${out_var}-NOTFOUND" PARENT_SCOPE)
|
|
|
|
endif()
|
|
|
|
endfunction()
|
2025-01-08 17:27:34 +00:00
|
|
|
|
|
|
|
function(_qt_internal_sort_android_platforms out_var)
|
|
|
|
if(CMAKE_VERSION GREATER_EQUAL 3.18)
|
|
|
|
set(platforms ${ARGN})
|
|
|
|
list(SORT platforms COMPARE NATURAL)
|
|
|
|
else()
|
|
|
|
# Simulate natural sorting:
|
|
|
|
# - prepend every platform with its version as three digits, zero-padded
|
|
|
|
# - regular sort
|
|
|
|
# - remove the padded version prefix
|
|
|
|
set(platforms)
|
|
|
|
foreach(platform IN LISTS ARGN)
|
|
|
|
set(version "000")
|
|
|
|
if(platform MATCHES ".*-([0-9]+)$")
|
|
|
|
set(version ${CMAKE_MATCH_1})
|
|
|
|
string(LENGTH "${version}" version_length)
|
|
|
|
math(EXPR padding_length "3 - ${version_length}")
|
|
|
|
string(REPEAT "0" ${padding_length} padding)
|
|
|
|
string(PREPEND version ${padding})
|
|
|
|
endif()
|
|
|
|
list(APPEND platforms "${version}~${platform}")
|
|
|
|
endforeach()
|
|
|
|
list(SORT platforms)
|
|
|
|
list(TRANSFORM platforms REPLACE "^.*~" "")
|
|
|
|
endif()
|
|
|
|
set("${out_var}" "${platforms}" PARENT_SCOPE)
|
|
|
|
endfunction()
|
2025-03-28 08:00:01 +00:00
|
|
|
|
|
|
|
function(_qt_internal_locate_android_jar)
|
|
|
|
# This variable specifies the API level used for building Java code, it can be the same as Qt
|
|
|
|
# for Android's maximum supported Android version or higher.
|
|
|
|
if(NOT QT_ANDROID_API_USED_FOR_JAVA)
|
|
|
|
set(QT_ANDROID_API_USED_FOR_JAVA "android-35")
|
|
|
|
endif()
|
|
|
|
|
|
|
|
set(jar_location "${ANDROID_SDK_ROOT}/platforms/${QT_ANDROID_API_USED_FOR_JAVA}/android.jar")
|
|
|
|
if(NOT EXISTS "${jar_location}")
|
|
|
|
_qt_internal_detect_latest_android_platform(android_platform_latest)
|
|
|
|
if(android_platform_latest)
|
|
|
|
message(NOTICE "The default platform SDK ${QT_ANDROID_API_USED_FOR_JAVA} not found, "
|
|
|
|
"using the latest installed ${android_platform_latest} instead.")
|
|
|
|
set(QT_ANDROID_API_USED_FOR_JAVA ${android_platform_latest})
|
|
|
|
endif()
|
|
|
|
endif()
|
|
|
|
|
|
|
|
set(QT_ANDROID_JAR "${ANDROID_SDK_ROOT}/platforms/${QT_ANDROID_API_USED_FOR_JAVA}/android.jar")
|
|
|
|
if(NOT EXISTS "${QT_ANDROID_JAR}")
|
|
|
|
message(FATAL_ERROR
|
|
|
|
"No suitable Android SDK platform found in '${ANDROID_SDK_ROOT}/platforms'."
|
|
|
|
" The minimum version required for building Java code is ${QT_ANDROID_API_USED_FOR_JAVA}"
|
|
|
|
)
|
|
|
|
endif()
|
|
|
|
|
|
|
|
message(STATUS "Using Android SDK API ${QT_ANDROID_API_USED_FOR_JAVA} from "
|
|
|
|
"${ANDROID_SDK_ROOT}/platforms")
|
|
|
|
|
|
|
|
set(QT_ANDROID_JAR "${QT_ANDROID_JAR}" PARENT_SCOPE)
|
|
|
|
set(QT_ANDROID_API_USED_FOR_JAVA "${QT_ANDROID_API_USED_FOR_JAVA}" PARENT_SCOPE)
|
|
|
|
endfunction()
|
|
|
|
|