diff --git a/.cmake.conf b/.cmake.conf index 9e1d227e1cd..96c28affffb 100644 --- a/.cmake.conf +++ b/.cmake.conf @@ -36,3 +36,13 @@ set(QT_SUPPORTED_MIN_CMAKE_VERSION_FOR_USING_QT_APPLE "3.21") # in sync. set(QT_MIN_NEW_POLICY_CMAKE_VERSION "3.16") set(QT_MAX_NEW_POLICY_CMAKE_VERSION "3.21") + +# These should be updated together with the documentation in +# qtdoc/doc/src/platforms/supported-platforms.qdocinc +set(QT_SUPPORTED_MIN_MACOS_SDK_VERSION "13") +set(QT_SUPPORTED_MAX_MACOS_SDK_VERSION "14") +set(QT_SUPPORTED_MIN_MACOS_XCODE_VERSION "14") + +set(QT_SUPPORTED_MIN_IOS_SDK_VERSION "16") +set(QT_SUPPORTED_MAX_IOS_SDK_VERSION "17") +set(QT_SUPPORTED_MIN_IOS_XCODE_VERSION "14") diff --git a/cmake/QtAutoDetectHelpers.cmake b/cmake/QtAutoDetectHelpers.cmake index 7a56b627278..095a8d06bfa 100644 --- a/cmake/QtAutoDetectHelpers.cmake +++ b/cmake/QtAutoDetectHelpers.cmake @@ -282,38 +282,6 @@ function(qt_auto_detect_cyclic_toolchain) endif() endfunction() -function(qt_internal_get_darwin_sdk_version out_var) - if(APPLE) - if(CMAKE_SYSTEM_NAME STREQUAL iOS) - set(sdk_name "iphoneos") - else() - # Default to macOS - set(sdk_name "macosx") - endif() - set(xcrun_version_arg "--show-sdk-version") - execute_process(COMMAND /usr/bin/xcrun --sdk ${sdk_name} ${xcrun_version_arg} - OUTPUT_VARIABLE sdk_version - ERROR_VARIABLE xcrun_error) - if(NOT sdk_version) - message(FATAL_ERROR - "Can't determine darwin ${sdk_name} SDK version. Error: ${xcrun_error}") - endif() - string(STRIP "${sdk_version}" sdk_version) - set(${out_var} "${sdk_version}" PARENT_SCOPE) - endif() -endfunction() - -function(qt_internal_get_xcode_version out_var) - if(APPLE) - execute_process(COMMAND /usr/bin/xcrun xcodebuild -version - OUTPUT_VARIABLE xcode_version - ERROR_VARIABLE xcrun_error) - string(REPLACE "\n" " " xcode_version "${xcode_version}") - string(STRIP "${xcode_version}" xcode_version) - set(${out_var} "${xcode_version}" PARENT_SCOPE) - endif() -endfunction() - function(qt_auto_detect_darwin) if(APPLE) # If no CMAKE_OSX_DEPLOYMENT_TARGET is provided, default to a value that Qt defines. @@ -334,11 +302,11 @@ function(qt_auto_detect_darwin) endif() endif() - qt_internal_get_darwin_sdk_version(darwin_sdk_version) - set(QT_MAC_SDK_VERSION "${darwin_sdk_version}" CACHE STRING "Darwin SDK version.") + _qt_internal_get_apple_sdk_version(apple_sdk_version) + set(QT_MAC_SDK_VERSION "${apple_sdk_version}" CACHE STRING "Darwin SDK version.") - qt_internal_get_xcode_version(xcode_version) - set(QT_MAC_XCODE_VERSION "${xcode_version}" CACHE STRING "Xcode version.") + _qt_internal_get_xcode_version_raw(xcode_version_raw) + set(QT_MAC_XCODE_VERSION "${xcode_version_raw}" CACHE STRING "Xcode version.") list(LENGTH CMAKE_OSX_ARCHITECTURES arch_count) if(NOT CMAKE_SYSTEM_NAME STREQUAL iOS AND arch_count GREATER 0) @@ -497,6 +465,7 @@ macro(qt_internal_setup_autodetect) # This needs to be here because QtAutoDetect loads before any other modules option(QT_USE_VCPKG "Enable the use of vcpkg" OFF) + include("${CMAKE_CURRENT_LIST_DIR}/QtPublicAppleHelpers.cmake") include("${CMAKE_CURRENT_LIST_DIR}/QtPublicWasmToolchainHelpers.cmake") # Let CMake load our custom platform modules. diff --git a/cmake/QtBaseGlobalTargets.cmake b/cmake/QtBaseGlobalTargets.cmake index 032f3f7b307..9a18cdd8a2b 100644 --- a/cmake/QtBaseGlobalTargets.cmake +++ b/cmake/QtBaseGlobalTargets.cmake @@ -183,6 +183,8 @@ configure_package_config_file( INSTALL_DESTINATION "${__GlobalConfig_install_dir}" ) +_qt_internal_export_apple_sdk_and_xcode_version_requirements(QT_CONFIG_EXTRAS_CODE) + configure_file( "${PROJECT_SOURCE_DIR}/cmake/QtConfigExtras.cmake.in" "${__GlobalConfig_build_dir}/${INSTALL_CMAKE_NAMESPACE}ConfigExtras.cmake" diff --git a/cmake/QtBuildHelpers.cmake b/cmake/QtBuildHelpers.cmake index bc5854cd3cd..327c0a536e4 100644 --- a/cmake/QtBuildHelpers.cmake +++ b/cmake/QtBuildHelpers.cmake @@ -416,6 +416,7 @@ macro(qt_internal_setup_build_and_global_variables) qt_internal_setup_platform_definitions_and_mkspec() qt_internal_check_macos_host_version() + _qt_internal_check_apple_sdk_and_xcode_versions() qt_internal_check_host_path_set_for_cross_compiling() qt_internal_setup_android_platform_specifics() qt_internal_setup_find_host_info_package() diff --git a/cmake/QtConfigExtras.cmake.in b/cmake/QtConfigExtras.cmake.in index bde3460cdcb..59010626ad9 100644 --- a/cmake/QtConfigExtras.cmake.in +++ b/cmake/QtConfigExtras.cmake.in @@ -1,2 +1,4 @@ set(QT_SUPPORTED_MIN_CMAKE_VERSION_FOR_USING_QT "@supported_min_version_for_using_qt@") set(QT_COMPUTED_MIN_CMAKE_VERSION_FOR_USING_QT "@computed_min_version_for_using_qt@") + +@QT_CONFIG_EXTRAS_CODE@ diff --git a/cmake/QtPublicAppleHelpers.cmake b/cmake/QtPublicAppleHelpers.cmake index fff797b689e..d04f57c0b67 100644 --- a/cmake/QtPublicAppleHelpers.cmake +++ b/cmake/QtPublicAppleHelpers.cmake @@ -669,6 +669,182 @@ function(_qt_internal_set_ios_simulator_arch target) "x86_64") endfunction() +# Export Apple platform sdk and xcode version requirements to Qt6ConfigExtras.cmake. +function(_qt_internal_export_apple_sdk_and_xcode_version_requirements out_var) + if(NOT APPLE) + return() + endif() + + if(IOS) + set(vars_to_assign + QT_SUPPORTED_MIN_IOS_SDK_VERSION + QT_SUPPORTED_MAX_IOS_SDK_VERSION + QT_SUPPORTED_MIN_IOS_XCODE_VERSION + ) + else() + set(vars_to_assign + QT_SUPPORTED_MIN_MACOS_SDK_VERSION + QT_SUPPORTED_MAX_MACOS_SDK_VERSION + QT_SUPPORTED_MIN_MACOS_XCODE_VERSION + ) + endif() + + set(assignments "") + foreach(var IN LISTS vars_to_assign) + set(value "${${var}}") + list(APPEND assignments "set(${var} \"${value}\")") + endforeach() + + list(JOIN assignments "\n" assignments) + set(${out_var} "${assignments}" PARENT_SCOPE) +endfunction() + +function(_qt_internal_get_apple_sdk_version out_var) + if(APPLE) + if(CMAKE_SYSTEM_NAME STREQUAL iOS) + set(sdk_name "iphoneos") + else() + # Default to macOS + set(sdk_name "macosx") + endif() + set(xcrun_version_arg "--show-sdk-version") + execute_process(COMMAND /usr/bin/xcrun --sdk ${sdk_name} ${xcrun_version_arg} + OUTPUT_VARIABLE sdk_version + ERROR_VARIABLE xcrun_error) + if(NOT sdk_version) + message(FATAL_ERROR + "Can't determine darwin ${sdk_name} SDK version. Error: ${xcrun_error}") + endif() + string(STRIP "${sdk_version}" sdk_version) + set(${out_var} "${sdk_version}" PARENT_SCOPE) + endif() +endfunction() + +function(_qt_internal_get_xcode_version_raw out_var) + if(APPLE) + execute_process(COMMAND /usr/bin/xcrun xcodebuild -version + OUTPUT_VARIABLE xcode_version + ERROR_VARIABLE xcrun_error) + string(REPLACE "\n" " " xcode_version "${xcode_version}") + string(STRIP "${xcode_version}" xcode_version) + set(${out_var} "${xcode_version}" PARENT_SCOPE) + endif() +endfunction() + +function(_qt_internal_get_xcode_version out_var) + if(APPLE) + _qt_internal_get_xcode_version_raw(xcode_version_raw) + + # The raw output is something like after the newlines are replaced with spaces: + # Xcode 14.3 Build version 14E222b + # We want only the '14.3' part. We could be more specific with the regex to match only + # digits separated by dots, but you never know how Apple might change the format. + string(REGEX REPLACE "Xcode (([^ ])+)" "\\2" xcode_version "${xcode_version_raw}") + if(xcode_version_raw MATCHES "Xcode ([^ ]+)") + set(xcode_version "${CMAKE_MATCH_1}") + else() + message(DEBUG "Failed to extract Xcode version from '${xcode_version_raw}'") + set(xcode_version "${xcode_version_raw}") + endif() + + set(${out_var} "${xcode_version}" PARENT_SCOPE) + endif() +endfunction() + +function(_qt_internal_get_cached_apple_sdk_version out_var) + if(QT_INTERNAL_APPLE_SDK_VERSION) + set(sdk_version "${QT_INTERNAL_APPLE_SDK_VERSION}") + else() + _qt_internal_get_apple_sdk_version(sdk_version) + set(QT_INTERNAL_APPLE_SDK_VERSION "${sdk_version}" CACHE STRING "Apple SDK version") + endif() + + set(${out_var} "${sdk_version}" PARENT_SCOPE) +endfunction() + +function(_qt_internal_get_cached_xcode_version out_var) + if(QT_INTERNAL_XCODE_VERSION) + set(xcode_version "${QT_INTERNAL_XCODE_VERSION}") + else() + _qt_internal_get_xcode_version(xcode_version) + set(QT_INTERNAL_XCODE_VERSION "${xcode_version}" CACHE STRING "Xcode version") + endif() + + set(${out_var} "${xcode_version}" PARENT_SCOPE) +endfunction() + +# Warn when the platform SDK or Xcode version are not supported. +# +# The warnings are currently only shown when building Qt, not when building user projects +# with CMake. +# The warnings ARE shown for qmake user projects. +# +# The qmake equivalent for user projects is in mkspecs/features/mac/default_post.prf. +function(_qt_internal_check_apple_sdk_and_xcode_versions) + if(QT_NO_APPLE_SDK_AND_XCODE_CHECK) + return() + endif() + + # Only show the warnings once in a top-level build. + get_property(warnings_shown GLOBAL PROPERTY _qt_internal_apple_sdk_and_xcode_warnings_shown) + if(warnings_shown) + return() + endif() + set_property(GLOBAL PROPERTY _qt_internal_apple_sdk_and_xcode_warnings_shown "TRUE") + + # Allow upgrading the warning into an error. + if(QT_FORCE_FATAL_APPLE_SDK_AND_XCODE_CHECK) + set(message_type FATAL_ERROR) + else() + set(message_type WARNING) + endif() + + if(IOS) + set(min_sdk_version "${QT_SUPPORTED_MIN_IOS_SDK_VERSION}") + set(max_sdk_version "${QT_SUPPORTED_MAX_IOS_SDK_VERSION}") + set(min_xcode_version "${QT_SUPPORTED_MIN_IOS_XCODE_VERSION}") + else() + set(min_sdk_version "${QT_SUPPORTED_MIN_MACOS_SDK_VERSION}") + set(max_sdk_version "${QT_SUPPORTED_MAX_MACOS_SDK_VERSION}") + set(min_xcode_version "${QT_SUPPORTED_MIN_MACOS_XCODE_VERSION}") + endif() + + _qt_internal_get_cached_apple_sdk_version(sdk_version) + _qt_internal_get_cached_xcode_version(xcode_version) + + if(sdk_version VERSION_LESS min_sdk_version AND NOT QT_NO_APPLE_SDK_MIN_VERSION_CHECK) + message(${message_type} + "Qt requires at least version ${min_sdk_version} of the platform SDK, " + "you're building against version ${sdk_version}. Please upgrade." + ) + endif() + + if(xcode_version VERSION_LESS min_xcode_version AND NOT QT_NO_XCODE_MIN_VERSION_CHECK) + message(${message_type} + "Qt requires at least version ${min_xcode_version} of Xcode, " + "you're building against version ${xcode_version}. Please upgrade." + ) + endif() + + if(QT_NO_APPLE_SDK_MAX_VERSION_CHECK) + return() + endif() + + if(sdk_version VERSION_GREATER_EQUAL max_sdk_version) + message(${message_type} + "Qt has only been tested with version ${max_sdk_version} " + "of the platform SDK, you're using ${sdk_version}. " + "This is an unsupported configuration. You may experience build issues, " + "and by using " + "the ${sdk_version} SDK you are opting in to new features " + "that Qt has not been prepared for. " + "Please downgrade the SDK you use to build your app to version " + "${max_sdk_version}, or configure " + "with -DQT_NO_APPLE_SDK_MAX_VERSION_CHECK=ON to silence this warning." + ) + endif() +endfunction() + function(_qt_internal_finalize_apple_app target) # Shared between macOS and iOS apps diff --git a/mkspecs/features/mac/default_post.prf b/mkspecs/features/mac/default_post.prf index f364716717c..0b64a586b93 100644 --- a/mkspecs/features/mac/default_post.prf +++ b/mkspecs/features/mac/default_post.prf @@ -17,6 +17,7 @@ contains(TEMPLATE, .*app) { } # Detect incompatible SDK versions + # The CMake equivalent is in cmake/QtPublicAppleHelpers.cmake. isEmpty(QT_MAC_SDK_VERSION_MIN): \ QT_MAC_SDK_VERSION_MIN = $$QT_MAC_SDK_VERSION