qt5base-lts/cmake/QtBaseConfigureTests.cmake

234 lines
10 KiB
CMake
Raw Normal View History

include(CheckCXXSourceCompiles)
function(qt_run_config_test_architecture)
set(QT_BASE_CONFIGURE_TESTS_VARS_TO_EXPORT
"" CACHE INTERNAL "Test variables that should be exported" FORCE)
# Compile test to find the target architecture and sub-architectures.
set(flags "")
qt_get_platform_try_compile_vars(platform_try_compile_vars)
list(APPEND flags ${platform_try_compile_vars})
list(TRANSFORM flags PREPEND " " OUTPUT_VARIABLE flags_indented)
list(JOIN flags_indented "\n" flags_indented)
message(STATUS
"Building architecture extraction project with the following CMake arguments:\n${flags_indented}")
try_compile(
_arch_result
"${CMAKE_CURRENT_BINARY_DIR}/config.tests/arch"
"${CMAKE_CURRENT_SOURCE_DIR}/config.tests/arch"
arch
CMAKE_FLAGS ${flags}
OUTPUT_VARIABLE arch_test_output
)
if (NOT _arch_result)
message(FATAL_ERROR
"Failed to build architecture extraction project. Build output:\n ${arch_test_output}")
endif()
set(_arch_file_suffix "${CMAKE_EXECUTABLE_SUFFIX}")
# With emscripten the application entry point is a .js file (to be run with node for example),
# but the real "data" is in the .wasm file, so that's where we need to look for the ABI, etc.
# information.
if (WASM)
set(_arch_file_suffix ".wasm")
endif()
Add initial support for CMake "Ninja Multi-Config" generator This allows doing debug_and_release builds with Ninja on all platforms. The "Ninja Multi-Config generator" is available starting with CMake 3.17. Desired configurations can be set via CMAKE_CONFIGURATION_TYPES. Possible values: "Release, Debug, RelWithDebInfo, MinRelSize". For example -DCMAKE_CONFIGURATION_TYPES="Release;Debug". The first configuration is the 'default' configuration which is built when calling ninja with no arguments. To build all targets of a certain configuration use "ninja all:Release" or "ninja all:Debug". To build all targets in all configurations use "ninja all:all". Note that the first configuration influences which configuration of tools will be used when building the libraries for all configurations. In simple terms, when configured with -DCMAKE_CONFIGURATION_TYPES="Release;Debug" the release version of moc is used by AUTOMOC. When configured with -DCMAKE_CONFIGURATION_TYPES="Debug;Release" the debug version of moc is used by AUTOMOC. Framework builds and Ninja Multi-Config don't currently work together due to multiple bugs in CMake, which ends up generating an invalid ninja file with duplicate rules. There are also issues with placement of the debug artifacts. This will be handled in a follow up patch after CMake is fixed. Task-number: QTBUG-76899 Change-Id: If224adc0b71b7d1d6606738101536146aa866cd7 Reviewed-by: Qt CMake Build Bot Reviewed-by: Leander Beernaert <leander.beernaert@qt.io> Reviewed-by: Cristian Adam <cristian.adam@qt.io>
2019-12-06 14:12:17 +00:00
set(arch_test_location "config.tests/arch")
if(QT_MULTI_CONFIG_FIRST_CONFIG)
string(APPEND arch_test_location "/${QT_MULTI_CONFIG_FIRST_CONFIG}")
endif()
set(arch_dir "${CMAKE_CURRENT_BINARY_DIR}/${arch_test_location}")
file(GLOB arch_dir_globbed_files RELATIVE "${arch_dir}" "${arch_dir}/*")
list(JOIN arch_dir_globbed_files "\n" arch_dir_globbed_files)
set(_arch_file
Add initial support for CMake "Ninja Multi-Config" generator This allows doing debug_and_release builds with Ninja on all platforms. The "Ninja Multi-Config generator" is available starting with CMake 3.17. Desired configurations can be set via CMAKE_CONFIGURATION_TYPES. Possible values: "Release, Debug, RelWithDebInfo, MinRelSize". For example -DCMAKE_CONFIGURATION_TYPES="Release;Debug". The first configuration is the 'default' configuration which is built when calling ninja with no arguments. To build all targets of a certain configuration use "ninja all:Release" or "ninja all:Debug". To build all targets in all configurations use "ninja all:all". Note that the first configuration influences which configuration of tools will be used when building the libraries for all configurations. In simple terms, when configured with -DCMAKE_CONFIGURATION_TYPES="Release;Debug" the release version of moc is used by AUTOMOC. When configured with -DCMAKE_CONFIGURATION_TYPES="Debug;Release" the debug version of moc is used by AUTOMOC. Framework builds and Ninja Multi-Config don't currently work together due to multiple bugs in CMake, which ends up generating an invalid ninja file with duplicate rules. There are also issues with placement of the debug artifacts. This will be handled in a follow up patch after CMake is fixed. Task-number: QTBUG-76899 Change-Id: If224adc0b71b7d1d6606738101536146aa866cd7 Reviewed-by: Qt CMake Build Bot Reviewed-by: Leander Beernaert <leander.beernaert@qt.io> Reviewed-by: Cristian Adam <cristian.adam@qt.io>
2019-12-06 14:12:17 +00:00
"${CMAKE_CURRENT_BINARY_DIR}/${arch_test_location}/architecture_test${_arch_file_suffix}")
if (NOT EXISTS "${_arch_file}")
message(FATAL_ERROR
"Failed to find compiled architecture detection executable at ${_arch_file}. \
The following files were found at: ${arch_dir} \
${arch_dir_globbed_files}")
endif()
message(STATUS "Extracting architecture info from ${_arch_file}.")
CMake: Fix arch parsing for oss-fuzz I'll preface by saying, it's not clear to me why the behavior is different. Our qt_run_config_test_architecture function builds a target executable, and then uses file(STRINGS) to try and parse out some magic strings that we expect the executable to have (architecture, abi, etc). In qmake this was done by matching with a regular expression ending on a \\0 null byte character. In CMake, we do a string(FIND) and string(SUBSTRING until the end of the line) on a *line* returned from file(STRINGS). Notably, I did not find any regexp syntax provided by CMake to try and match a null byte character. Note the docs for file(STRINGS) implies to me that *lines* are detected by looking for newline characters '\n'. The docs also mention that binary data in the file is ignored. What's binary data though? If you open the executable with a hex editor, at least on macOS, the strings we are interested in are indeed separated by null byte chars, not newline chars. On most platforms file(STRINGS) did end a line on the null byte character. Except, for some reason not when building Qt for the oss-fuzz project with clang under Docker. Calling message() on one of the lines prints a very long string with null characters seemingly replaced with semicolons, and of course the matched architecture string is wrong and fails configuration. For *some reason*, if I add a "REGEX ==Qt=magic=Qt==" option to the file(STRINGS) command, the captured output lines don't contain semicolons even when building for oss-fuzz. The extracted strings are then correct, and configuration succeeds. Use the REGEX option workaround, with the aim to quickly fix Qt building for oss-fuzz for 6.0.1 release. Pick-to: 6.0 Fixes: QTBUG-89047 Change-Id: Iad11c1090c1187aadd39082f196050bf3290df95 Reviewed-by: Robert Loehning <robert.loehning@qt.io> Reviewed-by: Cristian Adam <cristian.adam@qt.io> Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
2020-12-02 14:25:03 +00:00
file(STRINGS "${_arch_file}" _arch_lines LENGTH_MINIMUM 16 LENGTH_MAXIMUM 1024 ENCODING UTF-8
REGEX "==Qt=magic=Qt==")
foreach (_line ${_arch_lines})
string(LENGTH "${_line}" lineLength)
string(FIND "${_line}" "==Qt=magic=Qt== Architecture:" _pos)
if (_pos GREATER -1)
math(EXPR _pos "${_pos}+29")
string(SUBSTRING "${_line}" ${_pos} -1 _architecture)
endif()
string(FIND "${_line}" "==Qt=magic=Qt== Sub-architecture:" _pos)
if (_pos GREATER -1 AND ${lineLength} GREATER 33)
math(EXPR _pos "${_pos}+34")
string(SUBSTRING "${_line}" ${_pos} -1 _sub_architecture)
string(REPLACE " " ";" _sub_architecture "${_sub_architecture}")
endif()
string(FIND "${_line}" "==Qt=magic=Qt== Build-ABI:" _pos)
if (_pos GREATER -1)
math(EXPR _pos "${_pos}+26")
string(SUBSTRING "${_line}" ${_pos} -1 _build_abi)
endif()
endforeach()
if (NOT _architecture OR NOT _build_abi)
list(SUBLIST _arch_lines 0 5 arch_lines_fewer)
list(JOIN arch_lines_fewer "\n" arch_lines_output)
message(FATAL_ERROR
"Failed to extract architecture data from file. \
Here are the first few lines extracted:\n${arch_lines_output}")
endif()
set(TEST_architecture 1 CACHE INTERNAL "Ran the architecture test")
set(TEST_architecture_arch "${_architecture}" CACHE INTERNAL "Target machine architecture")
list(APPEND QT_BASE_CONFIGURE_TESTS_VARS_TO_EXPORT TEST_architecture_arch)
set(TEST_subarch 1 CACHE INTERNAL "Ran machine subArchitecture test")
set(TEST_subarch_result "${_sub_architecture}" CACHE INTERNAL "Target sub-architectures")
list(APPEND QT_BASE_CONFIGURE_TESTS_VARS_TO_EXPORT TEST_subarch_result)
foreach(it ${_sub_architecture})
# Equivalent to qmake's QT_CPU_FEATURES.$arch.
set(TEST_arch_${TEST_architecture_arch}_subarch_${it} 1 CACHE INTERNAL "Target sub architecture result")
list(APPEND QT_BASE_CONFIGURE_TESTS_VARS_TO_EXPORT TEST_arch_${TEST_architecture_arch}_subarch_${it})
endforeach()
set(TEST_buildAbi "${_build_abi}" CACHE INTERNAL "Target machine buildAbi")
list(APPEND QT_BASE_CONFIGURE_TESTS_VARS_TO_EXPORT TEST_buildAbi)
set(QT_BASE_CONFIGURE_TESTS_VARS_TO_EXPORT ${QT_BASE_CONFIGURE_TESTS_VARS_TO_EXPORT} CACHE INTERNAL "Test variables that should be exported")
list(JOIN _sub_architecture " " subarch_summary)
set_property(GLOBAL PROPERTY qt_configure_subarch_summary "${subarch_summary}")
endfunction()
function(qt_run_linker_version_script_support)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/version_flag.map" "VERS_1 { global: sym; };
VERS_2 { global: sym; }
VERS_1;
")
if(DEFINED CMAKE_REQUIRED_FLAGS)
set(CMAKE_REQUIRED_FLAGS_SAVE ${CMAKE_REQUIRED_FLAGS})
else()
set(CMAKE_REQUIRED_FLAGS "")
endif()
set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} "-Wl,--version-script=\"${CMAKE_CURRENT_BINARY_DIR}/version_flag.map\"")
check_cxx_source_compiles("int main(void){return 0;}" HAVE_LD_VERSION_SCRIPT)
if(DEFINED CMAKE_REQUIRED_FLAGS_SAVE)
set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS_SAVE})
endif()
file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/conftest.map")
# For some reason the linker command line written by the XCode generator, which is
# subsequently executed by xcodebuild, ignores the linker flag, and thus the test
# seemingly succeeds. Explicitly disable the version script test on darwin platforms.
if(APPLE)
set(HAVE_LD_VERSION_SCRIPT OFF)
endif()
set(TEST_ld_version_script "${HAVE_LD_VERSION_SCRIPT}" CACHE INTERNAL "linker version script support")
endfunction()
function(qt_run_qtbase_config_tests)
qt_run_config_test_architecture()
qt_run_linker_version_script_support()
endfunction()
# The qmake build of android does not perform the right architecture tests and
# forcefully disables sse4 on android x86. We have to mimic this behavior
# for now
if (CMAKE_ANDROID_ARCH_ABI STREQUAL x86)
set(QT_FEATURE_sse4_1 OFF CACHE BOOL INTERNAL FORCE)
set(QT_FEATURE_sse4_2 OFF CACHE BOOL INTERNAL FORCE)
set(TEST_subarch_sse4_1 FALSE CACHE BOOL INTERNAL FORCE)
set(TEST_subarch_sse4_2 FALSE CACHE BOOL INTERNAL FORCE)
endif()
qt_run_qtbase_config_tests()
function(qt_internal_print_cmake_darwin_info)
if(APPLE)
if(NOT CMAKE_OSX_ARCHITECTURES)
set(default_osx_arch " (defaults to ${CMAKE_SYSTEM_PROCESSOR})")
endif()
message(STATUS "CMAKE_OSX_ARCHITECTURES: \"${CMAKE_OSX_ARCHITECTURES}\"${default_osx_arch}")
message(STATUS "CMAKE_OSX_SYSROOT: \"${CMAKE_OSX_SYSROOT}\"")
message(STATUS "CMAKE_OSX_DEPLOYMENT_TARGET: \"${CMAKE_OSX_DEPLOYMENT_TARGET}\"")
message(STATUS "QT_MAC_SDK_VERSION: \"${QT_MAC_SDK_VERSION}\"")
message(STATUS "QT_MAC_XCODE_VERSION: \"${QT_MAC_XCODE_VERSION}\"")
CMake: Fix building multi-arch universal macOS Qt Use the same approach we use for iOS, which is to set multiple CMAKE_OSX_ARCHITECTURES values and let the clang front end deal with lipo-ing the final libraries. For now, Qt can be configured to build universal macOS libraries by passing 2 architectures to CMake, either via: -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" or -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" Currently we recommend specifying the intel x86_64 arch as the first one, to get an intel slice configuration that is comparable to a non-universal intel build. Specifying the arm64 slice first could pessimize optimizations and reduce the feature set for the intel slice due to the limitation that we run configure tests only once. The first specified architecture is the one used to do all the configure tests. It 'mostly' defines the common feature set of both architecture slices, with the excepion of some special handling for sse2 and neon instructions. In the future we might want to run at least the Qt architecture config test for all specified architectures, so that we can extract all the supported sub-arches and instruction sets in a reliable way. For now, we use the same sse2 hack as for iOS simulator_and_device builds, otherwise QtGui fails to link due to missing qt_memfill32_sse2 and other symbols. The hack is somewhat augmented to ensure that reconfiguration still succeeds (same issue happened with iOS). Previously the sse2 feature condition was broken due to force setting the feature to be ON. Now the condition also checks for a special QT_FORCE_FEATURE_sse2 variable which we set internally. Note that we shouldn't build for arm64e, because the binaries get killed when running on AS with the following message: kernel: exec_mach_imgact: not running binary built against preview arm64e ABI. Aslo, by default, we disable the arm64 slice for qt sql plugins, mostly because the CI provisioned sql libraries that we depend on only contain x86_64 slices, and trying to build the sql plugins for both slices will fail with linker errors. This behavior can be disabled for all targets marked by qt_internal_force_macos_intel_arch, by setting the QT_FORCE_MACOS_ALL_ARCHES CMake option to ON. To disble it per-target one can set QT_FORCE_MACOS_ALL_ARCHES_${target} to ON. Task-number: QTBUG-85447 Change-Id: Iccb5dfcc1a21a8a8292bd3817df0ea46c3445f75 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
2021-03-24 15:03:35 +00:00
if(DEFINED CACHE{QT_IS_MACOS_UNIVERSAL})
message(STATUS "QT_IS_MACOS_UNIVERSAL: \"${QT_IS_MACOS_UNIVERSAL}\"")
endif()
if(QT_UIKIT_SDK)
message(STATUS "QT_UIKIT_SDK: \"${QT_UIKIT_SDK}\"")
endif()
CMake: Fix building multi-arch universal macOS Qt Use the same approach we use for iOS, which is to set multiple CMAKE_OSX_ARCHITECTURES values and let the clang front end deal with lipo-ing the final libraries. For now, Qt can be configured to build universal macOS libraries by passing 2 architectures to CMake, either via: -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" or -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" Currently we recommend specifying the intel x86_64 arch as the first one, to get an intel slice configuration that is comparable to a non-universal intel build. Specifying the arm64 slice first could pessimize optimizations and reduce the feature set for the intel slice due to the limitation that we run configure tests only once. The first specified architecture is the one used to do all the configure tests. It 'mostly' defines the common feature set of both architecture slices, with the excepion of some special handling for sse2 and neon instructions. In the future we might want to run at least the Qt architecture config test for all specified architectures, so that we can extract all the supported sub-arches and instruction sets in a reliable way. For now, we use the same sse2 hack as for iOS simulator_and_device builds, otherwise QtGui fails to link due to missing qt_memfill32_sse2 and other symbols. The hack is somewhat augmented to ensure that reconfiguration still succeeds (same issue happened with iOS). Previously the sse2 feature condition was broken due to force setting the feature to be ON. Now the condition also checks for a special QT_FORCE_FEATURE_sse2 variable which we set internally. Note that we shouldn't build for arm64e, because the binaries get killed when running on AS with the following message: kernel: exec_mach_imgact: not running binary built against preview arm64e ABI. Aslo, by default, we disable the arm64 slice for qt sql plugins, mostly because the CI provisioned sql libraries that we depend on only contain x86_64 slices, and trying to build the sql plugins for both slices will fail with linker errors. This behavior can be disabled for all targets marked by qt_internal_force_macos_intel_arch, by setting the QT_FORCE_MACOS_ALL_ARCHES CMake option to ON. To disble it per-target one can set QT_FORCE_MACOS_ALL_ARCHES_${target} to ON. Task-number: QTBUG-85447 Change-Id: Iccb5dfcc1a21a8a8292bd3817df0ea46c3445f75 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
2021-03-24 15:03:35 +00:00
qt_internal_get_first_osx_arch(osx_first_arch)
if(osx_first_arch)
message(STATUS "Configure tests main architecture (in multi-arch build): \"${osx_first_arch}\"")
endif()
endif()
endfunction()
qt_internal_print_cmake_darwin_info()
function(qt_internal_print_cmake_host_and_target_info)
CMake: Bump the minimum required CMake version to build Qt to 3.18 Add a new function that returns the minimum CMake version required to build Qt. Pass that value to cmake_minimum_required() when building qtbase and its standalone tests. The minimum supported CMake version is read from qtbase/.cmake.conf and its value should be updated when the need arises. It's the main source of truth for all repos. Provide a way to lower the minimum CMake version at configure time by passing a value via QT_FORCE_MIN_CMAKE_VERSION. This is not an officially supported way of building Qt. If the specified version is lower than Qt's supported minimum, show a warning. Nevertheless the option is useful for testing how Qt builds with a different minimum CMake version due to different policies being enabled by default. Issue warnings for CMake versions that are higher than the minimum version but are known to cause issues when building Qt. A counterpart change is needed in qt5 to ensure the minimum CMake version is set at the proper time for top-level builds. Ideally we would use the same 'check the CMake minimum version` code in all our repositories, but that will cause lots of duplication because we can't really find_package() the code and doing something like include(../qtbase/foo.cmake) hardcodes assumptions about repo locations. So for now we don't bump the minimum version in child repo cmake_minimum_required calls (qtsvg, qtdeclarative, etc). Instead we record both the minimum supported version and the computed minimum version (in case a different version was forced) in QtBuildInternalsExtra.cmake. Then we require qtbase's computed min version in qt_build_repo_begin(). This won't set policies as cmake_minimum_required would, but at least it propagates what minimum CMake version should be used for child repos. We might still have to bump the versions in child repos at some point. Task-number: QTBUG-88086 Change-Id: Ida1c0d5d3e0fbb15d2aee9b68abab7a1648774b9 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Cristian Adam <cristian.adam@qt.io>
2020-10-30 16:42:34 +00:00
message(STATUS "CMAKE_VERSION: \"${CMAKE_VERSION}\"")
message(STATUS "CMAKE_HOST_SYSTEM: \"${CMAKE_HOST_SYSTEM}\"")
message(STATUS "CMAKE_HOST_SYSTEM_NAME: \"${CMAKE_HOST_SYSTEM_NAME}\"")
message(STATUS "CMAKE_HOST_SYSTEM_VERSION: \"${CMAKE_HOST_SYSTEM_VERSION}\"")
message(STATUS "CMAKE_HOST_SYSTEM_PROCESSOR: \"${CMAKE_HOST_SYSTEM_PROCESSOR}\"")
message(STATUS "CMAKE_SYSTEM: \"${CMAKE_SYSTEM_NAME}\"")
message(STATUS "CMAKE_SYSTEM_NAME: \"${CMAKE_SYSTEM_NAME}\"")
message(STATUS "CMAKE_SYSTEM_VERSION: \"${CMAKE_SYSTEM_VERSION}\"")
message(STATUS "CMAKE_SYSTEM_PROCESSOR: \"${CMAKE_SYSTEM_PROCESSOR}\"")
message(STATUS "CMAKE_CROSSCOMPILING: \"${CMAKE_CROSSCOMPILING}\"")
endfunction()
qt_internal_print_cmake_host_and_target_info()
function(qt_internal_print_cmake_compiler_info)
message(STATUS "CMAKE_C_COMPILER: \"${CMAKE_C_COMPILER}\" (${CMAKE_C_COMPILER_VERSION})")
message(STATUS "CMAKE_CXX_COMPILER: \"${CMAKE_CXX_COMPILER}\" (${CMAKE_CXX_COMPILER_VERSION})")
if(CMAKE_OBJC_COMPILER)
message(STATUS "CMAKE_OBJC_COMPILER: \"${CMAKE_OBJC_COMPILER}\" (${CMAKE_OBJC_COMPILER_VERSION})")
endif()
if(CMAKE_OBJCXX_COMPILER)
message(STATUS "CMAKE_OBJCXX_COMPILER: \"${CMAKE_OBJCXX_COMPILER}\" (${CMAKE_OBJCXX_COMPILER_VERSION})")
endif()
endfunction()
qt_internal_print_cmake_compiler_info()
function(qt_internal_print_cmake_windows_info)
if(MSVC_VERSION)
message(STATUS "MSVC_VERSION: \"${MSVC_VERSION}\"")
endif()
if(MSVC_TOOLSET_VERSION)
message(STATUS "MSVC_TOOLSET_VERSION: \"${MSVC_TOOLSET_VERSION}\"")
endif()
endfunction()
qt_internal_print_cmake_windows_info()
function(qt_internal_print_cmake_android_info)
if(ANDROID)
message(STATUS "ANDROID_TOOLCHAIN: \"${ANDROID_TOOLCHAIN}\"")
message(STATUS "ANDROID_NDK: \"${ANDROID_NDK}\"")
message(STATUS "ANDROID_ABI: \"${ANDROID_ABI}\"")
message(STATUS "ANDROID_PLATFORM: \"${ANDROID_PLATFORM}\"")
message(STATUS "ANDROID_STL: \"${ANDROID_STL}\"")
message(STATUS "ANDROID_PIE: \"${ANDROID_PIE}\"")
message(STATUS "ANDROID_CPP_FEATURES: \"${ANDROID_CPP_FEATURES}\"")
message(STATUS "ANDROID_ALLOW_UNDEFINED_SYMBOLS: \"${ANDROID_ALLOW_UNDEFINED_SYMBOLS}\"")
message(STATUS "ANDROID_ARM_MODE: \"${ANDROID_ARM_MODE}\"")
message(STATUS "ANDROID_ARM_NEON: \"${ANDROID_ARM_NEON}\"")
message(STATUS "ANDROID_DISABLE_FORMAT_STRING_CHECKS: \"${ANDROID_DISABLE_FORMAT_STRING_CHECKS}\"")
message(STATUS "ANDROID_NATIVE_API_LEVEL: \"${ANDROID_NATIVE_API_LEVEL}\"")
message(STATUS "ANDROID_LLVM_TRIPLE: \"${ANDROID_LLVM_TRIPLE}\"")
endif()
endfunction()
qt_internal_print_cmake_android_info()