diff options
Diffstat (limited to 'cmake')
36 files changed, 1232 insertions, 435 deletions
diff --git a/cmake/3rdparty/extra-cmake-modules/find-modules/FindWaylandScanner.cmake b/cmake/3rdparty/extra-cmake-modules/find-modules/FindWaylandScanner.cmake index 13291afcda..60adaf4184 100644 --- a/cmake/3rdparty/extra-cmake-modules/find-modules/FindWaylandScanner.cmake +++ b/cmake/3rdparty/extra-cmake-modules/find-modules/FindWaylandScanner.cmake @@ -107,9 +107,6 @@ set_package_properties(WaylandScanner PROPERTIES DESCRIPTION "Executable that converts XML protocol files to C code" ) - -include(CMakeParseArguments) - function(ecm_add_wayland_client_protocol out_var) # Parse arguments set(oneValueArgs PROTOCOL BASENAME) diff --git a/cmake/3rdparty/extra-cmake-modules/modules/ECMFindModuleHelpers.cmake b/cmake/3rdparty/extra-cmake-modules/modules/ECMFindModuleHelpers.cmake index 841453998a..a5dabb1074 100644 --- a/cmake/3rdparty/extra-cmake-modules/modules/ECMFindModuleHelpers.cmake +++ b/cmake/3rdparty/extra-cmake-modules/modules/ECMFindModuleHelpers.cmake @@ -123,8 +123,6 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -include(CMakeParseArguments) - macro(ecm_find_package_version_check module_name) if(CMAKE_VERSION VERSION_LESS 2.8.12) message(FATAL_ERROR "CMake 2.8.12 is required by Find${module_name}.cmake") diff --git a/cmake/FindCups.cmake b/cmake/FindCups.cmake deleted file mode 100644 index 7a78100aae..0000000000 --- a/cmake/FindCups.cmake +++ /dev/null @@ -1,98 +0,0 @@ -# Distributed under the OSI-approved BSD 3-Clause License. See accompanying -# file Copyright.txt or https://cmake.org/licensing for details. - -#[=======================================================================[.rst: -FindCups --------- - -Find the CUPS printing system. - -Set CUPS_REQUIRE_IPP_DELETE_ATTRIBUTE to TRUE if you need a version which -features this function (i.e. at least 1.1.19) - -Imported targets -^^^^^^^^^^^^^^^^ - -This module defines :prop_tgt:`IMPORTED` target ``Cups::Cups``, if Cups has -been found. - -Result variables -^^^^^^^^^^^^^^^^ - -This module will set the following variables in your project: - -``CUPS_FOUND`` - true if CUPS headers and libraries were found -``CUPS_INCLUDE_DIRS`` - the directory containing the Cups headers -``CUPS_LIBRARIES`` - the libraries to link against to use CUPS. -``CUPS_VERSION_STRING`` - the version of CUPS found (since CMake 2.8.8) - -Cache variables -^^^^^^^^^^^^^^^ - -The following cache variables may also be set: - -``CUPS_INCLUDE_DIR`` - the directory containing the Cups headers -#]=======================================================================] - -find_path(CUPS_INCLUDE_DIR cups/cups.h ) - -find_library(CUPS_LIBRARIES NAMES cups ) - -if (CUPS_INCLUDE_DIR AND CUPS_LIBRARIES AND CUPS_REQUIRE_IPP_DELETE_ATTRIBUTE) - include(${CMAKE_CURRENT_LIST_DIR}/CheckLibraryExists.cmake) - include(${CMAKE_CURRENT_LIST_DIR}/CMakePushCheckState.cmake) - cmake_push_check_state() - set(CMAKE_REQUIRED_QUIET ${Cups_FIND_QUIETLY}) - - # ippDeleteAttribute is new in cups-1.1.19 (and used by kdeprint) - CHECK_LIBRARY_EXISTS(cups ippDeleteAttribute "" CUPS_HAS_IPP_DELETE_ATTRIBUTE) - cmake_pop_check_state() -endif () - -if (CUPS_INCLUDE_DIR AND EXISTS "${CUPS_INCLUDE_DIR}/cups/cups.h") - file(STRINGS "${CUPS_INCLUDE_DIR}/cups/cups.h" cups_version_str - REGEX "^#[\t ]*define[\t ]+CUPS_VERSION_(MAJOR|MINOR|PATCH)[\t ]+[0-9]+$") - - unset(CUPS_VERSION_STRING) - foreach(VPART MAJOR MINOR PATCH) - foreach(VLINE ${cups_version_str}) - if(VLINE MATCHES "^#[\t ]*define[\t ]+CUPS_VERSION_${VPART}[\t ]+([0-9]+)$") - set(CUPS_VERSION_PART "${CMAKE_MATCH_1}") - if(CUPS_VERSION_STRING) - string(APPEND CUPS_VERSION_STRING ".${CUPS_VERSION_PART}") - else() - set(CUPS_VERSION_STRING "${CUPS_VERSION_PART}") - endif() - endif() - endforeach() - endforeach() -endif () - -include(FindPackageHandleStandardArgs) - -if (CUPS_REQUIRE_IPP_DELETE_ATTRIBUTE) - FIND_PACKAGE_HANDLE_STANDARD_ARGS(Cups - REQUIRED_VARS CUPS_LIBRARIES CUPS_INCLUDE_DIR CUPS_HAS_IPP_DELETE_ATTRIBUTE - VERSION_VAR CUPS_VERSION_STRING) -else () - FIND_PACKAGE_HANDLE_STANDARD_ARGS(Cups - REQUIRED_VARS CUPS_LIBRARIES CUPS_INCLUDE_DIR - VERSION_VAR CUPS_VERSION_STRING) -endif () - -mark_as_advanced(CUPS_INCLUDE_DIR CUPS_LIBRARIES) - -if (CUPS_FOUND) - set(CUPS_INCLUDE_DIRS "${CUPS_INCLUDE_DIR}") - if (NOT TARGET Cups::Cups) - add_library(Cups::Cups INTERFACE IMPORTED) - set_target_properties(Cups::Cups PROPERTIES - INTERFACE_LINK_LIBRARIES "${CUPS_LIBRARIES}" - INTERFACE_INCLUDE_DIRECTORIES "${CUPS_INCLUDE_DIR}") - endif () -endif () diff --git a/cmake/FindMySQL.cmake b/cmake/FindMySQL.cmake index a069a5eb12..f5cad361d7 100644 --- a/cmake/FindMySQL.cmake +++ b/cmake/FindMySQL.cmake @@ -3,7 +3,25 @@ # --------- # # Try to locate the mysql client library. -# If found, this will define the following variables: +# +# By default, pkg-config is used, if available. +# If pkg-config is not available or if you want to disable it, set the ``MySQL_ROOT`` variable. +# The following variables can be set to control the behavior of this find module. +# +# ``MySQL_ROOT`` +# The root directory of the mysql client library's installation. +# ``MySQL_INCLUDE_DIR`` +# The directory containing the include files of the mysql client library. +# If not set, the directory is detected within ``MySQL_ROOT`` using find_path. +# ``MySQL_LIBRARY_DIR`` +# The directory containing the binaries of the mysql client library. +# This is used to detect ``MySQL_LIBRARY`` and passed as HINT to find_library. +# ``MySQL_LIBRARY`` +# The file path to the mysql client library. +# ``MySQL_LIBRARY_DEBUG`` +# The file path to the mysql client library for the DEBUG configuration. +# +# If the mysql client library is found, this will define the following variables: # # ``MySQL_FOUND`` # True if the mysql library is available @@ -18,17 +36,39 @@ # ``MySQL::MySQL`` # The mysql client library -find_package(PkgConfig QUIET) -pkg_check_modules(PC_MySQL QUIET mysqlclient) +if(NOT DEFINED MySQL_ROOT) + find_package(PkgConfig QUIET) +endif() +if(PkgConfig_FOUND AND NOT DEFINED MySQL_ROOT) + pkg_check_modules(PC_MySQL QUIET mysqlclient) + set(MySQL_include_dir_hints ${PC_MySQL_INCLUDEDIR}) + set(MySQL_library_hints ${PC_MySQL_LIBDIR}) + set(MySQL_library_hints_debug "") +else() + set(MySQL_include_dir_hints "") + if(NOT DEFINED MySQL_LIBRARY_DIR) + set(MySQL_LIBRARY_DIR "${MySQL_ROOT}/lib") + endif() + set(MySQL_library_hints "${MySQL_LIBRARY_DIR}") + set(MySQL_library_hints_debug "${MySQL_LIBRARY_DIR}/debug") +endif() find_path(MySQL_INCLUDE_DIR NAMES mysql.h - HINTS ${PC_MySQL_INCLUDEDIR} + HINTS "${MySQL_include_dir_hints}" PATH_SUFFIXES mysql mariadb) find_library(MySQL_LIBRARY + NO_PACKAGE_ROOT_PATH NAMES libmysql mysql mysqlclient libmariadb mariadb - HINTS ${PC_MySQL_LIBDIR}) + HINTS ${MySQL_library_hints}) + +if(MySQL_library_hints_debug) + find_library(MySQL_LIBRARY_DEBUG + NO_PACKAGE_ROOT_PATH + NAMES libmysql mysql mysqlclient libmariadb mariadb + HINTS ${MySQL_library_hints_debug}) +endif() include(FindPackageHandleStandardArgs) find_package_handle_standard_args(MySQL DEFAULT_MSG MySQL_LIBRARY MySQL_INCLUDE_DIR) @@ -41,6 +81,10 @@ if(MySQL_FOUND) set_target_properties(MySQL::MySQL PROPERTIES IMPORTED_LOCATION "${MySQL_LIBRARIES}" INTERFACE_INCLUDE_DIRECTORIES "${MySQL_INCLUDE_DIRS}") + if(MySQL_LIBRARY_DEBUG) + set_target_properties(MySQL::MySQL PROPERTIES + IMPORTED_LOCATION_DEBUG "${MySQL_LIBRARY_DEBUG}") + endif() endif() endif() diff --git a/cmake/FindPPS.cmake b/cmake/FindPPS.cmake index fdcc87fa37..c1499f2241 100644 --- a/cmake/FindPPS.cmake +++ b/cmake/FindPPS.cmake @@ -16,8 +16,8 @@ mark_as_advanced(PPS_INCLUDE_DIR PPS_LIBRARY) if(PPS_FOUND) add_library(__PPS INTERFACE IMPORTED) - target_link_libraries(__PPS INTERFACE ${PPS_LIBRARY}) - target_include_directories(__PPS INTERFACE ${PPS_INCLUDE_DIR}) + target_link_libraries(__PPS INTERFACE "${PPS_LIBRARY}") + target_include_directories(__PPS INTERFACE "${PPS_INCLUDE_DIR}") add_library(PPS::PPS ALIAS __PPS) endif() diff --git a/cmake/FindWrapSystemDoubleConversion.cmake b/cmake/FindWrapSystemDoubleConversion.cmake index 164e79ed54..0d00a0c644 100644 --- a/cmake/FindWrapSystemDoubleConversion.cmake +++ b/cmake/FindWrapSystemDoubleConversion.cmake @@ -28,14 +28,19 @@ if(NOT __double_conversion_found) find_path(DOUBLE_CONVERSION_INCLUDE_DIR NAMES - double-conversion.h - PATH_SUFFIXES - double-conversion + double-conversion/double-conversion.h ) - find_library(DOUBLE_CONVERSION_LIBRARY NAMES double-conversion) + + find_library(DOUBLE_CONVERSION_LIBRARY_RELEASE NAMES double-conversion) + + # We assume a possible debug build of this library to be named with a d suffix. + # Adjust accordingly if a different naming scheme is established. + find_library(DOUBLE_CONVERSION_LIBRARY_DEBUG NAMES double-conversiond) + include(SelectLibraryConfigurations) select_library_configurations(DOUBLE_CONVERSION) mark_as_advanced(DOUBLE_CONVERSION_INCLUDE_DIR DOUBLE_CONVERSION_LIBRARY) + set(DOUBLE_CONVERSION_INCLUDE_DIRS "${DOUBLE_CONVERSION_INCLUDE_DIR}") if(DOUBLE_CONVERSION_LIBRARIES AND DOUBLE_CONVERSION_INCLUDE_DIRS) set(__double_conversion_found TRUE) diff --git a/cmake/QtAndroidHelpers.cmake b/cmake/QtAndroidHelpers.cmake index 49c384f698..157a78ee84 100644 --- a/cmake/QtAndroidHelpers.cmake +++ b/cmake/QtAndroidHelpers.cmake @@ -127,8 +127,9 @@ function(qt_internal_android_dependencies_content target file_content_out) if (init_class) set(init_class "initClass=\"${init_class}\"") endif() - file(TO_NATIVE_PATH ${jar_file} jar_file_native) - string(APPEND file_contents "<jar file=\"${jar_file_native}\" ${init_class} />\n") + # Use unix path to allow using files on any host platform. + file(TO_CMAKE_PATH ${jar_file} jar_file_unix_path) + string(APPEND file_contents "<jar file=\"${jar_file_unix_path}\" ${init_class} />\n") endforeach() endif() @@ -139,8 +140,10 @@ function(qt_internal_android_dependencies_content target file_content_out) if (init_class) set(init_class "initClass=\"${init_class}\"") endif() - file(TO_NATIVE_PATH ${bundle_file} jar_bundle_native) - string(APPEND file_contents "<jar bundling=\"1\" file=\"${jar_bundle_native}\" ${init_class} />\n") + # Use unix path to allow using files on any host platform. + file(TO_CMAKE_PATH ${bundle_file} jar_bundle_unix_path) + string(APPEND file_contents + "<jar bundling=\"1\" file=\"${jar_bundle_unix_path}\" ${init_class} />\n") endforeach() endif() @@ -152,8 +155,9 @@ function(qt_internal_android_dependencies_content target file_content_out) if (lib_extends) set(lib_extends "extends=\"${lib_extends}\"") endif() - file(TO_NATIVE_PATH ${lib_file} lib_file_native) - string(APPEND file_contents "<lib file=\"${lib_file_native}\" ${lib_extends} />\n") + # Use unix path to allow using files on any host platform. + file(TO_CMAKE_PATH ${lib_file} lib_file_unix_path) + string(APPEND file_contents "<lib file=\"${lib_file_unix_path}\" ${lib_extends} />\n") endforeach() endif() @@ -163,19 +167,23 @@ function(qt_internal_android_dependencies_content target file_content_out) string(REPLACE ".so" "_${CMAKE_ANDROID_ARCH_ABI}.so" lib ${lib}) 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}\"") + # Use unix path to allow using files on any host platform. + file(TO_CMAKE_PATH ${lib_replacement} lib_replacement_unix_path) + set(lib_replacement "replaces=\"${lib_replacement_unix_path}\"") endif() - file(TO_NATIVE_PATH ${lib_file} lib_file_native) - string(APPEND file_contents "<lib file=\"${lib_file_native}\" ${lib_replacement} />\n") + # Use unix path to allow using files on any host platform. + file(TO_CMAKE_PATH ${lib_file} lib_file_unix_path) + string(APPEND file_contents + "<lib file=\"${lib_file_unix_path}\" ${lib_replacement} />\n") endforeach() endif() # Bundled files if(arg_BUNDLED_FILES) foreach(bundled_file IN LISTS arg_BUNDLED_FILES) - file(TO_NATIVE_PATH ${bundled_file} file_native) - string(APPEND file_contents "<bundled file=\"${file_native}\" />\n") + # Use unix path to allow using files on any host platform. + file(TO_CMAKE_PATH ${bundled_file} file_unix_path) + string(APPEND file_contents "<bundled file=\"${file_unix_path}\" />\n") endforeach() endif() diff --git a/cmake/QtAppHelpers.cmake b/cmake/QtAppHelpers.cmake index 32614f492f..e80f13cd17 100644 --- a/cmake/QtAppHelpers.cmake +++ b/cmake/QtAppHelpers.cmake @@ -75,7 +75,7 @@ function(qt_internal_get_title_case value out_var) endif() string(SUBSTRING "${value}" 0 1 first_char) string(TOUPPER "${first_char}" first_char_upper) - string(SUBSTRING "${target}" 1 -1 rest_of_value) + string(SUBSTRING "${value}" 1 -1 rest_of_value) set(title_value "${first_char_upper}${rest_of_value}") set(${out_var} "${title_value}" PARENT_SCOPE) endfunction() diff --git a/cmake/QtAutoDetect.cmake b/cmake/QtAutoDetect.cmake index 3731707f88..21c49cb64a 100644 --- a/cmake/QtAutoDetect.cmake +++ b/cmake/QtAutoDetect.cmake @@ -182,9 +182,7 @@ function(qt_auto_detect_vcpkg) endfunction() function(qt_auto_detect_ios) - if(CMAKE_SYSTEM_NAME STREQUAL iOS - OR CMAKE_SYSTEM_NAME STREQUAL watchOS - OR CMAKE_SYSTEM_NAME STREQUAL tvOS) + if(CMAKE_SYSTEM_NAME STREQUAL iOS) message(STATUS "Using internal CMake ${CMAKE_SYSTEM_NAME} toolchain file.") # The QT_UIKIT_SDK check simulates the input.sdk condition for simulator_and_device in @@ -201,55 +199,21 @@ function(qt_auto_detect_ios) message(STATUS "simulator_and_device set to: \"${simulator_and_device}\".") # Choose relevant architectures. - # Using a non xcode generator requires explicit setting of the + # Using a non Xcode generator requires explicit setting of the # architectures, otherwise compilation fails with unknown defines. - if(CMAKE_SYSTEM_NAME STREQUAL iOS) - if(simulator_and_device) - set(osx_architectures "arm64;x86_64") - elseif(QT_UIKIT_SDK STREQUAL "iphoneos") - set(osx_architectures "arm64") - elseif(QT_UIKIT_SDK STREQUAL "iphonesimulator") - set(osx_architectures "x86_64") - else() - if(NOT DEFINED QT_UIKIT_SDK) - message(FATAL_ERROR "Please proviude a value for -DQT_UIKIT_SDK." - " Possible values: iphoneos, iphonesimulator.") - else() - message(FATAL_ERROR - "Unknown SDK argument given to QT_UIKIT_SDK: ${QT_UIKIT_SDK}.") - endif() - endif() - elseif(CMAKE_SYSTEM_NAME STREQUAL tvOS) - if(simulator_and_device) - set(osx_architectures "arm64;x86_64") - elseif(QT_UIKIT_SDK STREQUAL "appletvos") - set(osx_architectures "arm64") - elseif(QT_UIKIT_SDK STREQUAL "appletvsimulator") - set(osx_architectures "x86_64") - else() - if(NOT DEFINED QT_UIKIT_SDK) - message(FATAL_ERROR "Please proviude a value for -DQT_UIKIT_SDK." - " Possible values: appletvos, appletvsimulator.") - else() - message(FATAL_ERROR - "Unknown SDK argument given to QT_UIKIT_SDK: ${QT_UIKIT_SDK}.") - endif() - endif() - elseif(CMAKE_SYSTEM_NAME STREQUAL watchOS) - if(simulator_and_device) - set(osx_architectures "armv7k;i386") - elseif(QT_UIKIT_SDK STREQUAL "watchos") - set(osx_architectures "armv7k") - elseif(QT_UIKIT_SDK STREQUAL "watchsimulator") - set(osx_architectures "i386") + if(simulator_and_device) + set(osx_architectures "arm64;x86_64") + elseif(QT_UIKIT_SDK STREQUAL "iphoneos") + set(osx_architectures "arm64") + elseif(QT_UIKIT_SDK STREQUAL "iphonesimulator") + set(osx_architectures "x86_64") + else() + if(NOT DEFINED QT_UIKIT_SDK) + message(FATAL_ERROR "Please provide a value for -DQT_UIKIT_SDK." + " Possible values: iphoneos, iphonesimulator.") else() - if(NOT DEFINED QT_UIKIT_SDK) - message(FATAL_ERROR "Please proviude a value for -DQT_UIKIT_SDK." - " Possible values: watchos, watchsimulator.") - else() - message(FATAL_ERROR - "Unknown SDK argument given to QT_UIKIT_SDK: ${QT_UIKIT_SDK}.") - endif() + message(FATAL_ERROR + "Unknown SDK argument given to QT_UIKIT_SDK: ${QT_UIKIT_SDK}.") endif() endif() @@ -305,12 +269,8 @@ endfunction() function(qt_internal_get_darwin_sdk_version out_var) if(APPLE) - if(IOS) + if(CMAKE_SYSTEM_NAME STREQUAL iOS) set(sdk_name "iphoneos") - elseif(TVOS) - set(sdk_name "appletvos") - elseif(WATCHOS) - set(sdk_name "watchos") else() # Default to macOS set(sdk_name "macosx") @@ -352,10 +312,6 @@ function(qt_auto_detect_darwin) set(version "10.14") elseif(CMAKE_SYSTEM_NAME STREQUAL iOS) set(version "13.0") - elseif(CMAKE_SYSTEM_NAME STREQUAL watchOS) - set(version "6.0") - elseif(CMAKE_SYSTEM_NAME STREQUAL tvOS) - set(version "13.0") endif() if(version) set(CMAKE_OSX_DEPLOYMENT_TARGET "${version}" CACHE STRING "${description}") @@ -368,9 +324,8 @@ function(qt_auto_detect_darwin) qt_internal_get_xcode_version(xcode_version) set(QT_MAC_XCODE_VERSION "${xcode_version}" CACHE STRING "Xcode version.") - set(device_names "iOS" "watchOS" "tvOS") list(LENGTH CMAKE_OSX_ARCHITECTURES arch_count) - if(NOT CMAKE_SYSTEM_NAME IN_LIST device_names AND arch_count GREATER 0) + if(NOT CMAKE_SYSTEM_NAME STREQUAL iOS AND arch_count GREATER 0) foreach(arch ${CMAKE_OSX_ARCHITECTURES}) if(arch STREQUAL "arm64e") message(WARNING "Applications built against an arm64e Qt architecture will " @@ -383,8 +338,7 @@ function(qt_auto_detect_darwin) endfunction() function(qt_auto_detect_macos_universal) - set(device_names "iOS" "watchOS" "tvOS") - if(APPLE AND NOT CMAKE_SYSTEM_NAME IN_LIST device_names) + if(APPLE AND NOT CMAKE_SYSTEM_NAME STREQUAL iOS) list(LENGTH CMAKE_OSX_ARCHITECTURES arch_count) set(is_universal "OFF") diff --git a/cmake/QtBaseGlobalTargets.cmake b/cmake/QtBaseGlobalTargets.cmake index fef43a53e9..59960441e4 100644 --- a/cmake/QtBaseGlobalTargets.cmake +++ b/cmake/QtBaseGlobalTargets.cmake @@ -322,11 +322,13 @@ set(__public_cmake_helpers cmake/QtCopyFileIfDifferent.cmake cmake/QtFeature.cmake cmake/QtFeatureCommon.cmake + cmake/QtPublicAppleHelpers.cmake cmake/QtPublicCMakeHelpers.cmake cmake/QtPublicCMakeVersionHelpers.cmake cmake/QtPublicFinalizerHelpers.cmake cmake/QtPublicPluginHelpers.cmake cmake/QtPublicTargetHelpers.cmake + cmake/QtPublicTestHelpers.cmake cmake/QtPublicToolHelpers.cmake cmake/QtPublicWalkLibsHelpers.cmake cmake/QtPublicFindPackageHelpers.cmake diff --git a/cmake/QtBuild.cmake b/cmake/QtBuild.cmake index 4b7cc643bb..44b888f5aa 100644 --- a/cmake/QtBuild.cmake +++ b/cmake/QtBuild.cmake @@ -263,28 +263,11 @@ function(qt_setup_tool_path_command) list(APPEND command COMMAND) list(APPEND command set PATH=${bindir}$<SEMICOLON>%PATH%) set(QT_TOOL_PATH_SETUP_COMMAND "${command}" CACHE INTERNAL "internal command prefix for tool invocations" FORCE) - # QT_TOOL_PATH_SETUP_COMMAND is deprecated. Please use _qt_internal_wrap_tool_command + # QT_TOOL_PATH_SETUP_COMMAND is deprecated. Please use _qt_internal_get_wrap_tool_script_path # instead. endfunction() qt_setup_tool_path_command() -function(qt_internal_generate_tool_command_wrapper) - get_property(is_called GLOBAL PROPERTY _qt_internal_generate_tool_command_wrapper_called) - if(NOT CMAKE_HOST_WIN32 OR is_called) - return() - endif() - set(bindir "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}/${INSTALL_BINDIR}") - file(TO_NATIVE_PATH "${bindir}" bindir) - set(tool_command_wrapper_path "${QT_BUILD_DIR}/${INSTALL_LIBEXECDIR}/qt_setup_tool_path.bat") - file(WRITE "${tool_command_wrapper_path}" "@echo off -set PATH=${bindir};%PATH% -%*") - set(QT_TOOL_COMMAND_WRAPPER_PATH "${tool_command_wrapper_path}" - CACHE INTERNAL "Path to the wrapper of the tool commands") - set_property(GLOBAL PROPERTY _qt_internal_generate_tool_command_wrapper_called TRUE) -endfunction() -qt_internal_generate_tool_command_wrapper() - # Platform define path, etc. if(WIN32) set(QT_DEFAULT_PLATFORM_DEFINITIONS WIN32 _ENABLE_EXTENDED_ALIGNED_STORAGE) @@ -543,13 +526,19 @@ if(ANDROID) include(QtAndroidHelpers) endif() +if(WASM) + include(QtWasmHelpers) +endif() + # Helpers that are available in public projects and while building Qt itself. +include(QtPublicAppleHelpers) include(QtPublicCMakeHelpers) include(QtPublicPluginHelpers) include(QtPublicTargetHelpers) include(QtPublicWalkLibsHelpers) include(QtPublicFindPackageHelpers) include(QtPublicDependencyHelpers) +include(QtPublicTestHelpers) include(QtPublicToolHelpers) if(CMAKE_CROSSCOMPILING) @@ -598,6 +587,11 @@ if(COMMAND _qt_internal_get_add_plugin_keywords) unset(__qt_internal_add_plugin_multi_args) endif() +# Create tool script wrapper if necessary. +# TODO: Remove once all direct usages of QT_TOOL_COMMAND_WRAPPER_PATH are replaced with function +# calls. +_qt_internal_generate_tool_command_wrapper() + # This sets up the poor man's scope finalizer mechanism. # For newer CMake versions, we use cmake_language(DEFER CALL) instead. if(CMAKE_VERSION VERSION_LESS "3.19.0") diff --git a/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake b/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake index 9731eda061..f51e4d6ab5 100644 --- a/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake +++ b/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake @@ -255,7 +255,7 @@ macro(qt_build_internals_get_repo_targets subdir) if(_targets) foreach(_target IN LISTS _targets) get_target_property(_type ${_target} TYPE) - if(NOT (${_type} STREQUAL "UTILITY" OR ${_type} STREQUAL "INTERFACE")) + if(NOT ${_type} STREQUAL "UTILITY") list(APPEND qt_repo_targets "${_target}") endif() endforeach() diff --git a/cmake/QtBuildInternals/QtStandaloneTestTemplateProject/CMakeLists.txt b/cmake/QtBuildInternals/QtStandaloneTestTemplateProject/CMakeLists.txt index 368567c708..4fd442e82c 100644 --- a/cmake/QtBuildInternals/QtStandaloneTestTemplateProject/CMakeLists.txt +++ b/cmake/QtBuildInternals/QtStandaloneTestTemplateProject/CMakeLists.txt @@ -15,5 +15,14 @@ else() set(absolute_project_path "${QT_STANDALONE_TEST_PATH}") endif() +if(NOT IS_DIRECTORY "${absolute_project_path}") + get_filename_component(filename "${absolute_project_path}" NAME) + get_filename_component(directory "${absolute_project_path}" DIRECTORY) + + if(filename STREQUAL "CMakeLists.txt") + set(absolute_project_path "${directory}") + endif() +endif() + # Add the test project path as a subdirectory project. add_subdirectory("${absolute_project_path}" "build_dir") diff --git a/cmake/QtConfig.cmake.in b/cmake/QtConfig.cmake.in index cd7fdf7c02..2e49828472 100644 --- a/cmake/QtConfig.cmake.in +++ b/cmake/QtConfig.cmake.in @@ -38,86 +38,32 @@ elseif(APPLE AND CMAKE_SYSTEM_NAME STREQUAL "iOS") list(APPEND CMAKE_MODULE_PATH "${__qt_internal_cmake_ios_support_files_path}") endif() +# Public helpers available to all Qt packages. +include("${CMAKE_CURRENT_LIST_DIR}/QtFeature.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/QtPublicAppleHelpers.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/QtPublicFinalizerHelpers.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/QtPublicPluginHelpers.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/QtPublicTargetHelpers.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/QtPublicWalkLibsHelpers.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/QtPublicFindPackageHelpers.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/QtPublicDependencyHelpers.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/QtPublicTestHelpers.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/QtPublicToolHelpers.cmake") +include("${CMAKE_CURRENT_LIST_DIR}/QtPublicCMakeHelpers.cmake") + set(QT_ADDITIONAL_PACKAGES_PREFIX_PATH "" CACHE STRING "Additional directories where find(Qt6 ...) components are searched") set(QT_ADDITIONAL_HOST_PACKAGES_PREFIX_PATH "" CACHE STRING "Additional directories where find(Qt6 ...) host Qt components are searched") -# Collect additional package prefix paths to look for Qt packages, both from command line and the -# env variable ${prefixes_var}. The result is stored in ${out_var} and is a list of paths ending -# with "/lib/cmake". -function(__qt_internal_collect_additional_prefix_paths out_var prefixes_var) - if(DEFINED "${out_var}") - return() - endif() - - set(additional_packages_prefix_paths "") - - set(additional_packages_prefixes "") - if(${prefixes_var}) - list(APPEND additional_packages_prefixes ${${prefixes_var}}) - endif() - if(DEFINED ENV{${prefixes_var}} - AND NOT "$ENV{${prefixes_var}}" STREQUAL "") - set(prefixes_from_env "$ENV{${prefixes_var}}") - if(NOT CMAKE_HOST_WIN32) - string(REPLACE ":" ";" prefixes_from_env "${prefixes_from_env}") - endif() - list(APPEND additional_packages_prefixes ${prefixes_from_env}) - endif() - - foreach(additional_path IN LISTS additional_packages_prefixes) - file(TO_CMAKE_PATH "${additional_path}" additional_path) - - # The prefix paths need to end with lib/cmake to ensure the packages are found when - # cross compiling. Search for REROOT_PATH_ISSUE_MARKER in the qt.toolchain.cmake file for - # details. - # We must pass the values via the PATHS options because the main find_package call uses - # NO_DEFAULT_PATH, and thus CMAKE_PREFIX_PATH values are discarded. - # CMAKE_FIND_ROOT_PATH values are not discarded and togegher with the PATHS option, it - # ensures packages from additional prefixes are found. - if(NOT additional_path MATCHES "/lib/cmake$") - string(APPEND additional_path "/lib/cmake") - endif() - list(APPEND additional_packages_prefix_paths "${additional_path}") - endforeach() - - set("${out_var}" "${additional_packages_prefix_paths}" PARENT_SCOPE) -endfunction() - __qt_internal_collect_additional_prefix_paths(_qt_additional_packages_prefix_paths QT_ADDITIONAL_PACKAGES_PREFIX_PATH) __qt_internal_collect_additional_prefix_paths(_qt_additional_host_packages_prefix_paths QT_ADDITIONAL_HOST_PACKAGES_PREFIX_PATH) -# Take a list of prefix paths ending with "/lib/cmake", and return a list of absolute paths with -# "/lib/cmake" removed. -function(__qt_internal_prefix_paths_to_roots out_var prefix_paths) - set(result "") - foreach(path IN LISTS prefix_paths) - if(path MATCHES "/lib/cmake$") - string(APPEND path "/../..") - endif() - get_filename_component(path "${path}" ABSOLUTE) - list(APPEND result "${path}") - endforeach() - set("${out_var}" "${result}" PARENT_SCOPE) -endfunction() - __qt_internal_prefix_paths_to_roots(_qt_additional_host_packages_root_paths "${_qt_additional_host_packages_prefix_paths}") -# Public helpers available to all Qt packages. -include("${CMAKE_CURRENT_LIST_DIR}/QtFeature.cmake") -include("${CMAKE_CURRENT_LIST_DIR}/QtPublicFinalizerHelpers.cmake") -include("${CMAKE_CURRENT_LIST_DIR}/QtPublicPluginHelpers.cmake") -include("${CMAKE_CURRENT_LIST_DIR}/QtPublicTargetHelpers.cmake") -include("${CMAKE_CURRENT_LIST_DIR}/QtPublicWalkLibsHelpers.cmake") -include("${CMAKE_CURRENT_LIST_DIR}/QtPublicFindPackageHelpers.cmake") -include("${CMAKE_CURRENT_LIST_DIR}/QtPublicDependencyHelpers.cmake") -include("${CMAKE_CURRENT_LIST_DIR}/QtPublicToolHelpers.cmake") -include("${CMAKE_CURRENT_LIST_DIR}/QtPublicCMakeHelpers.cmake") - if(NOT DEFINED QT_CMAKE_EXPORT_NAMESPACE) set(QT_CMAKE_EXPORT_NAMESPACE @QT_CMAKE_EXPORT_NAMESPACE@) endif() diff --git a/cmake/QtExecutableHelpers.cmake b/cmake/QtExecutableHelpers.cmake index 916cb4d03c..96b067d898 100644 --- a/cmake/QtExecutableHelpers.cmake +++ b/cmake/QtExecutableHelpers.cmake @@ -37,8 +37,10 @@ function(qt_internal_add_executable name) endif() if(WASM) + qt_internal_wasm_add_finalizers("${name}") _qt_internal_wasm_add_target_helpers("${name}") endif() + if (arg_VERSION) if(arg_VERSION MATCHES "[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+") # nothing to do diff --git a/cmake/QtFeature.cmake b/cmake/QtFeature.cmake index 54222b6696..5d65915fab 100644 --- a/cmake/QtFeature.cmake +++ b/cmake/QtFeature.cmake @@ -236,7 +236,7 @@ function(qt_feature_check_and_save_user_provided_value resultVar feature conditi if (DEFINED "FEATURE_${feature}") # Revisit new user provided value set(user_value "${FEATURE_${feature}}") - set(result "${user_value}") + string(TOUPPER "${user_value}" result) # If the build is marked as dirty and the user_value doesn't meet the new condition, # reset it to the computed one. @@ -921,6 +921,7 @@ function(qt_config_compile_test name) # fail instead of cmake abort later via CMAKE_REQUIRED_LIBRARIES. string(FIND "${library}" "::" cmake_target_namespace_separator) if(NOT cmake_target_namespace_separator EQUAL -1) + message(STATUS "Performing Test ${arg_LABEL} - Failed because ${library} not found") set(HAVE_${name} FALSE) break() endif() @@ -995,6 +996,7 @@ function(qt_get_platform_try_compile_vars out_var) list(APPEND flags "CMAKE_CXX_FLAGS_RELEASE") list(APPEND flags "CMAKE_CXX_FLAGS_RELWITHDEBINFO") list(APPEND flags "CMAKE_OBJCOPY") + list(APPEND flags "CMAKE_EXE_LINKER_FLAGS") # Pass toolchain files. if(CMAKE_TOOLCHAIN_FILE) diff --git a/cmake/QtInternalTargets.cmake b/cmake/QtInternalTargets.cmake index c82b932239..8adc620495 100644 --- a/cmake/QtInternalTargets.cmake +++ b/cmake/QtInternalTargets.cmake @@ -223,7 +223,6 @@ if(UIKIT) # TODO: Figure out if this ok or not (sounds ok to me). target_compile_definitions(PlatformCommonInternal INTERFACE QT_COMPILER_SUPPORTS_SSE2) endif() - qt_internal_apply_bitcode_flags(PlatformCommonInternal) endif() if(WASM AND QT_FEATURE_sse2) diff --git a/cmake/QtModuleHelpers.cmake b/cmake/QtModuleHelpers.cmake index 81c088fe23..196c6a316f 100644 --- a/cmake/QtModuleHelpers.cmake +++ b/cmake/QtModuleHelpers.cmake @@ -669,6 +669,11 @@ set(QT_VISIBILITY_AVAILABLE TRUE)") set(QT_LIBINFIX \"${QT_LIBINFIX}\")") endif() + # Store whether find_package(Qt6Foo) should succeed if Qt6FooTools is missing. + if(QT_ALLOW_MISSING_TOOLS_PACKAGES) + string(APPEND qtcore_extra_cmake_code " +set(QT_ALLOW_MISSING_TOOLS_PACKAGES TRUE)") + endif() endif() configure_file("${CMAKE_CURRENT_LIST_DIR}/${INSTALL_CMAKE_NAMESPACE}${target}ConfigExtras.cmake.in" @@ -748,9 +753,8 @@ set(QT_LIBINFIX \"${QT_LIBINFIX}\")") qt_install(DIRECTORY "${arg_EXTERNAL_HEADERS_DIR}/" DESTINATION "${module_install_interface_include_dir}" ) - unset(public_header_destination) - else() - set(public_header_destination PUBLIC_HEADER DESTINATION "${module_install_interface_include_dir}") + get_target_property(public_header_backup ${target} PUBLIC_HEADER) + set_property(TARGET ${target} PROPERTY PUBLIC_HEADER "") endif() qt_install(TARGETS ${exported_targets} @@ -760,8 +764,12 @@ set(QT_LIBINFIX \"${QT_LIBINFIX}\")") ARCHIVE DESTINATION ${INSTALL_LIBDIR} FRAMEWORK DESTINATION ${INSTALL_LIBDIR} PRIVATE_HEADER DESTINATION "${module_install_interface_private_include_dir}" - ${public_header_destination} - ) + PUBLIC_HEADER DESTINATION "${module_install_interface_include_dir}" + ) + if(arg_EXTERNAL_HEADERS_DIR) + set_property(TARGET ${target} PROPERTY PUBLIC_HEADER ${public_header_backup}) + unset(public_header_backup) + endif() if(BUILD_SHARED_LIBS) qt_apply_rpaths(TARGET "${target}" INSTALL_PATH "${INSTALL_LIBDIR}" RELATIVE_RPATH) diff --git a/cmake/QtPkgConfigHelpers.cmake b/cmake/QtPkgConfigHelpers.cmake index 21a09365f2..03d0c6e774 100644 --- a/cmake/QtPkgConfigHelpers.cmake +++ b/cmake/QtPkgConfigHelpers.cmake @@ -19,7 +19,8 @@ endmacro() # Create a Qt6*.pc file intended for pkg-config consumption. function(qt_internal_generate_pkg_config_file module) # TODO: PkgConfig is supported under MSVC with pkgconf (github.com/pkgconf/pkgconf) - if((NOT UNIX OR QT_FEATURE_framework) AND NOT MINGW OR CMAKE_VERSION VERSION_LESS "3.20") + if((NOT UNIX OR QT_FEATURE_framework) + AND NOT MINGW OR CMAKE_VERSION VERSION_LESS "3.20" OR ANDROID) return() endif() if(NOT BUILD_SHARED_LIBS) diff --git a/cmake/QtPriHelpers.cmake b/cmake/QtPriHelpers.cmake index 71164c6718..b8c238c203 100644 --- a/cmake/QtPriHelpers.cmake +++ b/cmake/QtPriHelpers.cmake @@ -532,12 +532,15 @@ QT.${config_module_name}_private.disabled_features = ${disabled_private_features "-DIMPLICIT_LINK_DIRECTORIES=${implicit_link_directories}" -P "${QT_CMAKE_DIR}/QtGenerateLibPri.cmake" VERBATIM) - add_custom_target(${target}_lib_pri DEPENDS "${private_pri_file_path}") + # add_dependencies has no effect when adding interface libraries. So need to add the + # '_lib_pri' targets to ALL to make sure that the related rules executed. + unset(add_pri_target_to_all) if(arg_HEADER_MODULE) - add_dependencies(${target}_timestamp ${target}_lib_pri) - else() - add_dependencies(${target} ${target}_lib_pri) + set(add_pri_target_to_all ALL) endif() + add_custom_target(${target}_lib_pri ${add_pri_target_to_all} + DEPENDS "${private_pri_file_path}") + add_dependencies(${target} ${target}_lib_pri) endif() qt_install(FILES "${pri_files}" DESTINATION ${INSTALL_MKSPECSDIR}/modules) diff --git a/cmake/QtPublicAppleHelpers.cmake b/cmake/QtPublicAppleHelpers.cmake new file mode 100644 index 0000000000..b60ef5e448 --- /dev/null +++ b/cmake/QtPublicAppleHelpers.cmake @@ -0,0 +1,641 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +function(_qt_internal_handle_ios_launch_screen target) + # Check if user provided a launch screen path via a variable. + set(launch_screen "") + + # Check if the project provided a launch screen path via a variable. + # This variable is currently in Technical Preview. + if(QT_IOS_LAUNCH_SCREEN) + set(launch_screen "${QT_IOS_LAUNCH_SCREEN}") + endif() + + # Check if the project provided a launch screen path via a target property, it takes precedence + # over the variable. + # This property is currently in Technical Preview. + get_target_property(launch_screen_from_prop "${target}" QT_IOS_LAUNCH_SCREEN) + if(launch_screen_from_prop) + set(launch_screen "${launch_screen_from_prop}") + endif() + + # If the project hasn't provided a launch screen file path, use a copy of the template + # that qmake uses. + # It needs to be a copy because configure_file can't handle all the escaped double quotes + # present in the qmake template file. + set(is_default_launch_screen FALSE) + if(NOT launch_screen AND NOT QT_NO_SET_DEFAULT_IOS_LAUNCH_SCREEN) + set(is_default_launch_screen TRUE) + set(launch_screen + "${__qt_internal_cmake_ios_support_files_path}/LaunchScreen.storyboard") + endif() + + # Check that the launch screen exists. + if(launch_screen) + if(NOT IS_ABSOLUTE "${launch_screen}") + message(FATAL_ERROR + "Provided launch screen value should be an absolute path: '${launch_screen}'") + endif() + + if(NOT EXISTS "${launch_screen}") + message(FATAL_ERROR + "Provided launch screen file does not exist: '${launch_screen}'") + endif() + endif() + + if(launch_screen AND NOT QT_NO_ADD_IOS_LAUNCH_SCREEN_TO_BUNDLE) + get_filename_component(launch_screen_name "${launch_screen}" NAME) + + # Make a copy of the default launch screen template for this target and replace the + # label inside the template with the target name. + if(is_default_launch_screen) + # Configure our default template and place it in the build dir. + set(launch_screen_in_path "${launch_screen}") + + string(MAKE_C_IDENTIFIER "${target}" target_identifier) + set(launch_screen_out_dir + "${CMAKE_CURRENT_BINARY_DIR}/.qt/launch_screen_storyboards/${target_identifier}") + + set(launch_screen_out_path + "${launch_screen_out_dir}/${launch_screen_name}") + + file(MAKE_DIRECTORY "${launch_screen_out_dir}") + + # Replaces the value in the default template. + set(QT_IOS_LAUNCH_SCREEN_TEXT "${target}") + configure_file( + "${launch_screen_in_path}" + "${launch_screen_out_path}" + @ONLY + ) + + set(final_launch_screen_path "${launch_screen_out_path}") + else() + set(final_launch_screen_path "${launch_screen}") + endif() + + # Add the launch screen storyboard file as a source file, otherwise CMake doesn't consider + # it as a resource file and MACOSX_PACKAGE_LOCATION processing will be skipped. + target_sources("${target}" PRIVATE "${final_launch_screen_path}") + + # Ensure Xcode compiles the storyboard file and installs the compiled storyboard .nib files + # into the app bundle. + # We use target_sources and the MACOSX_PACKAGE_LOCATION source file property for that + # instead of the RESOURCE target property, becaues the latter could potentially end up + # needlessly installing the source storyboard file. + # + # We can't rely on policy CMP0118 since user project controls it. + set(scope_args) + if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.18") + set(scope_args TARGET_DIRECTORY ${target}) + endif() + set_source_files_properties("${final_launch_screen_path}" ${scope_args} + PROPERTIES MACOSX_PACKAGE_LOCATION Resources) + + # Save the launch screen name, so its value is added as an UILaunchStoryboardName entry + # in the Qt generated Info.plist file. + # Xcode expects an Info.plist storyboard entry without an extension. + get_filename_component(launch_screen_base_name "${launch_screen}" NAME_WE) + set_target_properties("${target}" PROPERTIES + _qt_ios_launch_screen_name "${launch_screen_name}" + _qt_ios_launch_screen_base_name "${launch_screen_base_name}" + _qt_ios_launch_screen_path "${final_launch_screen_path}") + endif() +endfunction() + +function(_qt_internal_find_ios_development_team_id out_var) + get_property(team_id GLOBAL PROPERTY _qt_internal_ios_development_team_id) + get_property(team_id_computed GLOBAL PROPERTY _qt_internal_ios_development_team_id_computed) + if(team_id_computed) + # Just in case if the value is non-empty but still booly FALSE. + if(NOT team_id) + set(team_id "") + endif() + set("${out_var}" "${team_id}" PARENT_SCOPE) + return() + endif() + + set_property(GLOBAL PROPERTY _qt_internal_ios_development_team_id_computed "TRUE") + + set(home_dir "$ENV{HOME}") + set(xcode_preferences_path "${home_dir}/Library/Preferences/com.apple.dt.Xcode.plist") + + # Extract the first account name (email) from the user's Xcode preferences + message(DEBUG "Trying to extract an Xcode development team id from '${xcode_preferences_path}'") + execute_process(COMMAND "/usr/libexec/PlistBuddy" + -x -c "print IDEProvisioningTeams" "${xcode_preferences_path}" + OUTPUT_VARIABLE teams_xml + ERROR_VARIABLE plist_error) + + # Parsing state. + set(is_free "") + set(current_team_id "") + set(parsing_is_free FALSE) + set(parsing_team_id FALSE) + set(first_team_id "") + + # Parse the xml output and return the first encountered non-free team id. If no non-free team id + # is found, return the first encountered free team id. + # If no team is found, return an empty string. + # + # Example input: + #<plist version="1.0"> + #<dict> + # <key>marty@planet.local</key> + # <array> + # <dict> + # <key>isFreeProvisioningTeam</key> + # <false/> + # <key>teamID</key> + # <string>AAA</string> + # ... + # </dict> + # <dict> + # <key>isFreeProvisioningTeam</key> + # <true/> + # <key>teamID</key> + # <string>BBB</string> + # ... + # </dict> + # </array> + #</dict> + #</plist> + if(teams_xml AND NOT plist_error) + string(REPLACE "\n" ";" teams_xml_lines "${teams_xml}") + + foreach(xml_line ${teams_xml_lines}) + string(STRIP "${xml_line}" xml_line) + if(xml_line STREQUAL "<dict>") + # Clean any previously found values when a new team dict is matched. + set(is_free "") + set(current_team_id "") + + elseif(xml_line STREQUAL "<key>isFreeProvisioningTeam</key>") + set(parsing_is_free TRUE) + + elseif(parsing_is_free) + set(parsing_is_free FALSE) + + if(xml_line MATCHES "true") + set(is_free TRUE) + else() + set(is_free FALSE) + endif() + + elseif(xml_line STREQUAL "<key>teamID</key>") + set(parsing_team_id TRUE) + + elseif(parsing_team_id) + set(parsing_team_id FALSE) + if(xml_line MATCHES "<string>([^<]+)</string>") + set(current_team_id "${CMAKE_MATCH_1}") + else() + continue() + endif() + + string(STRIP "${current_team_id}" current_team_id) + + # If this is the first team id we found so far, remember that, regardless if's free + # or not. + if(NOT first_team_id AND current_team_id) + set(first_team_id "${current_team_id}") + endif() + + # Break early if we found a non-free team id and use it, because we prefer + # a non-free team for signing, just like qmake. + if(NOT is_free AND current_team_id) + set(first_team_id "${current_team_id}") + break() + endif() + endif() + endforeach() + endif() + + if(NOT first_team_id) + message(DEBUG "Failed to extract an Xcode development team id.") + set("${out_var}" "" PARENT_SCOPE) + else() + message(DEBUG "Successfully extracted the first encountered Xcode development team id.") + set_property(GLOBAL PROPERTY _qt_internal_ios_development_team_id "${first_team_id}") + set("${out_var}" "${first_team_id}" PARENT_SCOPE) + endif() +endfunction() + +function(_qt_internal_get_ios_bundle_identifier_prefix out_var) + get_property(prefix GLOBAL PROPERTY _qt_internal_ios_bundle_identifier_prefix) + get_property(prefix_computed GLOBAL PROPERTY + _qt_internal_ios_bundle_identifier_prefix_computed) + if(prefix_computed) + # Just in case if the value is non-empty but still booly FALSE. + if(NOT prefix) + set(prefix "") + endif() + set("${out_var}" "${prefix}" PARENT_SCOPE) + return() + endif() + + set_property(GLOBAL PROPERTY _qt_internal_ios_bundle_identifier_prefix_computed "TRUE") + + set(home_dir "$ENV{HOME}") + set(xcode_preferences_path "${home_dir}/Library/Preferences/com.apple.dt.Xcode.plist") + + message(DEBUG "Trying to extract the default bundle identifier prefix from Xcode preferences.") + execute_process(COMMAND "/usr/libexec/PlistBuddy" + -c "print IDETemplateOptions:bundleIdentifierPrefix" + "${xcode_preferences_path}" + OUTPUT_VARIABLE prefix + ERROR_VARIABLE prefix_error) + if(prefix AND NOT prefix_error) + message(DEBUG "Successfully extracted the default bundle identifier prefix.") + string(STRIP "${prefix}" prefix) + else() + message(DEBUG "Failed to extract the default bundle identifier prefix.") + endif() + + if(prefix AND NOT prefix_error) + set_property(GLOBAL PROPERTY _qt_internal_ios_bundle_identifier_prefix "${prefix}") + set("${out_var}" "${prefix}" PARENT_SCOPE) + else() + set("${out_var}" "" PARENT_SCOPE) + endif() +endfunction() + +function(_qt_internal_escape_rfc_1034_identifier value out_var) + # According to https://datatracker.ietf.org/doc/html/rfc1034#section-3.5 + # we can only use letters, digits, dot (.) and hyphens (-). + # Underscores are not allowed. + string(REGEX REPLACE "[^A-Za-z0-9.]" "-" value "${value}") + + set("${out_var}" "${value}" PARENT_SCOPE) +endfunction() + +function(_qt_internal_get_default_ios_bundle_identifier out_var) + _qt_internal_get_ios_bundle_identifier_prefix(prefix) + if(NOT prefix) + set(prefix "com.yourcompany") + + # For a better out-of-the-box experience, try to create a unique prefix by appending + # the sha1 of the team id, if one is found. + _qt_internal_find_ios_development_team_id(team_id) + if(team_id) + string(SHA1 hash "${team_id}") + string(SUBSTRING "${hash}" 0 8 infix) + string(APPEND prefix ".${infix}") + else() + message(WARNING + "No organization bundle identifier prefix could be retrieved from Xcode " + "preferences. This can lead to code signing issues due to a non-unique bundle " + "identifier. Please set up an organization prefix by creating a new project within " + "Xcode, or consider providing a custom bundle identifier by specifying the " + "XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER property." + ) + endif() + endif() + + # Escape the prefix according to rfc 1034, it's important for code-signing. If an invalid + # identifier is used, calling xcodebuild on the command line says that no provisioning profile + # could be found, with no additional error message. If one opens the generated project with + # Xcode and clicks on 'Try again' to get a new profile, it shows a semi-useful error message + # that the identifier is invalid. + _qt_internal_escape_rfc_1034_identifier("${prefix}" prefix) + + set(identifier "${prefix}.\${PRODUCT_NAME:rfc1034identifier}") + set("${out_var}" "${identifier}" PARENT_SCOPE) +endfunction() + +function(_qt_internal_set_placeholder_apple_bundle_version target) + # If user hasn't provided neither a bundle version nor a bundle short version string for the + # app, set a placeholder value for both which will add them to the generated Info.plist file. + # This is required so that the app launches in the simulator (but apparently not for running + # on-device). + get_target_property(bundle_version "${target}" MACOSX_BUNDLE_BUNDLE_VERSION) + get_target_property(bundle_short_version "${target}" MACOSX_BUNDLE_SHORT_VERSION_STRING) + + if(NOT MACOSX_BUNDLE_BUNDLE_VERSION AND + NOT MACOSX_BUNDLE_SHORT_VERSION_STRING AND + NOT bundle_version AND + NOT bundle_short_version AND + NOT QT_NO_SET_XCODE_BUNDLE_VERSION + ) + get_target_property(version "${target}" VERSION) + if(NOT version) + set(version "${PROJECT_VERSION}") + if(NOT version) + set(version "1.0.0") + endif() + endif() + + # Use x.y for short version and x.y.z for full version + # Any versions longer than this will fail App Store + # submission. + string(REPLACE "." ";" version_list ${version}) + list(LENGTH version_list version_list_length) + list(GET version_list 0 version_major) + set(bundle_short_version "${version_major}") + if(version_list_length GREATER 1) + list(GET version_list 1 version_minor) + string(APPEND bundle_short_version ".${version_minor}") + endif() + set(bundle_version "${bundle_short_version}") + if(version_list_length GREATER 2) + list(GET version_list 2 version_patch) + string(APPEND bundle_version ".${version_patch}") + endif() + + + if(NOT CMAKE_XCODE_ATTRIBUTE_MARKETING_VERSION + AND NOT QT_NO_SET_XCODE_ATTRIBUTE_MARKETING_VERSION + AND NOT CMAKE_XCODE_ATTRIBUTE_CURRENT_PROJECT_VERSION + AND NOT QT_NO_SET_XCODE_ATTRIBUTE_CURRENT_PROJECT_VERSION + AND CMAKE_GENERATOR STREQUAL "Xcode") + get_target_property(marketing_version "${target}" + XCODE_ATTRIBUTE_MARKETING_VERSION) + get_target_property(current_project_version "${target}" + XCODE_ATTRIBUTE_CURRENT_PROJECT_VERSION) + if(NOT marketing_version AND NOT current_project_version) + set_target_properties("${target}" + PROPERTIES + XCODE_ATTRIBUTE_CURRENT_PROJECT_VERSION "${bundle_version}" + XCODE_ATTRIBUTE_MARKETING_VERSION "${bundle_short_version}" + ) + set(bundle_version "$(CURRENT_PROJECT_VERSION)") + set(bundle_short_version "$(MARKETING_VERSION)") + endif() + endif() + + set_target_properties("${target}" + PROPERTIES + MACOSX_BUNDLE_BUNDLE_VERSION "${bundle_version}" + MACOSX_BUNDLE_SHORT_VERSION_STRING "${bundle_short_version}" + ) + endif() +endfunction() + +function(_qt_internal_set_xcode_development_team_id target) + # If user hasn't provided a development team id, try to find the first one specified + # in the Xcode preferences. + if(NOT CMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM AND NOT QT_NO_SET_XCODE_DEVELOPMENT_TEAM_ID) + get_target_property(existing_team_id "${target}" XCODE_ATTRIBUTE_DEVELOPMENT_TEAM) + if(NOT existing_team_id) + _qt_internal_find_ios_development_team_id(team_id) + set_target_properties("${target}" + PROPERTIES XCODE_ATTRIBUTE_DEVELOPMENT_TEAM "${team_id}") + endif() + endif() +endfunction() + +function(_qt_internal_set_xcode_bundle_identifier target) + # Skip all logic if requested. + if(QT_NO_SET_XCODE_BUNDLE_IDENTIFIER) + return() + endif() + + # There are two fields to consider: the CFBundleIdentifier key (CFBI) to be written to + # Info.plist + # and the PRODUCT_BUNDLE_IDENTIFIER (PBI) property to set in the Xcode project. + # The following logic enables the best out-of-the-box experience combined with maximum + # customization. + # 1) If values for both fields are not provided, assign ${PRODUCT_BUNDLE_IDENTIFIER} to CFBI + # (which is expanded by xcodebuild at build time and will use the value of PBI) and + # auto-compute a default PBI from Xcode's ${PRODUCT_NAME}. + # 2) If CFBI is set and PBI isn't, use given CFBI and keep PBI empty. + # 3) If PBI is set and CFBI isn't, assign ${PRODUCT_BUNDLE_IDENTIFIER} to CFBI and use + # the given PBI. + # 4) If both are set, use both given values. + # TLDR: + # cfbi pbi -> result_cfbi result_pbi + # unset unset computed computed + # set unset given_val unset + # unset set computed given_val + # set set given_val given_val + + get_target_property(existing_cfbi "${target}" MACOSX_BUNDLE_GUI_IDENTIFIER) + if(NOT MACOSX_BUNDLE_GUI_IDENTIFIER AND NOT existing_cfbi) + set(is_cfbi_given FALSE) + else() + set(is_cfbi_given TRUE) + endif() + + if(NOT is_cfbi_given) + set_target_properties("${target}" + PROPERTIES + MACOSX_BUNDLE_GUI_IDENTIFIER "\${PRODUCT_BUNDLE_IDENTIFIER}") + endif() + + get_target_property(existing_pbi "${target}" XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER) + if(NOT CMAKE_XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER AND NOT existing_pbi) + set(is_pbi_given FALSE) + else() + set(is_pbi_given TRUE) + endif() + + if(NOT is_pbi_given AND NOT is_cfbi_given) + _qt_internal_get_default_ios_bundle_identifier(bundle_id) + set_target_properties("${target}" + PROPERTIES + XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "${bundle_id}") + endif() +endfunction() + +function(_qt_internal_set_xcode_targeted_device_family target) + if(NOT CMAKE_XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY + AND NOT QT_NO_SET_XCODE_TARGETED_DEVICE_FAMILY) + get_target_property(existing_device_family + "${target}" XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY) + if(NOT existing_device_family) + set(device_family_iphone_and_ipad "1,2") + set_target_properties("${target}" + PROPERTIES + XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY + "${device_family_iphone_and_ipad}") + endif() + endif() +endfunction() + +function(_qt_internal_set_xcode_code_sign_style target) + if(NOT CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_STYLE + AND NOT QT_NO_SET_XCODE_CODE_SIGN_STYLE) + get_target_property(existing_code_style + "${target}" XCODE_ATTRIBUTE_CODE_SIGN_STYLE) + if(NOT existing_code_style) + set(existing_code_style "Automatic") + set_target_properties("${target}" + PROPERTIES + XCODE_ATTRIBUTE_CODE_SIGN_STYLE + "${existing_code_style}") + endif() + endif() +endfunction() + +# Workaround for https://gitlab.kitware.com/cmake/cmake/-/issues/15183 +function(_qt_internal_set_xcode_install_path target) + if(NOT CMAKE_XCODE_ATTRIBUTE_INSTALL_PATH + AND NOT QT_NO_SET_XCODE_INSTALL_PATH) + get_target_property(existing_install_path + "${target}" XCODE_ATTRIBUTE_INSTALL_PATH) + if(NOT existing_install_path) + set_target_properties("${target}" + PROPERTIES + XCODE_ATTRIBUTE_INSTALL_PATH + "$(inherited)") + endif() + endif() +endfunction() + +function(_qt_internal_set_xcode_bundle_display_name target) + # We want the value of CFBundleDisplayName to be ${PRODUCT_NAME}, but we can't put that + # into the Info.plist.in template file directly, because the implicit configure_file(Info.plist) + # done by CMake is not using the @ONLY option, so CMake would treat the assignment as + # variable expansion. Escaping using backslashes does not help. + # Work around it by assigning the dollar char to a separate cache var, and expand it, so that + # the final value in the file will be ${PRODUCT_NAME}, to be evaluated at build time by Xcode. + set(QT_INTERNAL_DOLLAR_VAR "$" CACHE STRING "") +endfunction() + +# Adds ${PRODUCT_NAME} to the Info.plist file, which is then evaluated by Xcode itself. +function(_qt_internal_set_xcode_bundle_name target) + if(QT_NO_SET_XCODE_BUNDLE_NAME) + return() + endif() + + get_target_property(existing_bundle_name "${target}" MACOSX_BUNDLE_BUNDLE_NAME) + if(NOT MACOSX_BUNDLE_BUNDLE_NAME AND NOT existing_bundle_name) + if(CMAKE_GENERATOR STREQUAL Xcode) + set_target_properties("${target}" + PROPERTIES + MACOSX_BUNDLE_BUNDLE_NAME "\${PRODUCT_NAME}") + else() + set_target_properties("${target}" + PROPERTIES + MACOSX_BUNDLE_BUNDLE_NAME "${target}") + endif() + endif() +endfunction() + +function(_qt_internal_set_xcode_bitcode_enablement target) + if(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE + OR QT_NO_SET_XCODE_ENABLE_BITCODE) + return() + endif() + + get_target_property(existing_bitcode_enablement + "${target}" XCODE_ATTRIBUTE_ENABLE_BITCODE) + if(NOT existing_bitcode_enablement MATCHES "-NOTFOUND") + return() + endif() + + # Disable bitcode to match Xcode 14's new default + set_target_properties("${target}" + PROPERTIES + XCODE_ATTRIBUTE_ENABLE_BITCODE + "NO") +endfunction() + +function(_qt_internal_generate_ios_info_plist target) + # If the project already specifies a custom file, we don't override it. + get_target_property(existing_plist "${target}" MACOSX_BUNDLE_INFO_PLIST) + if(existing_plist) + return() + endif() + + set(info_plist_in "${__qt_internal_cmake_ios_support_files_path}/Info.plist.app.in") + + string(MAKE_C_IDENTIFIER "${target}" target_identifier) + set(info_plist_out_dir + "${CMAKE_CURRENT_BINARY_DIR}/.qt/info_plist/${target_identifier}") + set(info_plist_out "${info_plist_out_dir}/Info.plist") + + # Check if we need to specify a custom launch screen storyboard entry. + get_target_property(launch_screen_base_name "${target}" _qt_ios_launch_screen_base_name) + if(launch_screen_base_name) + set(qt_ios_launch_screen_plist_entry "${launch_screen_base_name}") + endif() + + # Call configure_file to substitute Qt-specific @FOO@ values, not ${FOO} values. + # + # The output file will be another template file to be fed to CMake via the + # MACOSX_BUNDLE_INFO_PLIST property. CMake will then call configure_file on it to provide + # content for regular entries like CFBundleName, etc. + # + # We require this extra configure_file call so we can create unique Info.plist files for each + # target in a project, while also providing a way to add Qt specific entries that CMake + # does not support out of the box (e.g. a launch screen name). + configure_file( + "${info_plist_in}" + "${info_plist_out}" + @ONLY + ) + + set_target_properties("${target}" PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${info_plist_out}") +endfunction() + +function(_qt_internal_set_ios_simulator_arch target) + if(CMAKE_XCODE_ATTRIBUTE_ARCHS + OR QT_NO_SET_XCODE_ARCHS) + return() + endif() + + get_target_property(existing_archs + "${target}" XCODE_ATTRIBUTE_ARCHS) + if(NOT existing_archs MATCHES "-NOTFOUND") + return() + endif() + + if(NOT x86_64 IN_LIST QT_OSX_ARCHITECTURES) + return() + endif() + + if(CMAKE_OSX_ARCHITECTURES AND NOT x86_64 IN_LIST CMAKE_OSX_ARCHITECTURES) + return() + endif() + + set_target_properties("${target}" + PROPERTIES + "XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*]" + "x86_64") +endfunction() + +function(_qt_internal_finalize_apple_app target) + # Shared between macOS and iOS apps + + # Only set the various properties if targeting the Xcode generator, otherwise the various + # Xcode tokens are embedded as-is instead of being dynamically evaluated. + # This affects things like the version number or application name as reported by Qt API. + if(CMAKE_GENERATOR STREQUAL "Xcode") + _qt_internal_set_xcode_development_team_id("${target}") + _qt_internal_set_xcode_bundle_identifier("${target}") + _qt_internal_set_xcode_code_sign_style("${target}") + _qt_internal_set_xcode_bundle_display_name("${target}") + _qt_internal_set_xcode_install_path("${target}") + endif() + _qt_internal_set_xcode_bundle_name("${target}") + _qt_internal_set_placeholder_apple_bundle_version("${target}") +endfunction() + +function(_qt_internal_finalize_ios_app target) + _qt_internal_finalize_apple_app("${target}") + + _qt_internal_set_xcode_targeted_device_family("${target}") + _qt_internal_set_xcode_bitcode_enablement("${target}") + _qt_internal_handle_ios_launch_screen("${target}") + _qt_internal_generate_ios_info_plist("${target}") + _qt_internal_set_ios_simulator_arch("${target}") +endfunction() + +function(_qt_internal_finalize_macos_app target) + get_target_property(is_bundle ${target} MACOSX_BUNDLE) + if(NOT is_bundle) + return() + endif() + + _qt_internal_finalize_apple_app("${target}") + + # Make sure the install rpath has at least the minimum needed if the app + # has any non-static frameworks. We can't rigorously know if the app will + # have any, even with a static Qt, so always add this. If there are no + # frameworks, it won't do any harm. + get_property(install_rpath TARGET ${target} PROPERTY INSTALL_RPATH) + list(APPEND install_rpath "@executable_path/../Frameworks") + list(REMOVE_DUPLICATES install_rpath) + set_property(TARGET ${target} PROPERTY INSTALL_RPATH "${install_rpath}") +endfunction() diff --git a/cmake/QtPublicCMakeHelpers.cmake b/cmake/QtPublicCMakeHelpers.cmake index 35cd4fe1f3..6001dfec11 100644 --- a/cmake/QtPublicCMakeHelpers.cmake +++ b/cmake/QtPublicCMakeHelpers.cmake @@ -32,3 +32,59 @@ function(_qt_internal_check_depfile_support out_var) endif() set(${out_var} "${${out_var}}" PARENT_SCOPE) endfunction() + +# Collect additional package prefix paths to look for Qt packages, both from command line and the +# env variable ${prefixes_var}. The result is stored in ${out_var} and is a list of paths ending +# with "/lib/cmake". +function(__qt_internal_collect_additional_prefix_paths out_var prefixes_var) + if(DEFINED "${out_var}") + return() + endif() + + set(additional_packages_prefix_paths "") + + set(additional_packages_prefixes "") + if(${prefixes_var}) + list(APPEND additional_packages_prefixes ${${prefixes_var}}) + endif() + if(DEFINED ENV{${prefixes_var}} + AND NOT "$ENV{${prefixes_var}}" STREQUAL "") + set(prefixes_from_env "$ENV{${prefixes_var}}") + if(NOT CMAKE_HOST_WIN32) + string(REPLACE ":" ";" prefixes_from_env "${prefixes_from_env}") + endif() + list(APPEND additional_packages_prefixes ${prefixes_from_env}) + endif() + + foreach(additional_path IN LISTS additional_packages_prefixes) + file(TO_CMAKE_PATH "${additional_path}" additional_path) + + # The prefix paths need to end with lib/cmake to ensure the packages are found when + # cross compiling. Search for REROOT_PATH_ISSUE_MARKER in the qt.toolchain.cmake file for + # details. + # We must pass the values via the PATHS options because the main find_package call uses + # NO_DEFAULT_PATH, and thus CMAKE_PREFIX_PATH values are discarded. + # CMAKE_FIND_ROOT_PATH values are not discarded and togegher with the PATHS option, it + # ensures packages from additional prefixes are found. + if(NOT additional_path MATCHES "/lib/cmake$") + string(APPEND additional_path "/lib/cmake") + endif() + list(APPEND additional_packages_prefix_paths "${additional_path}") + endforeach() + + set("${out_var}" "${additional_packages_prefix_paths}" PARENT_SCOPE) +endfunction() + +# Take a list of prefix paths ending with "/lib/cmake", and return a list of absolute paths with +# "/lib/cmake" removed. +function(__qt_internal_prefix_paths_to_roots out_var prefix_paths) + set(result "") + foreach(path IN LISTS prefix_paths) + if(path MATCHES "/lib/cmake$") + string(APPEND path "/../..") + endif() + get_filename_component(path "${path}" ABSOLUTE) + list(APPEND result "${path}") + endforeach() + set("${out_var}" "${result}" PARENT_SCOPE) +endfunction() diff --git a/cmake/QtPublicDependencyHelpers.cmake b/cmake/QtPublicDependencyHelpers.cmake index 803cb73e63..7fca0fa66d 100644 --- a/cmake/QtPublicDependencyHelpers.cmake +++ b/cmake/QtPublicDependencyHelpers.cmake @@ -67,7 +67,7 @@ macro(_qt_internal_find_tool_dependencies target target_dep_list) "${_qt_cmake_dir}" ${_qt_additional_packages_prefix_paths} ) - if (NOT ${__qt_${target}_pkg}_FOUND) + if (NOT ${__qt_${target}_pkg}_FOUND AND NOT QT_ALLOW_MISSING_TOOLS_PACKAGES) set(${CMAKE_FIND_PACKAGE_NAME}_FOUND FALSE) set(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE "${CMAKE_FIND_PACKAGE_NAME} could not be found because dependency \ diff --git a/cmake/QtPublicTestHelpers.cmake b/cmake/QtPublicTestHelpers.cmake new file mode 100644 index 0000000000..70fa45a898 --- /dev/null +++ b/cmake/QtPublicTestHelpers.cmake @@ -0,0 +1,104 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +# This function wraps COMMAND with cmake script, that makes possible standalone run with external +# arguments. +# +# Generated wrapper will be written to OUTPUT_FILE. +# If WORKING_DIRECTORY is not set COMMAND will be executed in CMAKE_CURRENT_BINARY_DIR. +# Variables from ENVIRONMENT will be set before COMMAND execution. +# PRE_RUN and POST_RUN arguments may contain extra cmake code that supposed to be executed before +# and after COMMAND, respectively. Both arguments accept a list of cmake script language +# constructions. Each item of the list will be concantinated into single string with '\n' separator. +# COMMAND_ECHO option takes a value like it does for execute_process, and passes that value to +# execute_process. +function(_qt_internal_create_command_script) + #This style of parsing keeps ';' in ENVIRONMENT variables + cmake_parse_arguments(PARSE_ARGV 0 arg + "" + "OUTPUT_FILE;WORKING_DIRECTORY;COMMAND_ECHO" + "COMMAND;ENVIRONMENT;PRE_RUN;POST_RUN" + ) + + if(NOT arg_COMMAND) + message(FATAL_ERROR "qt_internal_create_command_script: COMMAND is not specified") + endif() + + if(NOT arg_OUTPUT_FILE) + message(FATAL_ERROR "qt_internal_create_command_script: Wrapper OUTPUT_FILE\ +is not specified") + endif() + + if(NOT arg_WORKING_DIRECTORY AND NOT QNX) + set(arg_WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + endif() + + set(environment_extras) + set(skipNext false) + if(arg_ENVIRONMENT) + list(LENGTH arg_ENVIRONMENT length) + math(EXPR length "${length} - 1") + foreach(envIdx RANGE ${length}) + if(skipNext) + set(skipNext FALSE) + continue() + endif() + + set(envVariable "") + set(envValue "") + + list(GET arg_ENVIRONMENT ${envIdx} envVariable) + math(EXPR envIdx "${envIdx} + 1") + if (envIdx LESS_EQUAL ${length}) + list(GET arg_ENVIRONMENT ${envIdx} envValue) + endif() + + if(NOT "${envVariable}" STREQUAL "") + set(environment_extras "${environment_extras}\nset(ENV{${envVariable}} \ +\"${envValue}\")") + endif() + set(skipNext TRUE) + endforeach() + endif() + + #Escaping environment variables before expand them by file GENERATE + string(REPLACE "\\" "\\\\" environment_extras "${environment_extras}") + + if(WIN32) + # It's necessary to call actual test inside 'cmd.exe', because 'execute_process' uses + # SW_HIDE to avoid showing a console window, it affects other GUI as well. + # See https://gitlab.kitware.com/cmake/cmake/-/issues/17690 for details. + set(extra_runner "cmd /c") + endif() + + if(arg_PRE_RUN) + string(JOIN "\n" pre_run ${arg_PRE_RUN}) + endif() + + if(arg_POST_RUN) + string(JOIN "\n" post_run ${arg_POST_RUN}) + endif() + + set(command_echo "") + if(arg_COMMAND_ECHO) + set(command_echo "COMMAND_ECHO ${arg_COMMAND_ECHO}") + endif() + + file(GENERATE OUTPUT "${arg_OUTPUT_FILE}" CONTENT +"#!${CMAKE_COMMAND} -P +# Qt generated command wrapper + +${environment_extras} +${pre_run} +execute_process(COMMAND ${extra_runner} ${arg_COMMAND} + WORKING_DIRECTORY \"${arg_WORKING_DIRECTORY}\" + ${command_echo} + RESULT_VARIABLE result +) +${post_run} +if(NOT result EQUAL 0) + string(JOIN \" \" full_command ${arg_COMMAND}) + message(FATAL_ERROR \"\${full_command} execution failed with exit code \${result}.\") +endif()" + ) +endfunction() diff --git a/cmake/QtPublicToolHelpers.cmake b/cmake/QtPublicToolHelpers.cmake index cd4b093326..3e4214ca0d 100644 --- a/cmake/QtPublicToolHelpers.cmake +++ b/cmake/QtPublicToolHelpers.cmake @@ -41,3 +41,105 @@ function(__qt_internal_get_tool_imported_location out_var tool) set(${out_var} "${${out_var}}" PARENT_SCOPE) endfunction() + +function(_qt_internal_generate_tool_command_wrapper) + get_property(is_called GLOBAL PROPERTY _qt_internal_generate_tool_command_wrapper_called) + if(NOT CMAKE_HOST_WIN32 OR is_called) + return() + endif() + + set(prefixes "") + + # In a prefix build, the just-built tools should pick up libraries from the current repo build + # dir. + if(QT_BUILD_DIR) + list(APPEND prefixes "${QT_BUILD_DIR}") + endif() + + # Pick up libraries from the main location where Qt was installed during a Qt build. + if(QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX) + list(APPEND prefixes "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}") + endif() + + # Needed for ExternalProjects examples, where the Qt build dir is passed via this variable + # to the example project. + if(QT_ADDITIONAL_PACKAGES_PREFIX_PATH) + __qt_internal_prefix_paths_to_roots(additional_roots + "${QT_ADDITIONAL_PACKAGES_PREFIX_PATH}") + list(APPEND prefixes ${QT_ADDITIONAL_PACKAGES_PREFIX_PATH}) + endif() + + # Fallback to wherever Qt6 package is. + if(QT6_INSTALL_PREFIX) + list(APPEND prefixes "${QT6_INSTALL_PREFIX}") + endif() + + # When building qtbase, QT6_INSTALL_BINS is not set yet. + if(INSTALL_BINDIR) + set(bin_suffix "${INSTALL_BINDIR}") + else() + set(bin_suffix "${QT6_INSTALL_BINS}") + endif() + + set(path_dirs "") + foreach(prefix IN LISTS prefixes) + set(bin_dir "${prefix}/${bin_suffix}") + if(EXISTS "${bin_dir}") + file(TO_NATIVE_PATH "${bin_dir}" path_dir) + list(APPEND path_dirs "${path_dir}") + endif() + endforeach() + + set(tool_command_wrapper_dir "${CMAKE_BINARY_DIR}/.qt/bin") + file(MAKE_DIRECTORY "${tool_command_wrapper_dir}") + set(tool_command_wrapper_path "${tool_command_wrapper_dir}/qt_setup_tool_path.bat") + + file(WRITE "${tool_command_wrapper_path}" "@echo off +set PATH=${path_dirs};%PATH% +%*") + + set(QT_TOOL_COMMAND_WRAPPER_PATH "${tool_command_wrapper_path}" + CACHE INTERNAL "Path to the wrapper of the tool commands") + + set_property(GLOBAL PROPERTY _qt_internal_generate_tool_command_wrapper_called TRUE) +endfunction() + +# Wraps a tool command with a script that contains the necessary environment for the tool to run +# correctly. +# _qt_internal_wrap_tool_command(var <SET|APPEND> <command> [args...]) +# Arguments: +# APPEND Selects the 'append' mode for the out_variable argument. +# SET Selects the 'set' mode for the out_variable argument. +# +# FIXME: Replace all usages of _qt_internal_wrap_tool_command +# with _qt_internal_get_wrap_tool_script_path and remove the former. +# The former always adds the COMMAND keyword, which does not allow the caller to wrap the +# commands in a generator expression. See _qt_internal_target_enable_qmllint for an example. +function(_qt_internal_wrap_tool_command out_variable action) + set(append FALSE) + if(action STREQUAL "APPEND") + set(append TRUE) + elseif(NOT action STREQUAL "SET") + message(FATAL_ERROR "Invalid action specified ${action}. Supported actions: SET, APPEND") + endif() + + # Ensure the script wrapper exists. + _qt_internal_generate_tool_command_wrapper() + + set(cmd COMMAND ${QT_TOOL_COMMAND_WRAPPER_PATH} ${ARGN}) + + if(append) + list(APPEND ${out_variable} ${cmd}) + else() + set(${out_variable} ${cmd}) + endif() + set(${out_variable} "${${out_variable}}" PARENT_SCOPE) +endfunction() + +# Gets the path to tool wrapper shell script. +function(_qt_internal_get_tool_wrapper_script_path out_variable) + # Ensure the script wrapper exists. + _qt_internal_generate_tool_command_wrapper() + + set(${out_variable} "${QT_TOOL_COMMAND_WRAPPER_PATH}" PARENT_SCOPE) +endfunction() diff --git a/cmake/QtPublicWasmToolchainHelpers.cmake b/cmake/QtPublicWasmToolchainHelpers.cmake index c4d637c94e..2e8e34f1a3 100644 --- a/cmake/QtPublicWasmToolchainHelpers.cmake +++ b/cmake/QtPublicWasmToolchainHelpers.cmake @@ -50,7 +50,7 @@ endfunction() function(__qt_internal_get_emcc_recommended_version out_var) # This version of Qt needs this version of emscripten. - set(QT_EMCC_RECOMMENDED_VERSION "3.1.10") + set(QT_EMCC_RECOMMENDED_VERSION "3.1.14") set(${out_var} "${QT_EMCC_RECOMMENDED_VERSION}" PARENT_SCOPE) endfunction() @@ -69,3 +69,33 @@ function(__qt_internal_show_error_no_emscripten_toolchain_file_found_when_using_ "or provide a path to a valid emscripten installation via the EMSDK " "environment variable.") endfunction() + +function(__qt_internal_get_qt_build_emsdk_version out_var) + if(QT6_INSTALL_PREFIX) + set(WASM_BUILD_DIR "${QT6_INSTALL_PREFIX}") + elseif(QT_BUILD_DIR) + set(WASM_BUILD_DIR "${QT_BUILD_DIR}") + endif() + if(EXISTS "${WASM_BUILD_DIR}/src/corelib/global/qconfig.h") + file(READ "${WASM_BUILD_DIR}/src/corelib/global/qconfig.h" ver) + else() + file(READ "${WASM_BUILD_DIR}/include/QtCore/qconfig.h" ver) + endif() + string(REGEX MATCH "#define QT_EMCC_VERSION.\"[0-9]+\\.[0-9]+\\.[0-9]+\"" emOutput ${ver}) + string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" build_emcc_version "${emOutput}") + set(${out_var} "${build_emcc_version}" PARENT_SCOPE) +endfunction() + +function(_qt_test_emscripten_version) + __qt_internal_get_emcc_recommended_version(_recommended_emver) + __qt_internal_get_emroot_path_suffix_from_emsdk_env(emroot_path) + __qt_internal_query_emsdk_version("${emroot_path}" TRUE current_emsdk_ver) + __qt_internal_get_qt_build_emsdk_version(qt_build_emcc_version) + + if(NOT "${qt_build_emcc_version}" STREQUAL "${current_emsdk_ver}") + message("Qt Wasm built with Emscripten version: ${qt_build_emcc_version}") + message("You are using Emscripten version: ${current_emsdk_ver}") + message("The recommended version of Emscripten for this Qt is: ${_recommended_emver}") + message("This may not work correctly") + endif() +endfunction() diff --git a/cmake/QtQmakeHelpers.cmake b/cmake/QtQmakeHelpers.cmake index 1ad05d7a80..f7eb0a91eb 100644 --- a/cmake/QtQmakeHelpers.cmake +++ b/cmake/QtQmakeHelpers.cmake @@ -95,7 +95,8 @@ function(qt_generate_qmake_and_qtpaths_wrapper_for_target) "${host_prefix}") file(RELATIVE_PATH ext_prefix_relative_to_conf_file "${ext_prefix}/${INSTALL_BINDIR}" "${ext_prefix}") - file(RELATIVE_PATH ext_prefix_relative_to_host_prefix "${host_prefix}" "${ext_prefix}") + file(RELATIVE_PATH ext_datadir_relative_to_host_prefix "${host_prefix}" + "${ext_prefix}/${INSTALL_MKSPECSDIR}/..") set(content "") @@ -127,7 +128,10 @@ Prefix=${prefix} "[Paths] Prefix=${ext_prefix_relative_to_conf_file} HostPrefix=${host_prefix_relative_to_conf_file} -HostData=${ext_prefix_relative_to_host_prefix} +HostBinaries=${QT${PROJECT_VERSION_MAJOR}_HOST_INFO_BINDIR} +HostLibraries=${QT${PROJECT_VERSION_MAJOR}_HOST_INFO_LIBDIR} +HostLibraryExecutables=${QT${PROJECT_VERSION_MAJOR}_HOST_INFO_LIBEXECDIR} +HostData=${ext_datadir_relative_to_host_prefix} Sysroot=${sysroot} SysrootifyPrefix=${sysrootify_prefix} TargetSpec=${QT_QMAKE_TARGET_MKSPEC} diff --git a/cmake/QtSetup.cmake b/cmake/QtSetup.cmake index c9d2655bd9..4f0c98a6b9 100644 --- a/cmake/QtSetup.cmake +++ b/cmake/QtSetup.cmake @@ -59,6 +59,12 @@ elseif(CMAKE_CONFIGURATION_TYPES) message(STATUS "Default build configuration set to '${CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE}'.") endif() + if(CMAKE_GENERATOR STREQUAL "Ninja") + message(FATAL_ERROR + "It's not possible to build multiple configurations with the single config Ninja " + "generator. Consider configuring with -G\"Ninja Multi-Config\" instead of -GNinja." + ) + endif() else() message(STATUS "CMAKE_BUILD_TYPE was set to: '${CMAKE_BUILD_TYPE}'") endif() @@ -110,6 +116,10 @@ endif() ## Position independent code: set(CMAKE_POSITION_INDEPENDENT_CODE ON) +# Does the linker support position independent code? +include(CheckPIESupported) +check_pie_supported() + # Do not relink dependent libraries when no header has changed: set(CMAKE_LINK_DEPENDS_NO_SHARED ON) @@ -252,7 +262,12 @@ option(QT_BUILD_EXAMPLES_AS_EXTERNAL "Should examples be built as ExternalProjec unset(_qt_build_examples_as_external) option(QT_BUILD_MANUAL_TESTS "Build Qt manual tests" OFF) -option(QT_BUILD_MINIMAL_STATIC_TESTS "Build minimal subset of tests for static Qt builds" OFF) + +if(WASM) + option(QT_BUILD_MINIMAL_STATIC_TESTS "Build minimal subset of tests for static Qt builds" ON) +else() + option(QT_BUILD_MINIMAL_STATIC_TESTS "Build minimal subset of tests for static Qt builds" OFF) +endif() ## Path used to find host tools, either when cross-compiling or just when using the tools from ## a different host build. diff --git a/cmake/QtTestHelpers.cmake b/cmake/QtTestHelpers.cmake index 6bdbfeec2d..39736a4cf3 100644 --- a/cmake/QtTestHelpers.cmake +++ b/cmake/QtTestHelpers.cmake @@ -33,6 +33,10 @@ function(qt_internal_add_benchmark target) ${exec_args} ) + # Benchmarks on iOS must be app bundles. + if(IOS) + set_target_properties(${target} PROPERTIES MACOSX_BUNDLE TRUE) + endif() qt_internal_add_repo_local_defines(${target}) @@ -43,7 +47,7 @@ function(qt_internal_add_benchmark target) # Add a ${target}_benchmark generator target, to run single benchmark more easily. set(benchmark_wrapper_file "${arg_OUTPUT_DIRECTORY}/${target}Wrapper$<CONFIG>.cmake") - qt_internal_create_command_script(COMMAND "$<TARGET_FILE:${target}>" + _qt_internal_create_command_script(COMMAND "$<TARGET_FILE:${target}>" OUTPUT_FILE "${benchmark_wrapper_file}" ENVIRONMENT "PATH" "${benchmark_env_path}" "QT_PLUGIN_PATH" "${benchmark_env_plugin_path}" @@ -61,6 +65,8 @@ function(qt_internal_add_benchmark target) if (TARGET benchmark) add_dependencies("benchmark" "${target}_benchmark") endif() + + qt_internal_add_test_finalizers("${target}") endfunction() # Simple wrapper around qt_internal_add_executable for manual tests which insure that @@ -98,9 +104,15 @@ function(qt_internal_add_manual_test target) ${exec_args} ) + # Tests on iOS must be app bundles. + if(IOS) + set_target_properties(${target} PROPERTIES MACOSX_BUNDLE TRUE) + endif() + # Disable the QT_NO_NARROWING_CONVERSIONS_IN_CONNECT define for manual tests qt_internal_undefine_global_definition(${target} QT_NO_NARROWING_CONVERSIONS_IN_CONNECT) + qt_internal_add_test_finalizers("${target}") endfunction() # This function will configure the fixture for the network tests that require docker network services @@ -282,6 +294,11 @@ function(qt_internal_add_test name) # and not print anything. set_property(TARGET "${name}" PROPERTY WIN32_EXECUTABLE FALSE) + # Tests on iOS must be app bundles. + if(IOS) + set_target_properties(${name} PROPERTIES MACOSX_BUNDLE TRUE) + endif() + # QMLTest specifics qt_internal_extend_target("${name}" CONDITION arg_QMLTEST PUBLIC_LIBRARIES ${QT_CMAKE_EXPORT_NAMESPACE}::QuickTest @@ -467,6 +484,7 @@ function(qt_internal_add_test name) endif() endif() + qt_internal_add_test_finalizers("${name}") endfunction() # This function adds test with specified NAME and wraps given test COMMAND with standalone cmake @@ -477,7 +495,7 @@ endfunction() # directly by 'cmake -P path/to/scriptWrapper.cmake', COMMAND will be executed in specified # WORKING_DIRECTORY with arguments specified in ARGS. # -# See also qt_internal_create_command_script for details. +# See also _qt_internal_create_command_script for details. function(qt_internal_create_test_script) #This style of parsing keeps ';' in ENVIRONMENT variables cmake_parse_arguments(PARSE_ARGV 0 arg @@ -538,7 +556,7 @@ for this function. Will be ignored") endif() endif() - qt_internal_create_command_script(COMMAND "${crosscompiling_emulator} \${env_test_runner} \ + _qt_internal_create_command_script(COMMAND "${crosscompiling_emulator} \${env_test_runner} \ \"${executable_file}\" \${env_test_args} ${command_args}" OUTPUT_FILE "${arg_OUTPUT_FILE}" WORKING_DIRECTORY "${arg_WORKING_DIRECTORY}" @@ -550,99 +568,7 @@ for this function. Will be ignored") ) endfunction() -# This function wraps COMMAND with cmake script, that makes possible standalone run with external -# arguments. -# -# Generated wrapper will be written to OUTPUT_FILE. -# If WORKING_DIRECTORY is not set COMMAND will be executed in CMAKE_CURRENT_BINARY_DIR. -# Variables from ENVIRONMENT will be set before COMMAND execution. -# PRE_RUN and POST_RUN arguments may contain extra cmake code that supposed to be executed before -# and after COMMAND, respectively. Both arguments accept a list of cmake script language -# constructions. Each item of the list will be concantinated into single string with '\n' sepatator. -function(qt_internal_create_command_script) - #This style of parsing keeps ';' in ENVIRONMENT variables - cmake_parse_arguments(PARSE_ARGV 0 arg - "" - "OUTPUT_FILE;WORKING_DIRECTORY" - "COMMAND;ENVIRONMENT;PRE_RUN;POST_RUN" - ) - if(NOT arg_COMMAND) - message(FATAL_ERROR "qt_internal_create_command_script: COMMAND is not specified") - endif() - - if(NOT arg_OUTPUT_FILE) - message(FATAL_ERROR "qt_internal_create_command_script: Wrapper OUTPUT_FILE\ -is not specified") - endif() - - if(NOT arg_WORKING_DIRECTORY AND NOT QNX) - set(arg_WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") - endif() - - set(environment_extras) - set(skipNext false) - if(arg_ENVIRONMENT) - list(LENGTH arg_ENVIRONMENT length) - math(EXPR length "${length} - 1") - foreach(envIdx RANGE ${length}) - if(skipNext) - set(skipNext FALSE) - continue() - endif() - - set(envVariable "") - set(envValue "") - - list(GET arg_ENVIRONMENT ${envIdx} envVariable) - math(EXPR envIdx "${envIdx} + 1") - if (envIdx LESS_EQUAL ${length}) - list(GET arg_ENVIRONMENT ${envIdx} envValue) - endif() - - if(NOT "${envVariable}" STREQUAL "") - set(environment_extras "${environment_extras}\nset(ENV{${envVariable}} \ -\"${envValue}\")") - endif() - set(skipNext TRUE) - endforeach() - endif() - - #Escaping environment variables before expand them by file GENERATE - string(REPLACE "\\" "\\\\" environment_extras "${environment_extras}") - - if(WIN32) - # It's necessary to call actual test inside 'cmd.exe', because 'execute_process' uses - # SW_HIDE to avoid showing a console window, it affects other GUI as well. - # See https://gitlab.kitware.com/cmake/cmake/-/issues/17690 for details. - set(extra_runner "cmd /c") - endif() - - if(arg_PRE_RUN) - string(JOIN "\n" pre_run ${arg_PRE_RUN}) - endif() - - if(arg_POST_RUN) - string(JOIN "\n" post_run ${arg_POST_RUN}) - endif() - - file(GENERATE OUTPUT "${arg_OUTPUT_FILE}" CONTENT -"#!${CMAKE_COMMAND} -P -# Qt generated command wrapper - -${environment_extras} -${pre_run} -execute_process(COMMAND ${extra_runner} ${arg_COMMAND} - WORKING_DIRECTORY \"${arg_WORKING_DIRECTORY}\" - RESULT_VARIABLE result -) -${post_run} -if(NOT result EQUAL 0) - string(JOIN \" \" full_command ${arg_COMMAND}) - message(FATAL_ERROR \"\${full_command} execution failed with exit code \${result}.\") -endif()" - ) -endfunction() # This function creates an executable for use as a helper program with tests. Some # tests launch separate programs to test certain input/output behavior. @@ -730,3 +656,14 @@ function(qt_internal_collect_command_environment out_path out_plugin_path) string(REPLACE ";" "\;" plugin_paths_joined "${plugin_paths_joined}") set(${out_plugin_path} "${plugin_paths_joined}" PARENT_SCOPE) endfunction() + +function(qt_internal_add_test_finalizers target) + # It might not be safe to run all the finalizers of _qt_internal_finalize_executable + # within the context of a Qt build (not a user project) when targeting a host build. + # At least one issue is missing qmlimportscanner at configure time. + # For now, we limit it to iOS, where it was tested to work, an we know that host tools + # should already be built and available. + if(IOS) + qt_add_list_file_finalizer(_qt_internal_finalize_executable "${target}") + endif() +endfunction() diff --git a/cmake/QtToolHelpers.cmake b/cmake/QtToolHelpers.cmake index 2f49e4d872..8f488af21c 100644 --- a/cmake/QtToolHelpers.cmake +++ b/cmake/QtToolHelpers.cmake @@ -168,9 +168,22 @@ function(qt_internal_add_tool target_name) endif() if(NOT QT_WILL_BUILD_TOOLS) - message(FATAL_ERROR "The tool \"${full_name}\" was not found in the " - "${tools_package_name} package. " - "Package found: ${${tools_package_name}_FOUND}") + if(${${tools_package_name}_FOUND}) + set(pkg_found_msg "") + string(APPEND pkg_found_msg + "the ${tools_package_name} package, but the package did not contain the tool. " + "Make sure that the host module ${arg_TOOLS_TARGET} was built with all features " + "enabled (no explicitly disabled tools).") + else() + set(pkg_found_msg "") + string(APPEND pkg_found_msg + "the ${tools_package_name} package, but the package could not be found. " + "Make sure you have built and installed the host ${arg_TOOLS_TARGET} module, " + "which will ensure the creation of the ${tools_package_name} package.") + endif() + message(FATAL_ERROR + "Failed to find the host tool \"${full_name}\". It is part of " + ${pkg_found_msg}) else() message(STATUS "Tool '${full_name}' will be built from source.") endif() diff --git a/cmake/QtToolchainHelpers.cmake b/cmake/QtToolchainHelpers.cmake index 451e564221..41fee47670 100644 --- a/cmake/QtToolchainHelpers.cmake +++ b/cmake/QtToolchainHelpers.cmake @@ -195,8 +195,8 @@ set(__qt_chainload_toolchain_file \"\${__qt_initially_configured_toolchain_file} # xcodebuild from the command line would try to build with the wrong architecture. Also # provide an opt-out option just in case. # - # For a multi-architecture build (so simulator_and_device) we don't set an explicit - # architecture and let Xcode and the developer handle it. + # For a multi-architecture build (so simulator_and_device) we set an explicit + # architecture for simulator only, via _qt_internal_set_ios_simulator_arch. # # When using the Ninja generator, specify the first architecture from QT_OSX_ARCHITECTURES # (even with a simulator_and_device Qt build). This ensures that the default configuration diff --git a/cmake/QtWasmHelpers.cmake b/cmake/QtWasmHelpers.cmake index 9ed280fef5..3e14ee6e74 100644 --- a/cmake/QtWasmHelpers.cmake +++ b/cmake/QtWasmHelpers.cmake @@ -4,7 +4,6 @@ function (qt_internal_setup_wasm_target_properties wasmTarget) target_link_options("${wasmTarget}" INTERFACE "SHELL:-s ERROR_ON_UNDEFINED_SYMBOLS=1" - "SHELL:-s EXPORTED_RUNTIME_METHODS=UTF16ToString,stringToUTF16" "SHELL:-s MAX_WEBGL_VERSION=2" "SHELL:-s FETCH=1" "SHELL:-s WASM_BIGINT=1") @@ -73,7 +72,17 @@ function (qt_internal_setup_wasm_target_properties wasmTarget) set(QT_CFLAGS_OPTIMIZE_DEBUG "-Os" CACHE STRING INTERNAL FORCE) set(QT_FEATURE_optimize_debug ON CACHE BOOL INTERNAL FORCE) - target_link_options("${wasmTarget}" INTERFACE "SHELL:-s ASYNCIFY" "-Os" "-s" "ASYNCIFY_IMPORTS=[qt_asyncify_suspend_js, qt_asyncify_resume_js]") + target_link_options("${wasmTarget}" INTERFACE "SHELL:-s ASYNCIFY" "-Os") target_compile_definitions("${wasmTarget}" INTERFACE QT_HAVE_EMSCRIPTEN_ASYNCIFY) endif() + + # Set ASYNCIFY_IMPORTS unconditionally in order to support enabling asyncify at link time. + target_link_options("${wasmTarget}" INTERFACE "SHELL:-sASYNCIFY_IMPORTS=qt_asyncify_suspend_js,qt_asyncify_resume_js") + +endfunction() + +function(qt_internal_wasm_add_finalizers target) + qt_add_list_file_finalizer(_qt_internal_add_wasm_extra_exported_methods ${target}) endfunction() + + diff --git a/cmake/QtWrapperScriptHelpers.cmake b/cmake/QtWrapperScriptHelpers.cmake index adb50bf25b..d7efb726ac 100644 --- a/cmake/QtWrapperScriptHelpers.cmake +++ b/cmake/QtWrapperScriptHelpers.cmake @@ -95,8 +95,18 @@ function(qt_internal_create_wrapper_scripts) set(__qt_cmake_standalone_test_bin_name "qt-cmake-standalone-test") set(__qt_cmake_standalone_test_bin_path "${INSTALL_BINDIR}/${__qt_cmake_standalone_test_bin_name}") - set(__qt_cmake_private_path - "${QT_STAGING_PREFIX}/${INSTALL_BINDIR}/qt-cmake-private") + + # Configuring a standalone test on iOS should use the Xcode generator, but qt-cmake-private uses + # the generator that was used to build Qt itself (e.g. Ninja). + # Use qt-cmake instead, which does use the Xcode generator since Qt 6.2.5, 6.3.1, 6.4. + if(IOS) + set(__qt_cmake_private_path + "${QT_STAGING_PREFIX}/${INSTALL_BINDIR}/qt-cmake") + else() + set(__qt_cmake_private_path + "${QT_STAGING_PREFIX}/${INSTALL_BINDIR}/qt-cmake-private") + endif() + set(__qt_cmake_standalone_test_path "${__build_internals_install_dir}/${__build_internals_standalone_test_template_dir}") diff --git a/cmake/ios/Info.plist.app.in b/cmake/ios/Info.plist.app.in index f2cbe593b2..2f13828213 100644 --- a/cmake/ios/Info.plist.app.in +++ b/cmake/ios/Info.plist.app.in @@ -2,54 +2,53 @@ <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> - <key>CFBundleInfoDictionaryVersion</key> - <string>6.0</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> - <key>CFBundlePackageType</key> - <string>APPL</string> + <key>CFBundlePackageType</key> + <string>APPL</string> - <key>CFBundleName</key> - <string>${MACOSX_BUNDLE_BUNDLE_NAME}</string> + <key>CFBundleName</key> + <string>${MACOSX_BUNDLE_BUNDLE_NAME}</string> - <key>CFBundleDisplayName</key> - <string>${QT_INTERNAL_DOLLAR_VAR}{PRODUCT_NAME}</string> + <key>CFBundleDisplayName</key> + <string>${QT_INTERNAL_DOLLAR_VAR}{PRODUCT_NAME}</string> - <key>CFBundleIdentifier</key> - <string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string> + <key>CFBundleIdentifier</key> + <string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string> - <key>CFBundleExecutable</key> - <string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string> + <key>CFBundleExecutable</key> + <string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string> - <key>CFBundleVersion</key> - <string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string> + <key>CFBundleVersion</key> + <string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string> - <key>CFBundleShortVersionString</key> - <string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string> + <key>CFBundleShortVersionString</key> + <string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string> - <key>NSHumanReadableCopyright</key> - <string>${MACOSX_BUNDLE_COPYRIGHT}</string> + <key>CFBundleIconFile</key> + <string>${MACOSX_BUNDLE_ICON_FILE}</string> - <key>CFBundleIconFile</key> - <string>${MACOSX_BUNDLE_ICON_FILE}</string> + <key>CFBundleDevelopmentRegion</key> + <string>$(DEVELOPMENT_LANGUAGE)</string> + <key>CFBundleAllowMixedLocalizations</key> + <true/> - <key>CFBundleDevelopmentRegion</key> - <string>English</string> + <key>LSRequiresIPhoneOS</key> + <true/> - <key>LSRequiresIPhoneOS</key> - <true/> + <key>NOTE</key> + <string>This file was generated by Qt's default CMake support.</string> - <key>NOTE</key> - <string>This file was generated by Qt's default CMake support.</string> + <key>UILaunchStoryboardName</key> + <string>@qt_ios_launch_screen_plist_entry@</string> - <key>UILaunchStoryboardName</key> - <string>@qt_ios_launch_screen_plist_entry@</string> - - <key>UISupportedInterfaceOrientations</key> - <array> - <string>UIInterfaceOrientationPortrait</string> - <string>UIInterfaceOrientationPortraitUpsideDown</string> - <string>UIInterfaceOrientationLandscapeLeft</string> - <string>UIInterfaceOrientationLandscapeRight</string> - </array> + <key>UISupportedInterfaceOrientations</key> + <array> + <string>UIInterfaceOrientationPortrait</string> + <string>UIInterfaceOrientationPortraitUpsideDown</string> + <string>UIInterfaceOrientationLandscapeLeft</string> + <string>UIInterfaceOrientationLandscapeRight</string> + </array> </dict> </plist> diff --git a/cmake/macos/MacOSXBundleInfo.plist.in b/cmake/macos/MacOSXBundleInfo.plist.in index 2ead02b7d5..c791521655 100644 --- a/cmake/macos/MacOSXBundleInfo.plist.in +++ b/cmake/macos/MacOSXBundleInfo.plist.in @@ -29,7 +29,9 @@ <string>${MACOSX_BUNDLE_ICON_FILE}</string> <key>CFBundleDevelopmentRegion</key> - <string>English</string> + <string>en</string> + <key>CFBundleAllowMixedLocalizations</key> + <true/> <key>NSPrincipalClass</key> <string>NSApplication</string> diff --git a/cmake/modulecppexports.h.in b/cmake/modulecppexports.h.in index f4e976b540..78793080fb 100644 --- a/cmake/modulecppexports.h.in +++ b/cmake/modulecppexports.h.in @@ -16,8 +16,9 @@ # define Q_@module_define_infix@_EXPORT #endif -#if !defined(QT_BUILD_@module_define_infix@_LIB) || defined(QT_STATIC) +#if !defined(QT_BUILD_@module_define_infix@_LIB) && !defined(QT_STATIC) /* outside library → inline decl + defi */ +/* static builds treat everything as part of the library, so they never inline */ # define QT_@module_define_infix@_INLINE_SINCE(major, minor) inline # define QT_@module_define_infix@_INLINE_IMPL_SINCE(major, minor) 1 #elif defined(QT_@module_define_infix@_BUILD_REMOVED_API) |