summaryrefslogtreecommitdiffstats
path: root/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake
diff options
context:
space:
mode:
authorAlexandru Croitor <alexandru.croitor@qt.io>2023-11-16 19:57:25 +0100
committerAlexandru Croitor <alexandru.croitor@qt.io>2023-11-27 19:53:42 +0100
commit720b8ee6732f6fc8df5fb7133b569851356641b7 (patch)
tree78a91f7c30a6aa3bf997106eb58f754e981068ca /cmake/QtBuildInternals/QtBuildInternalsConfig.cmake
parent098a774998c85e10696bbde13b28af517548fe84 (diff)
CMake: Split and refactor QtBuildInternalsConfig.cmake
Move most of the code into two new files: - QtBuildRepoHelpers.cmake - QtBuildRepoExamplesHelpers.cmake Task-number: QTBUG-86035 Change-Id: I48c4e7c64f0ffb600118172b8e69b26018f36ffb Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
Diffstat (limited to 'cmake/QtBuildInternals/QtBuildInternalsConfig.cmake')
-rw-r--r--cmake/QtBuildInternals/QtBuildInternalsConfig.cmake1489
1 files changed, 20 insertions, 1469 deletions
diff --git a/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake b/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake
index 633d1b3140..21ff79f9c1 100644
--- a/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake
+++ b/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake
@@ -4,11 +4,7 @@
# These values should be kept in sync with those in qtbase/.cmake.conf
cmake_minimum_required(VERSION 3.16...3.21)
-###############################################
-#
-# Macros and functions for building Qt modules
-#
-###############################################
+set(QT_BACKUP_CMAKE_INSTALL_PREFIX_BEFORE_EXTRA_INCLUDE "${CMAKE_INSTALL_PREFIX}")
# Recursively reads the dependencies section from dependencies.yaml in ${repo_dir} and returns the
# list of dependencies, including transitive ones, in out_var.
@@ -51,22 +47,23 @@ function(qt_internal_read_repo_dependencies out_var repo_dir)
set(${out_var} "${dependencies}" PARENT_SCOPE)
endfunction()
-set(QT_BACKUP_CMAKE_INSTALL_PREFIX_BEFORE_EXTRA_INCLUDE "${CMAKE_INSTALL_PREFIX}")
-
+# This depends on qt_internal_read_repo_dependencies existing.
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/QtBuildInternalsExtra.cmake")
include(${CMAKE_CURRENT_LIST_DIR}/QtBuildInternalsExtra.cmake)
endif()
-# The variables might have already been set in QtBuildInternalsExtra.cmake if the file is included
-# while building a new module and not QtBase. In that case, stop overriding the value.
-if(NOT INSTALL_CMAKE_NAMESPACE)
- set(INSTALL_CMAKE_NAMESPACE "Qt${PROJECT_VERSION_MAJOR}"
- CACHE STRING "CMake namespace [Qt${PROJECT_VERSION_MAJOR}]")
-endif()
-if(NOT QT_CMAKE_EXPORT_NAMESPACE)
- set(QT_CMAKE_EXPORT_NAMESPACE "Qt${PROJECT_VERSION_MAJOR}"
- CACHE STRING "CMake namespace used when exporting targets [Qt${PROJECT_VERSION_MAJOR}]")
-endif()
+macro(qt_internal_setup_cmake_and_export_namespace)
+ # The variables might have already been set in QtBuildInternalsExtra.cmake if the file is
+ # included while building a new module and not QtBase. In that case, stop overriding the value.
+ if(NOT INSTALL_CMAKE_NAMESPACE)
+ set(INSTALL_CMAKE_NAMESPACE "Qt${PROJECT_VERSION_MAJOR}"
+ CACHE STRING "CMake namespace [Qt${PROJECT_VERSION_MAJOR}]")
+ endif()
+ if(NOT QT_CMAKE_EXPORT_NAMESPACE)
+ set(QT_CMAKE_EXPORT_NAMESPACE "Qt${PROJECT_VERSION_MAJOR}"
+ CACHE STRING "CMake namespace used when exporting targets [Qt${PROJECT_VERSION_MAJOR}]")
+ endif()
+endmacro()
macro(qt_set_up_build_internals_paths)
# Set up the paths for the cmake modules located in the prefix dir. Prepend, so the paths are
@@ -98,1461 +95,15 @@ macro(qt_set_up_build_internals_paths)
endif()
endmacro()
+qt_internal_setup_cmake_and_export_namespace()
+
# Set up the build internal paths unless explicitly requested not to.
if(NOT QT_BUILD_INTERNALS_SKIP_CMAKE_MODULE_PATH_ADDITION)
+ # Depends on qt_internal_setup_cmake_and_export_namespace
qt_set_up_build_internals_paths()
endif()
-# Define some constants to check for certain platforms, etc.
-# Needs to be loaded before qt_repo_build() to handle require() clauses before even starting a repo
-# build.
-include(QtPlatformSupport)
-
-# Set FEATURE_${feature} if INPUT_${feature} is set in certain circumstances.
-# Set FEATURE_${feature}_computed_from_input to TRUE or FALSE depending on whether the
-# INPUT_${feature} value has overridden the FEATURE_${feature} variable.
-#
-# Needs to be in QtBuildInternalsConfig.cmake instead of QtFeature.cmake because it's used in
-# qt_build_internals_disable_pkg_config_if_needed.
-function(qt_internal_compute_feature_value_from_possible_input feature)
- # If FEATURE_ is not defined try to use the INPUT_ variable to enable/disable feature.
- # If FEATURE_ is defined and the configure script is being used (so
- # QT_INTERNAL_CALLED_FROM_CONFIGURE is TRUE), ignore the FEATURE_ variable, and take into
- # account the INPUT_ variable instead, because a command line argument takes priority over
- # a pre-cached FEATURE_ variable.
- if((NOT DEFINED FEATURE_${feature} OR QT_INTERNAL_CALLED_FROM_CONFIGURE)
- AND DEFINED INPUT_${feature}
- AND NOT "${INPUT_${feature}}" STREQUAL "undefined"
- AND NOT "${INPUT_${feature}}" STREQUAL "")
- if(INPUT_${feature})
- set(FEATURE_${feature} ON)
- else()
- set(FEATURE_${feature} OFF)
- endif()
-
- set(FEATURE_${feature} "${FEATURE_${feature}}" PARENT_SCOPE)
- set(FEATURE_${feature}_computed_from_input TRUE PARENT_SCOPE)
- else()
- set(FEATURE_${feature}_computed_from_input FALSE PARENT_SCOPE)
- endif()
-endfunction()
-
-function(qt_build_internals_disable_pkg_config_if_needed)
- # pkg-config should not be used by default on Darwin and Windows platforms (and QNX), as defined
- # in the qtbase/configure.json. Unfortunately by the time the feature is evaluated there are
- # already a few find_package() calls that try to use the FindPkgConfig module.
- # Thus, we have to duplicate the condition logic here and disable pkg-config for those platforms
- # by default.
- # We also need to check if the pkg-config executable exists, to mirror the condition test in
- # configure.json. We do that by trying to find the executable ourselves, and not delegating to
- # the FindPkgConfig module because that has more unwanted side-effects.
- #
- # Note that on macOS, if the pkg-config feature is enabled by the user explicitly, we will also
- # tell CMake to consider paths like /usr/local (Homebrew) as system paths when looking for
- # packages.
- # We have to do that because disabling these paths but keeping pkg-config
- # enabled won't enable finding all system libraries via pkg-config alone, many libraries can
- # only be found via FooConfig.cmake files which means /usr/local should be in the system prefix
- # path.
-
- set(pkg_config_enabled ON)
- qt_build_internals_find_pkg_config_executable()
-
- if(APPLE OR WIN32 OR QNX OR ANDROID OR WASM OR (NOT PKG_CONFIG_EXECUTABLE))
- set(pkg_config_enabled OFF)
- endif()
-
- # Features won't have been evaluated yet if this is the first run, have to evaluate this here
- qt_internal_compute_feature_value_from_possible_input(pkg_config)
-
- # If user explicitly specified a value for the feature, honor it, even if it might break
- # the build.
- if(DEFINED FEATURE_pkg_config)
- if(FEATURE_pkg_config)
- set(pkg_config_enabled ON)
- else()
- set(pkg_config_enabled OFF)
- endif()
- endif()
-
- set(FEATURE_pkg_config "${pkg_config_enabled}" CACHE STRING "Using pkg-config")
- if(NOT pkg_config_enabled)
- qt_build_internals_disable_pkg_config()
- else()
- unset(PKG_CONFIG_EXECUTABLE CACHE)
- endif()
-endfunction()
-
-# This is a copy of the first few lines in FindPkgConfig.cmake.
-function(qt_build_internals_find_pkg_config_executable)
- # find pkg-config, use PKG_CONFIG if set
- if((NOT PKG_CONFIG_EXECUTABLE) AND (NOT "$ENV{PKG_CONFIG}" STREQUAL ""))
- set(PKG_CONFIG_EXECUTABLE "$ENV{PKG_CONFIG}" CACHE FILEPATH "pkg-config executable")
- endif()
- find_program(PKG_CONFIG_EXECUTABLE NAMES pkg-config DOC "pkg-config executable")
- mark_as_advanced(PKG_CONFIG_EXECUTABLE)
-endfunction()
-
-function(qt_build_internals_disable_pkg_config)
- # Disable pkg-config by setting an empty executable path. There's no documented way to
- # mark the package as not found, but we can force all pkg_check_modules calls to do nothing
- # by setting the variable to an empty value.
- set(PKG_CONFIG_EXECUTABLE "" CACHE STRING "Disabled pkg-config usage." FORCE)
-endfunction()
-
-if(NOT QT_BUILD_INTERNALS_SKIP_PKG_CONFIG_ADJUSTMENT)
- qt_build_internals_disable_pkg_config_if_needed()
-endif()
-
-macro(qt_build_internals_find_pkg_config)
- # Find package config once before any system prefix modifications.
- find_package(PkgConfig QUIET)
-endmacro()
-
-if(NOT QT_BUILD_INTERNALS_SKIP_FIND_PKG_CONFIG)
- qt_build_internals_find_pkg_config()
-endif()
-
-function(qt_build_internals_set_up_system_prefixes)
- if(APPLE AND NOT FEATURE_pkg_config)
- # Remove /usr/local and other paths like that which CMake considers as system prefixes on
- # darwin platforms. CMake considers them as system prefixes, but in qmake / Qt land we only
- # consider the SDK path as a system prefix.
- # 3rd party libraries in these locations should not be picked up when building Qt,
- # unless opted-in via the pkg-config feature, which in turn will disable this behavior.
- #
- # Note that we can't remove /usr as a system prefix path, because many programs won't be
- # found then (e.g. perl).
- set(QT_CMAKE_SYSTEM_PREFIX_PATH_BACKUP "${CMAKE_SYSTEM_PREFIX_PATH}" PARENT_SCOPE)
- set(QT_CMAKE_SYSTEM_FRAMEWORK_PATH_BACKUP "${CMAKE_SYSTEM_FRAMEWORK_PATH}" PARENT_SCOPE)
-
- list(REMOVE_ITEM CMAKE_SYSTEM_PREFIX_PATH
- "/usr/local" # Homebrew
- "/opt/homebrew" # Apple Silicon Homebrew
- "/usr/X11R6"
- "/usr/pkg"
- "/opt"
- "/sw" # Fink
- "/opt/local" # MacPorts
- )
- if(_CMAKE_INSTALL_DIR)
- list(REMOVE_ITEM CMAKE_SYSTEM_PREFIX_PATH "${_CMAKE_INSTALL_DIR}")
- endif()
- list(REMOVE_ITEM CMAKE_SYSTEM_FRAMEWORK_PATH "~/Library/Frameworks")
- set(CMAKE_SYSTEM_PREFIX_PATH "${CMAKE_SYSTEM_PREFIX_PATH}" PARENT_SCOPE)
- set(CMAKE_SYSTEM_FRAMEWORK_PATH "${CMAKE_SYSTEM_FRAMEWORK_PATH}" PARENT_SCOPE)
-
- # Also tell qt_find_package() not to use PATH when looking for packages.
- # We can't simply set CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH to OFF because that will break
- # find_program(), and for instance ccache won't be found.
- # That's why we set a different variable which is used by qt_find_package.
- set(QT_NO_USE_FIND_PACKAGE_SYSTEM_ENVIRONMENT_PATH "ON" PARENT_SCOPE)
- endif()
-endfunction()
-
-if(NOT QT_BUILD_INTERNALS_SKIP_SYSTEM_PREFIX_ADJUSTMENT)
- qt_build_internals_set_up_system_prefixes()
-endif()
-
-# The macro sets all the necessary pre-conditions and setup consistent environment for building
-# the Qt repository. It has to be called right after the find_package(Qt6 COMPONENTS BuildInternals)
-# call. Otherwise we cannot make sure that all the required policies will be applied to the Qt
-# components that are involved in build procedure.
-macro(qt_internal_project_setup)
- # Check for the minimum CMake version.
- include(QtCMakeVersionHelpers)
- qt_internal_require_suitable_cmake_version()
- qt_internal_upgrade_cmake_policies()
-endmacro()
-
-macro(qt_build_internals_set_up_private_api)
- # TODO: this call needs to be removed once all repositories got the qtbase update
- qt_internal_project_setup()
-
- # Qt specific setup common for all modules:
- include(QtSetup)
- include(FeatureSummary)
-
- # Optionally include a repo specific Setup module.
- include(${PROJECT_NAME}Setup OPTIONAL)
- include(QtRepoSetup OPTIONAL)
-
- # Find Apple frameworks if needed.
- qt_find_apple_system_frameworks()
-
- # Decide whether tools will be built.
- qt_check_if_tools_will_be_built()
-endmacro()
-
-# add toplevel targets for each subdirectory, e.g. qtbase_src
-function(qt_build_internals_add_toplevel_targets)
- set(qt_repo_target_all "")
- get_directory_property(directories DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" SUBDIRECTORIES)
- foreach(directory IN LISTS directories)
- set(qt_repo_targets "")
- get_filename_component(qt_repo_target_basename ${directory} NAME)
- _qt_internal_collect_buildsystem_targets(qt_repo_targets "${directory}" EXCLUDE UTILITY)
- if (qt_repo_targets)
- set(qt_repo_target_name "${qt_repo_targets_name}_${qt_repo_target_basename}")
- message(DEBUG "${qt_repo_target_name} depends on ${qt_repo_targets}")
- add_custom_target("${qt_repo_target_name}"
- COMMENT "Building everything in ${qt_repo_targets_name}/${qt_repo_target_basename}")
- add_dependencies("${qt_repo_target_name}" ${qt_repo_targets})
- list(APPEND qt_repo_target_all "${qt_repo_target_name}")
-
- # Create special dependency target for External Project examples excluding targets
- # marked as skipped.
- if(qt_repo_target_basename STREQUAL "src")
- set(qt_repo_target_name
- "${qt_repo_targets_name}_${qt_repo_target_basename}_for_examples")
- add_custom_target("${qt_repo_target_name}")
-
- set(unskipped_targets "")
- foreach(target IN LISTS qt_repo_targets)
- if(TARGET "${target}")
- qt_internal_is_target_skipped_for_examples("${target}" is_skipped)
- if(NOT is_skipped)
- list(APPEND unskipped_targets "${target}")
- endif()
- endif()
- endforeach()
- if(unskipped_targets)
- add_dependencies("${qt_repo_target_name}" ${unskipped_targets})
- endif()
- endif()
- endif()
-
- endforeach()
- if (qt_repo_target_all)
- # Note qt_repo_targets_name is different from qt_repo_target_name that is used above.
- add_custom_target("${qt_repo_targets_name}"
- COMMENT "Building everything in ${qt_repo_targets_name}")
- add_dependencies("${qt_repo_targets_name}" ${qt_repo_target_all})
- message(DEBUG "${qt_repo_targets_name} depends on ${qt_repo_target_all}")
- endif()
-endfunction()
-
-macro(qt_enable_cmake_languages)
- set(__qt_required_language_list C CXX)
- set(__qt_platform_required_language_list )
-
- if(APPLE)
- list(APPEND __qt_platform_required_language_list OBJC OBJCXX)
- endif()
-
- foreach(__qt_lang ${__qt_required_language_list})
- enable_language(${__qt_lang})
- endforeach()
-
- foreach(__qt_lang ${__qt_platform_required_language_list})
- enable_language(${__qt_lang})
- endforeach()
-
- # The qtbase call is handled in qtbase/CMakeLists.txt.
- # This call is used for projects other than qtbase, including for other project's standalone
- # tests.
- # Because the function uses QT_FEATURE_foo values, it's important that find_package(Qt6Core) is
- # called before this function. but that's usually the case for Qt repos.
- if(NOT PROJECT_NAME STREQUAL "QtBase")
- qt_internal_set_up_config_optimizations_like_in_qmake()
- endif()
-endmacro()
-
-# Minimum setup required to have any CMakeList.txt build as as a standalone
-# project after importing BuildInternals
-macro(qt_prepare_standalone_project)
- qt_set_up_build_internals_paths()
- qt_build_internals_set_up_private_api()
- qt_enable_cmake_languages()
-endmacro()
-
-# Define a repo target set, and store accompanying information.
-#
-# A repo target set is a subset of targets in a Qt module repository. To build a repo target set,
-# set QT_BUILD_SINGLE_REPO_TARGET_SET to the name of the repo target set.
-#
-# This function is to be called in the top-level project file of a repository,
-# before qt_internal_prepare_single_repo_target_set_build()
-#
-# This function stores information in variables of the parent scope.
-#
-# Positional Arguments:
-# name - The name of this repo target set.
-#
-# Named Arguments:
-# DEPENDS - List of Qt6 COMPONENTS that are build dependencies of this repo target set.
-function(qt_internal_define_repo_target_set name)
- set(oneValueArgs DEPENDS)
- set(prefix QT_REPO_TARGET_SET_)
- cmake_parse_arguments(${prefix}${name} "" ${oneValueArgs} "" ${ARGN})
- foreach(arg IN LISTS oneValueArgs)
- set(${prefix}${name}_${arg} ${${prefix}${name}_${arg}} PARENT_SCOPE)
- endforeach()
- set(QT_REPO_KNOWN_TARGET_SETS "${QT_REPO_KNOWN_TARGET_SETS};${name}" PARENT_SCOPE)
-endfunction()
-
-# Setup a single repo target set build if QT_BUILD_SINGLE_REPO_TARGET_SET is defined.
-#
-# This macro must be called in the top-level project file of the repository after all repo target
-# sets have been defined.
-macro(qt_internal_prepare_single_repo_target_set_build)
- if(DEFINED QT_BUILD_SINGLE_REPO_TARGET_SET)
- if(NOT QT_BUILD_SINGLE_REPO_TARGET_SET IN_LIST QT_REPO_KNOWN_TARGET_SETS)
- message(FATAL_ERROR
- "Repo target set '${QT_BUILD_SINGLE_REPO_TARGET_SET}' is undefined.")
- endif()
- message(STATUS
- "Preparing single repo target set build of ${QT_BUILD_SINGLE_REPO_TARGET_SET}")
- if (NOT "${QT_REPO_TARGET_SET_${QT_BUILD_SINGLE_REPO_TARGET_SET}_DEPENDS}" STREQUAL "")
- find_package(${INSTALL_CMAKE_NAMESPACE} ${PROJECT_VERSION} CONFIG REQUIRED
- COMPONENTS ${QT_REPO_TARGET_SET_${QT_BUILD_SINGLE_REPO_TARGET_SET}_DEPENDS})
- endif()
- endif()
-endmacro()
-
-macro(qt_build_repo_begin)
- set(QT_INTERNAL_REPO_POST_PROCESS_CALLED FALSE)
- list(APPEND CMAKE_MESSAGE_CONTEXT "${PROJECT_NAME}")
-
- qt_build_internals_set_up_private_api()
-
- # Prevent installation in non-prefix builds.
- # We need to associate targets with export names, and that is only possible to do with the
- # install(TARGETS) command. But in a non-prefix build, we don't want to install anything.
- # To make sure that developers don't accidentally run make install, add bail out code to
- # cmake_install.cmake.
- if(NOT QT_WILL_INSTALL)
- # In a top-level build, print a message only in qtbase, which is the first repository.
- if(NOT QT_SUPERBUILD OR (PROJECT_NAME STREQUAL "QtBase"))
- install(CODE [[message(FATAL_ERROR
- "Qt was configured as non-prefix build. "
- "Installation is not supported for this arrangement.")]])
- endif()
-
- install(CODE [[return()]])
- endif()
-
- qt_enable_cmake_languages()
-
- qt_internal_generate_binary_strip_wrapper()
-
- # Add global docs targets that will work both for per-repo builds, and super builds.
- if(NOT TARGET docs)
- add_custom_target(docs)
- add_custom_target(prepare_docs)
- add_custom_target(generate_docs)
- add_custom_target(html_docs)
- add_custom_target(qch_docs)
- add_custom_target(install_html_docs)
- add_custom_target(install_qch_docs)
- add_custom_target(install_docs)
- add_dependencies(html_docs generate_docs)
- add_dependencies(docs html_docs qch_docs)
- add_dependencies(install_docs install_html_docs install_qch_docs)
- endif()
-
- if(NOT TARGET sync_headers)
- add_custom_target(sync_headers)
- endif()
-
- # The special target that we use to sync 3rd-party headers before the gn run when building
- # qtwebengine in top-level builds.
- if(NOT TARGET thirdparty_sync_headers)
- add_custom_target(thirdparty_sync_headers)
- endif()
-
- # Add global qt_plugins, qpa_plugins and qpa_default_plugins convenience custom targets.
- # Internal executables will add a dependency on the qpa_default_plugins target,
- # so that building and running a test ensures it won't fail at runtime due to a missing qpa
- # plugin.
- if(NOT TARGET qt_plugins)
- add_custom_target(qt_plugins)
- add_custom_target(qpa_plugins)
- add_custom_target(qpa_default_plugins)
- endif()
-
- string(TOLOWER ${PROJECT_NAME} project_name_lower)
-
- # Target to build all plugins that are part of the current repo.
- set(qt_repo_plugins "qt_plugins_${project_name_lower}")
- if(NOT TARGET ${qt_repo_plugins})
- add_custom_target(${qt_repo_plugins})
- endif()
-
- # Target to build all plugins that are part of the current repo and the current repo's
- # dependencies plugins. Used for external project example dependencies.
- set(qt_repo_plugins_recursive "${qt_repo_plugins}_recursive")
- if(NOT TARGET ${qt_repo_plugins_recursive})
- add_custom_target(${qt_repo_plugins_recursive})
- add_dependencies(${qt_repo_plugins_recursive} "${qt_repo_plugins}")
- endif()
-
- qt_internal_read_repo_dependencies(qt_repo_deps "${PROJECT_SOURCE_DIR}")
- if(qt_repo_deps)
- foreach(qt_repo_dep IN LISTS qt_repo_deps)
- if(TARGET qt_plugins_${qt_repo_dep})
- message(DEBUG
- "${qt_repo_plugins_recursive} depends on qt_plugins_${qt_repo_dep}")
- add_dependencies(${qt_repo_plugins_recursive} "qt_plugins_${qt_repo_dep}")
- endif()
- endforeach()
- endif()
-
- set(qt_repo_targets_name ${project_name_lower})
- set(qt_docs_target_name docs_${project_name_lower})
- set(qt_docs_prepare_target_name prepare_docs_${project_name_lower})
- set(qt_docs_generate_target_name generate_docs_${project_name_lower})
- set(qt_docs_html_target_name html_docs_${project_name_lower})
- set(qt_docs_qch_target_name qch_docs_${project_name_lower})
- set(qt_docs_install_html_target_name install_html_docs_${project_name_lower})
- set(qt_docs_install_qch_target_name install_qch_docs_${project_name_lower})
- set(qt_docs_install_target_name install_docs_${project_name_lower})
-
- add_custom_target(${qt_docs_target_name})
- add_custom_target(${qt_docs_prepare_target_name})
- add_custom_target(${qt_docs_generate_target_name})
- add_custom_target(${qt_docs_qch_target_name})
- add_custom_target(${qt_docs_html_target_name})
- add_custom_target(${qt_docs_install_html_target_name})
- add_custom_target(${qt_docs_install_qch_target_name})
- add_custom_target(${qt_docs_install_target_name})
-
- add_dependencies(${qt_docs_generate_target_name} ${qt_docs_prepare_target_name})
- add_dependencies(${qt_docs_html_target_name} ${qt_docs_generate_target_name})
- add_dependencies(${qt_docs_target_name} ${qt_docs_html_target_name} ${qt_docs_qch_target_name})
- add_dependencies(${qt_docs_install_target_name} ${qt_docs_install_html_target_name} ${qt_docs_install_qch_target_name})
-
- # Make top-level prepare_docs target depend on the repository-level prepare_docs_<repo> target.
- add_dependencies(prepare_docs ${qt_docs_prepare_target_name})
-
- # Make top-level install_*_docs targets depend on the repository-level install_*_docs targets.
- add_dependencies(install_html_docs ${qt_docs_install_html_target_name})
- add_dependencies(install_qch_docs ${qt_docs_install_qch_target_name})
-
- # Add host_tools meta target, so that developrs can easily build only tools and their
- # dependencies when working in qtbase.
- if(NOT TARGET host_tools)
- add_custom_target(host_tools)
- add_custom_target(bootstrap_tools)
- endif()
-
- # Add benchmark meta target. It's collection of all benchmarks added/registered by
- # 'qt_internal_add_benchmark' helper.
- if(NOT TARGET benchmark)
- add_custom_target(benchmark)
- endif()
-
- if(QT_INTERNAL_SYNCED_MODULES)
- set_property(GLOBAL PROPERTY _qt_synced_modules ${QT_INTERNAL_SYNCED_MODULES})
- endif()
-endmacro()
-
-# Runs delayed actions on some of the Qt targets.
-# Can be called either explicitly or as part of qt_build_repo_end().
-macro(qt_build_repo_post_process)
- if(NOT QT_INTERNAL_REPO_POST_PROCESS_CALLED)
- set(QT_INTERNAL_REPO_POST_PROCESS_CALLED TRUE)
- if(NOT QT_BUILD_STANDALONE_TESTS)
- include(QtPostProcess)
- endif()
- endif()
-endmacro()
-
-macro(qt_build_repo_end)
- if(NOT QT_BUILD_STANDALONE_TESTS)
- qt_build_repo_post_process()
-
- # Install the repo-specific cmake find modules.
- qt_path_join(__qt_repo_install_dir ${QT_CONFIG_INSTALL_DIR} ${INSTALL_CMAKE_NAMESPACE})
- qt_path_join(__qt_repo_build_dir ${QT_CONFIG_BUILD_DIR} ${INSTALL_CMAKE_NAMESPACE})
-
- if(NOT PROJECT_NAME STREQUAL "QtBase")
- if(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
- qt_copy_or_install(DIRECTORY cmake/
- DESTINATION "${__qt_repo_install_dir}"
- FILES_MATCHING PATTERN "Find*.cmake"
- )
- if(QT_SUPERBUILD AND QT_WILL_INSTALL)
- file(COPY cmake/
- DESTINATION "${__qt_repo_build_dir}"
- FILES_MATCHING PATTERN "Find*.cmake"
- )
- endif()
- endif()
- endif()
-
- if(NOT QT_SUPERBUILD)
- qt_print_feature_summary()
- endif()
- endif()
-
- qt_build_internals_add_toplevel_targets()
-
- if(NOT QT_SUPERBUILD)
- qt_print_build_instructions()
- endif()
-
- get_property(synced_modules GLOBAL PROPERTY _qt_synced_modules)
- if(synced_modules)
- set(QT_INTERNAL_SYNCED_MODULES ${synced_modules} CACHE INTERNAL
- "List of the synced modules. Prevents running syncqt.cpp after the first configuring.")
- endif()
-
- if(NOT QT_SUPERBUILD)
- qt_internal_save_previously_visited_packages()
- endif()
-
- if(QT_INTERNAL_FRESH_REQUESTED)
- set(QT_INTERNAL_FRESH_REQUESTED "FALSE" CACHE INTERNAL "")
- endif()
-
- if(NOT QT_SUPERBUILD)
- qt_internal_qt_configure_end()
- endif()
-
- list(POP_BACK CMAKE_MESSAGE_CONTEXT)
-endmacro()
-
-# Function called either at the end of per-repo configuration, or at the end of configuration of
-# a super build.
-# At the moment it is called before examples are configured in a per-repo build. We might want
-# to change that at some point if needed.
-function(qt_internal_qt_configure_end)
- # If Qt is configued via the configure script, remove the marker variable, so that any future
- # reconfigurations that are done by calling cmake directly don't trigger configure specific
- # logic.
- unset(QT_INTERNAL_CALLED_FROM_CONFIGURE CACHE)
-endfunction()
-
-macro(qt_build_repo)
- qt_build_repo_begin(${ARGN})
-
- qt_build_repo_impl_find_package_tests()
- qt_build_repo_impl_src()
- qt_build_repo_impl_tools()
-
- qt_build_repo_post_process()
- qt_build_repo_impl_tests()
-
- qt_build_repo_end()
-
- qt_build_repo_impl_examples()
-endmacro()
-
-macro(qt_build_repo_impl_find_package_tests)
- # If testing is enabled, try to find the qtbase Test package.
- # Do this before adding src, because there might be test related conditions
- # in source.
- if (QT_BUILD_TESTS AND NOT QT_BUILD_STANDALONE_TESTS)
- # When looking for the Test package, do it using the Qt6 package version, in case if
- # PROJECT_VERSION is following a different versioning scheme.
- if(Qt6_VERSION)
- set(_qt_build_repo_impl_find_package_tests_version "${Qt6_VERSION}")
- else()
- set(_qt_build_repo_impl_find_package_tests_version "${PROJECT_VERSION}")
- endif()
-
- find_package(Qt6
- "${_qt_build_repo_impl_find_package_tests_version}"
- CONFIG REQUIRED COMPONENTS Test)
- unset(_qt_build_repo_impl_find_package_tests_version)
- endif()
-endmacro()
-
-macro(qt_build_repo_impl_src)
- if(NOT QT_BUILD_STANDALONE_TESTS)
- if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/src/CMakeLists.txt")
- add_subdirectory(src)
- endif()
- endif()
- if(QT_FEATURE_lttng AND NOT TARGET LTTng::UST)
- qt_find_package(LTTngUST PROVIDED_TARGETS LTTng::UST
- MODULE_NAME global QMAKE_LIB lttng-ust)
- endif()
-endmacro()
-
-macro(qt_build_repo_impl_tools)
- if(NOT QT_BUILD_STANDALONE_TESTS)
- if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tools/CMakeLists.txt")
- add_subdirectory(tools)
- endif()
- endif()
-endmacro()
-
-macro(qt_build_repo_impl_tests)
- if (QT_BUILD_TESTS AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tests/CMakeLists.txt")
- add_subdirectory(tests)
- if(NOT QT_BUILD_TESTS_BY_DEFAULT)
- set_property(DIRECTORY tests PROPERTY EXCLUDE_FROM_ALL TRUE)
- endif()
- endif()
-endmacro()
-
-macro(qt_build_repo_impl_examples)
- if(QT_BUILD_EXAMPLES
- AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/examples/CMakeLists.txt"
- AND NOT QT_BUILD_STANDALONE_TESTS)
- message(STATUS "Configuring examples.")
- add_subdirectory(examples)
- endif()
-endmacro()
-
-macro(qt_set_up_standalone_tests_build)
- # Remove this macro once all usages of it have been removed.
- # Standalone tests are not handled via the main repo project and qt_build_tests.
-endmacro()
-
-function(qt_get_standalone_tests_config_files_path out_var)
- set(path "${QT_CONFIG_INSTALL_DIR}/${INSTALL_CMAKE_NAMESPACE}BuildInternals/StandaloneTests")
-
- # QT_CONFIG_INSTALL_DIR is relative in prefix builds.
- if(QT_WILL_INSTALL)
- if(DEFINED CMAKE_STAGING_PREFIX)
- qt_path_join(path "${CMAKE_STAGING_PREFIX}" "${path}")
- else()
- qt_path_join(path "${CMAKE_INSTALL_PREFIX}" "${path}")
- endif()
- endif()
-
- set("${out_var}" "${path}" PARENT_SCOPE)
-endfunction()
-
-function(qt_internal_get_standalone_tests_config_file_name out_var)
- # When doing a "single repo target set" build (like in qtscxqml) ensure we use a unique tests
- # config file for each repo target set. Using the PROJECT_NAME only is not enough because
- # the same file will be overridden with different content on each repo set install.
- set(tests_config_file_name "${PROJECT_NAME}")
-
- if(QT_BUILD_SINGLE_REPO_TARGET_SET)
- string(APPEND tests_config_file_name "RepoSet${QT_BUILD_SINGLE_REPO_TARGET_SET}")
- endif()
- string(APPEND tests_config_file_name "TestsConfig.cmake")
-
- set(${out_var} "${tests_config_file_name}" PARENT_SCOPE)
-endfunction()
-
-macro(qt_build_tests)
- set(CMAKE_UNITY_BUILD OFF)
-
- # Prepending to QT_BUILD_CMAKE_PREFIX_PATH helps find components of Qt6, because those
- # find_package calls use NO_DEFAULT_PATH, and thus CMAKE_PREFIX_PATH is ignored.
- list(PREPEND CMAKE_FIND_ROOT_PATH "${QT_BUILD_DIR}")
- list(PREPEND QT_BUILD_CMAKE_PREFIX_PATH "${QT_BUILD_DIR}/${INSTALL_LIBDIR}/cmake")
-
- if(QT_BUILD_STANDALONE_TESTS)
- # Find location of TestsConfig.cmake. These contain the modules that need to be
- # find_package'd when testing.
- qt_get_standalone_tests_config_files_path(_qt_build_tests_install_prefix)
-
- qt_internal_get_standalone_tests_config_file_name(_qt_tests_config_file_name)
- set(_qt_standalone_tests_config_file_path
- "${_qt_build_tests_install_prefix}/${_qt_tests_config_file_name}")
- include("${_qt_standalone_tests_config_file_path}"
- OPTIONAL
- RESULT_VARIABLE _qt_standalone_tests_included)
- if(NOT _qt_standalone_tests_included)
- message(DEBUG
- "Standalone tests config file not included because it does not exist: "
- "${_qt_standalone_tests_config_file_path}"
- )
- else()
- message(DEBUG
- "Standalone tests config file included successfully: "
- "${_qt_standalone_tests_config_file_path}"
- )
- endif()
-
- unset(_qt_standalone_tests_config_file_path)
- unset(_qt_standalone_tests_included)
- unset(_qt_tests_config_file_name)
-
- # Of course we always need the test module as well.
- # When looking for the Test package, do it using the Qt6 package version, in case if
- # PROJECT_VERSION is following a different versioning scheme.
- if(Qt6_VERSION)
- set(_qt_build_tests_package_version "${Qt6_VERSION}")
- else()
- set(_qt_build_tests_package_version "${PROJECT_VERSION}")
- endif()
- find_package(Qt6 "${_qt_build_tests_package_version}" CONFIG REQUIRED COMPONENTS Test)
- unset(_qt_build_tests_package_version)
-
- # Set language standards after finding Core, because that's when the relevant
- # feature variables are available, and the call in QtSetup is too early when building
- # standalone tests, because Core was not find_package()'d yet.
- qt_set_language_standards()
-
- if(NOT QT_SUPERBUILD)
- # Set up fake standalone tests install prefix, so we don't pollute the Qt install
- # prefix. For super builds it needs to be done in qt5/CMakeLists.txt.
- qt_set_up_fake_standalone_tests_install_prefix()
- endif()
- else()
- if(ANDROID)
- # When building in-tree tests we need to specify the QT_ANDROID_ABIS list. Since we
- # build Qt for the single ABI, build tests for this ABI only.
- set(QT_ANDROID_ABIS "${CMAKE_ANDROID_ARCH_ABI}")
- endif()
- endif()
-
- if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/auto/CMakeLists.txt")
- add_subdirectory(auto)
- endif()
- if(NOT QT_BUILD_MINIMAL_STATIC_TESTS AND NOT QT_BUILD_MINIMAL_ANDROID_MULTI_ABI_TESTS)
- if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/baseline/CMakeLists.txt")
- add_subdirectory(baseline)
- endif()
- if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/benchmarks/CMakeLists.txt" AND QT_BUILD_BENCHMARKS)
- add_subdirectory(benchmarks)
- endif()
- if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/manual/CMakeLists.txt" AND QT_BUILD_MANUAL_TESTS)
- add_subdirectory(manual)
- # Adding this logic to all tests impacts the configure time ~3sec in addition. We still
- # might want this in the future for other test types since currently we have a moderate
- # subset of tests that require manual initialization of autotools.
- _qt_internal_collect_buildsystem_targets(targets
- "${CMAKE_CURRENT_SOURCE_DIR}/manual" EXCLUDE UTILITY ALIAS)
- foreach(target ${targets})
- qt_autogen_tools(${target} ENABLE_AUTOGEN_TOOLS "moc" "rcc")
- if(TARGET Qt::Widgets)
- qt_autogen_tools(${target} ENABLE_AUTOGEN_TOOLS "uic")
- endif()
- endforeach()
- endif()
- endif()
-
- set(CMAKE_UNITY_BUILD ${QT_UNITY_BUILD})
-endmacro()
-
-function(qt_compute_relative_path_from_cmake_config_dir_to_prefix)
- # Compute the reverse relative path from the CMake config dir to the install prefix.
- # This is used in QtBuildInternalsExtras to create a relocatable relative install prefix path.
- # This path is used for finding syncqt and other things, regardless of initial install prefix
- # (e.g installed Qt was archived and unpacked to a different path on a different machine).
- #
- # This is meant to be called only once when configuring qtbase.
- #
- # Similar code exists in Qt6CoreConfigExtras.cmake.in and src/corelib/CMakeLists.txt which
- # might not be needed anymore.
- if(CMAKE_STAGING_PREFIX)
- set(__qt_prefix "${CMAKE_STAGING_PREFIX}")
- else()
- set(__qt_prefix "${CMAKE_INSTALL_PREFIX}")
- endif()
-
- if(QT_WILL_INSTALL)
- get_filename_component(clean_config_prefix
- "${__qt_prefix}/${QT_CONFIG_INSTALL_DIR}" ABSOLUTE)
- else()
- get_filename_component(clean_config_prefix "${QT_CONFIG_BUILD_DIR}" ABSOLUTE)
- endif()
- file(RELATIVE_PATH
- qt_path_from_cmake_config_dir_to_prefix
- "${clean_config_prefix}" "${__qt_prefix}")
- set(qt_path_from_cmake_config_dir_to_prefix "${qt_path_from_cmake_config_dir_to_prefix}"
- PARENT_SCOPE)
-endfunction()
-
-function(qt_get_relocatable_install_prefix out_var)
- # We need to compute it only once while building qtbase. Afterwards it's loaded from
- # QtBuildInternalsExtras.cmake.
- if(QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX)
- return()
- endif()
- # The QtBuildInternalsExtras value is dynamically computed, whereas the initial qtbase
- # configuration uses an absolute path.
- set(${out_var} "${CMAKE_INSTALL_PREFIX}" PARENT_SCOPE)
-endfunction()
-
-function(qt_set_up_fake_standalone_tests_install_prefix)
- # Set a fake local (non-cache) CMAKE_INSTALL_PREFIX.
- # Needed for standalone tests, we don't want to accidentally install a test into the Qt prefix.
- # Allow opt-out, if a user knows what they're doing.
- if(QT_NO_FAKE_STANDALONE_TESTS_INSTALL_PREFIX)
- return()
- endif()
- set(new_install_prefix "${CMAKE_BINARY_DIR}/fake_prefix")
-
- # It's IMPORTANT that this is not a cache variable. Otherwise
- # qt_get_standalone_tests_confg_files_path() will not work on re-configuration.
- message(STATUS
- "Setting local standalone test install prefix (non-cached) to '${new_install_prefix}'.")
- set(CMAKE_INSTALL_PREFIX "${new_install_prefix}" PARENT_SCOPE)
-
- # We also need to clear the staging prefix if it's set, otherwise CMake will modify any computed
- # rpaths containing the staging prefix to point to the new fake prefix, which is not what we
- # want. This replacement is done in cmComputeLinkInformation::GetRPath().
- #
- # By clearing the staging prefix for the standalone tests, any detected link time
- # rpaths will be embedded as-is, which will point to the place where Qt was installed (aka
- # the staging prefix).
- if(DEFINED CMAKE_STAGING_PREFIX)
- message(STATUS "Clearing local standalone test staging prefix (non-cached).")
- set(CMAKE_STAGING_PREFIX "" PARENT_SCOPE)
- endif()
-endfunction()
-
-# Mean to be called when configuring examples as part of the main build tree, as well as for CMake
-# tests (tests that call CMake to try and build CMake applications).
-macro(qt_internal_set_up_build_dir_package_paths)
- list(PREPEND CMAKE_PREFIX_PATH "${QT_BUILD_DIR}/${INSTALL_LIBDIR}/cmake")
- # Make sure the CMake config files do not recreate the already-existing targets
- set(QT_NO_CREATE_TARGETS TRUE)
-endmacro()
-
-macro(qt_examples_build_begin)
- set(options EXTERNAL_BUILD)
- set(singleOpts "")
- set(multiOpts DEPENDS)
-
- cmake_parse_arguments(arg "${options}" "${singleOpts}" "${multiOpts}" ${ARGN})
-
- set(CMAKE_UNITY_BUILD OFF)
-
- # Use by qt_internal_add_example.
- set(QT_EXAMPLE_BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
-
- if(arg_EXTERNAL_BUILD AND QT_BUILD_EXAMPLES_AS_EXTERNAL)
- # Examples will be built using ExternalProject.
- # We depend on all plugins built as part of the current repo as well as current repo's
- # dependencies plugins, to prevent opportunities for
- # weird errors associated with loading out-of-date plugins from
- # unrelated Qt modules.
- # We also depend on all targets from this repo's src and tools subdirectories
- # to ensure that we've built anything that a find_package() call within
- # an example might use. Projects can add further dependencies if needed,
- # but that should rarely be necessary.
- set(QT_EXAMPLE_DEPENDENCIES ${qt_repo_plugins_recursive} ${arg_DEPENDS})
-
- if(TARGET ${qt_repo_targets_name}_src)
- list(APPEND QT_EXAMPLE_DEPENDENCIES ${qt_repo_targets_name}_src_for_examples)
- endif()
-
- if(TARGET ${qt_repo_targets_name}_tools)
- list(APPEND QT_EXAMPLE_DEPENDENCIES ${qt_repo_targets_name}_tools)
- endif()
-
- set(QT_IS_EXTERNAL_EXAMPLES_BUILD TRUE)
-
- string(TOLOWER ${PROJECT_NAME} project_name_lower)
- if(NOT TARGET examples)
- if(QT_BUILD_EXAMPLES_BY_DEFAULT)
- add_custom_target(examples ALL)
- else()
- add_custom_target(examples)
- endif()
- endif()
- if(NOT TARGET examples_${project_name_lower})
- add_custom_target(examples_${project_name_lower})
- add_dependencies(examples examples_${project_name_lower})
- endif()
-
- include(ExternalProject)
- else()
- # This repo has not yet been updated to build examples in a separate
- # build from this main build, or we can't use that arrangement yet.
- # Build them directly as part of the main build instead for backward
- # compatibility.
- if(NOT BUILD_SHARED_LIBS)
- # Ordinarily, it would be an error to call return() from within a
- # macro(), but in this case we specifically want to return from the
- # caller's scope if we are doing a static build and the project
- # isn't building examples in a separate build from the main build.
- # Configuring static builds requires tools that are not available
- # until build time.
- return()
- endif()
-
- if(NOT QT_BUILD_EXAMPLES_BY_DEFAULT)
- set_directory_properties(PROPERTIES EXCLUDE_FROM_ALL TRUE)
- endif()
- endif()
-
- # TODO: Change this to TRUE when all examples in all repos are ported to use
- # qt_internal_add_example.
- # We shouldn't need to call qt_internal_set_up_build_dir_package_paths when
- # QT_IS_EXTERNAL_EXAMPLES_BUILD is TRUE.
- # Due to not all examples being ported, if we don't
- # call qt_internal_set_up_build_dir_package_paths -> set(QT_NO_CREATE_TARGETS TRUE) we'll get
- # CMake configuration errors saying we redefine Qt targets because we both build them and find
- # them as part of find_package.
- set(__qt_all_examples_ported_to_external_projects FALSE)
-
- # Examples that are built as part of the Qt build need to use the CMake config files from the
- # build dir, because they are not installed yet in a prefix build.
- # Prepending to CMAKE_PREFIX_PATH helps find the initial Qt6Config.cmake.
- # Prepending to QT_BUILD_CMAKE_PREFIX_PATH helps find components of Qt6, because those
- # find_package calls use NO_DEFAULT_PATH, and thus CMAKE_PREFIX_PATH is ignored.
- # Prepending to CMAKE_FIND_ROOT_PATH ensures the components are found while cross-compiling
- # without setting CMAKE_FIND_ROOT_PATH_MODE_PACKAGE to BOTH.
- if(NOT QT_IS_EXTERNAL_EXAMPLES_BUILD OR NOT __qt_all_examples_ported_to_external_projects)
- qt_internal_set_up_build_dir_package_paths()
- list(PREPEND CMAKE_FIND_ROOT_PATH "${QT_BUILD_DIR}")
- list(PREPEND QT_BUILD_CMAKE_PREFIX_PATH "${QT_BUILD_DIR}/${INSTALL_LIBDIR}/cmake")
- endif()
-
- # Because CMAKE_INSTALL_RPATH is empty by default in the repo project, examples need to have
- # it set here, so they can run when installed.
- # This means that installed examples are not relocatable at the moment. We would need to
- # annotate where each example is installed to, to be able to derive a relative rpath, and it
- # seems there's no way to query such information from CMake itself.
- set(CMAKE_INSTALL_RPATH "${_default_install_rpath}")
-
- install(CODE "
-# Backup CMAKE_INSTALL_PREFIX because we're going to change it in each example subdirectory
-# and restore it after all examples are processed so that QtFooToolsAdditionalTargetInfo.cmake
-# files are installed into the original install prefix.
-set(_qt_internal_examples_cmake_install_prefix_backup \"\${CMAKE_INSTALL_PREFIX}\")
-")
-endmacro()
-
-macro(qt_examples_build_end)
- # We use AUTOMOC/UIC/RCC in the examples. When the examples are part of the
- # main build rather than being built in their own separate project, make
- # sure we do not fail on a fresh Qt build (e.g. the moc binary won't exist
- # yet because it is created at build time).
-
- _qt_internal_collect_buildsystem_targets(targets
- "${CMAKE_CURRENT_SOURCE_DIR}" EXCLUDE UTILITY ALIAS)
-
- foreach(target ${targets})
- qt_autogen_tools(${target} ENABLE_AUTOGEN_TOOLS "moc" "rcc")
- if(TARGET Qt::Widgets)
- qt_autogen_tools(${target} ENABLE_AUTOGEN_TOOLS "uic")
- endif()
- set_target_properties(${target} PROPERTIES UNITY_BUILD OFF)
- endforeach()
-
- install(CODE "
-# Restore backed up CMAKE_INSTALL_PREFIX.
-set(CMAKE_INSTALL_PREFIX \"\${_qt_internal_examples_cmake_install_prefix_backup}\")
-")
-
- set(CMAKE_UNITY_BUILD ${QT_UNITY_BUILD})
-endmacro()
-
-# Allows building an example either as an ExternalProject or in-tree with the Qt build.
-# Also allows installing the example sources.
-function(qt_internal_add_example subdir)
- # Pre-compute unique example name based on the subdir, in case of target name clashes.
- qt_internal_get_example_unique_name(unique_example_name "${subdir}")
-
- # QT_INTERNAL_NO_CONFIGURE_EXAMPLES is not meant to be used by Qt builders, it's here for faster
- # testing of the source installation code path for build system engineers.
- if(NOT QT_INTERNAL_NO_CONFIGURE_EXAMPLES)
- if(NOT QT_IS_EXTERNAL_EXAMPLES_BUILD)
- qt_internal_add_example_in_tree("${subdir}")
- else()
- qt_internal_add_example_external_project("${subdir}"
- NAME "${unique_example_name}")
- endif()
- endif()
-
- if(QT_INSTALL_EXAMPLES_SOURCES)
- string(TOLOWER ${PROJECT_NAME} project_name_lower)
-
- qt_internal_install_example_sources("${subdir}"
- NAME "${unique_example_name}"
- REPO_NAME "${project_name_lower}")
- endif()
-endfunction()
-
-# Gets the install prefix where an example should be installed.
-# Used for computing the final installation path.
-function(qt_internal_get_example_install_prefix out_var)
- # Allow customizing the installation path of the examples. Will be used in CI.
- if(QT_INTERNAL_EXAMPLES_INSTALL_PREFIX)
- set(qt_example_install_prefix "${QT_INTERNAL_EXAMPLES_INSTALL_PREFIX}")
- else()
- set(qt_example_install_prefix "${CMAKE_INSTALL_PREFIX}/${INSTALL_EXAMPLESDIR}")
- endif()
- file(TO_CMAKE_PATH "${qt_example_install_prefix}" qt_example_install_prefix)
- set(${out_var} "${qt_example_install_prefix}" PARENT_SCOPE)
-endfunction()
-
-# Gets the install prefix where an example's sources should be installed.
-# Used for computing the final installation path.
-function(qt_internal_get_examples_sources_install_prefix out_var)
- # Allow customizing the installation path of the examples source specifically.
- if(QT_INTERNAL_EXAMPLES_SOURCES_INSTALL_PREFIX)
- set(qt_example_install_prefix "${QT_INTERNAL_EXAMPLES_SOURCES_INSTALL_PREFIX}")
- else()
- qt_internal_get_example_install_prefix(qt_example_install_prefix)
- endif()
- file(TO_CMAKE_PATH "${qt_example_install_prefix}" qt_example_install_prefix)
- set(${out_var} "${qt_example_install_prefix}" PARENT_SCOPE)
-endfunction()
-
-# Gets the relative path of an example, relative to the current repo's examples source dir.
-# QT_EXAMPLE_BASE_DIR is meant to be already set in a parent scope.
-function(qt_internal_get_example_rel_path out_var subdir)
- file(RELATIVE_PATH example_rel_path
- "${QT_EXAMPLE_BASE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/${subdir}")
- set(${out_var} "${example_rel_path}" PARENT_SCOPE)
-endfunction()
-
-# Gets the install path where an example should be installed.
-function(qt_internal_get_example_install_path out_var subdir)
- qt_internal_get_example_install_prefix(qt_example_install_prefix)
- qt_internal_get_example_rel_path(example_rel_path "${subdir}")
- set(example_install_path "${qt_example_install_prefix}/${example_rel_path}")
-
- set(${out_var} "${example_install_path}" PARENT_SCOPE)
-endfunction()
-
-# Gets the install path where an example's sources should be installed.
-function(qt_internal_get_examples_sources_install_path out_var subdir)
- qt_internal_get_examples_sources_install_prefix(qt_example_install_prefix)
- qt_internal_get_example_rel_path(example_rel_path "${subdir}")
- set(example_install_path "${qt_example_install_prefix}/${example_rel_path}")
-
- set(${out_var} "${example_install_path}" PARENT_SCOPE)
-endfunction()
-
-# Get the unique name of an example project based on its subdir or explicitly given name.
-# Makes the name unique by appending a short sha1 hash of the relative path of the example
-# if a target of the same name already exist.
-function(qt_internal_get_example_unique_name out_var subdir)
- qt_internal_get_example_rel_path(example_rel_path "${subdir}")
-
- set(name "${subdir}")
-
- # qtdeclarative has calls like qt_internal_add_example(imagine/automotive)
- # so passing a nested subdirectory. Custom targets (and thus ExternalProjects) can't contain
- # slashes, so extract the last part of the path to be used as a name.
- if(name MATCHES "/")
- string(REPLACE "/" ";" exploded_path "${name}")
- list(POP_BACK exploded_path last_dir)
- if(NOT last_dir)
- message(FATAL_ERROR "Example subdirectory must have a name.")
- else()
- set(name "${last_dir}")
- endif()
- endif()
-
- # Likely a clash with an example subdir ExternalProject custom target of the same name in a
- # top-level build.
- if(TARGET "${name}")
- string(SHA1 rel_path_hash "${example_rel_path}")
- string(SUBSTRING "${rel_path_hash}" 0 4 short_hash)
- set(name "${name}-${short_hash}")
- endif()
-
- set(${out_var} "${name}" PARENT_SCOPE)
-endfunction()
-
-# Use old non-ExternalProject approach, aka build in-tree with the Qt build.
-function(qt_internal_add_example_in_tree subdir)
- # Unset the default CMAKE_INSTALL_PREFIX that's generated in
- # ${CMAKE_CURRENT_BINARY_DIR}/cmake_install.cmake
- # so we can override it with a different value in
- # ${CMAKE_CURRENT_BINARY_DIR}/${subdir}/cmake_install.cmake
- #
- install(CODE "
-# Unset the CMAKE_INSTALL_PREFIX in the current cmake_install.cmake file so that it can be
-# overridden in the included add_subdirectory-specific cmake_install.cmake files instead.
-unset(CMAKE_INSTALL_PREFIX)
-")
-
- # Override the install prefix in the subdir cmake_install.cmake, so that
- # relative install(TARGETS DESTINATION) calls in example projects install where we tell them to.
- qt_internal_get_example_install_path(example_install_path "${subdir}")
- set(CMAKE_INSTALL_PREFIX "${example_install_path}")
-
- # Make sure unclean example projects have their INSTALL_EXAMPLEDIR set to "."
- # Won't have any effect on example projects that don't use INSTALL_EXAMPLEDIR.
- # This plus the install prefix above takes care of installing examples where we want them to
- # be installed, while allowing us to remove INSTALL_EXAMPLEDIR code in each example
- # incrementally.
- # TODO: Remove once all repositories use qt_internal_add_example instead of add_subdirectory.
- set(QT_INTERNAL_SET_EXAMPLE_INSTALL_DIR_TO_DOT ON)
-
- add_subdirectory(${subdir})
-endfunction()
-
-function(qt_internal_add_example_external_project subdir)
- set(options "")
- set(singleOpts NAME)
- set(multiOpts "")
-
- cmake_parse_arguments(PARSE_ARGV 1 arg "${options}" "${singleOpts}" "${multiOpts}")
-
- _qt_internal_get_build_vars_for_external_projects(
- CMAKE_DIR_VAR qt_cmake_dir
- PREFIXES_VAR qt_prefixes
- ADDITIONAL_PACKAGES_PREFIXES_VAR qt_additional_packages_prefixes
- )
-
- list(APPEND QT_ADDITIONAL_PACKAGES_PREFIX_PATH "${qt_additional_packages_prefixes}")
-
- set(vars_to_pass_if_defined)
- set(var_defs)
- if(QT_HOST_PATH OR CMAKE_CROSSCOMPILING)
- list(APPEND var_defs
- -DCMAKE_TOOLCHAIN_FILE:FILEPATH=${qt_cmake_dir}/qt.toolchain.cmake
- )
- else()
- list(PREPEND CMAKE_PREFIX_PATH ${qt_prefixes})
-
- # Setting CMAKE_SYSTEM_NAME affects CMAKE_CROSSCOMPILING, even if it is
- # set to the same as the host, so it should only be set if it is different.
- # See https://gitlab.kitware.com/cmake/cmake/-/issues/21744
- if(NOT DEFINED CMAKE_TOOLCHAIN_FILE AND
- NOT CMAKE_SYSTEM_NAME STREQUAL CMAKE_HOST_SYSTEM_NAME)
- list(APPEND vars_to_pass_if_defined CMAKE_SYSTEM_NAME:STRING)
- endif()
- endif()
-
- # In multi-config mode by default we exclude building tools for configs other than the main one.
- # Trying to build an example in a non-default config using the non-installed
- # QtFooConfig.cmake files would error out saying moc is not found.
- # Make sure to build examples only with the main config.
- # When users build an example against an installed Qt they won't have this problem because
- # the generated non-main QtFooTargets-$<CONFIG>.cmake file is empty and doesn't advertise
- # a tool that is not there.
- if(QT_GENERATOR_IS_MULTI_CONFIG)
- set(CMAKE_CONFIGURATION_TYPES "${QT_MULTI_CONFIG_FIRST_CONFIG}")
- endif()
-
- # We need to pass the modified CXX flags of the parent project so that using sccache works
- # properly and doesn't error out due to concurrent access to the pdb files.
- # See qt_internal_set_up_config_optimizations_like_in_qmake, "/Zi" "/Z7".
- if(MSVC AND QT_FEATURE_msvc_obj_debug_info)
- qt_internal_get_enabled_languages_for_flag_manipulation(enabled_languages)
- set(configs RELWITHDEBINFO DEBUG)
- foreach(lang ${enabled_languages})
- foreach(config ${configs})
- set(flag_var_name "CMAKE_${lang}_FLAGS_${config}")
- list(APPEND vars_to_pass_if_defined "${flag_var_name}:STRING")
- endforeach()
- endforeach()
- endif()
-
- # When cross-compiling for a qemu target in our CI, we source an environment script
- # that sets environment variables like CC and CXX. These are parsed by CMake on initial
- # configuration to populate the cache vars CMAKE_${lang}_COMPILER.
- # If the environment variable specified not only the compiler path, but also a list of flags
- # to pass to the compiler, CMake parses those out into a separate CMAKE_${lang}_COMPILER_ARG1
- # cache variable. In such a case, we want to ensure that the external project also sees those
- # flags.
- # Unfortunately we can't do that by simply forwarding CMAKE_${lang}_COMPILER_ARG1 to the EP
- # because it breaks the compiler identification try_compile call, it simply doesn't consider
- # the cache var. From what I could gather, it's a limitation of try_compile and the list
- # of variables it considers for forwarding.
- # To fix this case, we ensure not to pass either cache variable, and let the external project
- # and its compiler identification try_compile project pick up the compiler and the flags
- # from the environment variables instead.
- foreach(lang_as_env_var CC CXX OBJC OBJCXX)
- if(lang_as_env_var STREQUAL "CC")
- set(lang_as_cache_var "C")
- else()
- set(lang_as_cache_var "${lang_as_env_var}")
- endif()
- set(lang_env_value "$ENV{${lang_as_env_var}}")
- if(lang_env_value
- AND CMAKE_${lang_as_cache_var}_COMPILER
- AND CMAKE_${lang_as_cache_var}_COMPILER_ARG1)
- # The compiler environment variable is set and specifies a list of extra flags, don't
- # forward the compiler cache vars and rely on the environment variable to be picked up
- # instead.
- else()
- list(APPEND vars_to_pass_if_defined "CMAKE_${lang_as_cache_var}_COMPILER:STRING")
- endif()
- endforeach()
- unset(lang_as_env_var)
- unset(lang_as_cache_var)
- unset(lang_env_value)
-
- list(APPEND vars_to_pass_if_defined
- CMAKE_BUILD_TYPE:STRING
- CMAKE_CONFIGURATION_TYPES:STRING
- CMAKE_PREFIX_PATH:STRING
- QT_BUILD_CMAKE_PREFIX_PATH:STRING
- QT_ADDITIONAL_PACKAGES_PREFIX_PATH:STRING
- CMAKE_FIND_ROOT_PATH:STRING
- BUILD_SHARED_LIBS:BOOL
- CMAKE_OSX_ARCHITECTURES:STRING
- CMAKE_OSX_DEPLOYMENT_TARGET:STRING
- CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED:BOOL
- CMAKE_XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH:BOOL
- CMAKE_C_COMPILER_LAUNCHER:STRING
- CMAKE_CXX_COMPILER_LAUNCHER:STRING
- CMAKE_OBJC_COMPILER_LAUNCHER:STRING
- CMAKE_OBJCXX_COMPILER_LAUNCHER:STRING
- )
-
- foreach(var_with_type IN LISTS vars_to_pass_if_defined)
- string(REPLACE ":" ";" key_as_list "${var_with_type}")
- list(GET key_as_list 0 var)
- if(NOT DEFINED ${var})
- continue()
- endif()
-
- # Preserve lists
- string(REPLACE ";" "$<SEMICOLON>" varForGenex "${${var}}")
-
- list(APPEND var_defs -D${var_with_type}=${varForGenex})
- endforeach()
-
- if(QT_INTERNAL_VERBOSE_EXAMPLES)
- list(APPEND var_defs -DCMAKE_MESSAGE_LOG_LEVEL:STRING=DEBUG)
- list(APPEND var_defs -DCMAKE_AUTOGEN_VERBOSE:BOOL=TRUE)
- endif()
-
- set(deps "")
- list(REMOVE_DUPLICATES QT_EXAMPLE_DEPENDENCIES)
- foreach(dep IN LISTS QT_EXAMPLE_DEPENDENCIES)
- if(TARGET ${dep})
- list(APPEND deps ${dep})
- endif()
- endforeach()
-
- set(independent_args)
- cmake_policy(PUSH)
- if(POLICY CMP0114)
- set(independent_args INDEPENDENT TRUE)
- cmake_policy(SET CMP0114 NEW)
- endif()
-
- # The USES_TERMINAL_BUILD setting forces the build step to the console pool
- # when using Ninja. This has two benefits:
- #
- # - You see build output as it is generated instead of at the end of the
- # build step.
- # - Only one task can use the console pool at a time, so it effectively
- # serializes all example build steps, thereby preventing CPU
- # over-commitment.
- #
- # If the loss of interactivity is not so important, one can allow CPU
- # over-commitment for Ninja builds. This may result in better throughput,
- # but is not allowed by default because it can make a machine almost
- # unusable while a compilation is running.
- set(terminal_args USES_TERMINAL_BUILD TRUE)
- if(CMAKE_GENERATOR MATCHES "Ninja")
- option(QT_BUILD_EXAMPLES_WITH_CPU_OVERCOMMIT
- "Allow CPU over-commitment when building examples (Ninja only)"
- )
- if(QT_BUILD_EXAMPLES_WITH_CPU_OVERCOMMIT)
- set(terminal_args)
- endif()
- endif()
-
- # QT_EXAMPLE_INSTALL_MARKER
- # The goal is to install each example project into a directory that keeps the example source dir
- # hierarchy, without polluting the example projects with dirty INSTALL_EXAMPLEDIR and
- # INSTALL_EXAMPLESDIR usage.
- # E.g. ensure qtbase/examples/widgets/widgets/wiggly is installed to
- # $qt_example_install_prefix/examples/widgets/widgets/wiggly/wiggly.exe
- # $qt_example_install_prefix defaults to ${CMAKE_INSTALL_PREFIX}/${INSTALL_EXAMPLEDIR}
- # but can also be set to a custom location.
- # This needs to work both:
- # - when using ExternalProject to build examples
- # - when examples are built in-tree as part of Qt (no ExternalProject).
- # The reason we want to support the latter is for nicer IDE integration: a can developer can
- # work with a Qt repo and its examples using the same build dir.
- #
- # In both case we have to ensure examples are not accidentally installed to $qt_prefix/bin or
- # similar.
- #
- # Example projects installation matrix.
- # 1) ExternalProject + unclean example install rules (INSTALL_EXAMPLEDIR is set) =>
- # use _qt_internal_override_example_install_dir_to_dot + ExternalProject_Add's INSTALL_DIR
- # using relative_dir from QT_EXAMPLE_BASE_DIR to example_source_dir
- #
- # 2) ExternalProject + clean example install rules =>
- # use ExternalProject_Add's INSTALL_DIR using relative_dir from QT_EXAMPLE_BASE_DIR to
- # example_source_dir, _qt_internal_override_example_install_dir_to_dot would be a no-op
- #
- # 3) in-tree + unclean example install rules (INSTALL_EXAMPLEDIR is set)
- # +
- # 4) in-tree + clean example install rules =>
- # ensure CMAKE_INSTALL_PREFIX is unset in parent cmake_install.cmake file, set non-cache
- # CMAKE_INSTALL_PREFIX using relative_dir from QT_EXAMPLE_BASE_DIR to
- # example_source_dir, use _qt_internal_override_example_install_dir_to_dot to ensure
- # INSTALL_EXAMPLEDIR does not interfere.
-
- qt_internal_get_example_install_path(example_install_path "${subdir}")
-
- set(ep_binary_dir "${CMAKE_CURRENT_BINARY_DIR}/${subdir}")
-
- set(build_command "")
- if(QT_INTERNAL_VERBOSE_EXAMPLES AND CMAKE_GENERATOR MATCHES "Ninja")
- set(build_command BUILD_COMMAND "${CMAKE_COMMAND}" --build "." -- -v)
- endif()
-
- ExternalProject_Add(${arg_NAME}
- EXCLUDE_FROM_ALL TRUE
- SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/${subdir}"
- PREFIX "${CMAKE_CURRENT_BINARY_DIR}/${subdir}-ep"
- STAMP_DIR "${CMAKE_CURRENT_BINARY_DIR}/${subdir}-ep/stamp"
- BINARY_DIR "${ep_binary_dir}"
- INSTALL_DIR "${example_install_path}"
- INSTALL_COMMAND ""
- ${build_command}
- TEST_COMMAND ""
- DEPENDS ${deps}
- CMAKE_CACHE_ARGS ${var_defs}
- -DCMAKE_INSTALL_PREFIX:STRING=<INSTALL_DIR>
- -DQT_INTERNAL_SET_EXAMPLE_INSTALL_DIR_TO_DOT:BOOL=TRUE
- ${terminal_args}
- )
-
- # Install the examples when the the user runs 'make install', and not at build time (which is
- # the default for ExternalProjects).
- install(CODE "\
-# Install example from inside ExternalProject into the main build's install prefix.
-execute_process(
- COMMAND
- \"${CMAKE_COMMAND}\" --build \"${ep_binary_dir}\" --target install
-)
-")
-
- # Force configure step to re-run after we configure the main project
- set(reconfigure_check_file ${CMAKE_CURRENT_BINARY_DIR}/reconfigure_${arg_NAME}.txt)
- file(TOUCH ${reconfigure_check_file})
- ExternalProject_Add_Step(${arg_NAME} reconfigure-check
- DEPENDERS configure
- DEPENDS ${reconfigure_check_file}
- ${independent_args}
- )
-
- # Create an apk external project step and custom target that invokes the apk target
- # within the external project.
- # Make the global apk target depend on that custom target.
- if(ANDROID)
- ExternalProject_Add_Step(${arg_NAME} apk
- COMMAND ${CMAKE_COMMAND} --build <BINARY_DIR> --target apk
- DEPENDEES configure
- EXCLUDE_FROM_MAIN YES
- ${terminal_args}
- )
- ExternalProject_Add_StepTargets(${arg_NAME} apk)
-
- if(TARGET apk)
- add_dependencies(apk ${arg_NAME}-apk)
- endif()
- endif()
-
- cmake_policy(POP)
-
- string(TOLOWER ${PROJECT_NAME} project_name_lower)
- add_dependencies(examples_${project_name_lower} ${arg_NAME})
-
-endfunction()
-
-function(qt_internal_install_example_sources subdir)
- set(options "")
- set(single_args NAME REPO_NAME)
- set(multi_args "")
-
- cmake_parse_arguments(PARSE_ARGV 1 arg "${options}" "${single_args}" "${multi_args}")
-
- qt_internal_get_examples_sources_install_path(example_install_path "${subdir}")
-
- # The trailing slash is important to avoid duplicate nested directory names.
- set(example_source_dir "${subdir}/")
-
- # Allow controlling whether sources should be part of the default install target.
- if(QT_INSTALL_EXAMPLES_SOURCES_BY_DEFAULT)
- set(exclude_from_all "")
- else()
- set(exclude_from_all "EXCLUDE_FROM_ALL")
- endif()
-
- # Create an install component for all example sources. Can also be part of the default
- # install target if EXCLUDE_FROM_ALL is not passed.
- install(
- DIRECTORY "${example_source_dir}"
- DESTINATION "${example_install_path}"
- COMPONENT "examples_sources"
- USE_SOURCE_PERMISSIONS
- ${exclude_from_all}
- )
-
- # Also create a specific install component just for this repo's examples.
- install(
- DIRECTORY "${example_source_dir}"
- DESTINATION "${example_install_path}"
- COMPONENT "examples_sources_${arg_REPO_NAME}"
- USE_SOURCE_PERMISSIONS
- EXCLUDE_FROM_ALL
- )
-
- # Also create a specific install component just for the current example's sources.
- install(
- DIRECTORY "${example_source_dir}"
- DESTINATION "${example_install_path}"
- COMPONENT "examples_sources_${arg_NAME}"
- USE_SOURCE_PERMISSIONS
- EXCLUDE_FROM_ALL
- )
-endfunction()
-
-if ("STANDALONE_TEST" IN_LIST Qt6BuildInternals_FIND_COMPONENTS)
- include(${CMAKE_CURRENT_LIST_DIR}/QtStandaloneTestTemplateProject/Main.cmake)
- if (NOT PROJECT_VERSION_MAJOR)
- get_property(_qt_major_version TARGET ${QT_CMAKE_EXPORT_NAMESPACE}::Core PROPERTY INTERFACE_QT_MAJOR_VERSION)
- set(PROJECT_VERSION ${Qt${_qt_major_version}Core_VERSION})
-
- string(REPLACE "." ";" _qt_core_version_list ${PROJECT_VERSION})
- list(GET _qt_core_version_list 0 PROJECT_VERSION_MAJOR)
- list(GET _qt_core_version_list 1 PROJECT_VERSION_MINOR)
- list(GET _qt_core_version_list 2 PROJECT_VERSION_PATCH)
- endif()
-endif()
-
-function(qt_internal_static_link_order_test)
- # The CMake versions greater than 3.21 take care about the resource object files order in a
- # linker line, it's expected that all object files are located at the beginning of the linker
- # line.
- # No need to run the test.
- if(CMAKE_VERSION VERSION_LESS 3.21)
- __qt_internal_check_link_order_matters(link_order_matters)
- if(link_order_matters)
- set(summary_message "no")
- else()
- set(summary_message "yes")
- endif()
- else()
- set(summary_message "yes")
- endif()
- qt_configure_add_summary_entry(TYPE "message"
- ARGS "Linker can resolve circular dependencies"
- MESSAGE "${summary_message}"
- )
-endfunction()
-
-function(qt_internal_check_cmp0099_available)
- # Don't care about CMP0099 in CMake versions greater than or equal to 3.21
- if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.21)
- return()
- endif()
-
- __qt_internal_check_cmp0099_available(result)
- if(result)
- set(summary_message "yes")
- else()
- set(summary_message "no")
- endif()
- qt_configure_add_summary_entry(TYPE "message"
- ARGS "CMake policy CMP0099 is supported"
- MESSAGE "${summary_message}"
- )
-endfunction()
-
-function(qt_internal_run_common_config_tests)
- qt_configure_add_summary_section(NAME "Common build options")
- qt_internal_static_link_order_test()
- qt_internal_check_cmp0099_available()
- qt_configure_end_summary_section()
-endfunction()
+include(QtBuildRepoExamplesHelpers)
+include(QtBuildRepoHelpers)
-# It is used in QtWebEngine to replace the REALPATH with ABSOLUTE path, which is
-# useful for building Qt in Homebrew.
-function(qt_internal_get_filename_path_mode out_var)
- set(mode REALPATH)
- if(APPLE AND QT_ALLOW_SYMLINK_IN_PATHS)
- set(mode ABSOLUTE)
- endif()
- set(${out_var} ${mode} PARENT_SCOPE)
-endfunction()
+qt_internal_setup_build_internals()