diff options
author | Alexandru Croitor <alexandru.croitor@qt.io> | 2021-04-13 17:16:44 +0200 |
---|---|---|
committer | Alexandru Croitor <alexandru.croitor@qt.io> | 2021-04-16 14:22:31 +0200 |
commit | 609d0d41553f71543e3013833185de3950bbd00e (patch) | |
tree | 58fcbe342e079396cdaee4b65dbec90de4f28843 | |
parent | 65d8a285df7788c69889dbf4d5dd69f5145ba86a (diff) |
CMake: Fix default architecture selection for macOS and iOS
Before this change, we created a CMake toolchain file for iOS and
macOS universal which propagated the initially configured
CMAKE_OSX_ARCHITECTURES values to user projects.
So if Qt was configured with 2 arches, configuring a CMake user
project using the generated toolchain file would also build the
user project targeting those 2 arches.
The reason for this that the same toolchain file is used for
configuring both Qt and users projects and we needed to ensure that
other Qt repos are built with the same set of arches. That
unfortunately led the multiple arches to carry over into user
projects.
This is different from qmake behavior which configured user projects
with 1 arch only.
Instead of the toolchain file explicitly setting
CMAKE_OSX_ARCHITECTURES for all projects, save the initial list of
arches into QT_OSX_ARCHITECTURES.
Then if the toolchain file detects that we're building a Qt repo (by
checking for the presence of QT_REPO_MODULE_VERSION) set
CMAKE_OSX_ARCHITECTURES to QT_OSX_ARCHITECTURES to propagate the
initial list of arches.
For user projects we want to have some sensible defaults.
For macOS projects, leave the decision of the architecture to build
to CMake.
For iOS Xcode projects, leave the decision to Xcode.
For iOS Ninja projects, set the architecture to the first value of the
architectures used when configuring Qt.
As a side note this fixes an issue in our CI where we configured macOS
Qt with 2 architectures and then tried to run CMake build tests for
both architectures on a machine that doesn't have the universal SDK.
This led to build failures.
Because the CMake build tests act as regular user projects, now they
are configured with a single architecture that is automtically
detected by CMake.
Task-number: QTBUG-85447
Change-Id: Id1b7e78d7e67c1796efed10751416e5f857c16d2
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
(cherry picked from commit e379147f9571af8c3af5768b9040e0180819a855)
-rw-r--r-- | cmake/QtFeature.cmake | 15 | ||||
-rw-r--r-- | cmake/QtToolchainHelpers.cmake | 50 |
2 files changed, 56 insertions, 9 deletions
diff --git a/cmake/QtFeature.cmake b/cmake/QtFeature.cmake index 61e645f6e0..c0962d7683 100644 --- a/cmake/QtFeature.cmake +++ b/cmake/QtFeature.cmake @@ -890,9 +890,8 @@ function(qt_get_platform_try_compile_vars out_var) # Pass darwin specific options. # The architectures need to be passed explicitly to project-based try_compile calls even on # macOS, so that arm64 compilation works on Apple silicon. - if(CMAKE_OSX_ARCHITECTURES) - list(GET CMAKE_OSX_ARCHITECTURES 0 osx_first_arch) - + qt_internal_get_first_osx_arch(osx_first_arch) + if(osx_first_arch) # Do what qmake does, aka when doing a simulator_and_device build, build the # target architecture test only with the first given architecture, which should be the # device architecture, aka some variation of "arm" (armv7, arm64). @@ -909,6 +908,16 @@ function(qt_get_platform_try_compile_vars out_var) set("${out_var}" "${flags_cmd_line}" PARENT_SCOPE) endfunction() +# Set out_var to the first value of CMAKE_OSX_ARCHITECTURES. +# Sets an empty string if no architecture is present. +function(qt_internal_get_first_osx_arch out_var) + set(value "") + if(CMAKE_OSX_ARCHITECTURES) + list(GET CMAKE_OSX_ARCHITECTURES 0 value) + endif() + set(${out_var} "${value}" PARENT_SCOPE) +endfunction() + function(qt_config_compile_test_x86simd extension label) if (DEFINED TEST_X86SIMD_${extension}) return() diff --git a/cmake/QtToolchainHelpers.cmake b/cmake/QtToolchainHelpers.cmake index 5495cbf6c5..f4ee35be31 100644 --- a/cmake/QtToolchainHelpers.cmake +++ b/cmake/QtToolchainHelpers.cmake @@ -112,15 +112,53 @@ function(qt_internal_create_toolchain_file) "set(CMAKE_OSX_DEPLOYMENT_TARGET \"${CMAKE_OSX_DEPLOYMENT_TARGET}\" CACHE STRING \"\")") endif() + # Save list of initial architectures Qt was configured with. + set(_qt_osx_architectures_escaped "${CMAKE_OSX_ARCHITECTURES}") + string(REPLACE ";" "LITERAL_SEMICOLON" + _qt_osx_architectures_escaped "${_qt_osx_architectures_escaped}") + set(docstring "List of architectures Qt was built with") + list(APPEND init_platform + "set(QT_OSX_ARCHITECTURES \"${_qt_osx_architectures_escaped}\" CACHE STRING \"${docstring}\")") + list(APPEND init_platform "") + + # When building another qt repo, ensure the same list of architectures is used by default. + # Detection of a qt repo is done by checking for QT_REPO_MODULE_VERSION which is set in + # the repo's .cmake.conf file. + # Standalone tests will be not be built with multiple architectures to avoid issues in the + # CI when trying to run cmake build tests on VMs that do not have a universal macOS + # SDK. + list(APPEND init_platform "# Only build multiple architectures when building Qt itself") + list(APPEND init_platform "if((QT_REPO_MODULE_VERSION AND NOT QT_BUILD_STANDALONE_TESTS) OR QT_FORCE_QT_OSX_ARCHITECTURES)") + list(APPEND init_platform " set(__qt_toolchain_building_qt_repo TRUE)") + list(APPEND init_platform " set(CMAKE_OSX_ARCHITECTURES \"\${QT_OSX_ARCHITECTURES}\" CACHE STRING \"\")") + list(APPEND init_platform "endif()") + list(APPEND init_platform "") + + # For macOS user projects, default to not specifying any architecture. This means CMake will + # not pass an -arch flag to the compiler and the compiler will choose the default + # architecture to build for. + # On Apple Silicon, CMake will introspect whether it's running under Rosetta and will + # pass the detected architecture (x86_64 under Rosetta or arm64 natively) to the compiler. + # This is line with default CMake behavior for user projects. + # + # For iOS, we provide a bit more convenience. + # When the user project is built using the Xcode generator, don't specify a default + # architecture and let Xcode and the developer handle it. + # 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 + # at least tries to build something. if(UIKIT) + qt_internal_get_first_osx_arch(osx_first_arch) + list(APPEND init_platform "if(NOT CMAKE_GENERATOR STREQUAL \"Xcode\" AND NOT __qt_toolchain_building_qt_repo)") list(APPEND init_platform - "set(CMAKE_SYSTEM_NAME \"${CMAKE_SYSTEM_NAME}\" CACHE STRING \"\")") - set(_qt_osx_architectures_escaped "${CMAKE_OSX_ARCHITECTURES}") - string(REPLACE ";" "LITERAL_SEMICOLON" - _qt_osx_architectures_escaped "${_qt_osx_architectures_escaped}") - list(APPEND init_platform - "set(CMAKE_OSX_ARCHITECTURES \"${_qt_osx_architectures_escaped}\" CACHE STRING \"\")") + " set(CMAKE_OSX_ARCHITECTURES \"${osx_first_arch}\" CACHE STRING \"\")") + list(APPEND init_platform "endif()") + list(APPEND init_platform "") + endif() + if(UIKIT) + list(APPEND init_platform + "set(CMAKE_SYSTEM_NAME \"${CMAKE_SYSTEM_NAME}\" CACHE STRING \"\")") list(APPEND init_platform "if(CMAKE_GENERATOR STREQUAL \"Xcode\" AND NOT QT_NO_XCODE_EMIT_EPN)") list(APPEND init_platform " set_property(GLOBAL PROPERTY XCODE_EMIT_EFFECTIVE_PLATFORM_NAME OFF)") list(APPEND init_platform "endif()") |