diff --git a/cmake/QtBaseGlobalTargets.cmake b/cmake/QtBaseGlobalTargets.cmake index db469992451..6398dbfb5bb 100644 --- a/cmake/QtBaseGlobalTargets.cmake +++ b/cmake/QtBaseGlobalTargets.cmake @@ -218,6 +218,7 @@ qt_copy_or_install(FILES cmake/QtAutogenHelpers.cmake cmake/QtBuild.cmake cmake/QtBuildHelpers.cmake + cmake/QtBuildOptionsHelpers.cmake cmake/QtBuildPathsHelpers.cmake cmake/QtBuildInformation.cmake cmake/QtCMakeHelpers.cmake diff --git a/cmake/QtBuildHelpers.cmake b/cmake/QtBuildHelpers.cmake index 64d84be8442..6e0cd66e78a 100644 --- a/cmake/QtBuildHelpers.cmake +++ b/cmake/QtBuildHelpers.cmake @@ -1,6 +1,75 @@ # Copyright (C) 2023 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause +macro(qt_internal_set_qt_building_qt) + # Set the QT_BUILDING_QT variable so we can verify whether we are building + # Qt from source. + # Make sure not to set it when building a standalone test, otherwise + # upon reconfiguration we get an error about qt_internal_add_test + # not being found due the if(NOT QT_BUILDING_QT) check we have + # in each standalone test. + if(NOT QT_INTERNAL_IS_STANDALONE_TEST) + set(QT_BUILDING_QT TRUE CACHE BOOL + "When this is present and set to true, it signals that we are building Qt from source.") + endif() +endmacro() + +macro(qt_internal_unset_extra_build_internals_vars) + # Reset content of extra build internal vars for each inclusion of QtSetup. + unset(QT_EXTRA_BUILD_INTERNALS_VARS) +endmacro() + +macro(qt_internal_get_generator_is_multi_config) + # Save the global property in a variable to make it available to feature conditions. + get_property(QT_GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +endmacro() + +macro(qt_internal_setup_position_independent_code) + ## Position independent code: + set(CMAKE_POSITION_INDEPENDENT_CODE ON) + + # Does the linker support position independent code? + include(CheckPIESupported) + check_pie_supported() +endmacro() + +macro(qt_internal_set_link_depends_no_shared) + # Do not relink dependent libraries when no header has changed: + set(CMAKE_LINK_DEPENDS_NO_SHARED ON) +endmacro() + +macro(qt_internal_set_qt_source_tree_var) + # Specify the QT_SOURCE_TREE only when building qtbase. Needed by some tests when the tests are + # built as part of the project, and not standalone. For standalone tests, the value is set in + # QtBuildInternalsExtra.cmake. + if(PROJECT_NAME STREQUAL "QtBase") + set(QT_SOURCE_TREE "${QtBase_SOURCE_DIR}" CACHE PATH + "A path to the source tree of the previously configured QtBase project." FORCE) + endif() +endmacro() + +macro(qt_internal_include_qt_platform_android) + ## Android platform settings + if(ANDROID) + include(QtPlatformAndroid) + endif() +endmacro() + +macro(qt_internal_set_compiler_optimization_flags) + include(QtCompilerOptimization) +endmacro() + +macro(qt_internal_set_compiler_warning_flags) + include(QtCompilerFlags) +endmacro() + +macro(qt_internal_set_skip_setup_deployment) + if(NOT QT_BUILD_EXAMPLES) + # Disable deployment setup to avoid warnings about missing patchelf with CMake < 3.21. + set(QT_SKIP_SETUP_DEPLOYMENT ON) + endif() +endmacro() + macro(qt_internal_reset_global_state) qt_internal_clear_qt_repo_known_modules() qt_internal_clear_qt_repo_known_plugin_types() @@ -60,12 +129,15 @@ macro(qt_internal_include_all_helpers) include(Qt3rdPartyLibraryHelpers) include(QtAppHelpers) include(QtAutogenHelpers) + include(QtBuildInformation) + include(QtBuildOptionsHelpers) include(QtBuildPathsHelpers) include(QtCMakeHelpers) include(QtDbusHelpers) include(QtDeferredDependenciesHelpers) include(QtDocsHelpers) include(QtExecutableHelpers) + include(QtFeature) include(QtFindPackageHelpers) include(QtFlagHandlingHelpers) include(QtFrameworkHelpers) @@ -176,11 +248,52 @@ macro(qt_internal_setup_android_platform_specifics) endmacro() macro(qt_internal_setup_build_and_global_variables) + qt_internal_set_qt_building_qt() + qt_internal_compute_features_from_possible_inputs() + + # Depends on qt_internal_compute_features_from_possible_inputs + qt_internal_set_default_build_type() + + qt_internal_set_message_log_level(CMAKE_MESSAGE_LOG_LEVEL) + qt_internal_unset_extra_build_internals_vars() + qt_internal_get_generator_is_multi_config() + + # Depends on qt_internal_set_default_build_type + qt_internal_setup_cmake_config_postfix() + + qt_internal_setup_position_independent_code() + qt_internal_set_link_depends_no_shared() + + # Depends on qt_internal_compute_features_from_possible_inputs + qt_internal_setup_default_install_prefix() + + qt_internal_set_qt_source_tree_var() + qt_internal_set_export_compile_commands() + qt_internal_set_configure_from_ide() + + # Depends on qt_internal_compute_features_from_possible_inputs + + qt_internal_setup_build_benchmarks() + + # Depends on qt_internal_compute_features_from_possible_inputs + # Depends on qt_internal_setup_build_benchmarks + qt_internal_setup_build_tests() + + qt_internal_setup_build_tools() + + # Depends on qt_internal_setup_default_install_prefix + qt_internal_setup_build_examples() + + qt_internal_set_qt_host_path() + + qt_internal_include_qt_platform_android() + + # Depends on qt_internal_setup_default_install_prefix qt_internal_setup_paths_and_prefixes() qt_internal_reset_global_state() - # Depends on paths and prefixes. + # Depends on qt_internal_setup_paths_and_prefixes qt_internal_set_mkspecs_dir() qt_internal_setup_platform_definitions_and_mkspec() @@ -199,5 +312,17 @@ macro(qt_internal_setup_build_and_global_variables) qt_internal_set_apple_archiver_flags() qt_internal_set_debug_extend_target() qt_internal_setup_poor_mans_scope_finalizer() + + qt_internal_set_compiler_optimization_flags() + qt_internal_set_compiler_warning_flags() + + qt_set_language_standards() + qt_internal_set_use_ccache() + qt_internal_set_unity_build() + qt_internal_set_allow_symlink_in_paths() + qt_internal_set_skip_setup_deployment() + qt_internal_set_qt_allow_download() + + qt_internal_detect_dirty_features() endmacro() diff --git a/cmake/QtBuildInformation.cmake b/cmake/QtBuildInformation.cmake index f9495bb0d26..e8172c99298 100644 --- a/cmake/QtBuildInformation.cmake +++ b/cmake/QtBuildInformation.cmake @@ -1,6 +1,22 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause +function(qt_internal_set_message_log_level out_var) + # Decide whether output should be verbose or not. + # Default to verbose (--log-level=STATUS) in a developer-build and + # non-verbose (--log-level=NOTICE) otherwise. + # If a custom CMAKE_MESSAGE_LOG_LEVEL was specified, it takes priority. + # Passing an explicit --log-level=Foo has the highest priority. + if(NOT CMAKE_MESSAGE_LOG_LEVEL) + if(FEATURE_developer_build OR QT_FEATURE_developer_build) + set(CMAKE_MESSAGE_LOG_LEVEL "STATUS") + else() + set(CMAKE_MESSAGE_LOG_LEVEL "NOTICE") + endif() + set(${out_var} "${CMAKE_MESSAGE_LOG_LEVEL}" PARENT_SCOPE) + endif() +endfunction() + function(qt_print_feature_summary) if(QT_SUPERBUILD) qt_internal_set_message_log_level(message_log_level) diff --git a/cmake/QtBuildOptionsHelpers.cmake b/cmake/QtBuildOptionsHelpers.cmake new file mode 100644 index 00000000000..eeff825b40d --- /dev/null +++ b/cmake/QtBuildOptionsHelpers.cmake @@ -0,0 +1,237 @@ +# Copyright (C) 2023 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +macro(qt_internal_set_default_build_type) + set(_default_build_type "Release") + if(FEATURE_developer_build) + set(_default_build_type "Debug") + endif() + + # Try to detect if an explicit CMAKE_BUILD_TYPE was set by the user. + # CMake sets CMAKE_BUILD_TYPE_INIT to Debug on most Windows platforms and doesn't set + # anything for UNIXes. CMake assigns CMAKE_BUILD_TYPE_INIT to CMAKE_BUILD_TYPE during + # first project() if CMAKE_BUILD_TYPE has no previous value. + # We use extra information about the state of CMAKE_BUILD_TYPE before the first + # project() call that's set in QtAutodetect. + # STREQUAL check needs to have expanded variables because an undefined var is not equal + # to an empty defined var. + # See also qt_internal_force_set_cmake_build_type_conditionally which is used + # to set the build type when building other repos or tests. + if("${CMAKE_BUILD_TYPE}" STREQUAL "${CMAKE_BUILD_TYPE_INIT}" + AND NOT __qt_auto_detect_cmake_build_type_before_project_call + AND NOT __qt_build_internals_cmake_build_type + AND NOT CMAKE_CONFIGURATION_TYPES) + message(STATUS "Setting build type to '${_default_build_type}' as none was specified.") + set(CMAKE_BUILD_TYPE "${_default_build_type}" CACHE STRING "Choose the type of build." FORCE) + set_property(CACHE CMAKE_BUILD_TYPE + PROPERTY STRINGS + "Debug" "Release" "MinSizeRel" "RelWithDebInfo") # Set the possible values for cmake-gui. + elseif(CMAKE_CONFIGURATION_TYPES) + message(STATUS "Building for multiple configurations: ${CMAKE_CONFIGURATION_TYPES}.") + message(STATUS "Main configuration is: ${QT_MULTI_CONFIG_FIRST_CONFIG}.") + if(CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE) + 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() +endmacro() + +macro(qt_internal_set_configure_from_ide) + # QT_INTERNAL_CONFIGURE_FROM_IDE is set to TRUE for the following known IDE applications: + # - Qt Creator, detected by QTC_RUN environment variable + # - CLion, detected by CLION_IDE environment variable + # - Visual Studio Code, detected by VSCODE_CLI environment variable + if("$ENV{QTC_RUN}" OR "$ENV{CLION_IDE}" OR "$ENV{VSCODE_CLI}") + set(QT_INTERNAL_CONFIGURE_FROM_IDE TRUE CACHE INTERNAL "Configuring Qt Project from IDE") + else() + set(QT_INTERNAL_CONFIGURE_FROM_IDE FALSE CACHE INTERNAL "Configuring Qt Project from IDE") + endif() +endmacro() + +macro(qt_internal_set_export_compile_commands) + if(FEATURE_developer_build) + if(DEFINED QT_CMAKE_EXPORT_COMPILE_COMMANDS) + set(CMAKE_EXPORT_COMPILE_COMMANDS ${QT_CMAKE_EXPORT_COMPILE_COMMANDS}) + else() + set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + endif() + endif() +endmacro() + +macro(qt_internal_setup_build_benchmarks) + if(FEATURE_developer_build) + set(__build_benchmarks ON) + + # Disable benchmarks for single configuration generators which do not build + # with release configuration. + if(CMAKE_BUILD_TYPE AND CMAKE_BUILD_TYPE STREQUAL Debug) + set(__build_benchmarks OFF) + endif() + else() + set(__build_benchmarks OFF) + endif() + + # Build Benchmarks + option(QT_BUILD_BENCHMARKS "Build Qt Benchmarks" ${__build_benchmarks}) +endmacro() + +macro(qt_internal_setup_build_tests) + if(FEATURE_developer_build) + set(_qt_build_tests_default ON) + + # Tests are not built by default with qmake for iOS and friends, and thus the overall build + # tends to fail. Disable them by default when targeting uikit. + if(UIKIT OR ANDROID) + set(_qt_build_tests_default OFF) + endif() + else() + set(_qt_build_tests_default OFF) + endif() + + # If benchmarks are explicitly enabled, force tests to also be built, even if they might + # not work on the platform. + if(QT_BUILD_BENCHMARKS) + set(_qt_build_tests_default ON) + endif() + + ## Set up testing + option(QT_BUILD_TESTS "Build the testing tree." ${_qt_build_tests_default}) + unset(_qt_build_tests_default) + option(QT_BUILD_TESTS_BY_DEFAULT + "Should tests be built as part of the default 'all' target." ON) + if(QT_BUILD_STANDALONE_TESTS) + # BuildInternals might have set it to OFF on initial configuration. So force it to ON when + # building standalone tests. + set(QT_BUILD_TESTS ON CACHE BOOL "Build the testing tree." FORCE) + + # Also force the tests to be built as part of the default build target. + set(QT_BUILD_TESTS_BY_DEFAULT ON CACHE BOOL + "Should tests be built as part of the default 'all' target." FORCE) + endif() + set(BUILD_TESTING ${QT_BUILD_TESTS} CACHE INTERNAL "") + + if(WASM) + set(_qt_batch_tests ON) + else() + set(_qt_batch_tests OFF) + endif() + + if(DEFINED INPUT_batch_tests) + if (${INPUT_batch_tests}) + set(_qt_batch_tests ON) + else() + set(_qt_batch_tests OFF) + endif() + endif() + + option(QT_BUILD_TESTS_BATCHED "Link all tests into a single binary." ${_qt_batch_tests}) + + if(QT_BUILD_TESTS AND QT_BUILD_TESTS_BATCHED AND CMAKE_VERSION VERSION_LESS "3.19") + message(FATAL_ERROR + "Test batching requires at least CMake 3.19, due to requiring per-source " + "TARGET_DIRECTORY assignments and DEFER calls.") + endif() + + option(QT_BUILD_MANUAL_TESTS "Build Qt manual tests" 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() + + option(QT_BUILD_MINIMAL_ANDROID_MULTI_ABI_TESTS + "Build minimal subset of tests for Android multi-ABI Qt builds" OFF) + + include(CTest) + enable_testing() +endmacro() + +macro(qt_internal_setup_build_tools) + # QT_BUILD_TOOLS_WHEN_CROSSCOMPILING -> QT_FORCE_BUILD_TOOLS + # pre-6.4 compatibility flag (remove sometime in the future) + if(CMAKE_CROSSCOMPILING AND QT_BUILD_TOOLS_WHEN_CROSSCOMPILING) + message(WARNING "QT_BUILD_TOOLS_WHEN_CROSSCOMPILING is deprecated. " + "Please use QT_FORCE_BUILD_TOOLS instead.") + set(QT_FORCE_BUILD_TOOLS TRUE CACHE INTERNAL "" FORCE) + endif() + + # When cross-building, we don't build tools by default. Sometimes this also covers Qt apps as + # well. Like in qttools/assistant/assistant.pro, load(qt_app), which is guarded by a + # qtNomakeTools() call. + set(_qt_build_tools_by_default_default ON) + if(CMAKE_CROSSCOMPILING AND NOT QT_FORCE_BUILD_TOOLS) + set(_qt_build_tools_by_default_default OFF) + endif() + option(QT_BUILD_TOOLS_BY_DEFAULT "Should tools be built as part of the default 'all' target." + "${_qt_build_tools_by_default_default}") + unset(_qt_build_tools_by_default_default) +endmacro() + +macro(qt_internal_setup_build_examples) + option(QT_BUILD_EXAMPLES "Build Qt examples" OFF) + option(QT_BUILD_EXAMPLES_BY_DEFAULT + "Should examples be built as part of the default 'all' target." ON) + option(QT_INSTALL_EXAMPLES_SOURCES "Install example sources" OFF) + option(QT_INSTALL_EXAMPLES_SOURCES_BY_DEFAULT + "Install example sources as part of the default 'install' target" ON) + + # FIXME: Support prefix builds as well QTBUG-96232 + if(QT_WILL_INSTALL) + set(_qt_build_examples_as_external OFF) + else() + set(_qt_build_examples_as_external ON) + endif() + option(QT_BUILD_EXAMPLES_AS_EXTERNAL "Should examples be built as ExternalProjects." + ${_qt_build_examples_as_external}) + unset(_qt_build_examples_as_external) +endmacro() + +macro(qt_internal_set_qt_host_path) + ## Path used to find host tools, either when cross-compiling or just when using the tools from + ## a different host build. + set(QT_HOST_PATH "$ENV{QT_HOST_PATH}" CACHE PATH + "Installed Qt host directory path, used for cross compiling.") +endmacro() + +macro(qt_internal_set_use_ccache) + option(QT_USE_CCACHE "Enable the use of ccache") + if(QT_USE_CCACHE) + find_program(CCACHE_PROGRAM ccache) + if(CCACHE_PROGRAM) + set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_PROGRAM}") + set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PROGRAM}") + set(CMAKE_OBJC_COMPILER_LAUNCHER "${CCACHE_PROGRAM}") + set(CMAKE_OBJCXX_COMPILER_LAUNCHER "${CCACHE_PROGRAM}") + else() + message(FATAL_ERROR "Ccache use was requested, but the program was not found.") + endif() + endif() +endmacro() + +macro(qt_internal_set_unity_build) + option(QT_UNITY_BUILD "Enable unity (jumbo) build") + set(QT_UNITY_BUILD_BATCH_SIZE "32" CACHE STRING "Unity build batch size") + if(QT_UNITY_BUILD) + set(CMAKE_UNITY_BUILD ON) + set(CMAKE_UNITY_BUILD_BATCH_SIZE "${QT_UNITY_BUILD_BATCH_SIZE}") + endif() +endmacro() + +macro(qt_internal_set_allow_symlink_in_paths) + option(QT_ALLOW_SYMLINK_IN_PATHS "Allows symlinks in paths." OFF) +endmacro() + +macro(qt_internal_set_qt_allow_download) + option(QT_ALLOW_DOWNLOAD "Allows files to be downloaded when building Qt." OFF) +endmacro() diff --git a/cmake/QtBuildPathsHelpers.cmake b/cmake/QtBuildPathsHelpers.cmake index 9b24f8bf913..edc43f2f140 100644 --- a/cmake/QtBuildPathsHelpers.cmake +++ b/cmake/QtBuildPathsHelpers.cmake @@ -1,6 +1,57 @@ # Copyright (C) 2023 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause +macro(qt_internal_setup_default_install_prefix) + # Detect non-prefix builds: either when the qtbase install prefix is set to the binary dir + # or when a developer build is explicitly enabled and no install prefix (or staging prefix) + # is specified. + # This detection only happens when building qtbase, and later is propagated via the generated + # QtBuildInternalsExtra.cmake file. + if (PROJECT_NAME STREQUAL "QtBase" AND NOT QT_BUILD_STANDALONE_TESTS) + if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + # Handle both FEATURE_ and QT_FEATURE_ cases when they are specified on the command line + # explicitly. It's possible for one to be set, but not the other, because + # qtbase/configure.cmake is not processed by this point. + if((FEATURE_developer_build + OR QT_FEATURE_developer_build + OR FEATURE_no_prefix + OR QT_FEATURE_no_prefix + ) + AND NOT CMAKE_STAGING_PREFIX) + # Handle non-prefix builds by setting the CMake install prefix to point to qtbase's + # build dir. While building another repo (like qtsvg) the CMAKE_PREFIX_PATH should + # be set on the command line to point to the qtbase build dir. + set(__qt_default_prefix "${QtBase_BINARY_DIR}") + else() + if(CMAKE_HOST_WIN32) + set(__qt_default_prefix "C:/Qt/") + else() + set(__qt_default_prefix "/usr/local/") + endif() + string(APPEND __qt_default_prefix + "Qt-${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") + endif() + set(CMAKE_INSTALL_PREFIX ${__qt_default_prefix} CACHE PATH + "Install path prefix, prepended onto install directories." FORCE) + unset(__qt_default_prefix) + endif() + if(CMAKE_STAGING_PREFIX) + set(__qt_prefix "${CMAKE_STAGING_PREFIX}") + else() + set(__qt_prefix "${CMAKE_INSTALL_PREFIX}") + endif() + if(__qt_prefix STREQUAL QtBase_BINARY_DIR) + set(__qt_will_install_value OFF) + else() + set(__qt_will_install_value ON) + endif() + set(QT_WILL_INSTALL ${__qt_will_install_value} CACHE BOOL + "Boolean indicating if doing a Qt prefix build (vs non-prefix build)." FORCE) + unset(__qt_prefix) + unset(__qt_will_install_value) + endif() +endmacro() + function(qt_internal_setup_build_and_install_paths) # Compute the values of QT_BUILD_DIR, QT_INSTALL_DIR, QT_CONFIG_BUILD_DIR, QT_CONFIG_INSTALL_DIR # taking into account whether the current build is a prefix build or a non-prefix build, diff --git a/cmake/QtFeature.cmake b/cmake/QtFeature.cmake index 9c8cbe60b37..ed2adaae741 100644 --- a/cmake/QtFeature.cmake +++ b/cmake/QtFeature.cmake @@ -911,6 +911,18 @@ function(qt_internal_detect_dirty_features) endif() endfunction() +macro(qt_internal_compute_features_from_possible_inputs) + # Pre-calculate the developer_build feature if it's set by the user via the I + # NPUT_developer_build variable when using the configure script. When not using configure, don't + # take the INPUT variable into account, so that users can toggle the feature directly in the + # cache or via IDE. + qt_internal_compute_feature_value_from_possible_input(developer_build) + + # Pre-calculate the no_prefix feature if it's set by configure via INPUT_no_prefix. + # This needs to be done before qtbase/configure.cmake is processed. + qt_internal_compute_feature_value_from_possible_input(no_prefix) +endmacro() + function(qt_config_compile_test name) if(DEFINED "TEST_${name}") return() diff --git a/cmake/QtSetup.cmake b/cmake/QtSetup.cmake index bf21e028a08..a420495756d 100644 --- a/cmake/QtSetup.cmake +++ b/cmake/QtSetup.cmake @@ -1,425 +1,6 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -## Set a default build type if none was specified - -# Set the QT_BUILDING_QT variable so we can verify whether we are building -# Qt from source. -# Make sure not to set it when building a standalone test, otherwise -# upon reconfiguration we get an error about qt_internal_add_test -# not being found due the if(NOT QT_BUILDING_QT) check we have -# in each standalone test. -if(NOT QT_INTERNAL_IS_STANDALONE_TEST) - set(QT_BUILDING_QT TRUE CACHE BOOL - "When this is present and set to true, it signals that we are building Qt from source.") -endif() - -# Pre-calculate the developer_build feature if it's set by the user via the INPUT_developer_build -# variable when using the configure script. When not using configure, don't take the INPUT variable -# into account, so that users can toggle the feature directly in the cache or via IDE. -qt_internal_compute_feature_value_from_possible_input(developer_build) - -# Pre-calculate the no_prefix feature if it's set by configure via INPUT_no_prefix. -# This needs to be done before qtbase/configure.cmake is processed. -qt_internal_compute_feature_value_from_possible_input(no_prefix) - -set(_default_build_type "Release") -if(FEATURE_developer_build) - set(_default_build_type "Debug") -endif() - -function(qt_internal_set_message_log_level out_var) - # Decide whether output should be verbose or not. - # Default to verbose (--log-level=STATUS) in a developer-build and - # non-verbose (--log-level=NOTICE) otherwise. - # If a custom CMAKE_MESSAGE_LOG_LEVEL was specified, it takes priority. - # Passing an explicit --log-level=Foo has the highest priority. - if(NOT CMAKE_MESSAGE_LOG_LEVEL) - if(FEATURE_developer_build OR QT_FEATURE_developer_build) - set(CMAKE_MESSAGE_LOG_LEVEL "STATUS") - else() - set(CMAKE_MESSAGE_LOG_LEVEL "NOTICE") - endif() - set(${out_var} "${CMAKE_MESSAGE_LOG_LEVEL}" PARENT_SCOPE) - endif() -endfunction() -qt_internal_set_message_log_level(CMAKE_MESSAGE_LOG_LEVEL) - -# Reset content of extra build internal vars for each inclusion of QtSetup. -unset(QT_EXTRA_BUILD_INTERNALS_VARS) - -# Save the global property in a variable to make it available to feature conditions. -get_property(QT_GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) - -# Try to detect if an explicit CMAKE_BUILD_TYPE was set by the user. -# CMake sets CMAKE_BUILD_TYPE_INIT to Debug on most Windows platforms and doesn't set -# anything for UNIXes. CMake assigns CMAKE_BUILD_TYPE_INIT to CMAKE_BUILD_TYPE during -# first project() if CMAKE_BUILD_TYPE has no previous value. -# We use extra information about the state of CMAKE_BUILD_TYPE before the first -# project() call that's set in QtAutodetect. -# STREQUAL check needs to have expanded variables because an undefined var is not equal -# to an empty defined var. -# See also qt_internal_force_set_cmake_build_type_conditionally which is used -# to set the build type when building other repos or tests. -if("${CMAKE_BUILD_TYPE}" STREQUAL "${CMAKE_BUILD_TYPE_INIT}" - AND NOT __qt_auto_detect_cmake_build_type_before_project_call - AND NOT __qt_build_internals_cmake_build_type - AND NOT CMAKE_CONFIGURATION_TYPES) - message(STATUS "Setting build type to '${_default_build_type}' as none was specified.") - set(CMAKE_BUILD_TYPE "${_default_build_type}" CACHE STRING "Choose the type of build." FORCE) - set_property(CACHE CMAKE_BUILD_TYPE - PROPERTY STRINGS - "Debug" "Release" "MinSizeRel" "RelWithDebInfo") # Set the possible values for cmake-gui. -elseif(CMAKE_CONFIGURATION_TYPES) - message(STATUS "Building for multiple configurations: ${CMAKE_CONFIGURATION_TYPES}.") - message(STATUS "Main configuration is: ${QT_MULTI_CONFIG_FIRST_CONFIG}.") - if(CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE) - 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() - -# Append a config-specific postfix to library names to ensure distinct names -# in a multi-config build. -# e.g. lib/libQt6DBus_relwithdebinfo.6.3.0.dylib -# Don't apply the postfix to the first encountered release-like config, so we have at least one -# config without a postifx. -# If postfixes are set by user warn about potential issues. -function(qt_internal_setup_cmake_config_postfix) - # Collect configuration that require postfix in Qt library names. - if(QT_GENERATOR_IS_MULTI_CONFIG) - set(postfix_configurations ${CMAKE_CONFIGURATION_TYPES}) - else() - set(postfix_configurations ${CMAKE_BUILD_TYPE}) - - # Set the default postfix to empty by default for single-config builds. - string(TOLOWER "${CMAKE_BUILD_TYPE}" build_type_lower) - set(default_cmake_${build_type_lower}_postfix "") - endif() - - # Override the generic debug postfixes above with custom debug postfixes (even in a single - # config build) to follow the conventions we had since Qt 5. - # e.g. lib/libQt6DBus_debug.6.3.0.dylib - if(WIN32) - if(MINGW) - # On MinGW we don't have "d" suffix for debug libraries like on Linux, - # unless we're building debug and release libraries in one go. - if(QT_GENERATOR_IS_MULTI_CONFIG) - set(default_cmake_debug_postfix "d") - endif() - else() - set(default_cmake_debug_postfix "d") - endif() - elseif(APPLE) - set(default_cmake_debug_postfix "_debug") - endif() - - set(custom_postfix_vars "") - set(release_configs Release RelWithDebInfo MinSizeRel) - set(found_first_release_config FALSE) - foreach(config_type IN LISTS postfix_configurations) - string(TOLOWER "${config_type}" config_type_lower) - string(TOUPPER "${config_type}" config_type_upper) - set(postfix_var CMAKE_${config_type_upper}_POSTFIX) - - # Skip assigning postfix for the first release-like config. - if(NOT found_first_release_config - AND config_type IN_LIST release_configs) - set(found_first_release_config TRUE) - if(NOT "${${postfix_var}}" STREQUAL "") - list(APPEND custom_postfix_vars ${postfix_var}) - endif() - continue() - endif() - - # Check if the default postfix is set, use '_' otherwise. - set(default_postfix_var - default_cmake_${config_type_lower}_postfix) - if(NOT DEFINED ${default_postfix_var}) - set(${default_postfix_var} - "_${config_type_lower}") - endif() - - # If postfix is set by user avoid changing it, but save postfix variable that has - # a non-default value for further warning. - if("${${postfix_var}}" STREQUAL "") - set(${postfix_var} "${${default_postfix_var}}" PARENT_SCOPE) - elseif(NOT "${${postfix_var}}" STREQUAL "${${default_postfix_var}}") - list(APPEND custom_postfix_vars ${postfix_var}) - endif() - - # Adjust framework postfixes accordingly - if(APPLE) - set(CMAKE_FRAMEWORK_MULTI_CONFIG_POSTFIX_${config_type_upper} - "${${postfix_var}}" PARENT_SCOPE) - endif() - endforeach() - if(custom_postfix_vars) - list(REMOVE_DUPLICATES custom_postfix_vars) - list(JOIN custom_postfix_vars ", " postfix_vars_string) - - message(WARNING "You are using custom library postfixes: '${postfix_vars_string}' which are" - " considered experimental and are not officially supported by Qt." - " Expect unforeseen issues and user projects built with qmake to be broken." - ) - endif() -endfunction() -qt_internal_setup_cmake_config_postfix() - -## 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) - -# Detect non-prefix builds: either when the qtbase install prefix is set to the binary dir -# or when a developer build is explicitly enabled and no install prefix (or staging prefix) -# is specified. -# This detection only happens when building qtbase, and later is propagated via the generated -# QtBuildInternalsExtra.cmake file. -if (PROJECT_NAME STREQUAL "QtBase" AND NOT QT_BUILD_STANDALONE_TESTS) - if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) - # Handle both FEATURE_ and QT_FEATURE_ cases when they are specified on the command line - # explicitly. It's possible for one to be set, but not the other, because - # qtbase/configure.cmake is not processed by this point. - if((FEATURE_developer_build - OR QT_FEATURE_developer_build - OR FEATURE_no_prefix - OR QT_FEATURE_no_prefix - ) - AND NOT CMAKE_STAGING_PREFIX) - # Handle non-prefix builds by setting the CMake install prefix to point to qtbase's - # build dir. While building another repo (like qtsvg) the CMAKE_PREFIX_PATH should be - # set on the command line to point to the qtbase build dir. - set(__qt_default_prefix "${QtBase_BINARY_DIR}") - else() - if(CMAKE_HOST_WIN32) - set(__qt_default_prefix "C:/Qt/") - else() - set(__qt_default_prefix "/usr/local/") - endif() - string(APPEND __qt_default_prefix - "Qt-${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") - endif() - set(CMAKE_INSTALL_PREFIX ${__qt_default_prefix} CACHE PATH - "Install path prefix, prepended onto install directories." FORCE) - unset(__qt_default_prefix) - endif() - if(CMAKE_STAGING_PREFIX) - set(__qt_prefix "${CMAKE_STAGING_PREFIX}") - else() - set(__qt_prefix "${CMAKE_INSTALL_PREFIX}") - endif() - if(__qt_prefix STREQUAL QtBase_BINARY_DIR) - set(__qt_will_install_value OFF) - else() - set(__qt_will_install_value ON) - endif() - set(QT_WILL_INSTALL ${__qt_will_install_value} CACHE BOOL - "Boolean indicating if doing a Qt prefix build (vs non-prefix build)." FORCE) - unset(__qt_prefix) - unset(__qt_will_install_value) -endif() - -# Specify the QT_SOURCE_TREE only when building qtbase. Needed by some tests when the tests are -# built as part of the project, and not standalone. For standalone tests, the value is set in -# QtBuildInternalsExtra.cmake. -if(PROJECT_NAME STREQUAL "QtBase") - set(QT_SOURCE_TREE "${QtBase_SOURCE_DIR}" CACHE PATH - "A path to the source tree of the previously configured QtBase project." FORCE) -endif() - -# QT_INTERNAL_CONFIGURE_FROM_IDE is set to TRUE for the following known IDE applications: -# - Qt Creator, detected by QTC_RUN environment variable -# - CLion, detected by CLION_IDE environment variable -# - Visual Studio Code, detected by VSCODE_CLI environment variable -if("$ENV{QTC_RUN}" OR "$ENV{CLION_IDE}" OR "$ENV{VSCODE_CLI}") - set(QT_INTERNAL_CONFIGURE_FROM_IDE TRUE CACHE INTERNAL "Configuring Qt Project from IDE") -else() - set(QT_INTERNAL_CONFIGURE_FROM_IDE FALSE CACHE INTERNAL "Configuring Qt Project from IDE") -endif() - -if(FEATURE_developer_build) - if(DEFINED QT_CMAKE_EXPORT_COMPILE_COMMANDS) - set(CMAKE_EXPORT_COMPILE_COMMANDS ${QT_CMAKE_EXPORT_COMPILE_COMMANDS}) - else() - set(CMAKE_EXPORT_COMPILE_COMMANDS ON) - endif() - set(_qt_build_tests_default ON) - set(__build_benchmarks ON) - - # Tests are not built by default with qmake for iOS and friends, and thus the overall build - # tends to fail. Disable them by default when targeting uikit. - if(UIKIT OR ANDROID) - set(_qt_build_tests_default OFF) - endif() - - # Disable benchmarks for single configuration generators which do not build - # with release configuration. - if (CMAKE_BUILD_TYPE AND CMAKE_BUILD_TYPE STREQUAL Debug) - set(__build_benchmarks OFF) - endif() -else() - set(_qt_build_tests_default OFF) - set(__build_benchmarks OFF) -endif() - -# Build Benchmarks -option(QT_BUILD_BENCHMARKS "Build Qt Benchmarks" ${__build_benchmarks}) -if(QT_BUILD_BENCHMARKS) - set(_qt_build_tests_default ON) -endif() - -## Set up testing -option(QT_BUILD_TESTS "Build the testing tree." ${_qt_build_tests_default}) -unset(_qt_build_tests_default) -option(QT_BUILD_TESTS_BY_DEFAULT "Should tests be built as part of the default 'all' target." ON) -if(QT_BUILD_STANDALONE_TESTS) - # BuildInternals might have set it to OFF on initial configuration. So force it to ON when - # building standalone tests. - set(QT_BUILD_TESTS ON CACHE BOOL "Build the testing tree." FORCE) - - # Also force the tests to be built as part of the default build target. - set(QT_BUILD_TESTS_BY_DEFAULT ON CACHE BOOL - "Should tests be built as part of the default 'all' target." FORCE) -endif() -set(BUILD_TESTING ${QT_BUILD_TESTS} CACHE INTERNAL "") - -if (WASM) - set(_qt_batch_tests ON) -else() - set(_qt_batch_tests OFF) -endif() - -if(DEFINED INPUT_batch_tests) - if (${INPUT_batch_tests}) - set(_qt_batch_tests ON) - else() - set(_qt_batch_tests OFF) - endif() -endif() - -option(QT_BUILD_TESTS_BATCHED "Link all tests into a single binary." ${_qt_batch_tests}) - -if(QT_BUILD_TESTS AND QT_BUILD_TESTS_BATCHED AND CMAKE_VERSION VERSION_LESS "3.19") - message(FATAL_ERROR - "Test batching requires at least CMake 3.19, due to requiring per-source " - "TARGET_DIRECTORY assignments and DEFER calls.") -endif() - -# QT_BUILD_TOOLS_WHEN_CROSSCOMPILING -> QT_FORCE_BUILD_TOOLS -# pre-6.4 compatibility flag (remove sometime in the future) -if(CMAKE_CROSSCOMPILING AND QT_BUILD_TOOLS_WHEN_CROSSCOMPILING) - message(WARNING "QT_BUILD_TOOLS_WHEN_CROSSCOMPILING is deprecated. " - "Please use QT_FORCE_BUILD_TOOLS instead.") - set(QT_FORCE_BUILD_TOOLS TRUE CACHE INTERNAL "" FORCE) -endif() - -# When cross-building, we don't build tools by default. Sometimes this also covers Qt apps as well. -# Like in qttools/assistant/assistant.pro, load(qt_app), which is guarded by a qtNomakeTools() call. - -set(_qt_build_tools_by_default_default ON) -if(CMAKE_CROSSCOMPILING AND NOT QT_FORCE_BUILD_TOOLS) - set(_qt_build_tools_by_default_default OFF) -endif() -option(QT_BUILD_TOOLS_BY_DEFAULT "Should tools be built as part of the default 'all' target." - "${_qt_build_tools_by_default_default}") -unset(_qt_build_tools_by_default_default) - -include(CTest) -enable_testing() - -option(QT_BUILD_EXAMPLES "Build Qt examples" OFF) -option(QT_BUILD_EXAMPLES_BY_DEFAULT "Should examples be built as part of the default 'all' target." ON) -option(QT_INSTALL_EXAMPLES_SOURCES "Install example sources" OFF) -option(QT_INSTALL_EXAMPLES_SOURCES_BY_DEFAULT - "Install example sources as part of the default 'install' target" ON) - -# FIXME: Support prefix builds as well QTBUG-96232 -if(QT_WILL_INSTALL) - set(_qt_build_examples_as_external OFF) -else() - set(_qt_build_examples_as_external ON) -endif() -option(QT_BUILD_EXAMPLES_AS_EXTERNAL "Should examples be built as ExternalProjects." - ${_qt_build_examples_as_external}) -unset(_qt_build_examples_as_external) - -option(QT_BUILD_MANUAL_TESTS "Build Qt manual tests" 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() - -option(QT_BUILD_MINIMAL_ANDROID_MULTI_ABI_TESTS - "Build minimal subset of tests for Android multi-ABI Qt builds" OFF) - -## Path used to find host tools, either when cross-compiling or just when using the tools from -## a different host build. -set(QT_HOST_PATH "$ENV{QT_HOST_PATH}" CACHE PATH - "Installed Qt host directory path, used for cross compiling.") - -## Android platform settings -if(ANDROID) - include(QtPlatformAndroid) -endif() - -## qt_add_module and co.: +# Any new code should go into QtBuildHelpers.cmake or other appropriate files and then called in +# qt_internal_setup_build_and_global_variables(). include(QtBuild) - -## Qt Feature support: -include(QtBuildInformation) -include(QtFeature) - -## Compiler optimization flags: -include(QtCompilerOptimization) - -## Compiler flags: -include(QtCompilerFlags) - -qt_set_language_standards() - -option(QT_USE_CCACHE "Enable the use of ccache") -if(QT_USE_CCACHE) - find_program(CCACHE_PROGRAM ccache) - if(CCACHE_PROGRAM) - set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_PROGRAM}") - set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PROGRAM}") - set(CMAKE_OBJC_COMPILER_LAUNCHER "${CCACHE_PROGRAM}") - set(CMAKE_OBJCXX_COMPILER_LAUNCHER "${CCACHE_PROGRAM}") - else() - message(FATAL_ERROR "Ccache use was requested, but the program was not found.") - endif() -endif() - -option(QT_UNITY_BUILD "Enable unity (jumbo) build") -set(QT_UNITY_BUILD_BATCH_SIZE "32" CACHE STRING "Unity build batch size") -if(QT_UNITY_BUILD) - set(CMAKE_UNITY_BUILD ON) - set(CMAKE_UNITY_BUILD_BATCH_SIZE "${QT_UNITY_BUILD_BATCH_SIZE}") -endif() - -option(QT_ALLOW_SYMLINK_IN_PATHS "Allows symlinks in paths." OFF) - -qt_internal_detect_dirty_features() - -if(NOT QT_BUILD_EXAMPLES) - # Disable deployment setup to avoid warnings about missing patchelf with CMake < 3.21. - set(QT_SKIP_SETUP_DEPLOYMENT ON) -endif() - -option(QT_ALLOW_DOWNLOAD "Allows files to be downloaded when building Qt." OFF) diff --git a/cmake/QtTargetHelpers.cmake b/cmake/QtTargetHelpers.cmake index baaf5400897..75db1822d12 100644 --- a/cmake/QtTargetHelpers.cmake +++ b/cmake/QtTargetHelpers.cmake @@ -368,6 +368,92 @@ macro(qt_internal_setup_default_target_function_options) ) endmacro() +# Append a config-specific postfix to library names to ensure distinct names +# in a multi-config build. +# e.g. lib/libQt6DBus_relwithdebinfo.6.3.0.dylib +# Don't apply the postfix to the first encountered release-like config, so we have at least one +# config without a postifx. +# If postfixes are set by user warn about potential issues. +function(qt_internal_setup_cmake_config_postfix) + # Collect configuration that require postfix in Qt library names. + if(QT_GENERATOR_IS_MULTI_CONFIG) + set(postfix_configurations ${CMAKE_CONFIGURATION_TYPES}) + else() + set(postfix_configurations ${CMAKE_BUILD_TYPE}) + + # Set the default postfix to empty by default for single-config builds. + string(TOLOWER "${CMAKE_BUILD_TYPE}" build_type_lower) + set(default_cmake_${build_type_lower}_postfix "") + endif() + + # Override the generic debug postfixes above with custom debug postfixes (even in a single + # config build) to follow the conventions we had since Qt 5. + # e.g. lib/libQt6DBus_debug.6.3.0.dylib + if(WIN32) + if(MINGW) + # On MinGW we don't have "d" suffix for debug libraries like on Linux, + # unless we're building debug and release libraries in one go. + if(QT_GENERATOR_IS_MULTI_CONFIG) + set(default_cmake_debug_postfix "d") + endif() + else() + set(default_cmake_debug_postfix "d") + endif() + elseif(APPLE) + set(default_cmake_debug_postfix "_debug") + endif() + + set(custom_postfix_vars "") + set(release_configs Release RelWithDebInfo MinSizeRel) + set(found_first_release_config FALSE) + foreach(config_type IN LISTS postfix_configurations) + string(TOLOWER "${config_type}" config_type_lower) + string(TOUPPER "${config_type}" config_type_upper) + set(postfix_var CMAKE_${config_type_upper}_POSTFIX) + + # Skip assigning postfix for the first release-like config. + if(NOT found_first_release_config + AND config_type IN_LIST release_configs) + set(found_first_release_config TRUE) + if(NOT "${${postfix_var}}" STREQUAL "") + list(APPEND custom_postfix_vars ${postfix_var}) + endif() + continue() + endif() + + # Check if the default postfix is set, use '_' otherwise. + set(default_postfix_var + default_cmake_${config_type_lower}_postfix) + if(NOT DEFINED ${default_postfix_var}) + set(${default_postfix_var} + "_${config_type_lower}") + endif() + + # If postfix is set by user avoid changing it, but save postfix variable that has + # a non-default value for further warning. + if("${${postfix_var}}" STREQUAL "") + set(${postfix_var} "${${default_postfix_var}}" PARENT_SCOPE) + elseif(NOT "${${postfix_var}}" STREQUAL "${${default_postfix_var}}") + list(APPEND custom_postfix_vars ${postfix_var}) + endif() + + # Adjust framework postfixes accordingly + if(APPLE) + set(CMAKE_FRAMEWORK_MULTI_CONFIG_POSTFIX_${config_type_upper} + "${${postfix_var}}" PARENT_SCOPE) + endif() + endforeach() + if(custom_postfix_vars) + list(REMOVE_DUPLICATES custom_postfix_vars) + list(JOIN custom_postfix_vars ", " postfix_vars_string) + + message(WARNING "You are using custom library postfixes: '${postfix_vars_string}' which are" + " considered experimental and are not officially supported by Qt." + " Expect unforeseen issues and user projects built with qmake to be broken." + ) + endif() +endfunction() + function(qt_is_imported_target target out_var) if(NOT TARGET "${target}") set(target "${QT_CMAKE_EXPORT_NAMESPACE}::${target}")