summaryrefslogtreecommitdiffstats
path: root/cmake
diff options
context:
space:
mode:
Diffstat (limited to 'cmake')
-rw-r--r--cmake/3rdparty/extra-cmake-modules/find-modules/FindEGL.cmake3
-rw-r--r--cmake/3rdparty/extra-cmake-modules/find-modules/FindXCB.cmake3
-rw-r--r--cmake/3rdparty/extra-cmake-modules/modules/ECMEnableSanitizers.cmake10
-rw-r--r--cmake/CODESTYLE.md197
-rw-r--r--cmake/FindGSSAPI.cmake21
-rw-r--r--cmake/FindMimer.cmake56
-rw-r--r--cmake/FindPPS.cmake8
-rw-r--r--cmake/FindPostgreSQL.cmake3
-rw-r--r--cmake/FindRenderDoc.cmake20
-rw-r--r--cmake/FindWrapBrotli.cmake7
-rw-r--r--cmake/FindWrapOpenGL.cmake18
-rw-r--r--cmake/FindWrapResolv.cmake53
-rw-r--r--cmake/FindWrapSystemHarfbuzz.cmake7
-rw-r--r--cmake/FindWrapSystemPCRE2.cmake7
-rw-r--r--cmake/FindWrapSystemZLIB.cmake10
-rw-r--r--cmake/FindWrapVulkanHeaders.cmake20
-rw-r--r--cmake/FindWrapZSTD.cmake12
-rw-r--r--cmake/Qt3rdPartyLibraryConfig.cmake.in9
-rw-r--r--cmake/Qt3rdPartyLibraryHelpers.cmake1
-rw-r--r--cmake/QtAndroidHelpers.cmake166
-rw-r--r--cmake/QtAppHelpers.cmake23
-rw-r--r--cmake/QtAutoDetect.cmake498
-rw-r--r--cmake/QtAutoDetectHelpers.cmake487
-rw-r--r--cmake/QtAutogenHelpers.cmake46
-rw-r--r--cmake/QtBaseConfigureTests.cmake66
-rw-r--r--cmake/QtBaseGlobalTargets.cmake226
-rw-r--r--cmake/QtBaseHelpers.cmake222
-rw-r--r--cmake/QtBaseTopLevelHelpers.cmake96
-rw-r--r--cmake/QtBuild.cmake573
-rw-r--r--cmake/QtBuildHelpers.cmake458
-rw-r--r--cmake/QtBuildInformation.cmake36
-rw-r--r--cmake/QtBuildInternals/QtBuildInternalsConfig.cmake1394
-rw-r--r--cmake/QtBuildInternals/QtStandaloneTestTemplateProject/CMakeLists.txt17
-rw-r--r--cmake/QtBuildInternals/QtStandaloneTestTemplateProject/Main.cmake10
-rw-r--r--cmake/QtBuildInternalsExtra.cmake.in43
-rw-r--r--cmake/QtBuildOptionsHelpers.cmake383
-rw-r--r--cmake/QtBuildPathsHelpers.cmake247
-rw-r--r--cmake/QtBuildRepoExamplesHelpers.cmake652
-rw-r--r--cmake/QtBuildRepoHelpers.cmake1079
-rw-r--r--cmake/QtCMakeHelpers.cmake63
-rw-r--r--cmake/QtCMakePackageVersionFile.cmake.in3
-rw-r--r--cmake/QtCMakeVersionHelpers.cmake6
-rw-r--r--cmake/QtCompilerFlags.cmake15
-rw-r--r--cmake/QtCompilerOptimization.cmake68
-rw-r--r--cmake/QtConfig.cmake.in54
-rw-r--r--cmake/QtConfigDependencies.cmake.in3
-rw-r--r--cmake/QtConfigExtras.cmake.in5
-rw-r--r--cmake/QtConfigureTimeExecutableCMakeLists.txt.in3
-rw-r--r--cmake/QtDocsHelpers.cmake37
-rw-r--r--cmake/QtExecutableHelpers.cmake186
-rw-r--r--cmake/QtFeature.cmake277
-rw-r--r--cmake/QtFindPackageHelpers.cmake118
-rw-r--r--cmake/QtFindWrapConfigExtra.cmake.in3
-rw-r--r--cmake/QtFindWrapHelper.cmake31
-rw-r--r--cmake/QtFlagHandlingHelpers.cmake238
-rw-r--r--cmake/QtFrameworkHelpers.cmake95
-rw-r--r--cmake/QtHeadersClean.cmake52
-rw-r--r--cmake/QtHostInfoConfig.cmake.in3
-rw-r--r--cmake/QtInitProject.cmake2
-rw-r--r--cmake/QtInstallPaths.cmake.in16
-rw-r--r--cmake/QtInternalTargets.cmake128
-rw-r--r--cmake/QtJavaHelpers.cmake11
-rw-r--r--cmake/QtMkspecHelpers.cmake146
-rw-r--r--cmake/QtModuleConfig.cmake.in32
-rw-r--r--cmake/QtModuleDependencies.cmake.in6
-rw-r--r--cmake/QtModuleHeadersCheck.cmake3
-rw-r--r--cmake/QtModuleHelpers.cmake224
-rw-r--r--cmake/QtModuleToolsConfig.cmake.in3
-rw-r--r--cmake/QtModuleToolsDependencies.cmake.in3
-rw-r--r--cmake/QtModuleToolsVersionlessTargets.cmake.in3
-rw-r--r--cmake/QtPkgConfigHelpers.cmake13
-rw-r--r--cmake/QtPlatformAndroid.cmake16
-rw-r--r--cmake/QtPlatformSupport.cmake4
-rw-r--r--cmake/QtPlatformTargetHelpers.cmake9
-rw-r--r--cmake/QtPluginConfig.cmake.in5
-rw-r--r--cmake/QtPluginDependencies.cmake.in3
-rw-r--r--cmake/QtPluginHelpers.cmake139
-rw-r--r--cmake/QtPlugins.cmake.in8
-rw-r--r--cmake/QtPostProcess.cmake2
-rw-r--r--cmake/QtPostProcessHelpers.cmake146
-rw-r--r--cmake/QtPriHelpers.cmake43
-rw-r--r--cmake/QtProcessConfigureArgs.cmake207
-rw-r--r--cmake/QtPublicAppleHelpers.cmake451
-rw-r--r--cmake/QtPublicCMakeHelpers.cmake587
-rw-r--r--cmake/QtPublicDependencyHelpers.cmake2
-rw-r--r--cmake/QtPublicExternalProjectHelpers.cmake86
-rw-r--r--cmake/QtPublicFindPackageHelpers.cmake49
-rw-r--r--cmake/QtPublicPluginHelpers.cmake2
-rw-r--r--cmake/QtPublicTargetHelpers.cmake26
-rw-r--r--cmake/QtPublicTestHelpers.cmake4
-rw-r--r--cmake/QtPublicWalkLibsHelpers.cmake14
-rw-r--r--cmake/QtPublicWasmToolchainHelpers.cmake16
-rw-r--r--cmake/QtQmakeHelpers.cmake4
-rw-r--r--cmake/QtRpathHelpers.cmake47
-rw-r--r--cmake/QtSanitizerHelpers.cmake32
-rw-r--r--cmake/QtSeparateDebugInfo.Info.plist.in5
-rw-r--r--cmake/QtSeparateDebugInfo.cmake20
-rw-r--r--cmake/QtSetup.cmake380
-rw-r--r--cmake/QtStandaloneTestsConfig.cmake.in5
-rw-r--r--cmake/QtSyncQtHelpers.cmake71
-rw-r--r--cmake/QtTargetHelpers.cmake451
-rw-r--r--cmake/QtTestHelpers.cmake183
-rw-r--r--cmake/QtToolHelpers.cmake130
-rw-r--r--cmake/QtToolchainHelpers.cmake68
-rw-r--r--cmake/QtUnityBuildHelpers.cmake11
-rw-r--r--cmake/QtVersionlessAliasTargets.cmake.in7
-rw-r--r--cmake/QtVersionlessTargets.cmake.in7
-rw-r--r--cmake/QtWasmHelpers.cmake20
-rw-r--r--cmake/QtWrapperScriptHelpers.cmake111
-rw-r--r--cmake/QtWriteArgsFile.cmake8
-rw-r--r--cmake/README.md15
-rw-r--r--cmake/configure-cmake-mapping.md33
-rw-r--r--cmake/ios/LaunchScreen.storyboard29
-rw-r--r--cmake/ios/PrivacyInfo.xcprivacy14
-rw-r--r--cmake/macos/Info.plist.app.in (renamed from cmake/macos/MacOSXBundleInfo.plist.in)0
-rw-r--r--cmake/macos/PrivacyInfo.xcprivacy12
-rw-r--r--cmake/modulecppexports.h.in16
-rw-r--r--cmake/modulecppexports_p.h.in22
-rw-r--r--cmake/qbatchedtestrunner.in.cpp2
-rw-r--r--cmake/tests/main.cpp2
-rw-r--r--cmake/visionos/Info.plist.app.in50
-rw-r--r--cmake/visionos/PrivacyInfo.xcprivacy14
122 files changed, 8454 insertions, 4171 deletions
diff --git a/cmake/3rdparty/extra-cmake-modules/find-modules/FindEGL.cmake b/cmake/3rdparty/extra-cmake-modules/find-modules/FindEGL.cmake
index 0733f1f702..9ac8e2fa0c 100644
--- a/cmake/3rdparty/extra-cmake-modules/find-modules/FindEGL.cmake
+++ b/cmake/3rdparty/extra-cmake-modules/find-modules/FindEGL.cmake
@@ -128,7 +128,8 @@ check_cxx_source_compiles("
#include <EGL/egl.h>
int main(int, char **) {
- EGLint x = 0; EGLDisplay dpy = 0; EGLContext ctx = 0;
+ [[maybe_unused]] EGLint x = 0;
+ EGLDisplay dpy = 0; EGLContext ctx = 0;
eglDestroyContext(dpy, ctx);
}" HAVE_EGL)
diff --git a/cmake/3rdparty/extra-cmake-modules/find-modules/FindXCB.cmake b/cmake/3rdparty/extra-cmake-modules/find-modules/FindXCB.cmake
index dc60289401..26b9bf8963 100644
--- a/cmake/3rdparty/extra-cmake-modules/find-modules/FindXCB.cmake
+++ b/cmake/3rdparty/extra-cmake-modules/find-modules/FindXCB.cmake
@@ -137,6 +137,9 @@ foreach(_comp ${XCB_known_components})
set(XCB_${_comp}_pkg_config "xcb-${_lc_comp}")
set(XCB_${_comp}_lib "xcb-${_lc_comp}")
set(XCB_${_comp}_header "xcb/${_lc_comp}.h")
+ if(USE_XCB_${_comp}_STATIC)
+ set(XCB_${_comp}_lib "lib${XCB_${_comp}_lib}.a")
+ endif()
endforeach()
# exceptions
set(XCB_XCB_component_deps)
diff --git a/cmake/3rdparty/extra-cmake-modules/modules/ECMEnableSanitizers.cmake b/cmake/3rdparty/extra-cmake-modules/modules/ECMEnableSanitizers.cmake
index dcdb8621d3..15610587bd 100644
--- a/cmake/3rdparty/extra-cmake-modules/modules/ECMEnableSanitizers.cmake
+++ b/cmake/3rdparty/extra-cmake-modules/modules/ECMEnableSanitizers.cmake
@@ -158,7 +158,15 @@ if (ECM_ENABLE_SANITIZERS)
endif()
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${XSAN_COMPILE_FLAGS}" )
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
- link_libraries(${XSAN_LINKER_FLAGS})
+ string(JOIN "" linker_flags
+ "$<"
+ "$<NOT:"
+ "$<BOOL:$<TARGET_PROPERTY:SKIP_SANITIZER>>"
+ ">:"
+ "${XSAN_LINKER_FLAGS}"
+ ">"
+ )
+ link_libraries("${linker_flags}")
endif()
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
string(REPLACE "-Wl,--no-undefined" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
diff --git a/cmake/CODESTYLE.md b/cmake/CODESTYLE.md
new file mode 100644
index 0000000000..6dfc676d16
--- /dev/null
+++ b/cmake/CODESTYLE.md
@@ -0,0 +1,197 @@
+# Unofficial Qt CMake Coding Style
+
+CMake scripts are a bit of a wild west. Depending on when the code was written, there were
+different conventions as well as syntax facilities available. It's also unfortunate that there is
+no agreed upon CMake code formatter similar to clang-format.
+https://github.com/cheshirekow/cmake_format exists, but appears abandoned. We might look into
+using it at some point.
+
+It's hard to convince people to use a certain code style for a language like CMake.
+
+Nevertheless this short document aims to be a guideline for formatting CMake code within the Qt
+project.
+
+## Common conventions
+
+* When in doubt, prefer the local code conventions of the function or file you are editing.
+* Prefer functions over macros (macros have certain problems with parameter escaping)
+* Prefix macro local variables to avoid naming collisions
+
+## Case Styles
+
+For CMake identifiers we refer to following case styles in the text below.
+
+| Case style name | Example identifier |
+|-------------------|----------------------------|
+| Snake case | `moc_options` |
+| Shouty case | `INTERFACE_LINK_LIBRARIES` |
+| Pascal case | `QmlModels` |
+
+## Indentation
+
+* When in doubt, follow local indentation
+* Prefer indenting with 4 spaces, e.g.
+
+```
+if(1)
+ if(2)
+ message("3")
+ endif()
+endif()
+
+```
+
+## Variables
+
+* local variables inside a function should be snake cased => `list_of_arguments`
+* local variables inside a macro should be snake cased and have a unique prefix =>
+ `__qt_list_of_packages`
+ * If your macro is recursively called, you might need to prepend a dynamically computed prefix
+ to avoid overriding the same variable in nested calls =>
+ `__qt_${dependency_name}_list_of_packages`
+* cache variables should be shouty cased => `BUILD_SHARED_LIBS`
+ * Qt cache variables should be prefixed with `QT_`
+
+## Properties
+
+Currently the Qt property naming is a bit of a mess. The upstream issue
+https://gitlab.kitware.com/cmake/cmake/-/issues/19261 mentions that properties prefixed with
+`INTERFACE_` are reserved for CMake use.
+
+Prefer to use snake case for new property names.
+
+* Most upstream CMake properties are shouty cased => `INTERFACE_LINK_LIBRARIES`
+* Properties created in Qt 5 times follow the same CMake convention => `QT_ENABLED_PUBLIC_FEATURES`
+ No such new properties should be added.
+* New Qt properties should be snake cased and prefixed with `qt_` => `qt_qmake_module_name`
+* Other internal Qt properties should be snake cased and prefixed with `_qt_` => `_qt_target_deps`
+
+## Functions
+
+* Function names should be snake cased => `qt_add_module`
+ * public Qt functions should be prefixed with `qt_`
+ * internal Qt functions should be prefixed with `qt_internal_`
+ * internal Qt functions that live in public CMake API files should be prefixed with
+ `_qt_internal_`
+ * some internal functions that live in public CMake API files are prefixed with
+ `__qt_internal_`, prefer not to introduce such functions for now
+* If a public function takes more than 1 parameter, consider using `cmake_parse_arguments`
+* If an internal Qt function takes more than 1 parameter, consider using `qt_parse_all_arguments`
+* Public functions should usually have both a version-full and version-less name => `qt_add_plugin`
+ and `qt6_add_plugin`
+
+### Macros
+
+* Try to avoid macros where a function can be used instead
+ * A common case when a macro can not be avoided is when it wraps a CMake macro e.g
+ `find_package` => `qt_find_package`
+* Macro names should be snake cased => `qt_find_package`
+* Prefix macro local variables to avoid naming collisions => `__qt_find_package_arguments`
+
+## Commands
+
+Command names in CMake are case-insensitive, therefore:
+* Only use lower case command names e.g `add_executable(app main.cpp)` not `ADD_EXECUTABLE(app
+ main.cpp)`
+* Command flags / options are usually shouty cased => `file(GENERATE OUTPUT "foo" CONTENT "bar")`
+
+## 'If' command
+
+* Keep the parenthesis next to the `if()`, so don't write `if ()`. `if` is a command name and like
+ other command names e.g. `find_package(foo bar)` the parenethesis are next to the name.
+
+* To check that a variable is an empty string (and not just a falsy value, think Javascript's
+ `foo === ""`) use the following snippet
+```
+if(var_name STREQUAL "")
+ message("${var_name}")
+endif()
+```
+
+If you are not sure if the variable is defined, make sure to evaluate the variable name
+```
+if("${var_name}" STREQUAL "")
+ message("${var_name}")
+endif()
+```
+
+
+* Falsy values are `0`, `OFF`, `NO`, `FALSE`, `N`, `IGNORE`, `NOTFOUND`, the empty string `""`, or
+ a string ending in `-NOTFOUND`. To check that a variable is NOT falsy use the first suggested
+ code snippet
+```
+# Nice and clean
+if(var_name)
+ message("${var_name}")
+endif()
+
+# Wrong, can lead to problems due to double variable evaluation
+if(${var_name})
+ message("${var_name}")
+endif()
+
+# Incorrect if you want to check for all falsy values. This only checks for string emptiness.
+if("${var_name}" STREQUAL "")
+ message("${var_name}")
+endif()
+```
+
+* To check if a variable is defined, use
+```
+if(DEFINED var_name)
+endif()
+```
+
+* To compare a defined variable's contents to a string, use
+```
+if(var_name STREQUAL "my_string")
+endif()
+```
+
+* To compare a defined variable's contents to another defined variable's contents, use
+```
+if(var_name STREQUAL var_name_2)
+endif()
+```
+
+* To compare a possibly undefined variable make sure to explicitly evaluate it first
+```
+if("${var_name}" STREQUAL "my_string")
+endif()
+
+if("${var_name}" STREQUAL "${var_name_2}")
+endif()
+```
+
+## find_package
+
+* Inside Qt module projects, use the private Qt-specific `qt_find_package` macro to look for
+ dependencies.
+ * Make sure to specify the `PROVIDED_TARGETS` option to properly register 3rd party target
+ dependencies with Qt's internal build system.
+* Inside examples / projects (which only use public CMake API) use the regular `find_package`
+ command.
+
+## CMake Target names
+
+* Qt target names should be pascal cased => `QuickParticles`.
+* When Qt is installed, the Qt CMake targets are put inside the `Qt6::` namespace. Associated
+ versionless targets in the `Qt::` namespace are usually automatically created by appropriate
+ functions (`qt_internal_add_module`, `qt_internal_add_tool`)
+* Wrapper 3rd party system libraries usually repeat the target name as the namespace e.g.
+ ```WrapSystemHarfbuzz::WrapSystemHarfbuzz```
+
+## Finding 3rd party libraries via Find modules (FindWrapFoo.cmake)
+
+qmake-Qt uses `configure.json` and `configure.pri` and `QT_LIBS_FOO` variables to implement a
+mechnism that searches for system 3rd party libraries.
+
+The equivalent CMake mechanism are Find modules (and CMake package Config files; not to be confused
+with pkg-config). Usually Qt provides wrapper Find modules that use any available upstream Find
+modules or Config package files.
+
+The naming convention for the files are:
+
+* `FindWrapFoo.cmake` => `FindWrapPCRE2.cmake`
+* `FindWrapSystemFoo.cmake` => `FindWrapSystemPCRE2.cmake`
+
diff --git a/cmake/FindGSSAPI.cmake b/cmake/FindGSSAPI.cmake
index cc89406a72..44594941e3 100644
--- a/cmake/FindGSSAPI.cmake
+++ b/cmake/FindGSSAPI.cmake
@@ -12,12 +12,24 @@ find_path(GSSAPI_INCLUDE_DIRS
HINTS ${PC_GSSAPI_INCLUDEDIR}
)
+# On macOS, vcpkg opts for finding frameworks LAST. This is generally fine;
+# however, in the case of GSSAPI, `usr/lib/libgssapi_krb5.tbd` which is a
+# symlink to `Kerberos.framework` misses a few symols, e.g.,
+# `___gss_c_nt_hostbased_service_oid_desc`, and it causes build failure.
+# So, we need to make sure that we find `GSS.framework`.
+set(gssapi_library_names
+ GSS # framework
+ gss # solaris
+ gssapi # FreeBSD
+ gssapi_krb5
+)
+if(APPLE)
+ list(REMOVE_ITEM gssapi_library_names "gssapi_krb5")
+endif()
+
find_library(GSSAPI_LIBRARIES
NAMES
- GSS # framework
- gss # solaris
- gssapi # FreeBSD
- gssapi_krb5
+ ${gssapi_library_names}
HINTS ${PC_GSSAPI_LIBDIR}
)
@@ -44,4 +56,3 @@ mark_as_advanced(GSSAPI_INCLUDE_DIRS GSSAPI_LIBRARIES)
include(FeatureSummary)
set_package_properties(GSSAPI PROPERTIES
DESCRIPTION "Generic Security Services Application Program Interface")
-
diff --git a/cmake/FindMimer.cmake b/cmake/FindMimer.cmake
index 5bc8d95a5a..5cbc6e6907 100644
--- a/cmake/FindMimer.cmake
+++ b/cmake/FindMimer.cmake
@@ -5,18 +5,62 @@
# FindMimer
# ---------
# Try to locate the Mimer SQL client library
+if(NOT DEFINED MimerSQL_ROOT)
+ if(DEFINED ENV{MIMERSQL_DEV_ROOT})
+ set(MimerSQL_ROOT "$ENV{MIMERSQL_DEV_ROOT}")
+ endif()
+endif()
-find_package(PkgConfig QUIET)
-pkg_check_modules(PC_Mimer QUIET mimctrl)
+if(NOT DEFINED MimerSQL_ROOT)
+ find_package(PkgConfig QUIET)
+endif()
+if(PkgConfig_FOUND AND NOT DEFINED MimerSQL_ROOT)
+ pkg_check_modules(PC_Mimer QUIET mimcontrol)
+ set(MimerSQL_include_dir_hints "${PC_MimerSQL_INCLUDEDIR}")
+ set(MimerSQL_library_hints "${PC_MimerSQL_LIBDIR}")
+else()
+ if(DEFINED MimerSQL_ROOT)
+ if(WIN32)
+ set(MimerSQL_include_dir_hints "${MimerSQL_ROOT}\\include")
+ if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86|X86)$")
+ set(MimerSQL_library_hints "${MimerSQL_ROOT}\\lib\\x86")
+ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(amd64|AMD64)$")
+ set(MimerSQL_library_hints "${MimerSQL_ROOT}\\lib\\amd64")
+ else()
+ set(MimerSQL_library_hints "")
+ endif()
+ else()
+ set(MimerSQL_include_dir_hints "${MimerSQL_ROOT}/include")
+ set(MimerSQL_library_hints "${MimerSQL_ROOT}/lib")
+ endif()
+ else()
+ if(WIN32)
+ set(MimerSQL_include_dir_hints "C:\\MimerSQLDev\\include")
+ if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86|X86)$")
+ set(MimerSQL_library_hints "C:\\MimerSQLDev\\lib\\x86")
+ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(amd64|AMD64)$")
+ set(MimerSQL_library_hints "C:\\MimerSQLDev\\lib\\amd64")
+ else()
+ set(MimerSQL_library_hints "")
+ endif()
+ elseif(APPLE AND ${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+ set(MimerSQL_library_hints "/usr/local/lib")
+ set(MimerSQL_include_dir_hints "/usr/local/include")
+ else()
+ set(MimerSQL_include_dir_hints "")
+ set(MimerSQL_library_hints "")
+ endif()
+ endif()
+endif()
find_path(Mimer_INCLUDE_DIR
NAMES mimerapi.h
- HINTS ${PC_Mimer_INCLUDEDIR})
+ HINTS ${MimerSQL_include_dir_hints})
if(WIN32)
- if("$ENV{PROCESSOR_ARCHITECTURE}" STREQUAL "x86")
+ if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86|X86)$")
set(MIMER_LIBS_NAMES mimapi32)
- else()
+ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(amd64|AMD64)$")
set(MIMER_LIBS_NAMES mimapi64)
endif()
else()
@@ -25,7 +69,7 @@ endif()
find_library(Mimer_LIBRARIES
NAMES ${MIMER_LIBS_NAMES}
- HINTS ${PC_Mimer_LIBDIR})
+ HINTS ${MimerSQL_library_hints})
include(FindPackageHandleStandardArgs)
diff --git a/cmake/FindPPS.cmake b/cmake/FindPPS.cmake
index 6556091c11..099019243c 100644
--- a/cmake/FindPPS.cmake
+++ b/cmake/FindPPS.cmake
@@ -18,9 +18,7 @@ find_package_handle_standard_args(PPS DEFAULT_MSG PPS_INCLUDE_DIR PPS_LIBRARY)
mark_as_advanced(PPS_INCLUDE_DIR PPS_LIBRARY)
if(PPS_FOUND)
- add_library(__PPS INTERFACE IMPORTED)
- target_link_libraries(__PPS INTERFACE "${PPS_LIBRARY}")
- target_include_directories(__PPS INTERFACE "${PPS_INCLUDE_DIR}")
-
- add_library(PPS::PPS ALIAS __PPS)
+ add_library(PPS::PPS INTERFACE IMPORTED)
+ target_link_libraries(PPS::PPS INTERFACE "${PPS_LIBRARY}")
+ target_include_directories(PPS::PPS INTERFACE "${PPS_INCLUDE_DIR}")
endif()
diff --git a/cmake/FindPostgreSQL.cmake b/cmake/FindPostgreSQL.cmake
index ca3a454527..a61bec9337 100644
--- a/cmake/FindPostgreSQL.cmake
+++ b/cmake/FindPostgreSQL.cmake
@@ -99,6 +99,9 @@ endif()
cmake_policy(PUSH)
cmake_policy(SET CMP0057 NEW) # if IN_LIST
+if(POLICY CMP0159)
+ cmake_policy(SET CMP0159 NEW)
+endif()
set(PostgreSQL_INCLUDE_PATH_DESCRIPTION "top-level directory containing the PostgreSQL include directories. E.g /usr/local/include/PostgreSQL/8.4 or C:/Program Files/PostgreSQL/8.4/include")
set(PostgreSQL_INCLUDE_DIR_MESSAGE "Set the PostgreSQL_INCLUDE_DIR cmake cache entry to the ${PostgreSQL_INCLUDE_PATH_DESCRIPTION}")
diff --git a/cmake/FindRenderDoc.cmake b/cmake/FindRenderDoc.cmake
new file mode 100644
index 0000000000..02970fc7d6
--- /dev/null
+++ b/cmake/FindRenderDoc.cmake
@@ -0,0 +1,20 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+if(WIN32 OR UNIX)
+ find_path(RenderDoc_INCLUDE_DIR
+ NAMES renderdoc_app.h)
+endif()
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(RenderDoc
+ DEFAULT_MSG
+ RenderDoc_INCLUDE_DIR)
+
+mark_as_advanced(RenderDoc_INCLUDE_DIR)
+
+if(RenderDoc_FOUND AND NOT TARGET RenderDoc::RenderDoc)
+ add_library(RenderDoc::RenderDoc INTERFACE IMPORTED)
+ set_target_properties(RenderDoc::RenderDoc PROPERTIES
+ INTERFACE_INCLUDE_DIRECTORIES "${RenderDoc_INCLUDE_DIR}")
+endif()
diff --git a/cmake/FindWrapBrotli.cmake b/cmake/FindWrapBrotli.cmake
index e2d7b564f6..d254f4292e 100644
--- a/cmake/FindWrapBrotli.cmake
+++ b/cmake/FindWrapBrotli.cmake
@@ -20,6 +20,13 @@ if (unofficial-brotli_FOUND)
set(WrapBrotli_FOUND ON)
else()
+ get_cmake_property(__packages_not_found PACKAGES_NOT_FOUND)
+ if(__packages_not_found)
+ list(REMOVE_ITEM __packages_not_found unofficial-brotli)
+ set_property(GLOBAL PROPERTY PACKAGES_NOT_FOUND "${__packages_not_found}")
+ endif()
+ unset(__packages_not_found)
+
find_package(PkgConfig QUIET)
if (PKG_CONFIG_FOUND)
pkg_check_modules(libbrotlidec QUIET IMPORTED_TARGET "libbrotlidec")
diff --git a/cmake/FindWrapOpenGL.cmake b/cmake/FindWrapOpenGL.cmake
index c4e0fe5d3e..7295a159ca 100644
--- a/cmake/FindWrapOpenGL.cmake
+++ b/cmake/FindWrapOpenGL.cmake
@@ -17,14 +17,18 @@ if (OpenGL_FOUND)
add_library(WrapOpenGL::WrapOpenGL INTERFACE IMPORTED)
if(APPLE)
+ # CMake 3.27 and older:
# On Darwin platforms FindOpenGL sets IMPORTED_LOCATION to the absolute path of the library
# within the framework. This ends up as an absolute path link flag, which we don't want,
# because that makes our .prl files un-relocatable.
# Extract the framework path instead, and use that in INTERFACE_LINK_LIBRARIES,
- # which CMake ends up transforming into a reloctable -framework flag.
+ # which CMake ends up transforming into a relocatable -framework flag.
# See https://gitlab.kitware.com/cmake/cmake/-/issues/20871 for details.
+ #
+ # CMake 3.28 and above:
+ # IMPORTED_LOCATION is the absolute path the the OpenGL.framework folder.
get_target_property(__opengl_fw_lib_path OpenGL::GL IMPORTED_LOCATION)
- if(__opengl_fw_lib_path)
+ if(__opengl_fw_lib_path AND NOT __opengl_fw_lib_path MATCHES "/([^/]+)\\.framework$")
get_filename_component(__opengl_fw_path "${__opengl_fw_lib_path}" DIRECTORY)
endif()
@@ -46,6 +50,16 @@ if (OpenGL_FOUND)
else()
target_link_libraries(WrapOpenGL::WrapOpenGL INTERFACE OpenGL::GL)
endif()
+elseif(UNIX AND NOT APPLE AND NOT CMAKE_SYSTEM_NAME STREQUAL "Integrity")
+ # Requesting only the OpenGL component ensures CMake does not mark the package as
+ # not found if neither GLX nor libGL are available. This allows finding OpenGL
+ # on an X11-less Linux system.
+ find_package(OpenGL ${WrapOpenGL_FIND_VERSION} COMPONENTS OpenGL)
+ if (OpenGL_FOUND)
+ set(WrapOpenGL_FOUND ON)
+ add_library(WrapOpenGL::WrapOpenGL INTERFACE IMPORTED)
+ target_link_libraries(WrapOpenGL::WrapOpenGL INTERFACE OpenGL::OpenGL)
+ endif()
endif()
include(FindPackageHandleStandardArgs)
diff --git a/cmake/FindWrapResolv.cmake b/cmake/FindWrapResolv.cmake
new file mode 100644
index 0000000000..1afd253ee8
--- /dev/null
+++ b/cmake/FindWrapResolv.cmake
@@ -0,0 +1,53 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# Copyright (C) 2023 Intel Corpotation.
+# SPDX-License-Identifier: BSD-3-Clause
+
+# We can't create the same interface imported target multiple times, CMake will complain if we do
+# that. This can happen if the find_package call is done in multiple different subdirectories.
+if(TARGET WrapResolv::WrapResolv)
+ set(WrapResolv_FOUND ON)
+ return()
+endif()
+
+set(WrapResolv_FOUND OFF)
+
+include(CheckCXXSourceCompiles)
+include(CMakePushCheckState)
+
+if(QNX)
+ find_library(LIBRESOLV socket)
+else()
+ find_library(LIBRESOLV resolv)
+endif()
+
+cmake_push_check_state()
+if(LIBRESOLV)
+ list(APPEND CMAKE_REQUIRED_LIBRARIES "${LIBRESOLV}")
+endif()
+
+check_cxx_source_compiles("
+#include <netinet/in.h>
+#include <resolv.h>
+
+int main(int, char **argv)
+{
+ res_state statep = 0;
+ int n = res_nmkquery(statep, 0, argv[1], 0, 0, NULL, 0, NULL, NULL, 0);
+ n = res_nsend(statep, NULL, 0, NULL, 0);
+ n = dn_expand(NULL, NULL, NULL, NULL, 0);
+ return n;
+}
+" HAVE_LIBRESOLV_FUNCTIONS)
+
+cmake_pop_check_state()
+
+if(HAVE_LIBRESOLV_FUNCTIONS)
+ set(WrapResolv_FOUND ON)
+ add_library(WrapResolv::WrapResolv INTERFACE IMPORTED)
+ if(LIBRESOLV)
+ target_link_libraries(WrapResolv::WrapResolv INTERFACE "${LIBRESOLV}")
+ endif()
+endif()
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(WrapResolv DEFAULT_MSG WrapResolv_FOUND)
diff --git a/cmake/FindWrapSystemHarfbuzz.cmake b/cmake/FindWrapSystemHarfbuzz.cmake
index 07b3405bc0..d989c93e44 100644
--- a/cmake/FindWrapSystemHarfbuzz.cmake
+++ b/cmake/FindWrapSystemHarfbuzz.cmake
@@ -28,6 +28,13 @@ if(harfbuzz_FOUND AND TARGET "${__harfbuzz_target_name}")
if(harfbuzz_VERSION)
set(WrapSystemHarfbuzz_VERSION "${harfbuzz_VERSION}")
endif()
+else()
+ get_cmake_property(__packages_not_found PACKAGES_NOT_FOUND)
+ if(__packages_not_found)
+ list(REMOVE_ITEM __packages_not_found harfbuzz)
+ set_property(GLOBAL PROPERTY PACKAGES_NOT_FOUND "${__packages_not_found}")
+ endif()
+ unset(__packages_not_found)
endif()
if(__harfbuzz_broken_config_file OR NOT __harfbuzz_found)
diff --git a/cmake/FindWrapSystemPCRE2.cmake b/cmake/FindWrapSystemPCRE2.cmake
index 61e0d2fb5b..ce00252c8c 100644
--- a/cmake/FindWrapSystemPCRE2.cmake
+++ b/cmake/FindWrapSystemPCRE2.cmake
@@ -16,6 +16,13 @@ if(PCRE2_FOUND AND TARGET "${__pcre2_target_name}")
if(PCRE2_VERSION)
set(WrapSystemPCRE2_VERSION "${PCRE2_VERSION}")
endif()
+else()
+ get_cmake_property(__packages_not_found PACKAGES_NOT_FOUND)
+ if(__packages_not_found)
+ list(REMOVE_ITEM __packages_not_found PCRE2)
+ set_property(GLOBAL PROPERTY PACKAGES_NOT_FOUND "${__packages_not_found}")
+ endif()
+ unset(__packages_not_found)
endif()
if(NOT __pcre2_found)
diff --git a/cmake/FindWrapSystemZLIB.cmake b/cmake/FindWrapSystemZLIB.cmake
index 5db43db626..f9a8f004ec 100644
--- a/cmake/FindWrapSystemZLIB.cmake
+++ b/cmake/FindWrapSystemZLIB.cmake
@@ -28,5 +28,13 @@ if(ZLIB_FOUND)
endif()
endif()
+if(ZLIB_VERSION)
+ set(WrapSystemZLIB_VERSION "${ZLIB_VERSION}")
+elseif(ZLIB_VERSION_STRING)
+ set(WrapSystemZLIB_VERSION "${ZLIB_VERSION_STRING}")
+endif()
+
include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(WrapSystemZLIB DEFAULT_MSG WrapSystemZLIB_FOUND)
+find_package_handle_standard_args(WrapSystemZLIB
+ REQUIRED_VARS WrapSystemZLIB_FOUND
+ VERSION_VAR WrapSystemZLIB_VERSION)
diff --git a/cmake/FindWrapVulkanHeaders.cmake b/cmake/FindWrapVulkanHeaders.cmake
index 79f5dfc975..92510ae000 100644
--- a/cmake/FindWrapVulkanHeaders.cmake
+++ b/cmake/FindWrapVulkanHeaders.cmake
@@ -48,6 +48,26 @@ if(Vulkan_INCLUDE_DIR)
target_include_directories(WrapVulkanHeaders::WrapVulkanHeaders INTERFACE
${__qt_molten_vk_homebrew_include_path})
endif()
+
+ # Check for homebrew vulkan-headers folder structure
+ # If instead of molten-vk folder, CMAKE_PREFIX_PATH points to Homebrew's
+ # vulkan-headers installation, then we will not be able to find molten-vk
+ # headers. If we assume that user has installed the molten-vk formula as
+ # well, then we might have a chance to pick it up like this.
+ if(Vulkan_INCLUDE_DIR MATCHES "/homebrew/Cellar/")
+ set(__qt_standalone_molten_vk_homebrew_include_path
+ "${Vulkan_INCLUDE_DIR}/../../../../opt/molten-vk/include")
+ else()
+ set(__qt_standalone_molten_vk_homebrew_include_path
+ "${Vulkan_INCLUDE_DIR}/../../molten-vk/include")
+ endif()
+ get_filename_component(
+ __qt_standalone_molten_vk_homebrew_include_path
+ "${__qt_standalone_molten_vk_homebrew_include_path}" ABSOLUTE)
+ if(EXISTS "${__qt_standalone_molten_vk_homebrew_include_path}")
+ target_include_directories(WrapVulkanHeaders::WrapVulkanHeaders INTERFACE
+ ${__qt_standalone_molten_vk_homebrew_include_path})
+ endif()
endif()
endif()
diff --git a/cmake/FindWrapZSTD.cmake b/cmake/FindWrapZSTD.cmake
index fb424236b8..310f6cf960 100644
--- a/cmake/FindWrapZSTD.cmake
+++ b/cmake/FindWrapZSTD.cmake
@@ -25,20 +25,30 @@ find_package(zstd CONFIG QUIET)
include(FindPackageHandleStandardArgs)
-if(TARGET zstd::libzstd_static OR TARGET zstd::libzstd_shared)
+if(TARGET zstd::libzstd_static OR TARGET zstd::libzstd_shared OR TARGET zstd::libzstd)
find_package_handle_standard_args(WrapZSTD
REQUIRED_VARS zstd_VERSION VERSION_VAR zstd_VERSION)
if(TARGET zstd::libzstd_shared)
set(zstdtargetsuffix "_shared")
+ elseif(TARGET zstd::libzstd)
+ set(zstdtargetsuffix "")
else()
set(zstdtargetsuffix "_static")
endif()
+
if(NOT TARGET WrapZSTD::WrapZSTD)
add_library(WrapZSTD::WrapZSTD INTERFACE IMPORTED)
set_target_properties(WrapZSTD::WrapZSTD PROPERTIES
INTERFACE_LINK_LIBRARIES "zstd::libzstd${zstdtargetsuffix}")
endif()
else()
+ get_cmake_property(__packages_not_found PACKAGES_NOT_FOUND)
+ if(__packages_not_found)
+ list(REMOVE_ITEM __packages_not_found zstd)
+ set_property(GLOBAL PROPERTY PACKAGES_NOT_FOUND "${__packages_not_found}")
+ endif()
+ unset(__packages_not_found)
+
find_package(PkgConfig QUIET)
pkg_check_modules(PC_ZSTD QUIET "libzstd")
diff --git a/cmake/Qt3rdPartyLibraryConfig.cmake.in b/cmake/Qt3rdPartyLibraryConfig.cmake.in
index 3f59d212d8..869c67443f 100644
--- a/cmake/Qt3rdPartyLibraryConfig.cmake.in
+++ b/cmake/Qt3rdPartyLibraryConfig.cmake.in
@@ -1,3 +1,6 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
@PACKAGE_INIT@
cmake_minimum_required(VERSION @min_new_policy_version@...@max_new_policy_version@)
@@ -20,7 +23,11 @@ if (NOT QT_NO_CREATE_TARGETS)
include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target@Targets.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target@AdditionalTargetInfo.cmake")
if(NOT QT_NO_CREATE_VERSIONLESS_TARGETS)
- include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target@VersionlessTargets.cmake")
+ if(CMAKE_VERSION VERSION_LESS 3.18 OR QT_USE_OLD_VERSION_LESS_TARGETS)
+ include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target@VersionlessTargets.cmake")
+ else()
+ include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target@VersionlessAliasTargets.cmake")
+ endif()
endif()
endif()
diff --git a/cmake/Qt3rdPartyLibraryHelpers.cmake b/cmake/Qt3rdPartyLibraryHelpers.cmake
index dca360d074..924db182be 100644
--- a/cmake/Qt3rdPartyLibraryHelpers.cmake
+++ b/cmake/Qt3rdPartyLibraryHelpers.cmake
@@ -310,6 +310,7 @@ function(qt_internal_add_3rdparty_library target)
qt_internal_export_modern_cmake_config_targets_file(
TARGETS ${target}
EXPORT_NAME_PREFIX ${INSTALL_CMAKE_NAMESPACE}${target}
+ CONFIG_BUILD_DIR "${config_build_dir}"
CONFIG_INSTALL_DIR "${config_install_dir}"
)
diff --git a/cmake/QtAndroidHelpers.cmake b/cmake/QtAndroidHelpers.cmake
index 857a029991..0743fe41a9 100644
--- a/cmake/QtAndroidHelpers.cmake
+++ b/cmake/QtAndroidHelpers.cmake
@@ -5,87 +5,88 @@
# Android specific functions/macros/properties required for building Qt Modules
#
-define_property(TARGET
- PROPERTY
- QT_ANDROID_MODULE_INSTALL_DIR
- BRIEF_DOCS
- "Recorded install location for a Qt Module."
- FULL_DOCS
- "Recorded install location for a Qt Module. Used by qt_internal_android_dependencies()."
-)
-
-
-define_property(TARGET
- PROPERTY
- QT_ANDROID_JAR_DEPENDENCIES
- BRIEF_DOCS
- "Qt Module Jar dependencies list."
- FULL_DOCS
- "Qt Module Jar dependencies list."
-)
-
-define_property(TARGET
- PROPERTY
- QT_ANDROID_BUNDLED_JAR_DEPENDENCIES
- BRIEF_DOCS
- "Qt Module Jars that should be bundled with it during packing."
- FULL_DOCS
- "Qt Module Jars that should be bundled with it during packing."
-)
-
-define_property(TARGET
- PROPERTY
- QT_ANDROID_LIB_DEPENDENCIES
- BRIEF_DOCS
- "Qt Module C++ libraries that should be bundled with it during packing."
- FULL_DOCS
- "Qt Module C++ libraries that should be bundled with it during packing."
-)
-
-define_property(TARGET
- PROPERTY
- QT_ANDROID_LIB_DEPENDENCY_REPLACEMENTS
- BRIEF_DOCS
- "Qt Module C++ libraries that can replace libraries declared with the QT_ANDROID_LIB_DEPENDENCIES property."
- FULL_DOCS
- "Qt Module C++ libraries that can replace libraries declared with the QT_ANDROID_LIB_DEPENDENCIES property."
-)
-
-define_property(TARGET
- PROPERTY
- QT_ANDROID_BUNDLED_FILES
- BRIEF_DOCS
- "Qt Module files that need to be bundled during packing."
- FULL_DOCS
- "Qt Module files that need to be bundled during packing."
-)
-
-define_property(TARGET
- PROPERTY
- QT_ANDROID_PERMISSIONS
- BRIEF_DOCS
- "Qt Module android permission list."
- FULL_DOCS
- "Qt Module android permission list."
-)
-
-define_property(TARGET
- PROPERTY
- QT_ANDROID_FEATURES
- BRIEF_DOCS
- "Qt Module android feature list."
- FULL_DOCS
- "Qt Module android feature list."
-)
-
-define_property(TARGET
- PROPERTY
- QT_ANDROID_ABIS
- BRIEF_DOCS
- "List of ABIs that the target packages are built with."
- FULL_DOCS
- "List of ABIs that the target packages are built with."
-)
+macro(qt_internal_setup_android_target_properties)
+ define_property(TARGET
+ PROPERTY
+ QT_ANDROID_MODULE_INSTALL_DIR
+ BRIEF_DOCS
+ "Recorded install location for a Qt Module."
+ FULL_DOCS
+ "Recorded install location for a Qt Module. Used by qt_internal_android_dependencies()."
+ )
+
+ define_property(TARGET
+ PROPERTY
+ QT_ANDROID_JAR_DEPENDENCIES
+ BRIEF_DOCS
+ "Qt Module Jar dependencies list."
+ FULL_DOCS
+ "Qt Module Jar dependencies list."
+ )
+
+ define_property(TARGET
+ PROPERTY
+ QT_ANDROID_BUNDLED_JAR_DEPENDENCIES
+ BRIEF_DOCS
+ "Qt Module Jars that should be bundled with it during packing."
+ FULL_DOCS
+ "Qt Module Jars that should be bundled with it during packing."
+ )
+
+ define_property(TARGET
+ PROPERTY
+ QT_ANDROID_LIB_DEPENDENCIES
+ BRIEF_DOCS
+ "Qt Module C++ libraries that should be bundled with it during packing."
+ FULL_DOCS
+ "Qt Module C++ libraries that should be bundled with it during packing."
+ )
+
+ define_property(TARGET
+ PROPERTY
+ QT_ANDROID_LIB_DEPENDENCY_REPLACEMENTS
+ BRIEF_DOCS
+ "Qt Module C++ libraries that can replace libraries declared with the QT_ANDROID_LIB_DEPENDENCIES property."
+ FULL_DOCS
+ "Qt Module C++ libraries that can replace libraries declared with the QT_ANDROID_LIB_DEPENDENCIES property."
+ )
+
+ define_property(TARGET
+ PROPERTY
+ QT_ANDROID_BUNDLED_FILES
+ BRIEF_DOCS
+ "Qt Module files that need to be bundled during packing."
+ FULL_DOCS
+ "Qt Module files that need to be bundled during packing."
+ )
+
+ define_property(TARGET
+ PROPERTY
+ QT_ANDROID_PERMISSIONS
+ BRIEF_DOCS
+ "Qt Module android permission list."
+ FULL_DOCS
+ "Qt Module android permission list."
+ )
+
+ define_property(TARGET
+ PROPERTY
+ QT_ANDROID_FEATURES
+ BRIEF_DOCS
+ "Qt Module android feature list."
+ FULL_DOCS
+ "Qt Module android feature list."
+ )
+
+ define_property(TARGET
+ PROPERTY
+ QT_ANDROID_ABIS
+ BRIEF_DOCS
+ "List of ABIs that the target packages are built with."
+ FULL_DOCS
+ "List of ABIs that the target packages are built with."
+ )
+endmacro()
function(qt_internal_android_dependencies_content target file_content_out)
get_target_property(arg_JAR_DEPENDENCIES ${target} QT_ANDROID_JAR_DEPENDENCIES)
@@ -252,7 +253,8 @@ function(qt_internal_android_dependencies target)
# Module plugins
if(module_plugin_types)
foreach(plugin IN LISTS module_plugin_types)
- string(APPEND file_contents "<bundled file=\"${INSTALL_PLUGINSDIR}/${plugin}\" />\n")
+ string(APPEND file_contents
+ "<bundled file=\"${INSTALL_PLUGINSDIR}/${plugin}\" type=\"plugin_dir\"/>\n")
endforeach()
endif()
diff --git a/cmake/QtAppHelpers.cmake b/cmake/QtAppHelpers.cmake
index 01ca0a5ca2..f0dbd110ab 100644
--- a/cmake/QtAppHelpers.cmake
+++ b/cmake/QtAppHelpers.cmake
@@ -5,7 +5,7 @@
# Such projects had a load(qt_app) command.
function(qt_internal_add_app target)
cmake_parse_arguments(PARSE_ARGV 1 arg
- "NO_INSTALL;INSTALL_VERSIONED_LINK;EXCEPTIONS"
+ "NO_INSTALL;INSTALL_VERSIONED_LINK;EXCEPTIONS;NO_UNITY_BUILD"
"${__default_target_info_args};INSTALL_DIR"
"${__default_private_args};PUBLIC_LIBRARIES"
)
@@ -35,7 +35,11 @@ function(qt_internal_add_app target)
"a future Qt version. Use the LIBRARIES option instead.")
endif()
- qt_internal_library_deprecation_level(deprecation_define)
+ if(arg_NO_UNITY_BUILD)
+ set(arg_NO_UNITY_BUILD "NO_UNITY_BUILD")
+ else()
+ set(arg_NO_UNITY_BUILD "")
+ endif()
qt_internal_add_executable("${target}"
QT_APP
@@ -44,8 +48,11 @@ function(qt_internal_add_app target)
OUTPUT_DIRECTORY "${output_directory}"
${exceptions}
${no_install}
+ ${arg_NO_UNITY_BUILD}
${forward_install_dir}
SOURCES ${arg_SOURCES}
+ NO_PCH_SOURCES ${arg_NO_PCH_SOURCES}
+ NO_UNITY_BUILD_SOURCES ${arg_NO_UNITY_BUILD_SOURCES}
INCLUDE_DIRECTORIES
${arg_INCLUDE_DIRECTORIES}
DEFINES
@@ -60,11 +67,13 @@ function(qt_internal_add_app target)
MOC_OPTIONS ${arg_MOC_OPTIONS}
ENABLE_AUTOGEN_TOOLS ${arg_ENABLE_AUTOGEN_TOOLS}
DISABLE_AUTOGEN_TOOLS ${arg_DISABLE_AUTOGEN_TOOLS}
- TARGET_VERSION "${arg_TARGET_VERSION}"
- TARGET_PRODUCT "${arg_TARGET_PRODUCT}"
- TARGET_DESCRIPTION "${arg_TARGET_DESCRIPTION}"
- TARGET_COMPANY "${arg_TARGET_COMPANY}"
- TARGET_COPYRIGHT "${arg_TARGET_COPYRIGHT}"
+ TARGET_VERSION ${arg_TARGET_VERSION}
+ TARGET_PRODUCT ${arg_TARGET_PRODUCT}
+ TARGET_DESCRIPTION ${arg_TARGET_DESCRIPTION}
+ TARGET_COMPANY ${arg_TARGET_COMPANY}
+ TARGET_COPYRIGHT ${arg_TARGET_COPYRIGHT}
+ # If you are putting anything after these, make sure that
+ # qt_set_target_info_properties knows how to process them
)
qt_internal_add_target_aliases("${target}")
_qt_internal_apply_strict_cpp("${target}")
diff --git a/cmake/QtAutoDetect.cmake b/cmake/QtAutoDetect.cmake
index a994fc5e55..464e8e900b 100644
--- a/cmake/QtAutoDetect.cmake
+++ b/cmake/QtAutoDetect.cmake
@@ -1,499 +1,5 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-#
-# Collection of auto detection routines to improve the user experience when
-# building Qt from source.
-#
-# Make sure to not run detection when building standalone tests, because the detection was already
-# done when initially configuring qtbase.
-
-function(qt_internal_ensure_static_qt_config)
- if(NOT DEFINED BUILD_SHARED_LIBS)
- set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build Qt statically or dynamically" FORCE)
- endif()
-
- if(BUILD_SHARED_LIBS)
- message(FATAL_ERROR
- "Building Qt for ${CMAKE_SYSTEM_NAME} as shared libraries is not supported.")
- endif()
-endfunction()
-
-include("${CMAKE_CURRENT_LIST_DIR}/QtPublicWasmToolchainHelpers.cmake")
-function(qt_auto_detect_wasm)
- if("${QT_QMAKE_TARGET_MKSPEC}" STREQUAL "wasm-emscripten" OR "${QT_QMAKE_TARGET_MKSPEC}" STREQUAL "wasm-emscripten-64")
- if (NOT DEFINED ENV{EMSDK})
- message(FATAL_ERROR
- "Can't find an Emscripten SDK! Make sure the EMSDK environment variable is "
- "available by activating and sourcing the emscripten sdk. Also ensure emcc is in "
- "your path.")
- endif()
- if(NOT DEFINED QT_AUTODETECT_WASM_IS_DONE)
- message(STATUS "Extracting Emscripten SDK info from EMSDK env var: $ENV{EMSDK}")
- __qt_internal_get_emroot_path_suffix_from_emsdk_env(EMROOT_PATH)
-
- __qt_internal_query_emsdk_version("${EMROOT_PATH}" TRUE CMAKE_EMSDK_REGEX_VERSION)
- set(EMCC_VERSION "${CMAKE_EMSDK_REGEX_VERSION}" CACHE STRING INTERNAL FORCE)
-
- if(NOT DEFINED BUILD_SHARED_LIBS)
- qt_internal_ensure_static_qt_config()
- endif()
-
- # Find toolchain file
- if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
- __qt_internal_get_emscripten_cmake_toolchain_file_path_from_emsdk_env(
- "${EMROOT_PATH}" wasm_toolchain_file)
- set(CMAKE_TOOLCHAIN_FILE "${wasm_toolchain_file}" CACHE STRING "" FORCE)
- endif()
-
- if(EXISTS "${CMAKE_TOOLCHAIN_FILE}")
- message(STATUS
- "Emscripten ${EMCC_VERSION} toolchain file detected at ${CMAKE_TOOLCHAIN_FILE}")
- else()
- __qt_internal_show_error_no_emscripten_toolchain_file_found_when_building_qt()
- endif()
-
- __qt_internal_get_emcc_recommended_version(recommended_version)
- set(QT_EMCC_RECOMMENDED_VERSION "${recommended_version}" CACHE STRING INTERNAL FORCE)
-
- set(QT_AUTODETECT_WASM_IS_DONE TRUE CACHE BOOL "")
- else()
- message(STATUS
- "Reusing cached Emscripten ${EMCC_VERSION} toolchain file detected at "
- "${CMAKE_TOOLCHAIN_FILE}")
- endif()
- endif()
-endfunction()
-
-function(qt_auto_detect_cmake_generator)
- if(NOT CMAKE_GENERATOR MATCHES "Ninja" AND NOT QT_SILENCE_CMAKE_GENERATOR_WARNING)
- message(WARNING
- "The officially supported CMake generator for building Qt is Ninja. "
- "You are using: '${CMAKE_GENERATOR}' instead. "
- "Thus, you might encounter issues. Use at your own risk.")
- endif()
-endfunction()
-
-function(qt_auto_detect_android)
- # We assume an Android build if any of the ANDROID_* cache variables are set.
- if(DEFINED ANDROID_SDK_ROOT
- OR DEFINED ANDROID_NDK_ROOT
- OR DEFINED ANDROID_ABI
- OR DEFINED ANDROID_NATIVE_ABI_LEVEL
- OR DEFINED ANDROID_STL)
- set(android_detected TRUE)
- else()
- set(android_detected FALSE)
- endif()
-
- # Auto-detect NDK root
- if(NOT DEFINED ANDROID_NDK_ROOT AND DEFINED ANDROID_SDK_ROOT)
- file(GLOB ndk_versions LIST_DIRECTORIES true RELATIVE "${ANDROID_SDK_ROOT}/ndk"
- "${ANDROID_SDK_ROOT}/ndk/*")
- unset(ndk_root)
- if(NOT ndk_versions STREQUAL "")
- # Use the NDK with the highest version number.
- if(CMAKE_VERSION VERSION_LESS 3.18)
- list(SORT ndk_versions)
- list(REVERSE ndk_versions)
- else()
- list(SORT ndk_versions COMPARE NATURAL ORDER DESCENDING)
- endif()
- list(GET ndk_versions 0 ndk_root)
- string(PREPEND ndk_root "${ANDROID_SDK_ROOT}/ndk/")
- else()
- # Fallback: use the deprecated "ndk-bundle" directory within the SDK root.
- set(ndk_root "${ANDROID_SDK_ROOT}/ndk-bundle")
- if(NOT IS_DIRECTORY "${ndk_root}")
- unset(ndk_root)
- endif()
- endif()
- if(DEFINED ndk_root)
- message(STATUS "Android NDK detected: ${ndk_root}")
- set(ANDROID_NDK_ROOT "${ndk_root}" CACHE STRING "")
- endif()
- endif()
-
- # Auto-detect toolchain file
- if(NOT DEFINED CMAKE_TOOLCHAIN_FILE AND DEFINED ANDROID_NDK_ROOT)
- set(toolchain_file "${ANDROID_NDK_ROOT}/build/cmake/android.toolchain.cmake")
- if(EXISTS "${toolchain_file}")
- message(STATUS "Android toolchain file within NDK detected: ${toolchain_file}")
- set(CMAKE_TOOLCHAIN_FILE "${toolchain_file}" CACHE STRING "")
- else()
- message(FATAL_ERROR "Cannot find the toolchain file '${toolchain_file}'. "
- "Please specify the toolchain file with -DCMAKE_TOOLCHAIN_FILE=<file>.")
- endif()
- endif()
-
- if(NOT DEFINED CMAKE_TOOLCHAIN_FILE AND android_detected)
- message(FATAL_ERROR "An Android build was requested, but no Android toolchain file was "
- "specified nor detected.")
- endif()
-
- if(DEFINED CMAKE_TOOLCHAIN_FILE AND NOT DEFINED QT_AUTODETECT_ANDROID)
- # Peek into the toolchain file and check if it looks like an Android one.
- if(NOT android_detected)
- file(READ ${CMAKE_TOOLCHAIN_FILE} toolchain_file_content OFFSET 0 LIMIT 80)
- string(FIND "${toolchain_file_content}" "The Android Open Source Project"
- find_result REVERSE)
- if(NOT ${find_result} EQUAL -1)
- set(android_detected TRUE)
- endif()
- endif()
-
- if(android_detected)
- message(STATUS "Android build detected, checking configuration defaults...")
- # ANDROID_NATIVE_API_LEVEL is an just an alias to ANDROID_PLATFORM, check for both
- if(NOT DEFINED ANDROID_PLATFORM AND NOT DEFINED ANDROID_NATIVE_API_LEVEL)
- message(STATUS "Neither ANDROID_PLATFORM nor ANDROID_NATIVE_API_LEVEL were specified, using API level 23 as default")
- set(ANDROID_PLATFORM "android-23" CACHE STRING "")
- set(ANDROID_NATIVE_API_LEVEL 23 CACHE STRING "")
- endif()
- if(NOT DEFINED ANDROID_STL)
- set(ANDROID_STL "c++_shared" CACHE STRING "")
- endif()
- endif()
- set(QT_AUTODETECT_ANDROID ${android_detected} CACHE STRING "")
- elseif (QT_AUTODETECT_ANDROID)
- message(STATUS "Android build detected")
- endif()
-endfunction()
-
-function(qt_auto_detect_vcpkg)
- if(DEFINED ENV{VCPKG_ROOT})
- set(vcpkg_toolchain_file "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake")
- get_filename_component(vcpkg_toolchain_file "${vcpkg_toolchain_file}" ABSOLUTE)
-
- if(DEFINED CMAKE_TOOLCHAIN_FILE)
- get_filename_component(supplied_toolchain_file "${CMAKE_TOOLCHAIN_FILE}" ABSOLUTE)
- if(NOT supplied_toolchain_file STREQUAL vcpkg_toolchain_file)
- set(VCPKG_CHAINLOAD_TOOLCHAIN_FILE "${CMAKE_TOOLCHAIN_FILE}" CACHE STRING "")
- endif()
- unset(supplied_toolchain_file)
- endif()
- set(CMAKE_TOOLCHAIN_FILE "${vcpkg_toolchain_file}" CACHE STRING "" FORCE)
- message(STATUS "Using vcpkg from $ENV{VCPKG_ROOT}")
- if(DEFINED ENV{VCPKG_DEFAULT_TRIPLET} AND NOT DEFINED VCPKG_TARGET_TRIPLET)
- set(VCPKG_TARGET_TRIPLET "$ENV{VCPKG_DEFAULT_TRIPLET}" CACHE STRING "")
- message(STATUS "Using vcpkg triplet ${VCPKG_TARGET_TRIPLET}")
- endif()
- unset(vcpkg_toolchain_file)
- message(STATUS "CMAKE_TOOLCHAIN_FILE is: ${CMAKE_TOOLCHAIN_FILE}")
- if(DEFINED VCPKG_CHAINLOAD_TOOLCHAIN_FILE)
- message(STATUS "VCPKG_CHAINLOAD_TOOLCHAIN_FILE is: ${VCPKG_CHAINLOAD_TOOLCHAIN_FILE}")
- endif()
- endif()
-endfunction()
-
-function(qt_auto_detect_ios)
- if(CMAKE_SYSTEM_NAME STREQUAL iOS)
- message(STATUS "Using internal CMake ${CMAKE_SYSTEM_NAME} toolchain file.")
-
- # The QT_UIKIT_SDK check simulates the input.sdk condition for simulator_and_device in
- # configure.json.
- # If the variable is explicitly provided, assume simulator_and_device to be off.
- if(QT_UIKIT_SDK)
- set(simulator_and_device OFF)
- else()
- # Default to simulator_and_device when an explicit sdk is not requested.
- # Requires CMake 3.17.0+.
- set(simulator_and_device ON)
- endif()
-
- message(STATUS "simulator_and_device set to: \"${simulator_and_device}\".")
-
- # Choose relevant architectures.
- # Using a non Xcode generator requires explicit setting of the
- # architectures, otherwise compilation fails with unknown defines.
- if(simulator_and_device)
- set(osx_architectures "arm64;x86_64")
- elseif(QT_UIKIT_SDK STREQUAL "iphoneos")
- set(osx_architectures "arm64")
- elseif(QT_UIKIT_SDK STREQUAL "iphonesimulator")
- set(osx_architectures "x86_64")
- else()
- if(NOT DEFINED QT_UIKIT_SDK)
- message(FATAL_ERROR "Please provide a value for -DQT_UIKIT_SDK."
- " Possible values: iphoneos, iphonesimulator.")
- else()
- message(FATAL_ERROR
- "Unknown SDK argument given to QT_UIKIT_SDK: ${QT_UIKIT_SDK}.")
- endif()
- endif()
-
- # For non simulator_and_device builds, we need to explicitly set the SYSROOT aka the sdk
- # value.
- if(QT_UIKIT_SDK)
- set(CMAKE_OSX_SYSROOT "${QT_UIKIT_SDK}" CACHE STRING "")
- endif()
- set(CMAKE_OSX_ARCHITECTURES "${osx_architectures}" CACHE STRING "")
-
- if(NOT DEFINED BUILD_SHARED_LIBS)
- qt_internal_ensure_static_qt_config()
- endif()
-
- # Disable qt rpaths for iOS, just like mkspecs/common/uikit.conf does, due to those
- # bundles not being able to use paths outside the app bundle. Not sure this is strictly
- # needed though.
- set(QT_DISABLE_RPATH "OFF" CACHE BOOL "Disable automatic Qt rpath handling." FORCE)
- endif()
-endfunction()
-
-function(qt_auto_detect_cmake_config)
- if(CMAKE_CONFIGURATION_TYPES)
- # Allow users to specify this option.
- if(NOT QT_MULTI_CONFIG_FIRST_CONFIG)
- list(GET CMAKE_CONFIGURATION_TYPES 0 first_config_type)
- set(QT_MULTI_CONFIG_FIRST_CONFIG "${first_config_type}")
- set(QT_MULTI_CONFIG_FIRST_CONFIG "${first_config_type}" PARENT_SCOPE)
- endif()
-
- set(CMAKE_TRY_COMPILE_CONFIGURATION "${QT_MULTI_CONFIG_FIRST_CONFIG}" PARENT_SCOPE)
- if(CMAKE_GENERATOR STREQUAL "Ninja Multi-Config")
- # Create build-<config>.ninja files for all specified configurations.
- set(CMAKE_CROSS_CONFIGS "all" CACHE STRING "")
-
- # The configuration that will be considered the main one (for example when
- # configuring standalone tests with a single-config generator like Ninja).
- set(CMAKE_DEFAULT_BUILD_TYPE "${QT_MULTI_CONFIG_FIRST_CONFIG}" CACHE STRING "")
-
- # By default when ninja is called without parameters, it will build all configurations.
- set(CMAKE_DEFAULT_CONFIGS "all" CACHE STRING "")
- endif()
- endif()
-endfunction()
-
-function(qt_auto_detect_cyclic_toolchain)
- if(CMAKE_TOOLCHAIN_FILE AND CMAKE_TOOLCHAIN_FILE MATCHES "/qt.toolchain.cmake$")
- message(FATAL_ERROR
- "Woah there! You can't use the Qt generated qt.toolchain.cmake file to configure "
- "qtbase, because that will create a toolchain file that includes itself!\n"
- "Did you accidentally use qt-cmake to configure qtbase? Make sure to remove the "
- "CMakeCache.txt file, and configure qtbase with 'cmake' instead of 'qt-cmake'.")
- endif()
-endfunction()
-
-function(qt_internal_get_darwin_sdk_version out_var)
- if(APPLE)
- if(CMAKE_SYSTEM_NAME STREQUAL iOS)
- set(sdk_name "iphoneos")
- else()
- # Default to macOS
- set(sdk_name "macosx")
- endif()
- set(xcrun_version_arg "--show-sdk-version")
- execute_process(COMMAND /usr/bin/xcrun --sdk ${sdk_name} ${xcrun_version_arg}
- OUTPUT_VARIABLE sdk_version
- ERROR_VARIABLE xcrun_error)
- if(NOT sdk_version)
- message(FATAL_ERROR
- "Can't determine darwin ${sdk_name} SDK version. Error: ${xcrun_error}")
- endif()
- string(STRIP "${sdk_version}" sdk_version)
- set(${out_var} "${sdk_version}" PARENT_SCOPE)
- endif()
-endfunction()
-
-function(qt_internal_get_xcode_version out_var)
- if(APPLE)
- execute_process(COMMAND /usr/bin/xcrun xcodebuild -version
- OUTPUT_VARIABLE xcode_version
- ERROR_VARIABLE xcrun_error)
- string(REPLACE "\n" " " xcode_version "${xcode_version}")
- string(STRIP "${xcode_version}" xcode_version)
- set(${out_var} "${xcode_version}" PARENT_SCOPE)
- endif()
-endfunction()
-
-function(qt_auto_detect_darwin)
- if(APPLE)
- # If no CMAKE_OSX_DEPLOYMENT_TARGET is provided, default to a value that Qt defines.
- # This replicates the behavior in mkspecs/common/macx.conf where
- # QMAKE_MACOSX_DEPLOYMENT_TARGET is set.
- set(description
- "Minimum OS X version to target for deployment (at runtime); newer APIs weak linked. Set to empty string for default value.")
- if(NOT CMAKE_OSX_DEPLOYMENT_TARGET)
- if(NOT CMAKE_SYSTEM_NAME)
- # macOS
- set(version "11.0")
- elseif(CMAKE_SYSTEM_NAME STREQUAL iOS)
- set(version "14.0")
- endif()
- if(version)
- set(CMAKE_OSX_DEPLOYMENT_TARGET "${version}" CACHE STRING "${description}")
- endif()
- endif()
-
- qt_internal_get_darwin_sdk_version(darwin_sdk_version)
- set(QT_MAC_SDK_VERSION "${darwin_sdk_version}" CACHE STRING "Darwin SDK version.")
-
- qt_internal_get_xcode_version(xcode_version)
- set(QT_MAC_XCODE_VERSION "${xcode_version}" CACHE STRING "Xcode version.")
-
- list(LENGTH CMAKE_OSX_ARCHITECTURES arch_count)
- if(NOT CMAKE_SYSTEM_NAME STREQUAL iOS AND arch_count GREATER 0)
- foreach(arch ${CMAKE_OSX_ARCHITECTURES})
- if(arch STREQUAL "arm64e")
- message(WARNING "Applications built against an arm64e Qt architecture will "
- "likely fail to run on Apple Silicon. Consider targeting "
- "'arm64' instead.")
- endif()
- endforeach()
- endif()
- endif()
-endfunction()
-
-function(qt_auto_detect_macos_universal)
- if(APPLE AND NOT CMAKE_SYSTEM_NAME STREQUAL iOS)
- list(LENGTH CMAKE_OSX_ARCHITECTURES arch_count)
-
- set(is_universal "OFF")
- if(arch_count GREATER 1)
- set(is_universal "ON")
- endif()
-
- set(QT_IS_MACOS_UNIVERSAL "${is_universal}" CACHE INTERNAL "Build universal Qt for macOS")
- endif()
-endfunction()
-
-function(qt_auto_detect_pch)
- set(default_value "ON")
-
- if(CMAKE_OSX_ARCHITECTURES AND CMAKE_VERSION VERSION_LESS 3.18.0 AND NOT QT_FORCE_PCH)
- list(LENGTH CMAKE_OSX_ARCHITECTURES arch_count)
- # CMake versions lower than 3.18 don't support PCH when multiple architectures are set.
- # This is the case for simulator_and_device builds.
- if(arch_count GREATER 1)
- set(default_value "OFF")
- message(WARNING "PCH support disabled due to usage of multiple architectures.")
- endif()
- endif()
-
- option(BUILD_WITH_PCH "Build Qt using precompiled headers?" "${default_value}")
-endfunction()
-
-function(qt_auto_detect_win32_arm)
- if("${QT_QMAKE_TARGET_MKSPEC}" STREQUAL "win32-arm64-msvc")
- set(CMAKE_SYSTEM_NAME "Windows" CACHE STRING "")
- set(CMAKE_SYSTEM_VERSION "10" CACHE STRING "")
- set(CMAKE_SYSTEM_PROCESSOR "arm64" CACHE STRING "")
- endif()
-endfunction()
-
-function(qt_auto_detect_linux_x86)
- if("${QT_QMAKE_TARGET_MKSPEC}" STREQUAL "linux-g++-32" AND NOT QT_NO_AUTO_DETECT_LINUX_X86)
-
- # Add flag to ensure code is compiled for 32bit x86 ABI aka i386 or its flavors.
- set(__qt_toolchain_common_flags_init "-m32")
-
- if(NOT QT_NO_OVERRIDE_LANG_FLAGS_INIT)
- set(CMAKE_C_FLAGS_INIT "${__qt_toolchain_common_flags_init}" PARENT_SCOPE)
- set(CMAKE_CXX_FLAGS_INIT "${__qt_toolchain_common_flags_init}" PARENT_SCOPE)
- set(CMAKE_ASM_FLAGS_INIT "${__qt_toolchain_common_flags_init}" PARENT_SCOPE)
- endif()
-
- # Each distro places arch-specific libraries according to its own file system layout.
- #
- # https://wiki.debian.org/Multiarch/TheCaseForMultiarch
- # https://wiki.ubuntu.com/MultiarchSpec
- # https://wiki.gentoo.org/wiki/Project:AMD64/Multilib_layout
- # https://wiki.archlinux.org/title/official_repositories#multilib
- # https://documentation.suse.com/sles/15-SP3/html/SLES-all/cha-64bit.html
- # https://pilotlogic.com/sitejoom/index.php/wiki?id=398
- # https://unix.stackexchange.com/questions/458069/multilib-and-multiarch
- #
- # CMake can usually find 32 bit libraries just fine on its own.
- # find_library will use prefixes from CMAKE_PREFIX_PATH / CMAKE_SYSTEM_PREFIX_PATH
- # and add arch-specific lib folders like 'lib/i386-linux-gnu' on debian based systems
- # or lib32/lib64 on other distros.
- # The problem is that if no 32 bit library is found, a 64 bit one might get picked up.
- # That's why we need to specify additional ignore paths.
- #
- # The paths used in the code below are Ubuntu specific.
- # You can opt out of using them if you are using a different distro, but then you need to
- # specify appropriate paths yourself in your own CMake toolchain file.
- #
- # Note that to absolutely ensure no x86_64 library is picked up on a multiarch /
- # multilib-enabled system, you might need to specify extra directories in
- # CMAKE_INGORE_PATH for each sub-directory containing a library.
- #
- # For example to exclude /usr/lib/x86_64-linux-gnu/mit-krb5/libgssapi_krb5.so
- # you need to add /usr/lib/x86_64-linux-gnu/mit-krb5 explicitly to CMAKE_IGNORE_PATH.
- # Adding just /usr/lib/x86_64-linux-gnu to either CMAKE_IGNORE_PATH or
- # CMAKE_IGNORE_PREFIX_PATH is not enough.
- #
- # Another consideration are results returned by CMake's pkg_check_modules which uses
- # pkg-config.
- # CMAKE_IGNORE_PATH is not read by pkg_check_modules, but CMAKE_PREFIX_PATH
- # values are passed as additional prefixes to look for .pc files, IN ADDITION to the default
- # prefixes searched by pkg-config of each specific distro.
- # For example on Ubuntu, the default searched paths on an x86_64 host are:
- # /usr/local/lib/x86_64-linux-gnu/pkgconfig
- # /usr/local/lib/pkgconfig
- # /usr/local/share/pkgconfig
- # /usr/lib/x86_64-linux-gnu/pkgconfig
- # /usr/lib/pkgconfig
- # /usr/share/pkgconfig
- # To ensure the x86_64 packages are not picked up, the PKG_CONFIG_LIBDIR environment
- # variable can be overridden with an explicit list of prefixes.
- # Again, the paths below are Ubuntu specific.
- if(NOT QT_NO_OVERRIDE_CMAKE_IGNORE_PATH)
- set(linux_x86_ignore_path "/usr/lib/x86_64-linux-gnu;/lib/x86_64-linux-gnu")
- set(CMAKE_IGNORE_PATH "${linux_x86_ignore_path}" PARENT_SCOPE)
- set_property(GLOBAL PROPERTY
- _qt_internal_linux_x86_ignore_path "${linux_x86_ignore_path}")
- endif()
- if(NOT QT_NO_OVERRIDE_PKG_CONFIG_LIBDIR)
- set(pc_config_libdir "")
- list(APPEND pc_config_libdir "/usr/local/lib/i386-linux-gnu/pkgconfig")
- list(APPEND pc_config_libdir "/usr/local/lib/pkgconfig")
- list(APPEND pc_config_libdir "/usr/local/share/pkgconfig")
- list(APPEND pc_config_libdir "/usr/lib/i386-linux-gnu/pkgconfig")
- list(APPEND pc_config_libdir "/usr/lib/pkgconfig")
- list(APPEND pc_config_libdir "/usr/share/pkgconfig")
- list(JOIN pc_config_libdir ":" pc_config_libdir)
-
- set_property(GLOBAL PROPERTY
- _qt_internal_linux_x86_pc_config_libdir "${pc_config_libdir}")
-
- # Overrides the default prefix list.
- set(ENV{PKG_CONFIG_LIBDIR} "${pc_config_libdir}")
-
- # Overrides the additional prefixes list.
- set(ENV{PKG_CONFIG_DIR} "")
- endif()
- endif()
-endfunction()
-
-function(qt_auto_detect_integrity)
- if(
- # Qt's custom CMake toolchain file sets this value.
- CMAKE_SYSTEM_NAME STREQUAL "Integrity" OR
-
- # Upstream CMake expects this name, but we don't currently use it in Qt.
- CMAKE_SYSTEM_NAME STREQUAL "GHS-MULTI"
- )
- qt_internal_ensure_static_qt_config()
- endif()
-endfunction()
-
-# Let CMake load our custom platform modules.
-# CMake-provided platform modules take precedence.
-if(NOT QT_AVOID_CUSTOM_PLATFORM_MODULES)
- list(PREPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/platforms")
-endif()
-
-qt_auto_detect_cmake_generator()
-qt_auto_detect_cyclic_toolchain()
-qt_auto_detect_cmake_config()
-qt_auto_detect_darwin()
-qt_auto_detect_macos_universal()
-qt_auto_detect_ios()
-qt_auto_detect_android()
-qt_auto_detect_vcpkg()
-qt_auto_detect_pch()
-qt_auto_detect_wasm()
-qt_auto_detect_win32_arm()
-qt_auto_detect_linux_x86()
-qt_auto_detect_integrity()
+include("${CMAKE_CURRENT_LIST_DIR}/QtAutoDetectHelpers.cmake")
+qt_internal_setup_autodetect()
diff --git a/cmake/QtAutoDetectHelpers.cmake b/cmake/QtAutoDetectHelpers.cmake
new file mode 100644
index 0000000000..5621888308
--- /dev/null
+++ b/cmake/QtAutoDetectHelpers.cmake
@@ -0,0 +1,487 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+# Collection of auto detection routines to improve the user experience when
+# building Qt from source.
+#
+# Make sure to not run detection when building standalone tests, because the detection was already
+# done when initially configuring qtbase.
+
+function(qt_internal_ensure_static_qt_config)
+ if(NOT DEFINED BUILD_SHARED_LIBS)
+ set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build Qt statically or dynamically" FORCE)
+ endif()
+
+ if(BUILD_SHARED_LIBS)
+ message(FATAL_ERROR
+ "Building Qt for ${CMAKE_SYSTEM_NAME} as shared libraries is not supported.")
+ endif()
+endfunction()
+
+function(qt_auto_detect_wasm)
+ if("${QT_QMAKE_TARGET_MKSPEC}" STREQUAL "wasm-emscripten"
+ OR "${QT_QMAKE_TARGET_MKSPEC}" STREQUAL "wasm-emscripten-64")
+ if (NOT DEFINED ENV{EMSDK})
+ message(FATAL_ERROR
+ "Can't find an Emscripten SDK! Make sure the EMSDK environment variable is "
+ "available by activating and sourcing the emscripten sdk. Also ensure emcc is in "
+ "your path.")
+ endif()
+ if(NOT DEFINED QT_AUTODETECT_WASM_IS_DONE)
+ message(STATUS "Extracting Emscripten SDK info from EMSDK env var: $ENV{EMSDK}")
+ __qt_internal_get_emroot_path_suffix_from_emsdk_env(EMROOT_PATH)
+
+ __qt_internal_query_emsdk_version("${EMROOT_PATH}" TRUE CMAKE_EMSDK_REGEX_VERSION)
+ set(EMCC_VERSION "${CMAKE_EMSDK_REGEX_VERSION}" CACHE STRING INTERNAL FORCE)
+
+ if(NOT DEFINED BUILD_SHARED_LIBS)
+ qt_internal_ensure_static_qt_config()
+ endif()
+
+ # Find toolchain file
+ if(NOT DEFINED CMAKE_TOOLCHAIN_FILE)
+ __qt_internal_get_emscripten_cmake_toolchain_file_path_from_emsdk_env(
+ "${EMROOT_PATH}" wasm_toolchain_file)
+ set(CMAKE_TOOLCHAIN_FILE "${wasm_toolchain_file}" CACHE STRING "" FORCE)
+ endif()
+
+ if(EXISTS "${CMAKE_TOOLCHAIN_FILE}")
+ message(STATUS
+ "Emscripten ${EMCC_VERSION} toolchain file detected at ${CMAKE_TOOLCHAIN_FILE}")
+ else()
+ __qt_internal_show_error_no_emscripten_toolchain_file_found_when_building_qt()
+ endif()
+
+ __qt_internal_get_emcc_recommended_version(recommended_version)
+ set(QT_EMCC_RECOMMENDED_VERSION "${recommended_version}" CACHE STRING INTERNAL FORCE)
+
+ set(QT_AUTODETECT_WASM_IS_DONE TRUE CACHE BOOL "")
+ else()
+ message(STATUS
+ "Reusing cached Emscripten ${EMCC_VERSION} toolchain file detected at "
+ "${CMAKE_TOOLCHAIN_FILE}")
+ endif()
+ endif()
+endfunction()
+
+function(qt_auto_detect_android)
+ # We assume an Android build if any of the ANDROID_* cache variables are set.
+ if(DEFINED ANDROID_SDK_ROOT
+ OR DEFINED ANDROID_NDK_ROOT
+ OR DEFINED ANDROID_ABI
+ OR DEFINED ANDROID_NATIVE_ABI_LEVEL
+ OR DEFINED ANDROID_STL)
+ set(android_detected TRUE)
+ else()
+ set(android_detected FALSE)
+ endif()
+
+ # Auto-detect NDK root
+ if(NOT DEFINED ANDROID_NDK_ROOT AND DEFINED ANDROID_SDK_ROOT)
+ file(GLOB ndk_versions LIST_DIRECTORIES true RELATIVE "${ANDROID_SDK_ROOT}/ndk"
+ "${ANDROID_SDK_ROOT}/ndk/*")
+ unset(ndk_root)
+ if(NOT ndk_versions STREQUAL "")
+ # Use the NDK with the highest version number.
+ if(CMAKE_VERSION VERSION_LESS 3.18)
+ list(SORT ndk_versions)
+ list(REVERSE ndk_versions)
+ else()
+ list(SORT ndk_versions COMPARE NATURAL ORDER DESCENDING)
+ endif()
+ list(GET ndk_versions 0 ndk_root)
+ string(PREPEND ndk_root "${ANDROID_SDK_ROOT}/ndk/")
+ else()
+ # Fallback: use the deprecated "ndk-bundle" directory within the SDK root.
+ set(ndk_root "${ANDROID_SDK_ROOT}/ndk-bundle")
+ if(NOT IS_DIRECTORY "${ndk_root}")
+ unset(ndk_root)
+ endif()
+ endif()
+ if(DEFINED ndk_root)
+ message(STATUS "Android NDK detected: ${ndk_root}")
+ set(ANDROID_NDK_ROOT "${ndk_root}" CACHE STRING "")
+ endif()
+ endif()
+
+ # Auto-detect toolchain file
+ if(NOT DEFINED CMAKE_TOOLCHAIN_FILE AND DEFINED ANDROID_NDK_ROOT)
+ set(toolchain_file "${ANDROID_NDK_ROOT}/build/cmake/android.toolchain.cmake")
+ if(EXISTS "${toolchain_file}")
+ message(STATUS "Android toolchain file within NDK detected: ${toolchain_file}")
+ set(CMAKE_TOOLCHAIN_FILE "${toolchain_file}" CACHE STRING "")
+ else()
+ message(FATAL_ERROR "Cannot find the toolchain file '${toolchain_file}'. "
+ "Please specify the toolchain file with -DCMAKE_TOOLCHAIN_FILE=<file>.")
+ endif()
+ endif()
+
+ if(NOT DEFINED CMAKE_TOOLCHAIN_FILE AND android_detected)
+ message(FATAL_ERROR "An Android build was requested, but no Android toolchain file was "
+ "specified nor detected.")
+ endif()
+
+ if(DEFINED CMAKE_TOOLCHAIN_FILE AND NOT DEFINED QT_AUTODETECT_ANDROID)
+ # Peek into the toolchain file and check if it looks like an Android one.
+ if(NOT android_detected)
+ file(READ ${CMAKE_TOOLCHAIN_FILE} toolchain_file_content OFFSET 0 LIMIT 80)
+ string(FIND "${toolchain_file_content}" "The Android Open Source Project"
+ find_result REVERSE)
+ if(NOT ${find_result} EQUAL -1)
+ set(android_detected TRUE)
+ endif()
+ endif()
+
+ if(android_detected)
+ message(STATUS "Android build detected, checking configuration defaults...")
+ # ANDROID_NATIVE_API_LEVEL is an just an alias to ANDROID_PLATFORM, check for both
+ if(NOT DEFINED ANDROID_PLATFORM AND NOT DEFINED ANDROID_NATIVE_API_LEVEL)
+ message(STATUS "Neither ANDROID_PLATFORM nor ANDROID_NATIVE_API_LEVEL"
+ " were specified, using API level 28 as default")
+ set(ANDROID_PLATFORM "android-28" CACHE STRING "")
+ set(ANDROID_NATIVE_API_LEVEL 28 CACHE STRING "")
+ endif()
+ if(NOT DEFINED ANDROID_STL)
+ set(ANDROID_STL "c++_shared" CACHE STRING "")
+ endif()
+ endif()
+ set(QT_AUTODETECT_ANDROID ${android_detected} CACHE STRING "")
+ elseif (QT_AUTODETECT_ANDROID)
+ message(STATUS "Android build detected")
+ endif()
+endfunction()
+
+function(qt_auto_detect_vcpkg)
+ if(QT_USE_VCPKG AND DEFINED ENV{VCPKG_ROOT})
+ set(vcpkg_toolchain_file "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake")
+ get_filename_component(vcpkg_toolchain_file "${vcpkg_toolchain_file}" ABSOLUTE)
+
+ if(DEFINED CMAKE_TOOLCHAIN_FILE)
+ get_filename_component(supplied_toolchain_file "${CMAKE_TOOLCHAIN_FILE}" ABSOLUTE)
+ if(NOT supplied_toolchain_file STREQUAL vcpkg_toolchain_file)
+ set(VCPKG_CHAINLOAD_TOOLCHAIN_FILE "${supplied_toolchain_file}" CACHE STRING "")
+ endif()
+ unset(supplied_toolchain_file)
+ endif()
+ set(CMAKE_TOOLCHAIN_FILE "${vcpkg_toolchain_file}" CACHE STRING "" FORCE)
+ message(STATUS "Using vcpkg from $ENV{VCPKG_ROOT}")
+ if(DEFINED ENV{QT_VCPKG_TARGET_TRIPLET} AND NOT DEFINED VCPKG_TARGET_TRIPLET)
+ set(VCPKG_TARGET_TRIPLET "$ENV{QT_VCPKG_TARGET_TRIPLET}" CACHE STRING "")
+ message(STATUS "Using vcpkg triplet ${VCPKG_TARGET_TRIPLET}")
+ endif()
+ unset(vcpkg_toolchain_file)
+ message(STATUS "CMAKE_TOOLCHAIN_FILE is: ${CMAKE_TOOLCHAIN_FILE}")
+ if(DEFINED VCPKG_CHAINLOAD_TOOLCHAIN_FILE)
+ message(STATUS "VCPKG_CHAINLOAD_TOOLCHAIN_FILE is: ${VCPKG_CHAINLOAD_TOOLCHAIN_FILE}")
+ endif()
+ endif()
+endfunction()
+
+function(qt_auto_detect_apple)
+ if(NOT APPLE)
+ return()
+ endif()
+
+ if("${QT_QMAKE_TARGET_MKSPEC}" STREQUAL "macx-ios-clang")
+ set(CMAKE_SYSTEM_NAME "iOS" CACHE STRING "")
+ elseif("${QT_QMAKE_TARGET_MKSPEC}" STREQUAL "macx-visionos-clang")
+ set(CMAKE_SYSTEM_NAME "visionOS" CACHE STRING "")
+ endif()
+
+ if(CMAKE_SYSTEM_NAME STREQUAL iOS)
+ message(STATUS "Using internal CMake ${CMAKE_SYSTEM_NAME} toolchain file.")
+
+ # Pass on QT_UIKIT_SDK for compatibility
+ if(QT_UIKIT_SDK AND NOT QT_APPLE_SDK)
+ set(QT_APPLE_SDK "${QT_UIKIT_SDK}" CACHE STRING "")
+ endif()
+
+ # The QT_APPLE_SDK check simulates the input.sdk condition for simulator_and_device in
+ # configure.json.
+ # If the variable is explicitly provided, assume simulator_and_device to be off.
+ if(QT_APPLE_SDK)
+ set(simulator_and_device OFF)
+ else()
+ # Default to simulator_and_device when an explicit sdk is not requested.
+ # Requires CMake 3.17.0+.
+ set(simulator_and_device ON)
+ endif()
+
+ message(STATUS "simulator_and_device set to: \"${simulator_and_device}\".")
+
+ # Choose relevant architectures.
+ # Using a non Xcode generator requires explicit setting of the
+ # architectures, otherwise compilation fails with unknown defines.
+ if(simulator_and_device)
+ set(osx_architectures "arm64;x86_64")
+ elseif(QT_APPLE_SDK STREQUAL "iphoneos")
+ set(osx_architectures "arm64")
+ elseif(QT_APPLE_SDK STREQUAL "iphonesimulator")
+ set(osx_architectures "x86_64")
+ else()
+ if(NOT DEFINED QT_APPLE_SDK)
+ message(FATAL_ERROR "Please provide a value for -DQT_APPLE_SDK."
+ " Possible values: iphoneos, iphonesimulator.")
+ else()
+ message(FATAL_ERROR
+ "Unknown SDK argument given to QT_APPLE_SDK: ${QT_APPLE_SDK}.")
+ endif()
+ endif()
+
+ set(CMAKE_OSX_ARCHITECTURES "${osx_architectures}" CACHE STRING "")
+ endif()
+
+ if(QT_APPLE_SDK)
+ set(CMAKE_OSX_SYSROOT "${QT_APPLE_SDK}" CACHE STRING "")
+ endif()
+
+ if(CMAKE_SYSTEM_NAME STREQUAL iOS OR CMAKE_SYSTEM_NAME STREQUAL visionOS)
+ if(NOT DEFINED BUILD_SHARED_LIBS)
+ qt_internal_ensure_static_qt_config()
+ endif()
+
+ # Disable qt rpaths for iOS, just like mkspecs/common/uikit.conf does, due to those
+ # bundles not being able to use paths outside the app bundle. Not sure this is strictly
+ # needed though.
+ set(QT_DISABLE_RPATH "OFF" CACHE BOOL "Disable automatic Qt rpath handling." FORCE)
+ endif()
+
+ # If no CMAKE_OSX_DEPLOYMENT_TARGET is provided, default to a value that Qt defines.
+ # This replicates the behavior in mkspecs/common/macx.conf where
+ # QMAKE_MACOSX_DEPLOYMENT_TARGET is set.
+ set(description
+ "Minimum OS X version to target for deployment (at runtime); newer APIs weak linked."
+ " Set to empty string for default value.")
+ if(NOT CMAKE_OSX_DEPLOYMENT_TARGET)
+ if(NOT CMAKE_SYSTEM_NAME)
+ # macOS
+ set(version "12.0")
+ elseif(CMAKE_SYSTEM_NAME STREQUAL iOS)
+ set(version "16.0")
+ endif()
+ if(version)
+ set(CMAKE_OSX_DEPLOYMENT_TARGET "${version}" CACHE STRING "${description}")
+ endif()
+ endif()
+
+ _qt_internal_get_apple_sdk_version(apple_sdk_version)
+ set(QT_MAC_SDK_VERSION "${apple_sdk_version}" CACHE STRING "Darwin SDK version.")
+
+ _qt_internal_get_xcode_version_raw(xcode_version_raw)
+ set(QT_MAC_XCODE_VERSION "${xcode_version_raw}" CACHE STRING "Xcode version.")
+
+ if(NOT CMAKE_SYSTEM_NAME)
+ # macOS
+ list(LENGTH CMAKE_OSX_ARCHITECTURES arch_count)
+ if(arch_count GREATER 0)
+ foreach(arch ${CMAKE_OSX_ARCHITECTURES})
+ if(arch STREQUAL "arm64e")
+ message(WARNING "Applications built against an arm64e Qt architecture will "
+ "likely fail to run on Apple Silicon. Consider targeting "
+ "'arm64' instead.")
+ endif()
+ endforeach()
+ endif()
+
+ set(is_universal "OFF")
+ if(arch_count GREATER 1)
+ set(is_universal "ON")
+ endif()
+ set(QT_IS_MACOS_UNIVERSAL "${is_universal}" CACHE INTERNAL "Build universal Qt for macOS")
+ endif()
+endfunction()
+
+function(qt_auto_detect_cmake_config)
+ # If CMAKE_CONFIGURATION_TYPES are not set for the multi-config generator use Release and
+ # Debug configurations by default, instead of those are proposed by the CMake internal logic.
+ get_property(is_multi GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+ if(is_multi)
+ if(NOT CMAKE_CONFIGURATION_TYPES)
+ set(CMAKE_CONFIGURATION_TYPES Release Debug)
+ set(CMAKE_CONFIGURATION_TYPES "${CMAKE_CONFIGURATION_TYPES}" PARENT_SCOPE)
+ endif()
+
+ # Allow users to specify this option.
+ if(NOT QT_MULTI_CONFIG_FIRST_CONFIG)
+ list(GET CMAKE_CONFIGURATION_TYPES 0 first_config_type)
+ set(QT_MULTI_CONFIG_FIRST_CONFIG "${first_config_type}")
+ set(QT_MULTI_CONFIG_FIRST_CONFIG "${first_config_type}" PARENT_SCOPE)
+ endif()
+
+ set(CMAKE_TRY_COMPILE_CONFIGURATION "${QT_MULTI_CONFIG_FIRST_CONFIG}" PARENT_SCOPE)
+ if(CMAKE_GENERATOR STREQUAL "Ninja Multi-Config")
+ # Create build-<config>.ninja files for all specified configurations.
+ set(CMAKE_CROSS_CONFIGS "all" CACHE STRING "")
+
+ # The configuration that will be considered the main one (for example when
+ # configuring standalone tests with a single-config generator like Ninja).
+ set(CMAKE_DEFAULT_BUILD_TYPE "${QT_MULTI_CONFIG_FIRST_CONFIG}" CACHE STRING "")
+
+ # By default when ninja is called without parameters, it will build all configurations.
+ set(CMAKE_DEFAULT_CONFIGS "all" CACHE STRING "")
+ endif()
+ endif()
+endfunction()
+
+function(qt_auto_detect_cyclic_toolchain)
+ if(CMAKE_TOOLCHAIN_FILE AND CMAKE_TOOLCHAIN_FILE MATCHES "/qt\\.toolchain\\.cmake$")
+ message(FATAL_ERROR
+ "Woah there! You can't use the Qt generated qt.toolchain.cmake file to configure "
+ "qtbase, because that will create a toolchain file that includes itself!\n"
+ "Did you accidentally use qt-cmake to configure qtbase? Make sure to remove the "
+ "CMakeCache.txt file, and configure qtbase with 'cmake' instead of 'qt-cmake'.")
+ endif()
+endfunction()
+
+function(qt_auto_detect_pch)
+ set(default_value "ON")
+
+ if(CMAKE_OSX_ARCHITECTURES AND CMAKE_VERSION VERSION_LESS 3.18.0 AND NOT QT_FORCE_PCH)
+ list(LENGTH CMAKE_OSX_ARCHITECTURES arch_count)
+ # CMake versions lower than 3.18 don't support PCH when multiple architectures are set.
+ # This is the case for simulator_and_device builds.
+ if(arch_count GREATER 1)
+ set(default_value "OFF")
+ message(WARNING "PCH support disabled due to usage of multiple architectures.")
+ endif()
+ endif()
+
+ option(BUILD_WITH_PCH "Build Qt using precompiled headers?" "${default_value}")
+endfunction()
+
+function(qt_auto_detect_win32_arm)
+ if("${QT_QMAKE_TARGET_MKSPEC}" STREQUAL "win32-arm64-msvc")
+ set(CMAKE_SYSTEM_NAME "Windows" CACHE STRING "")
+ set(CMAKE_SYSTEM_VERSION "10" CACHE STRING "")
+ set(CMAKE_SYSTEM_PROCESSOR "arm64" CACHE STRING "")
+ endif()
+endfunction()
+
+function(qt_auto_detect_linux_x86)
+ if("${QT_QMAKE_TARGET_MKSPEC}" STREQUAL "linux-g++-32" AND NOT QT_NO_AUTO_DETECT_LINUX_X86)
+
+ # Add flag to ensure code is compiled for 32bit x86 ABI aka i386 or its flavors.
+ set(__qt_toolchain_common_flags_init "-m32")
+
+ if(NOT QT_NO_OVERRIDE_LANG_FLAGS_INIT)
+ set(CMAKE_C_FLAGS_INIT "${__qt_toolchain_common_flags_init}" PARENT_SCOPE)
+ set(CMAKE_CXX_FLAGS_INIT "${__qt_toolchain_common_flags_init}" PARENT_SCOPE)
+ set(CMAKE_ASM_FLAGS_INIT "${__qt_toolchain_common_flags_init}" PARENT_SCOPE)
+ endif()
+
+ # Each distro places arch-specific libraries according to its own file system layout.
+ #
+ # https://wiki.debian.org/Multiarch/TheCaseForMultiarch
+ # https://wiki.ubuntu.com/MultiarchSpec
+ # https://wiki.gentoo.org/wiki/Project:AMD64/Multilib_layout
+ # https://wiki.archlinux.org/title/official_repositories#multilib
+ # https://documentation.suse.com/sles/15-SP3/html/SLES-all/cha-64bit.html
+ # https://pilotlogic.com/sitejoom/index.php/wiki?id=398
+ # https://unix.stackexchange.com/questions/458069/multilib-and-multiarch
+ #
+ # CMake can usually find 32 bit libraries just fine on its own.
+ # find_library will use prefixes from CMAKE_PREFIX_PATH / CMAKE_SYSTEM_PREFIX_PATH
+ # and add arch-specific lib folders like 'lib/i386-linux-gnu' on debian based systems
+ # or lib32/lib64 on other distros.
+ # The problem is that if no 32 bit library is found, a 64 bit one might get picked up.
+ # That's why we need to specify additional ignore paths.
+ #
+ # The paths used in the code below are Ubuntu specific.
+ # You can opt out of using them if you are using a different distro, but then you need to
+ # specify appropriate paths yourself in your own CMake toolchain file.
+ #
+ # Note that to absolutely ensure no x86_64 library is picked up on a multiarch /
+ # multilib-enabled system, you might need to specify extra directories in
+ # CMAKE_INGORE_PATH for each sub-directory containing a library.
+ #
+ # For example to exclude /usr/lib/x86_64-linux-gnu/mit-krb5/libgssapi_krb5.so
+ # you need to add /usr/lib/x86_64-linux-gnu/mit-krb5 explicitly to CMAKE_IGNORE_PATH.
+ # Adding just /usr/lib/x86_64-linux-gnu to either CMAKE_IGNORE_PATH or
+ # CMAKE_IGNORE_PREFIX_PATH is not enough.
+ #
+ # Another consideration are results returned by CMake's pkg_check_modules which uses
+ # pkg-config.
+ # CMAKE_IGNORE_PATH is not read by pkg_check_modules, but CMAKE_PREFIX_PATH
+ # values are passed as additional prefixes to look for .pc files, IN ADDITION to the default
+ # prefixes searched by pkg-config of each specific distro.
+ # For example on Ubuntu, the default searched paths on an x86_64 host are:
+ # /usr/local/lib/x86_64-linux-gnu/pkgconfig
+ # /usr/local/lib/pkgconfig
+ # /usr/local/share/pkgconfig
+ # /usr/lib/x86_64-linux-gnu/pkgconfig
+ # /usr/lib/pkgconfig
+ # /usr/share/pkgconfig
+ # To ensure the x86_64 packages are not picked up, the PKG_CONFIG_LIBDIR environment
+ # variable can be overridden with an explicit list of prefixes.
+ # Again, the paths below are Ubuntu specific.
+ if(NOT QT_NO_OVERRIDE_CMAKE_IGNORE_PATH)
+ set(linux_x86_ignore_path "/usr/lib/x86_64-linux-gnu;/lib/x86_64-linux-gnu")
+ set(CMAKE_IGNORE_PATH "${linux_x86_ignore_path}" PARENT_SCOPE)
+ set_property(GLOBAL PROPERTY
+ _qt_internal_linux_x86_ignore_path "${linux_x86_ignore_path}")
+ endif()
+ if(NOT QT_NO_OVERRIDE_PKG_CONFIG_LIBDIR)
+ set(pc_config_libdir "")
+ list(APPEND pc_config_libdir "/usr/local/lib/i386-linux-gnu/pkgconfig")
+ list(APPEND pc_config_libdir "/usr/local/lib/pkgconfig")
+ list(APPEND pc_config_libdir "/usr/local/share/pkgconfig")
+ list(APPEND pc_config_libdir "/usr/lib/i386-linux-gnu/pkgconfig")
+ list(APPEND pc_config_libdir "/usr/lib/pkgconfig")
+ list(APPEND pc_config_libdir "/usr/share/pkgconfig")
+ list(JOIN pc_config_libdir ":" pc_config_libdir)
+
+ set_property(GLOBAL PROPERTY
+ _qt_internal_linux_x86_pc_config_libdir "${pc_config_libdir}")
+
+ # Overrides the default prefix list.
+ set(ENV{PKG_CONFIG_LIBDIR} "${pc_config_libdir}")
+
+ # Overrides the additional prefixes list.
+ set(ENV{PKG_CONFIG_DIR} "")
+ endif()
+ endif()
+endfunction()
+
+function(qt_auto_detect_integrity)
+ if(
+ # Qt's custom CMake toolchain file sets this value.
+ CMAKE_SYSTEM_NAME STREQUAL "Integrity" OR
+
+ # Upstream CMake expects this name, but we don't currently use it in Qt.
+ CMAKE_SYSTEM_NAME STREQUAL "GHS-MULTI"
+ )
+ qt_internal_ensure_static_qt_config()
+ endif()
+endfunction()
+
+# Save the build type before project() might set one.
+# This allows us to determine if the user has set an explicit build type that we should use.
+function(qt_auto_detect_cmake_build_type)
+ set(__qt_auto_detect_cmake_build_type_before_project_call "${CMAKE_BUILD_TYPE}" PARENT_SCOPE)
+endfunction()
+
+macro(qt_internal_setup_autodetect)
+ # This needs to be here because QtAutoDetect loads before any other modules
+ option(QT_USE_VCPKG "Enable the use of vcpkg" OFF)
+
+ include("${CMAKE_CURRENT_LIST_DIR}/QtPublicAppleHelpers.cmake")
+ include("${CMAKE_CURRENT_LIST_DIR}/QtPublicWasmToolchainHelpers.cmake")
+
+ # Let CMake load our custom platform modules.
+ # CMake-provided platform modules take precedence.
+ if(NOT QT_AVOID_CUSTOM_PLATFORM_MODULES)
+ list(PREPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/platforms")
+ endif()
+
+ qt_auto_detect_cyclic_toolchain()
+ qt_auto_detect_cmake_config()
+ qt_auto_detect_apple()
+ qt_auto_detect_android()
+ qt_auto_detect_pch()
+ qt_auto_detect_wasm()
+ qt_auto_detect_win32_arm()
+ qt_auto_detect_linux_x86()
+ qt_auto_detect_integrity()
+ qt_auto_detect_cmake_build_type()
+ qt_auto_detect_vcpkg()
+endmacro()
diff --git a/cmake/QtAutogenHelpers.cmake b/cmake/QtAutogenHelpers.cmake
index eb0ca29ff3..029a709e90 100644
--- a/cmake/QtAutogenHelpers.cmake
+++ b/cmake/QtAutogenHelpers.cmake
@@ -39,8 +39,7 @@ function(qt_enable_autogen_tool target tool enable)
# that the moc scanner has to look for. Inform the CMake moc scanner about it.
if(tool STREQUAL "moc" AND enable)
set_target_properties("${target}" PROPERTIES
- AUTOMOC_MACRO_NAMES "Q_OBJECT;Q_GADGET;Q_GADGET_EXPORT;Q_NAMESPACE;Q_NAMESPACE_EXPORT;Q_ENUM_NS")
-
+ AUTOMOC_MACRO_NAMES "${CMAKE_AUTOMOC_MACRO_NAMES};Q_ENUM_NS;Q_GADGET_EXPORT")
if (TARGET Qt::Platform)
get_target_property(_abi_tag Qt::Platform qt_libcpp_abi_tag)
if (_abi_tag)
@@ -79,14 +78,23 @@ endfunction()
# Complete manual moc invocation with full control.
# Use AUTOMOC whenever possible.
-# INCLUDE_DIRECTORIES specifies a list of include directories used by 'moc'.
-# INCLUDE_DIRECTORY_TARGETS specifies a list of targets to extract the INTERFACE_INCLUDE_DIRECTORIES
-# property and use it as the 'moc' include directories.
+# Multi-value Arguments:
+# INCLUDE_DIRECTORIES
+# Specifies a list of include directories used by 'moc'.
+# INCLUDE_DIRECTORY_TARGETS
+# Specifies a list of targets to extract the INTERFACE_INCLUDE_DIRECTORIES
+# property and use it as the 'moc' include directories.(Deprecated use TARGETS instead)
+# DEFINITIONS
+# List of the definitions that should be added to the moc command line arguments.
+# Supports the syntax both with and without the prepending '-D'.
+# TARGETS
+# The list of targets that will be used to collect the INTERFACE_INCLUDE_DIRECTORIES,
+# INCLUDE_DIRECTORIES, and COMPILE_DEFINITIONS properties.
function(qt_manual_moc result)
cmake_parse_arguments(arg
""
"OUTPUT_MOC_JSON_FILES"
- "FLAGS;INCLUDE_DIRECTORIES;INCLUDE_DIRECTORY_TARGETS"
+ "FLAGS;INCLUDE_DIRECTORIES;INCLUDE_DIRECTORY_TARGETS;DEFINITIONS;TARGETS"
${ARGN})
set(moc_files)
set(metatypes_json_list)
@@ -103,7 +111,7 @@ function(qt_manual_moc result)
"-I\n${dir}")
endforeach()
- foreach(dep IN ITEMS ${arg_INCLUDE_DIRECTORY_TARGETS})
+ foreach(dep IN LISTS arg_INCLUDE_DIRECTORY_TARGETS arg_TARGETS)
set(include_expr "$<TARGET_PROPERTY:${dep},INTERFACE_INCLUDE_DIRECTORIES>")
list(APPEND moc_parameters
"$<$<BOOL:${include_expr}>:-I\n$<JOIN:${include_expr},\n-I\n>>")
@@ -129,6 +137,30 @@ function(qt_manual_moc result)
endif()
endforeach()
+ foreach(dep IN LISTS arg_TARGETS)
+ set(include_property_expr
+ "$<TARGET_GENEX_EVAL:${dep},$<TARGET_PROPERTY:${dep},INCLUDE_DIRECTORIES>>")
+ list(APPEND moc_parameters
+ "$<$<BOOL:${include_property_expr}>:-I\n$<JOIN:${include_property_expr},\n-I\n>>")
+
+ set(defines_property_expr
+ "$<TARGET_GENEX_EVAL:${dep},$<TARGET_PROPERTY:${dep},COMPILE_DEFINITIONS>>")
+ set(defines_with_d "$<FILTER:${defines_property_expr},INCLUDE,^-D>")
+ set(defines_without_d "$<FILTER:${defines_property_expr},EXCLUDE,^-D>")
+ list(APPEND moc_parameters
+ "$<$<BOOL:${defines_with_d}>:$<JOIN:${defines_with_d},\n>>")
+ list(APPEND moc_parameters
+ "$<$<BOOL:${defines_without_d}>:-D\n$<JOIN:${defines_without_d},\n-D\n>>")
+ endforeach()
+
+ foreach(def IN LISTS arg_DEFINITIONS)
+ if(NOT def MATCHES "^-D")
+ list(APPEND moc_parameters "-D\n${def}")
+ else()
+ list(APPEND moc_parameters "${def}")
+ endif()
+ endforeach()
+
set(metatypes_byproducts)
if (arg_OUTPUT_MOC_JSON_FILES)
set(moc_json_file "${outfile}.json")
diff --git a/cmake/QtBaseConfigureTests.cmake b/cmake/QtBaseConfigureTests.cmake
index b79294261c..66a0b3b6dd 100644
--- a/cmake/QtBaseConfigureTests.cmake
+++ b/cmake/QtBaseConfigureTests.cmake
@@ -62,8 +62,13 @@ function(qt_run_config_test_architecture)
endif()
message(STATUS "Extracting architecture info from ${_arch_file}.")
+ cmake_policy(PUSH)
+ if(POLICY CMP0159)
+ cmake_policy(SET CMP0159 NEW)
+ endif()
file(STRINGS "${_arch_file}" _arch_lines LENGTH_MINIMUM 16 LENGTH_MAXIMUM 1024 ENCODING UTF-8
REGEX "==Qt=magic=Qt==")
+ cmake_policy(POP)
foreach (_line ${_arch_lines})
string(LENGTH "${_line}" lineLength)
@@ -73,7 +78,7 @@ function(qt_run_config_test_architecture)
string(SUBSTRING "${_line}" ${_pos} -1 _architecture)
endif()
string(FIND "${_line}" "==Qt=magic=Qt== Sub-architecture:" _pos)
- if (_pos GREATER -1 AND ${lineLength} GREATER 33)
+ if (_pos GREATER -1 AND NOT _line MATCHES "Sub-architecture:$")
math(EXPR _pos "${_pos}+34")
string(SUBSTRING "${_line}" ${_pos} -1 _sub_architecture)
string(REPLACE " " ";" _sub_architecture "${_sub_architecture}")
@@ -115,43 +120,38 @@ endfunction()
function(qt_run_linker_version_script_support)
- file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/version_flag.map" "VERS_1 { global: sym; };
-VERS_2 { global: sym; }
-VERS_1;
-")
- if(DEFINED CMAKE_REQUIRED_FLAGS)
- set(CMAKE_REQUIRED_FLAGS_SAVE ${CMAKE_REQUIRED_FLAGS})
- else()
- set(CMAKE_REQUIRED_FLAGS "")
- endif()
- set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} "-Wl,--version-script=\"${CMAKE_CURRENT_BINARY_DIR}/version_flag.map\"")
-
- # Pass the linker that the main project uses to the version script compile test.
- qt_internal_get_active_linker_flags(linker_flags)
- if(linker_flags)
- set(CMAKE_REQUIRED_LINK_OPTIONS ${linker_flags})
- endif()
-
- check_cxx_source_compiles("int main(void){return 0;}" HAVE_LD_VERSION_SCRIPT)
- if(DEFINED CMAKE_REQUIRED_FLAGS_SAVE)
- set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS_SAVE})
- endif()
- file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/conftest.map")
-
# For some reason the linker command line written by the XCode generator, which is
# subsequently executed by xcodebuild, ignores the linker flag, and thus the test
# seemingly succeeds. Explicitly disable the version script test on darwin platforms.
- if(APPLE)
- set(HAVE_LD_VERSION_SCRIPT OFF)
- endif()
# Also makes no sense with MSVC-style command-line
- if(MSVC)
+ if(NOT APPLE AND NOT MSVC)
+ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/version_flag.map" [=[
+ VERS_1 { global: sym1; };
+ VERS_2 { global: sym2; } VERS_1;
+ ]=])
+ set(CMAKE_REQUIRED_LINK_OPTIONS "")
+ list(APPEND CMAKE_REQUIRED_LINK_OPTIONS
+ "-Wl,--version-script=${CMAKE_CURRENT_BINARY_DIR}/version_flag.map")
+ # Pass the linker that the main project uses to the version script compile test.
+ qt_internal_get_active_linker_flags(linker_flags)
+ if(linker_flags)
+ list(APPEND CMAKE_REQUIRED_LINK_OPTIONS ${linker_flags})
+ endif()
+ check_cxx_source_compiles([=[
+ int sym1;
+ int sym2;
+ int main(void) { return 0; }
+ ]=] HAVE_LD_VERSION_SCRIPT)
+ file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/version_flag.map")
+ else()
set(HAVE_LD_VERSION_SCRIPT OFF)
endif()
- set(TEST_ld_version_script "${HAVE_LD_VERSION_SCRIPT}" CACHE INTERNAL "linker version script support")
+ set(TEST_ld_version_script "${HAVE_LD_VERSION_SCRIPT}"
+ CACHE INTERNAL "linker version script support")
list(APPEND QT_BASE_CONFIGURE_TESTS_VARS_TO_EXPORT TEST_ld_version_script)
- set(QT_BASE_CONFIGURE_TESTS_VARS_TO_EXPORT ${QT_BASE_CONFIGURE_TESTS_VARS_TO_EXPORT} CACHE INTERNAL "Test variables that should be exported")
+ set(QT_BASE_CONFIGURE_TESTS_VARS_TO_EXPORT ${QT_BASE_CONFIGURE_TESTS_VARS_TO_EXPORT}
+ CACHE INTERNAL "Test variables that should be exported")
endfunction()
function(qt_internal_ensure_latest_win_nt_api)
@@ -200,7 +200,7 @@ function(qt_internal_print_cmake_darwin_info)
set(default_osx_arch " (defaults to ${CMAKE_SYSTEM_PROCESSOR})")
endif()
message(STATUS "CMAKE_OSX_ARCHITECTURES: \"${CMAKE_OSX_ARCHITECTURES}\"${default_osx_arch}")
- message(STATUS "CMAKE_OSX_SYSROOT: \"${CMAKE_OSX_SYSROOT}\"")
+ message(STATUS "CMAKE_OSX_SYSROOT: \"$CACHE{CMAKE_OSX_SYSROOT}\" / \"${CMAKE_OSX_SYSROOT}\"")
message(STATUS "CMAKE_OSX_DEPLOYMENT_TARGET: \"${CMAKE_OSX_DEPLOYMENT_TARGET}\"")
message(STATUS "QT_MAC_SDK_VERSION: \"${QT_MAC_SDK_VERSION}\"")
message(STATUS "QT_MAC_XCODE_VERSION: \"${QT_MAC_XCODE_VERSION}\"")
@@ -208,8 +208,8 @@ function(qt_internal_print_cmake_darwin_info)
if(DEFINED CACHE{QT_IS_MACOS_UNIVERSAL})
message(STATUS "QT_IS_MACOS_UNIVERSAL: \"${QT_IS_MACOS_UNIVERSAL}\"")
endif()
- if(QT_UIKIT_SDK)
- message(STATUS "QT_UIKIT_SDK: \"${QT_UIKIT_SDK}\"")
+ if(QT_APPLE_SDK)
+ message(STATUS "QT_APPLE_SDK: \"${QT_APPLE_SDK}\"")
endif()
qt_internal_get_first_osx_arch(osx_first_arch)
if(osx_first_arch)
diff --git a/cmake/QtBaseGlobalTargets.cmake b/cmake/QtBaseGlobalTargets.cmake
index 6a885fc4ce..1e604559ed 100644
--- a/cmake/QtBaseGlobalTargets.cmake
+++ b/cmake/QtBaseGlobalTargets.cmake
@@ -63,12 +63,8 @@ qt_copy_or_install(
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/QtBuildInternals/${__build_internals_standalone_test_template_dir}/CMakeLists.txt")
-include(QtToolchainHelpers)
qt_internal_create_toolchain_file()
-include(QtWrapperScriptHelpers)
-qt_internal_create_wrapper_scripts()
-
## Library to hold global features:
## These features are stored and accessed via Qt::GlobalConfig, but the
## files always lived in Qt::Core, so we keep it that way
@@ -101,7 +97,8 @@ if(MACOS AND QT_IS_MACOS_UNIVERSAL
QT_FEATURE_x86intrin)
endif()
-if(MACOS AND QT_IS_MACOS_UNIVERSAL AND __qt_osx_first_arch STREQUAL "x86_64")
+if(MACOS AND QT_IS_MACOS_UNIVERSAL AND
+ (__qt_osx_first_arch STREQUAL "x86_64" OR __qt_osx_first_arch STREQUAL "x86_64h"))
set(QT_FORCE_FEATURE_neon ON CACHE INTERNAL "Force enable neon due to platform requirements.")
set(__QtFeature_custom_enabled_cache_variables
TEST_subarch_neon
@@ -121,6 +118,9 @@ qt_generate_global_module_pri_file()
qt_generate_global_device_pri_file()
qt_generate_qmake_and_qtpaths_wrapper_for_target()
+# Depends on the global features being evaluated.
+qt_internal_create_wrapper_scripts()
+
add_library(Qt::GlobalConfig ALIAS GlobalConfig)
add_library(GlobalConfigPrivate INTERFACE)
@@ -132,8 +132,8 @@ target_include_directories(GlobalConfigPrivate INTERFACE
$<INSTALL_INTERFACE:${INSTALL_INCLUDEDIR}/QtCore/${PROJECT_VERSION}/QtCore>
)
add_library(Qt::GlobalConfigPrivate ALIAS GlobalConfigPrivate)
+add_library(${QT_CMAKE_EXPORT_NAMESPACE}::GlobalConfigPrivate ALIAS GlobalConfigPrivate)
-include(QtPlatformTargetHelpers)
qt_internal_setup_public_platform_target()
# defines PlatformCommonInternal PlatformModuleInternal PlatformPluginInternal PlatformToolInternal
@@ -159,9 +159,10 @@ qt_install(EXPORT ${__export_name}
DESTINATION "${__GlobalConfig_install_dir}")
qt_internal_export_modern_cmake_config_targets_file(TARGETS ${__export_targets}
- EXPORT_NAME_PREFIX ${INSTALL_CMAKE_NAMESPACE}
- CONFIG_INSTALL_DIR
- ${__GlobalConfig_install_dir})
+ EXPORT_NAME_PREFIX ${INSTALL_CMAKE_NAMESPACE}
+ CONFIG_BUILD_DIR "${__GlobalConfig_build_dir}"
+ CONFIG_INSTALL_DIR "${__GlobalConfig_install_dir}"
+)
# Save minimum required CMake version to use Qt.
qt_internal_get_supported_min_cmake_version_for_using_qt(supported_min_version_for_using_qt)
@@ -171,6 +172,11 @@ qt_internal_get_computed_min_cmake_version_for_using_qt(computed_min_version_for
qt_internal_get_min_new_policy_cmake_version(min_new_policy_version)
qt_internal_get_max_new_policy_cmake_version(max_new_policy_version)
+# Get the list of public helper files that should be automatically included in Qt6Config.cmake.
+# Used in QtConfig.cmake.in template and further down for installation purposes.
+qt_internal_get_qt_build_public_helpers(__qt_cmake_public_helpers)
+list(JOIN __qt_cmake_public_helpers "\n " QT_PUBLIC_FILES_TO_INCLUDE)
+
# Generate and install Qt6 config file. Make sure it happens after the global feature evaluation so
# they can be accessed in the Config file if needed.
configure_package_config_file(
@@ -179,6 +185,8 @@ configure_package_config_file(
INSTALL_DESTINATION "${__GlobalConfig_install_dir}"
)
+_qt_internal_export_apple_sdk_and_xcode_version_requirements(QT_CONFIG_EXTRAS_CODE)
+
configure_file(
"${PROJECT_SOURCE_DIR}/cmake/QtConfigExtras.cmake.in"
"${__GlobalConfig_build_dir}/${INSTALL_CMAKE_NAMESPACE}ConfigExtras.cmake"
@@ -195,101 +203,48 @@ qt_internal_write_qt_package_version_file(
"${__GlobalConfig_build_dir}/${INSTALL_CMAKE_NAMESPACE}ConfigVersion.cmake"
)
+# Compute the reverse relative path from QtConfig.cmake to the install prefix
+# this is used in QtInstallPaths to make the install paths relocatable
+if(QT_WILL_INSTALL)
+ get_filename_component(_clean_prefix
+ "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}/${QT_CONFIG_INSTALL_DIR}" ABSOLUTE)
+else()
+ get_filename_component(_clean_prefix "${QT_CONFIG_BUILD_DIR}" ABSOLUTE)
+endif()
+file(RELATIVE_PATH QT_INVERSE_CONFIG_INSTALL_DIR
+ "${_clean_prefix}" "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}")
+configure_file(
+ "${PROJECT_SOURCE_DIR}/cmake/QtInstallPaths.cmake.in"
+ "${__GlobalConfig_build_dir}/QtInstallPaths.cmake"
+ @ONLY
+)
+
qt_install(FILES
"${__GlobalConfig_build_dir}/${INSTALL_CMAKE_NAMESPACE}Config.cmake"
"${__GlobalConfig_build_dir}/${INSTALL_CMAKE_NAMESPACE}ConfigExtras.cmake"
"${__GlobalConfig_build_dir}/${INSTALL_CMAKE_NAMESPACE}ConfigVersion.cmake"
"${__GlobalConfig_build_dir}/${INSTALL_CMAKE_NAMESPACE}ConfigVersionImpl.cmake"
+ "${__GlobalConfig_build_dir}/QtInstallPaths.cmake"
DESTINATION "${__GlobalConfig_install_dir}"
COMPONENT Devel
)
+qt_internal_get_qt_build_private_helpers(__qt_cmake_private_helpers)
+list(TRANSFORM __qt_cmake_private_helpers PREPEND "cmake/")
+list(TRANSFORM __qt_cmake_private_helpers APPEND ".cmake")
+
+qt_internal_get_qt_build_private_files_to_install(__qt_private_files_to_install)
+list(TRANSFORM __qt_private_files_to_install PREPEND "cmake/")
+
# Install internal CMake files.
# The functions defined inside can not be used in public projects.
# They can only be used while building Qt itself.
+set(__private_files
+ ${__qt_cmake_private_helpers}
+ ${__qt_private_files_to_install}
+)
qt_copy_or_install(FILES
- cmake/ModuleDescription.json.in
- cmake/PkgConfigLibrary.pc.in
- cmake/Qt3rdPartyLibraryConfig.cmake.in
- cmake/Qt3rdPartyLibraryHelpers.cmake
- cmake/QtAndroidHelpers.cmake
- cmake/QtAppHelpers.cmake
- cmake/QtAutogenHelpers.cmake
- cmake/QtBuild.cmake
- cmake/QtBuildInformation.cmake
- cmake/QtCMakeHelpers.cmake
- cmake/QtCMakeVersionHelpers.cmake
- cmake/QtCMakePackageVersionFile.cmake.in
- cmake/QtCompilerFlags.cmake
- cmake/QtCompilerOptimization.cmake
- cmake/QtConfigDependencies.cmake.in
- cmake/QtConfigureTimeExecutableCMakeLists.txt.in
- cmake/QtDeferredDependenciesHelpers.cmake
- cmake/QtDbusHelpers.cmake
- cmake/QtDocsHelpers.cmake
- cmake/QtExecutableHelpers.cmake
- cmake/QtFileConfigure.txt.in
- cmake/QtFindPackageHelpers.cmake
- cmake/QtFindWrapConfigExtra.cmake.in
- cmake/QtFindWrapHelper.cmake
- cmake/QtFinishPkgConfigFile.cmake
- cmake/QtFinishPrlFile.cmake
- cmake/QtFlagHandlingHelpers.cmake
- cmake/QtFrameworkHelpers.cmake
- cmake/QtGenerateExtPri.cmake
- cmake/QtGenerateLibHelpers.cmake
- cmake/QtGenerateLibPri.cmake
- cmake/QtGenerateVersionScript.cmake
- cmake/QtGlobalStateHelpers.cmake
- cmake/QtHeadersClean.cmake
- cmake/QtInstallHelpers.cmake
- cmake/QtJavaHelpers.cmake
- cmake/QtLalrHelpers.cmake
- cmake/QtModuleConfig.cmake.in
- cmake/QtModuleDependencies.cmake.in
- cmake/QtModuleHeadersCheck.cmake
- cmake/QtModuleHelpers.cmake
- cmake/QtModuleToolsConfig.cmake.in
- cmake/QtModuleToolsDependencies.cmake.in
- cmake/QtModuleToolsVersionlessTargets.cmake.in
- cmake/QtNoLinkTargetHelpers.cmake
- cmake/QtPkgConfigHelpers.cmake
- cmake/QtPlatformAndroid.cmake
- cmake/QtPlatformSupport.cmake
- cmake/QtPluginConfig.cmake.in
- cmake/QtPluginDependencies.cmake.in
- cmake/QtPluginHelpers.cmake
- cmake/QtPlugins.cmake.in
- cmake/QtPostProcess.cmake
- cmake/QtPostProcessHelpers.cmake
- cmake/QtPrecompiledHeadersHelpers.cmake
- cmake/QtUnityBuildHelpers.cmake
- cmake/QtPriHelpers.cmake
- cmake/QtPrlHelpers.cmake
- cmake/QtPlatformTargetHelpers.cmake
- cmake/QtProcessConfigureArgs.cmake
- cmake/QtQmakeHelpers.cmake
- cmake/QtResourceHelpers.cmake
- cmake/QtRpathHelpers.cmake
- cmake/QtSanitizerHelpers.cmake
- cmake/QtScopeFinalizerHelpers.cmake
- cmake/QtSeparateDebugInfo.Info.plist.in
- cmake/QtSeparateDebugInfo.cmake
- cmake/QtSetup.cmake
- cmake/QtSimdHelpers.cmake
- cmake/QtSingleRepoTargetSetBuildHelpers.cmake
- cmake/QtStandaloneTestsConfig.cmake.in
- cmake/QtSyncQtHelpers.cmake
- cmake/QtTargetHelpers.cmake
- cmake/QtTestHelpers.cmake
- cmake/QtToolchainHelpers.cmake
- cmake/QtToolHelpers.cmake
- cmake/QtWasmHelpers.cmake
- cmake/QtWrapperScriptHelpers.cmake
- cmake/QtWriteArgsFile.cmake
- cmake/modulecppexports.h.in
- cmake/modulecppexports_p.h.in
- cmake/qbatchedtestrunner.in.cpp
+ ${__private_files}
DESTINATION "${__GlobalConfig_install_dir}"
)
@@ -323,39 +278,29 @@ if(QT_WILL_INSTALL)
endforeach()
endif()
+# Wrap previously queried helpers file.
+list(TRANSFORM __qt_cmake_public_helpers PREPEND "cmake/")
+list(TRANSFORM __qt_cmake_public_helpers APPEND ".cmake")
+
+qt_internal_get_qt_build_public_files_to_install(__qt_public_files_to_install)
+list(TRANSFORM __qt_public_files_to_install PREPEND "cmake/")
+
# Install public CMake files.
# The functions defined inside can be used in both public projects and while building Qt.
# Usually we put such functions into Qt6CoreMacros.cmake, but that's getting bloated.
# These files will be included by Qt6Config.cmake.
-set(__public_cmake_helpers
- cmake/QtCopyFileIfDifferent.cmake
- cmake/QtFeature.cmake
- cmake/QtFeatureCommon.cmake
- cmake/QtInitProject.cmake
- cmake/QtPublicAppleHelpers.cmake
- cmake/QtPublicCMakeHelpers.cmake
- cmake/QtPublicCMakeVersionHelpers.cmake
- cmake/QtPublicFinalizerHelpers.cmake
- cmake/QtPublicPluginHelpers.cmake
- cmake/QtPublicTargetHelpers.cmake
- cmake/QtPublicTestHelpers.cmake
- cmake/QtPublicToolHelpers.cmake
- cmake/QtPublicWalkLibsHelpers.cmake
- cmake/QtPublicFindPackageHelpers.cmake
- cmake/QtPublicDependencyHelpers.cmake
-
- # Public CMake files that are installed next Qt6Config.cmake, but are NOT included by it.
- # Instead they are included by the generated CMake toolchain file.
- cmake/QtPublicWasmToolchainHelpers.cmake
+set(__public_files
+ ${__qt_cmake_public_helpers}
+ ${__qt_public_files_to_install}
)
-qt_copy_or_install(FILES ${__public_cmake_helpers} DESTINATION "${__GlobalConfig_install_dir}")
+qt_copy_or_install(FILES ${__public_files} DESTINATION "${__GlobalConfig_install_dir}")
# In prefix builds we also need to copy the files into the build config directory, so that the
# build-dir Qt6Config.cmake finds the files when building examples in-tree.
if(QT_WILL_INSTALL)
- foreach(_public_cmake_helper ${__public_cmake_helpers})
- file(COPY "${_public_cmake_helper}" DESTINATION "${__GlobalConfig_build_dir}")
+ foreach(_public_file ${__public_files})
+ file(COPY "${_public_file}" DESTINATION "${__GlobalConfig_build_dir}")
endforeach()
endif()
@@ -374,6 +319,11 @@ qt_copy_or_install(DIRECTORY cmake/
FILES_MATCHING PATTERN "Find*.cmake"
PATTERN "tests" EXCLUDE
PATTERN "3rdparty" EXCLUDE
+ PATTERN "macos" EXCLUDE
+ PATTERN "ios" EXCLUDE
+ PATTERN "visionos" EXCLUDE
+ PATTERN "platforms" EXCLUDE
+ PATTERN "QtBuildInternals" EXCLUDE
)
# In prefix builds we also need to copy the files into the build config directory, so that the
@@ -384,20 +334,50 @@ if(QT_WILL_INSTALL)
FILES_MATCHING PATTERN "Find*.cmake"
PATTERN "tests" EXCLUDE
PATTERN "3rdparty" EXCLUDE
+ PATTERN "macos" EXCLUDE
+ PATTERN "ios" EXCLUDE
+ PATTERN "visionos" EXCLUDE
+ PATTERN "platforms" EXCLUDE
+ PATTERN "QtBuildInternals" EXCLUDE
)
endif()
-if(MACOS)
- qt_copy_or_install(FILES
- cmake/macos/MacOSXBundleInfo.plist.in
- DESTINATION "${__GlobalConfig_install_dir}/macos"
+if(APPLE)
+ if(MACOS)
+ set(platform_shortname "macos")
+ elseif(IOS)
+ set(platform_shortname "ios")
+ elseif(VISIONOS)
+ set(platform_shortname "visionos")
+ endif()
+
+ # Info.plist
+ qt_copy_or_install(FILES "cmake/${platform_shortname}/Info.plist.app.in"
+ DESTINATION "${__GlobalConfig_install_dir}/${platform_shortname}"
+ )
+ # For examples built as part of prefix build before install
+ file(COPY "cmake/${platform_shortname}/Info.plist.app.in"
+ DESTINATION "${__GlobalConfig_build_dir}/${platform_shortname}"
)
-elseif(IOS)
- qt_copy_or_install(FILES
- cmake/ios/Info.plist.app.in
- cmake/ios/LaunchScreen.storyboard
- DESTINATION "${__GlobalConfig_install_dir}/ios"
+
+ # Privacy manifest
+ qt_copy_or_install(FILES "cmake/${platform_shortname}/PrivacyInfo.xcprivacy"
+ DESTINATION "${__GlobalConfig_install_dir}/${platform_shortname}"
)
+ # For examples built as part of prefix build before install
+ file(COPY "cmake/${platform_shortname}/PrivacyInfo.xcprivacy"
+ DESTINATION "${__GlobalConfig_build_dir}/${platform_shortname}"
+ )
+
+ if(IOS)
+ qt_copy_or_install(FILES "cmake/ios/LaunchScreen.storyboard"
+ DESTINATION "${__GlobalConfig_install_dir}/ios"
+ )
+ # For examples built as part of prefix build before install
+ file(COPY "cmake/ios/LaunchScreen.storyboard"
+ DESTINATION "${__GlobalConfig_build_dir}/ios"
+ )
+ endif()
elseif(WASM)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/util/wasm/wasmtestrunner/qt-wasmtestrunner.py"
"${QT_BUILD_DIR}/${INSTALL_LIBEXECDIR}/qt-wasmtestrunner.py" @ONLY)
diff --git a/cmake/QtBaseHelpers.cmake b/cmake/QtBaseHelpers.cmake
new file mode 100644
index 0000000000..a16f6987b4
--- /dev/null
+++ b/cmake/QtBaseHelpers.cmake
@@ -0,0 +1,222 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+#
+# Note that this file is not installed.
+
+# Bail out if any part of the build directory's path is symlinked.
+function(qt_internal_check_if_path_has_symlinks path)
+ get_filename_component(dir "${path}" ABSOLUTE)
+ set(is_symlink FALSE)
+ if(CMAKE_HOST_WIN32)
+ # CMake marks Windows mount points as symbolic links, so use simplified REALPATH check
+ # on Windows platforms instead of IS_SYMLINK.
+ get_filename_component(dir_realpath "${dir}" REALPATH)
+ if(NOT dir STREQUAL dir_realpath)
+ set(is_symlink TRUE)
+ endif()
+ else()
+ while(TRUE)
+ if(IS_SYMLINK "${dir}")
+ set(is_symlink TRUE)
+ break()
+ endif()
+
+ set(prev_dir "${dir}")
+ get_filename_component(dir "${dir}" DIRECTORY)
+ if("${dir}" STREQUAL "${prev_dir}")
+ return()
+ endif()
+ endwhile()
+ endif()
+ if(is_symlink)
+ set(possible_solutions_for_resolving_symlink [[
+ - Map directories using a transparent mechanism such as mount --bind
+ - Pass the real path of the build directory to CMake, e.g. using
+ cd $(realpath <path>) before invoking cmake <source_dir>.
+ ]])
+ if(QT_ALLOW_SYMLINK_IN_PATHS)
+ # In some cases, e.g., Homebrew, it is beneficial to skip this check.
+ # Before this, Homebrew had to patch this out to be able to get their build.
+ message(WARNING
+ "The path \"${path}\" contains symlinks. "
+ "This is not recommended, and it may lead to unexpected issues. If you do "
+ "not have a good reason for enabling 'QT_ALLOW_SYMLINK_IN_PATHS', disable "
+ "it, and follow one of the following solutions: \n"
+ "${possible_solutions_for_resolving_symlink} ")
+ else()
+ message(FATAL_ERROR
+ "The path \"${path}\" contains symlinks. "
+ "This is not supported. Possible solutions: \n"
+ "${possible_solutions_for_resolving_symlink} ")
+ endif()
+ endif()
+endfunction()
+
+# There are three necessary copies of this macro in
+# qtbase/cmake/QtBaseHelpers.cmake
+# qtbase/cmake/QtBaseTopLevelHelpers.cmake
+# qtbase/cmake/QtBuildRepoHelpers.cmake
+macro(qt_internal_qtbase_setup_standalone_parts)
+ # A generic marker for any kind of standalone builds, either tests or examples.
+ if(NOT DEFINED QT_INTERNAL_BUILD_STANDALONE_PARTS
+ AND (QT_BUILD_STANDALONE_TESTS OR QT_BUILD_STANDALONE_EXAMPLES))
+ set(QT_INTERNAL_BUILD_STANDALONE_PARTS TRUE CACHE INTERNAL
+ "Whether standalone tests or examples are being built")
+ endif()
+endmacro()
+
+macro(qt_internal_qtbase_run_autodetect)
+ qt_internal_qtbase_setup_standalone_parts()
+
+ # Run auto detection routines, but not when doing standalone tests or standalone examples.
+ # In that case, the detection
+ # results are taken from either QtBuildInternals or the qt.toolchain.cmake file. Also, inhibit
+ # auto-detection in a top-level build, because the top-level project file already includes it.
+ if(NOT QT_INTERNAL_BUILD_STANDALONE_PARTS AND NOT QT_SUPERBUILD)
+ include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/QtAutoDetect.cmake)
+ endif()
+endmacro()
+
+macro(qt_internal_qtbase_pre_project_setup)
+ if(NOT QT_INTERNAL_BUILD_STANDALONE_PARTS)
+ # Should this Qt be static or dynamically linked?
+ option(BUILD_SHARED_LIBS "Build Qt statically or dynamically" ON)
+ set(QT_BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS})
+
+ # This variable is also set in Qt6CoreConfigExtras.cmake, but it's not loaded when building
+ # qtbase. Set it here so qt_add_plugin can compute the proper plugin flavor.
+ set(QT6_IS_SHARED_LIBS_BUILD ${BUILD_SHARED_LIBS})
+
+ # BUILD_SHARED_LIBS influences the minimum required CMake version. The value is set either
+ # by:
+ # a cache variable provided on the configure command line
+ # or set by QtAutoDetect.cmake depending on the platform
+ # or specified via a toolchain file that is loaded by the project() call
+ # or set by the option() call above
+ include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/QtCMakeVersionHelpers.cmake")
+ include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/QtPublicCMakeVersionHelpers.cmake")
+ qt_internal_check_and_warn_about_unsuitable_cmake_version()
+
+ ## Add some paths to check for cmake modules:
+ list(PREPEND CMAKE_MODULE_PATH
+ "${CMAKE_CURRENT_SOURCE_DIR}/cmake"
+ "${CMAKE_CURRENT_SOURCE_DIR}/cmake/3rdparty/extra-cmake-modules/find-modules"
+ "${CMAKE_CURRENT_SOURCE_DIR}/cmake/3rdparty/kwin"
+ )
+
+ if(MACOS)
+ # Add module directory to pick up custom Info.plist template
+ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/macos")
+ elseif(IOS)
+ # Add module directory to pick up custom Info.plist template
+ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/ios")
+ endif()
+
+ ## Find the build internals package.
+ set(QT_BUILD_INTERNALS_SKIP_CMAKE_MODULE_PATH_ADDITION TRUE)
+ list(PREPEND CMAKE_PREFIX_PATH
+ "${CMAKE_CURRENT_SOURCE_DIR}/cmake"
+ )
+ find_package(QtBuildInternals CMAKE_FIND_ROOT_PATH_BOTH)
+ unset(QT_BUILD_INTERNALS_SKIP_CMAKE_MODULE_PATH_ADDITION)
+ else()
+ # When building standalone parts, an istalled BuildInternals package already exists.
+ find_package(Qt6 REQUIRED COMPONENTS BuildInternals CMAKE_FIND_ROOT_PATH_BOTH)
+ endif()
+endmacro()
+
+macro(qt_internal_qtbase_install_mkspecs)
+ # As long as we use the mkspecs (for qplatformdefs.h), we need to always
+ # install it, especially when cross-compiling.
+ set(mkspecs_install_dir "${INSTALL_MKSPECSDIR}")
+ qt_path_join(mkspecs_install_dir ${QT_INSTALL_DIR} ${mkspecs_install_dir})
+
+ file(GLOB mkspecs_subdirs
+ LIST_DIRECTORIES TRUE
+ "${PROJECT_SOURCE_DIR}/mkspecs/*")
+ foreach(entry IN LISTS mkspecs_subdirs)
+ if (IS_DIRECTORY ${entry})
+ qt_copy_or_install(DIRECTORY "${entry}"
+ DESTINATION ${mkspecs_install_dir}
+ USE_SOURCE_PERMISSIONS)
+ else()
+ qt_copy_or_install(FILES "${entry}"
+ DESTINATION ${mkspecs_install_dir})
+ endif()
+ endforeach()
+endmacro()
+
+macro(qt_internal_qtbase_build_repo)
+ qt_internal_qtbase_pre_project_setup()
+
+ qt_internal_project_setup()
+
+ qt_build_repo_begin()
+
+ if(NOT QT_INTERNAL_BUILD_STANDALONE_PARTS)
+ ## Should this Qt be built with Werror?
+ option(WARNINGS_ARE_ERRORS "Build Qt with warnings as errors" ${FEATURE_developer_build})
+
+ ## Should this Qt create versioned hard link for some tools?
+ option(QT_CREATE_VERSIONED_HARD_LINK "Enable the use of versioned hard link" ON)
+
+ ## QtBase specific configure tests:
+ include(QtBaseConfigureTests)
+
+ ## Build System tests:
+ include(QtBaseCMakeTesting)
+
+ ## Targets for global features, etc.:
+ include(QtBaseGlobalTargets)
+
+ ## Set language standards after QtBaseGlobalTargets, because that's when the relevant
+ ## feature variables are available.
+ qt_set_language_standards()
+
+ #include CoreMacros() for qt6_generate_meta_types()
+ set(QT_DEFAULT_MAJOR_VERSION 6)
+ include(src/corelib/Qt6CoreMacros.cmake)
+
+ # Needed when building qtbase for android.
+ if(ANDROID)
+ include(src/corelib/Qt6AndroidMacros.cmake)
+ _qt_internal_create_global_android_targets()
+ endif()
+
+ if(WASM)
+ # Needed when building for WebAssembly.
+ include(cmake/QtWasmHelpers.cmake)
+ include(src/corelib/Qt6WasmMacros.cmake)
+ qt_internal_setup_wasm_target_properties(Platform)
+ endif()
+
+ # Set up optimization flags like in qmake.
+ # This function must be called after the global QT_FEATURE_xxx variables have been set up,
+ # aka after QtBaseGlobalTargets is processed.
+ # It also has to be called /before/ adding add_subdirectory(src), so that per-directory
+ # modifications can still be applied if necessary (like in done in Core and Gui).
+ qt_internal_set_up_config_optimizations_like_in_qmake()
+
+ ## Setup documentation
+ add_subdirectory(doc)
+
+ ## Visit all the directories:
+ add_subdirectory(src)
+ endif()
+
+ if(NOT QT_INTERNAL_BUILD_STANDALONE_PARTS)
+ if(QT_WILL_BUILD_TOOLS AND QT_FEATURE_settings)
+ add_subdirectory(qmake)
+ endif()
+
+ qt_internal_qtbase_install_mkspecs()
+ endif()
+
+ qt_build_repo_post_process()
+
+ qt_build_repo_impl_tests()
+
+ qt_build_repo_end()
+
+ qt_build_repo_impl_examples()
+endmacro()
diff --git a/cmake/QtBaseTopLevelHelpers.cmake b/cmake/QtBaseTopLevelHelpers.cmake
new file mode 100644
index 0000000000..07893b6cec
--- /dev/null
+++ b/cmake/QtBaseTopLevelHelpers.cmake
@@ -0,0 +1,96 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+# There are three necessary copies of this macro in
+# qtbase/cmake/QtBaseHelpers.cmake
+# qtbase/cmake/QtBaseTopLevelHelpers.cmake
+# qtbase/cmake/QtBuildRepoHelpers.cmake
+macro(qt_internal_top_level_setup_standalone_parts)
+ # A generic marker for any kind of standalone builds, either tests or examples.
+ if(NOT DEFINED QT_INTERNAL_BUILD_STANDALONE_PARTS
+ AND (QT_BUILD_STANDALONE_TESTS OR QT_BUILD_STANDALONE_EXAMPLES))
+ set(QT_INTERNAL_BUILD_STANDALONE_PARTS TRUE CACHE INTERNAL
+ "Whether standalone tests or examples are being built")
+ endif()
+endmacro()
+
+# Depends on __qt6_qtbase_src_path being set in the top-level dir.
+macro(qt_internal_top_level_setup_autodetect)
+ qt_internal_top_level_setup_standalone_parts()
+
+ # Run platform auto-detection /before/ the first project() call and thus
+ # before the toolchain file is loaded.
+ # Don't run auto-detection when doing standalone tests. In that case, the detection
+ # results are taken from either QtBuildInternals or the qt.toolchain.cmake file.
+
+ if(NOT QT_INTERNAL_BUILD_STANDALONE_PARTS)
+ set(__qt6_auto_detect_path "${__qt6_qtbase_src_path}/cmake/QtAutoDetect.cmake")
+ if(NOT EXISTS "${__qt6_auto_detect_path}")
+ message(FATAL_ERROR "Required file does not exist: '${__qt6_auto_detect_path}'")
+ endif()
+ include("${__qt6_auto_detect_path}")
+ endif()
+endmacro()
+
+macro(qt_internal_top_level_setup_after_project)
+ qt_internal_top_level_setup_testing()
+endmacro()
+
+macro(qt_internal_top_level_setup_testing)
+ # Required so we can call ctest from the root build directory
+ enable_testing()
+endmacro()
+
+# Depends on __qt6_qtbase_src_path being set in the top-level dir.
+macro(qt_internal_top_level_setup_cmake_module_path)
+ if (NOT QT_INTERNAL_BUILD_STANDALONE_PARTS)
+ set(__qt6_cmake_module_path "${__qt6_qtbase_src_path}/cmake")
+ if(NOT EXISTS "${__qt6_cmake_module_path}")
+ message(FATAL_ERROR "Required directory does not exist: '${__qt6_cmake_module_path}'")
+ endif()
+
+ list(APPEND CMAKE_MODULE_PATH "${__qt6_cmake_module_path}")
+
+ list(APPEND CMAKE_MODULE_PATH
+ "${__qt6_cmake_module_path}/3rdparty/extra-cmake-modules/find-modules")
+ list(APPEND CMAKE_MODULE_PATH "${__qt6_cmake_module_path}/3rdparty/kwin")
+ endif()
+endmacro()
+
+macro(qt_internal_top_level_before_build_submodules)
+ qt_internal_top_level_setup_no_create_targets()
+endmacro()
+
+macro(qt_internal_top_level_setup_no_create_targets)
+ # Also make sure the CMake config files do not recreate the already-existing targets
+ if (NOT QT_INTERNAL_BUILD_STANDALONE_PARTS)
+ set(QT_NO_CREATE_TARGETS TRUE)
+ endif()
+endmacro()
+
+macro(qt_internal_top_level_end)
+ qt_internal_print_top_level_info()
+
+ # Depends on QtBuildInternalsConfig being included, which is the case whenver any repo is
+ # configured.
+ qt_internal_qt_configure_end()
+endmacro()
+
+function(qt_internal_print_top_level_info)
+ if(NOT QT_INTERNAL_BUILD_STANDALONE_PARTS)
+ # Display a summary of everything
+ include(QtBuildInformation)
+ include(QtPlatformSupport)
+ qt_print_feature_summary()
+ qt_print_build_instructions()
+ endif()
+endfunction()
+
+macro(qt_internal_top_level_after_add_subdirectory)
+ if(module STREQUAL "qtbase")
+ if (NOT QT_INTERNAL_BUILD_STANDALONE_PARTS)
+ list(APPEND CMAKE_PREFIX_PATH "${QtBase_BINARY_DIR}/${INSTALL_LIBDIR}/cmake")
+ list(APPEND CMAKE_FIND_ROOT_PATH "${QtBase_BINARY_DIR}")
+ endif()
+ endif()
+endmacro()
diff --git a/cmake/QtBuild.cmake b/cmake/QtBuild.cmake
index 322926a5b3..ee24ba188e 100644
--- a/cmake/QtBuild.cmake
+++ b/cmake/QtBuild.cmake
@@ -1,575 +1,4 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-include(CMakePackageConfigHelpers)
-include(QtSeparateDebugInfo)
-
-function(qt_configure_process_path name default docstring)
- # Values are computed once for qtbase, and then exported and reused for other projects.
- if(NOT PROJECT_NAME STREQUAL "QtBase")
- return()
- endif()
-
- # No value provided, set the default.
- if(NOT DEFINED "${name}")
- set("${name}" "${default}" CACHE STRING "${docstring}")
- else()
- get_filename_component(given_path_as_abs "${${name}}" ABSOLUTE BASE_DIR
- "${CMAKE_INSTALL_PREFIX}")
- file(RELATIVE_PATH rel_path "${CMAKE_INSTALL_PREFIX}"
- "${given_path_as_abs}")
-
- # If absolute path given, check that it's inside the prefix (error out if not).
- # TODO: Figure out if we need to support paths that are outside the prefix.
- #
- # If relative path given, it's relative to the install prefix (rather than the binary dir,
- # which is what qmake does for some reason).
- # In both cases, store the value as a relative path.
- if("${rel_path}" STREQUAL "")
- # file(RELATIVE_PATH) returns an empty string if the given absolute paths are equal
- set(rel_path ".")
- elseif(rel_path MATCHES "^\.\./")
- # INSTALL_SYSCONFDIR is allowed to be outside the prefix.
- if(NOT name STREQUAL "INSTALL_SYSCONFDIR")
- message(FATAL_ERROR
- "Path component '${name}' is outside computed install prefix: ${rel_path} ")
- return()
- endif()
- set("${name}" "${${name}}" CACHE STRING "${docstring}" FORCE)
- else()
- set("${name}" "${rel_path}" CACHE STRING "${docstring}" FORCE)
- endif()
- endif()
-endfunction()
-
-# Install locations:
-qt_configure_process_path(INSTALL_BINDIR "bin" "Executables [PREFIX/bin]")
-qt_configure_process_path(INSTALL_INCLUDEDIR "include" "Header files [PREFIX/include]")
-qt_configure_process_path(INSTALL_LIBDIR "lib" "Libraries [PREFIX/lib]")
-qt_configure_process_path(INSTALL_MKSPECSDIR "mkspecs" "Mkspecs files [PREFIX/mkspecs]")
-qt_configure_process_path(INSTALL_ARCHDATADIR "." "Arch-dependent data [PREFIX]")
-qt_configure_process_path(INSTALL_PLUGINSDIR
- "${INSTALL_ARCHDATADIR}/plugins"
- "Plugins [ARCHDATADIR/plugins]")
-
-if(NOT INSTALL_MKSPECSDIR MATCHES "(^|/)mkspecs")
- message(FATAL_ERROR "INSTALL_MKSPECSDIR must end with '/mkspecs'")
-endif()
-
-# Given CMAKE_CONFIG and ALL_CMAKE_CONFIGS, determines if a directory suffix needs to be appended
-# to each destination, and sets the computed install target destination arguments in OUT_VAR.
-# Defaults used for each of the destination types, and can be configured per destination type.
-function(qt_get_install_target_default_args)
- cmake_parse_arguments(PARSE_ARGV 0 arg
- ""
- "OUT_VAR;CMAKE_CONFIG;RUNTIME;LIBRARY;ARCHIVE;INCLUDES;BUNDLE"
- "ALL_CMAKE_CONFIGS")
- _qt_internal_validate_all_args_are_parsed(arg)
-
- if(NOT arg_CMAKE_CONFIG)
- message(FATAL_ERROR "No value given for CMAKE_CONFIG.")
- endif()
- if(NOT arg_ALL_CMAKE_CONFIGS)
- message(FATAL_ERROR "No value given for ALL_CMAKE_CONFIGS.")
- endif()
- list(LENGTH arg_ALL_CMAKE_CONFIGS all_configs_count)
- list(GET arg_ALL_CMAKE_CONFIGS 0 first_config)
-
- set(suffix "")
- if(all_configs_count GREATER 1 AND NOT arg_CMAKE_CONFIG STREQUAL first_config)
- set(suffix "/${arg_CMAKE_CONFIG}")
- endif()
-
- set(runtime "${INSTALL_BINDIR}")
- if(arg_RUNTIME)
- set(runtime "${arg_RUNTIME}")
- endif()
-
- set(library "${INSTALL_LIBDIR}")
- if(arg_LIBRARY)
- set(library "${arg_LIBRARY}")
- endif()
-
- set(archive "${INSTALL_LIBDIR}")
- if(arg_ARCHIVE)
- set(archive "${arg_ARCHIVE}")
- endif()
-
- set(includes "${INSTALL_INCLUDEDIR}")
- if(arg_INCLUDES)
- set(includes "${arg_INCLUDES}")
- endif()
-
- set(bundle "${INSTALL_BINDIR}")
- if(arg_BUNDLE)
- set(bundle "${arg_BUNDLE}")
- endif()
-
- set(args
- RUNTIME DESTINATION "${runtime}${suffix}"
- LIBRARY DESTINATION "${library}${suffix}"
- ARCHIVE DESTINATION "${archive}${suffix}" COMPONENT Devel
- BUNDLE DESTINATION "${bundle}${suffix}"
- INCLUDES DESTINATION "${includes}${suffix}")
- set(${arg_OUT_VAR} "${args}" PARENT_SCOPE)
-endfunction()
-
-if (WIN32)
- set(_default_libexec "${INSTALL_ARCHDATADIR}/bin")
-else()
- set(_default_libexec "${INSTALL_ARCHDATADIR}/libexec")
-endif()
-
-qt_configure_process_path(
- INSTALL_LIBEXECDIR
- "${_default_libexec}"
- "Helper programs [ARCHDATADIR/bin on Windows, ARCHDATADIR/libexec otherwise]")
-qt_configure_process_path(INSTALL_QMLDIR
- "${INSTALL_ARCHDATADIR}/qml"
- "QML imports [ARCHDATADIR/qml]")
-qt_configure_process_path(INSTALL_DATADIR "." "Arch-independent data [PREFIX]")
-qt_configure_process_path(INSTALL_DOCDIR "${INSTALL_DATADIR}/doc" "Documentation [DATADIR/doc]")
-qt_configure_process_path(INSTALL_TRANSLATIONSDIR "${INSTALL_DATADIR}/translations"
- "Translations [DATADIR/translations]")
-if(APPLE)
- set(QT_DEFAULT_SYS_CONF_DIR "/Library/Preferences/Qt")
-else()
- set(QT_DEFAULT_SYS_CONF_DIR "etc/xdg")
-endif()
-qt_configure_process_path(INSTALL_SYSCONFDIR
- "${QT_DEFAULT_SYS_CONF_DIR}"
- "Settings used by Qt programs [PREFIX/etc/xdg]/[/Library/Preferences/Qt]")
-qt_configure_process_path(INSTALL_EXAMPLESDIR "examples" "Examples [PREFIX/examples]")
-qt_configure_process_path(INSTALL_TESTSDIR "tests" "Tests [PREFIX/tests]")
-qt_configure_process_path(INSTALL_DESCRIPTIONSDIR
- "${INSTALL_ARCHDATADIR}/modules"
- "Module description files directory")
-
-if(NOT "${CMAKE_STAGING_PREFIX}" STREQUAL "")
- set(QT_STAGING_PREFIX "${CMAKE_STAGING_PREFIX}")
-else()
- set(QT_STAGING_PREFIX "${CMAKE_INSTALL_PREFIX}")
-endif()
-
-if(PROJECT_NAME STREQUAL "QtBase")
- set(QT_COORD_TYPE double CACHE STRING "Type of qreal")
-endif()
-
-function(qt_internal_set_up_global_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,
- # and whether it is a superbuild or non-superbuild.
- # A third case is when another module or standalone tests are built against a super-built Qt.
- # The layout for the third case is the same as for non-superbuilds.
- #
- # These values should be prepended to file paths in commands or properties,
- # in order to correctly place generated Config files, generated Targets files,
- # executables / libraries, when copying / installing files, etc.
- #
- # The build dir variables will always be absolute paths.
- # The QT_INSTALL_DIR variable will have a relative path in a prefix build,
- # which means that it can be empty, so use qt_join_path to prevent accidental absolute paths.
- if(QT_SUPERBUILD)
- # In this case, we always copy all the build products in qtbase/{bin,lib,...}
- if(QT_WILL_INSTALL)
- set(QT_BUILD_DIR "${QtBase_BINARY_DIR}")
- set(QT_INSTALL_DIR "")
- else()
- if("${CMAKE_STAGING_PREFIX}" STREQUAL "")
- set(QT_BUILD_DIR "${QtBase_BINARY_DIR}")
- set(QT_INSTALL_DIR "${QtBase_BINARY_DIR}")
- else()
- set(QT_BUILD_DIR "${CMAKE_STAGING_PREFIX}")
- set(QT_INSTALL_DIR "${CMAKE_STAGING_PREFIX}")
- endif()
- endif()
- else()
- if(QT_WILL_INSTALL)
- # In the usual prefix build case, the build dir is the current module build dir,
- # and the install dir is the prefix, so we don't set it.
- set(QT_BUILD_DIR "${CMAKE_BINARY_DIR}")
- set(QT_INSTALL_DIR "")
- else()
- # When doing a non-prefix build, both the build dir and install dir are the same,
- # pointing to the qtbase build dir.
- set(QT_BUILD_DIR "${QT_STAGING_PREFIX}")
- set(QT_INSTALL_DIR "${QT_BUILD_DIR}")
- endif()
- endif()
-
- set(__config_path_part "${INSTALL_LIBDIR}/cmake")
- set(QT_CONFIG_BUILD_DIR "${QT_BUILD_DIR}/${__config_path_part}")
- set(QT_CONFIG_INSTALL_DIR "${QT_INSTALL_DIR}")
- if(QT_CONFIG_INSTALL_DIR)
- string(APPEND QT_CONFIG_INSTALL_DIR "/")
- endif()
- string(APPEND QT_CONFIG_INSTALL_DIR ${__config_path_part})
-
- set(QT_BUILD_DIR "${QT_BUILD_DIR}" PARENT_SCOPE)
- set(QT_INSTALL_DIR "${QT_INSTALL_DIR}" PARENT_SCOPE)
- set(QT_CONFIG_BUILD_DIR "${QT_CONFIG_BUILD_DIR}" PARENT_SCOPE)
- set(QT_CONFIG_INSTALL_DIR "${QT_CONFIG_INSTALL_DIR}" PARENT_SCOPE)
-endfunction()
-qt_internal_set_up_global_paths()
-qt_get_relocatable_install_prefix(QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX)
-
-set(QT_CMAKE_DIR "${CMAKE_CURRENT_LIST_DIR}")
-
-# Find the path to mkspecs/, depending on whether we are building as part of a standard qtbuild,
-# or a module against an already installed version of qt.
-if(NOT QT_MKSPECS_DIR)
- if("${QT_BUILD_INTERNALS_PATH}" STREQUAL "")
- get_filename_component(QT_MKSPECS_DIR "${CMAKE_CURRENT_LIST_DIR}/../mkspecs" ABSOLUTE)
- else()
- # We can rely on QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX being set by
- # QtBuildInternalsExtra.cmake.
- get_filename_component(
- QT_MKSPECS_DIR
- "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}/${INSTALL_MKSPECSDIR}" ABSOLUTE)
- endif()
- set(QT_MKSPECS_DIR "${QT_MKSPECS_DIR}" CACHE INTERNAL "")
-endif()
-
-# macOS versions 10.14 and less don't have the implementation of std::filesystem API.
-if(CMAKE_HOST_APPLE AND CMAKE_HOST_SYSTEM_VERSION VERSION_LESS "19.0.0")
- message(FATAL_ERROR "macOS versions less than 10.15 are not supported for building Qt.")
-endif()
-
-# the default RPATH to be used when installing, but only if it's not a system directory
-list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/${INSTALL_LIBDIR}" isSystemDir)
-if("${isSystemDir}" STREQUAL "-1")
- set(_default_install_rpath "${CMAKE_INSTALL_PREFIX}/${INSTALL_LIBDIR}")
-endif("${isSystemDir}" STREQUAL "-1")
-
-# The default rpath settings for installed targets is empty.
-# The rpaths will instead be computed for each target separately using qt_apply_rpaths().
-# Additional rpaths can be passed via QT_EXTRA_RPATHS.
-# By default this will include $ORIGIN / @loader_path, so the installation is relocatable.
-# Bottom line: No need to pass anything to CMAKE_INSTALL_RPATH.
-set(CMAKE_INSTALL_RPATH "" CACHE STRING "RPATH for installed binaries")
-
-# By default, don't embed auto-determined RPATHs pointing to directories
-# outside of the build tree, into the installed binaries.
-# This ended up adding rpaths like ${CMAKE_INSTALL_PREFIX}/lib (or /Users/qt/work/install/lib into
-# the official libraries created by the CI) into the non-qtbase libraries, plugins, etc.
-#
-# It should not be necessary, given that qt_apply_rpaths() already adds the necessary rpaths, either
-# relocatable ones or absolute ones, depending on what the platform supports.
-if(NOT QT_NO_DISABLE_CMAKE_INSTALL_RPATH_USE_LINK_PATH)
- set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE)
-endif()
-
-# Ensure that GNUInstallDirs's CMAKE_INSTALL_LIBDIR points to the same lib dir that Qt was
-# configured with. Currently this is important for QML plugins, which embed an rpath based
-# on that value.
-set(CMAKE_INSTALL_LIBDIR "${INSTALL_LIBDIR}")
-
-function(qt_setup_tool_path_command)
- if(NOT CMAKE_HOST_WIN32)
- return()
- endif()
- set(bindir "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}/${INSTALL_BINDIR}")
- file(TO_NATIVE_PATH "${bindir}" bindir)
- list(APPEND command COMMAND)
- list(APPEND command set PATH=${bindir}$<SEMICOLON>%PATH%)
- set(QT_TOOL_PATH_SETUP_COMMAND "${command}" CACHE INTERNAL "internal command prefix for tool invocations" FORCE)
- # QT_TOOL_PATH_SETUP_COMMAND is deprecated. Please use _qt_internal_get_wrap_tool_script_path
- # instead.
-endfunction()
-qt_setup_tool_path_command()
-
-# Platform define path, etc.
-if(WIN32)
- set(QT_DEFAULT_PLATFORM_DEFINITIONS WIN32 _ENABLE_EXTENDED_ALIGNED_STORAGE)
- if(CMAKE_SIZEOF_VOID_P EQUAL 8)
- list(APPEND QT_DEFAULT_PLATFORM_DEFINITIONS WIN64 _WIN64)
- endif()
- if(MSVC)
- if (CLANG)
- set(QT_DEFAULT_MKSPEC win32-clang-msvc)
- elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
- set(QT_DEFAULT_MKSPEC win32-arm64-msvc)
- else()
- set(QT_DEFAULT_MKSPEC win32-msvc)
- endif()
- elseif(CLANG AND MINGW)
- set(QT_DEFAULT_MKSPEC win32-clang-g++)
- elseif(MINGW)
- set(QT_DEFAULT_MKSPEC win32-g++)
- endif()
-
- if (MINGW)
- list(APPEND QT_DEFAULT_PLATFORM_DEFINITIONS MINGW_HAS_SECURE_API=1)
- endif()
-elseif(LINUX)
- if(GCC)
- set(QT_DEFAULT_MKSPEC linux-g++)
- elseif(CLANG)
- set(QT_DEFAULT_MKSPEC linux-clang)
- endif()
-elseif(ANDROID)
- if(GCC)
- set(QT_DEFAULT_MKSPEC android-g++)
- elseif(CLANG)
- set(QT_DEFAULT_MKSPEC android-clang)
- endif()
-elseif(IOS)
- set(QT_DEFAULT_MKSPEC macx-ios-clang)
-elseif(APPLE)
- set(QT_DEFAULT_MKSPEC macx-clang)
-elseif(WASM)
- if(WASM64)
- set(QT_DEFAULT_MKSPEC wasm-emscripten-64)
- else()
- set(QT_DEFAULT_MKSPEC wasm-emscripten)
- endif()
-elseif(QNX)
- # Certain POSIX defines are not set if we don't compile with -std=gnuXX
- set(QT_ENABLE_CXX_EXTENSIONS ON)
-
- list(APPEND QT_DEFAULT_PLATFORM_DEFINITIONS _FORTIFY_SOURCE=2 _REENTRANT)
-
- set(compiler_aarch64le aarch64le)
- set(compiler_armle-v7 armv7le)
- set(compiler_x86-64 x86_64)
- set(compiler_x86 x86)
- foreach(arch aarch64le armle-v7 x86-64 x86)
- if (CMAKE_CXX_COMPILER_TARGET MATCHES "${compiler_${arch}}$")
- set(QT_DEFAULT_MKSPEC qnx-${arch}-qcc)
- endif()
- endforeach()
-elseif(FREEBSD)
- if(CLANG)
- set(QT_DEFAULT_MKSPEC freebsd-clang)
- elseif(GCC)
- set(QT_DEFAULT_MKSPEC freebsd-g++)
- endif()
-elseif(NETBSD)
- set(QT_DEFAULT_MKSPEC netbsd-g++)
-elseif(OPENBSD)
- set(QT_DEFAULT_MKSPEC openbsd-g++)
-elseif(SOLARIS)
- if(GCC)
- if(QT_64BIT)
- set(QT_DEFAULT_MKSPEC solaris-g++-64)
- else()
- set(QT_DEFAULT_MKSPEC solaris-g++)
- endif()
- else()
- if(QT_64BIT)
- set(QT_DEFAULT_MKSPEC solaris-cc-64)
- else()
- set(QT_DEFAULT_MKSPEC solaris-cc)
- endif()
- endif()
-elseif(HURD)
- set(QT_DEFAULT_MKSPEC hurd-g++)
-endif()
-
-if(NOT QT_QMAKE_TARGET_MKSPEC)
- set(QT_QMAKE_TARGET_MKSPEC "${QT_DEFAULT_MKSPEC}" CACHE STRING "QMake target mkspec")
-endif()
-
-if(CMAKE_CROSSCOMPILING)
- set(QT_QMAKE_HOST_MKSPEC "${QT${PROJECT_VERSION_MAJOR}_HOST_INFO_QMAKE_MKSPEC}")
-else()
- set(QT_QMAKE_HOST_MKSPEC "${QT_QMAKE_TARGET_MKSPEC}")
-endif()
-
-if(NOT EXISTS "${QT_MKSPECS_DIR}/${QT_QMAKE_TARGET_MKSPEC}")
- file(GLOB known_platforms
- LIST_DIRECTORIES true
- RELATIVE "${QT_MKSPECS_DIR}"
- "${QT_MKSPECS_DIR}/*"
- )
- list(JOIN known_platforms "\n " known_platforms)
- message(FATAL_ERROR "Unknown platform ${QT_QMAKE_TARGET_MKSPEC}\n\
-Known platforms:\n ${known_platforms}")
-endif()
-
-if(NOT DEFINED QT_DEFAULT_PLATFORM_DEFINITIONS)
- set(QT_DEFAULT_PLATFORM_DEFINITIONS "")
-endif()
-
-set(QT_PLATFORM_DEFINITIONS ${QT_DEFAULT_PLATFORM_DEFINITIONS}
- CACHE STRING "Qt platform specific pre-processor defines")
-
-set(QT_NAMESPACE "" CACHE STRING "Qt Namespace")
-
-include(QtGlobalStateHelpers)
-
-# Reset global state:
-qt_internal_clear_qt_repo_known_modules()
-qt_internal_clear_qt_repo_known_plugin_types()
-qt_internal_set_qt_known_plugins("")
-
-set(QT_KNOWN_MODULES_WITH_TOOLS "" CACHE INTERNAL "Known Qt modules with tools" FORCE)
-
-# For adjusting variables when running tests, we need to know what
-# the correct variable is for separating entries in PATH-alike
-# variables.
-if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
- set(QT_PATH_SEPARATOR "\\;")
-else()
- set(QT_PATH_SEPARATOR ":")
-endif()
-
-# This is used to hold extra cmake code that should be put into QtBuildInternalsExtra.cmake file
-# at the QtPostProcess stage.
-set(QT_BUILD_INTERNALS_EXTRA_CMAKE_CODE "")
-
-# Save the value of the current first project source dir.
-# This will be /path/to/qtbase for qtbase both in a super-build and a non super-build.
-# This will be /path/to/qtbase/tests when building standalone tests.
-set(QT_TOP_LEVEL_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
-
-# Prevent warnings about object files without any symbols. This is a common
-# thing in Qt as we tend to build files unconditionally, and then use ifdefs
-# to compile out parts that are not relevant.
-if(CMAKE_CXX_COMPILER_ID MATCHES "AppleClang")
- foreach(lang ASM C CXX)
- # We have to tell 'ar' to not run ranlib by itself, by passing the 'S' option
- set(CMAKE_${lang}_ARCHIVE_CREATE "<CMAKE_AR> qcS <TARGET> <LINK_FLAGS> <OBJECTS>")
- set(CMAKE_${lang}_ARCHIVE_APPEND "<CMAKE_AR> qS <TARGET> <LINK_FLAGS> <OBJECTS>")
- set(CMAKE_${lang}_ARCHIVE_FINISH "<CMAKE_RANLIB> -no_warning_for_no_symbols <TARGET>")
- endforeach()
-endif()
-
-# Functions and macros:
-
-# Needed for qt_internal_add_link_flags_no_undefined.
-include(CheckCXXSourceCompiles)
-
-set(__default_private_args
- SOURCES
- LIBRARIES
- INCLUDE_DIRECTORIES
- SYSTEM_INCLUDE_DIRECTORIES
- DEFINES
- DBUS_ADAPTOR_BASENAME
- DBUS_ADAPTOR_FLAGS
- DBUS_ADAPTOR_SOURCES
- DBUS_INTERFACE_BASENAME
- DBUS_INTERFACE_FLAGS
- DBUS_INTERFACE_SOURCES
- FEATURE_DEPENDENCIES
- COMPILE_OPTIONS
- LINK_OPTIONS
- MOC_OPTIONS
- DISABLE_AUTOGEN_TOOLS
- ENABLE_AUTOGEN_TOOLS
- PLUGIN_TYPES
- NO_UNITY_BUILD_SOURCES
-)
-set(__default_public_args
- PUBLIC_LIBRARIES
- PUBLIC_INCLUDE_DIRECTORIES
- PUBLIC_DEFINES
- PUBLIC_COMPILE_OPTIONS
- PUBLIC_LINK_OPTIONS
-)
-set(__default_private_module_args
- PRIVATE_MODULE_INTERFACE
-)
-set(__default_target_info_args
- TARGET_VERSION
- TARGET_PRODUCT
- TARGET_DESCRIPTION
- TARGET_COMPANY
- TARGET_COPYRIGHT
-)
-
-# Collection of arguments so they can be shared across qt_internal_add_executable
-# and qt_internal_add_test_helper.
-set(__qt_internal_add_executable_optional_args
- GUI
- NO_INSTALL
- EXCEPTIONS
- DELAY_RC
- DELAY_TARGET_INFO
- QT_APP
- NO_UNITY_BUILD
-)
-set(__qt_internal_add_executable_single_args
- CORE_LIBRARY
- OUTPUT_DIRECTORY
- INSTALL_DIRECTORY
- VERSION
- ${__default_target_info_args}
-)
-set(__qt_internal_add_executable_multi_args
- ${__default_private_args}
- ${__default_public_args}
-)
-
-option(QT_CMAKE_DEBUG_EXTEND_TARGET "Debug extend_target calls in Qt's build system" OFF)
-
-# Internal helpers available only while building Qt itself.
-include(Qt3rdPartyLibraryHelpers)
-include(QtAppHelpers)
-include(QtAutogenHelpers)
-include(QtCMakeHelpers)
-include(QtDeferredDependenciesHelpers)
-include(QtDbusHelpers)
-include(QtDocsHelpers)
-include(QtExecutableHelpers)
-include(QtFindPackageHelpers)
-include(QtFlagHandlingHelpers)
-include(QtFrameworkHelpers)
-include(QtInstallHelpers)
-include(QtLalrHelpers)
-include(QtModuleHelpers)
-include(QtNoLinkTargetHelpers)
-include(QtPluginHelpers)
-include(QtPrecompiledHeadersHelpers)
-include(QtUnityBuildHelpers)
-include(QtPkgConfigHelpers)
-include(QtPriHelpers)
-include(QtPrlHelpers)
-include(QtQmakeHelpers)
-include(QtResourceHelpers)
-include(QtRpathHelpers)
-include(QtSanitizerHelpers)
-include(QtScopeFinalizerHelpers)
-include(QtSimdHelpers)
-include(QtSingleRepoTargetSetBuildHelpers)
-include(QtSyncQtHelpers)
-include(QtTargetHelpers)
-include(QtTestHelpers)
-include(QtToolHelpers)
-include(QtHeadersClean)
-include(QtJavaHelpers)
-
-if(ANDROID)
- include(QtAndroidHelpers)
-endif()
-
-if(WASM)
- include(QtWasmHelpers)
-endif()
-
-# Helpers that are available in public projects and while building Qt itself.
-include(QtPublicAppleHelpers)
-include(QtPublicCMakeHelpers)
-include(QtPublicPluginHelpers)
-include(QtPublicTargetHelpers)
-include(QtPublicWalkLibsHelpers)
-include(QtPublicFindPackageHelpers)
-include(QtPublicDependencyHelpers)
-include(QtPublicTestHelpers)
-include(QtPublicToolHelpers)
-
-if(CMAKE_CROSSCOMPILING)
- if(NOT IS_DIRECTORY "${QT_HOST_PATH}")
- message(FATAL_ERROR "You need to set QT_HOST_PATH to cross compile Qt.")
- endif()
-endif()
-
-_qt_internal_determine_if_host_info_package_needed(__qt_build_requires_host_info_package)
-_qt_internal_find_host_info_package("${__qt_build_requires_host_info_package}")
-
-# This sets up the poor man's scope finalizer mechanism.
-# For newer CMake versions, we use cmake_language(DEFER CALL) instead.
-if(CMAKE_VERSION VERSION_LESS "3.19.0")
- variable_watch(CMAKE_CURRENT_LIST_DIR qt_watch_current_list_dir)
-endif()
+qt_internal_setup_build_and_global_variables()
diff --git a/cmake/QtBuildHelpers.cmake b/cmake/QtBuildHelpers.cmake
new file mode 100644
index 0000000000..cce57cd5f6
--- /dev/null
+++ b/cmake/QtBuildHelpers.cmake
@@ -0,0 +1,458 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+function(qt_internal_validate_cmake_generator)
+ get_property(warning_shown GLOBAL PROPERTY _qt_validate_cmake_generator_warning_shown)
+
+ if(NOT warning_shown
+ AND NOT CMAKE_GENERATOR MATCHES "Ninja"
+ AND NOT QT_SILENCE_CMAKE_GENERATOR_WARNING
+ AND NOT DEFINED ENV{QT_SILENCE_CMAKE_GENERATOR_WARNING})
+ set_property(GLOBAL PROPERTY _qt_validate_cmake_generator_warning_shown TRUE)
+ message(WARNING
+ "The officially supported CMake generator for building Qt is "
+ "Ninja / Ninja Multi-Config. "
+ "You are using: '${CMAKE_GENERATOR}' instead. "
+ "Thus, you might encounter issues. Use at your own risk.")
+ endif()
+endfunction()
+
+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()
+ qt_internal_set_qt_known_plugins("")
+
+ set(QT_KNOWN_MODULES_WITH_TOOLS "" CACHE INTERNAL "Known Qt modules with tools" FORCE)
+endmacro()
+
+macro(qt_internal_set_qt_path_separator)
+ # For adjusting variables when running tests, we need to know what
+ # the correct variable is for separating entries in PATH-alike
+ # variables.
+ if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
+ set(QT_PATH_SEPARATOR "\\;")
+ else()
+ set(QT_PATH_SEPARATOR ":")
+ endif()
+endmacro()
+
+macro(qt_internal_set_internals_extra_cmake_code)
+ # This is used to hold extra cmake code that should be put into QtBuildInternalsExtra.cmake file
+ # at the QtPostProcess stage.
+ set(QT_BUILD_INTERNALS_EXTRA_CMAKE_CODE "")
+endmacro()
+
+macro(qt_internal_set_top_level_source_dir)
+ # Save the value of the current first project source dir.
+ # This will be /path/to/qtbase for qtbase both in a super-build and a non super-build.
+ # This will be /path/to/qtbase/tests when building standalone tests.
+ set(QT_TOP_LEVEL_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
+endmacro()
+
+macro(qt_internal_set_apple_archiver_flags)
+ # Prevent warnings about object files without any symbols. This is a common
+ # thing in Qt as we tend to build files unconditionally, and then use ifdefs
+ # to compile out parts that are not relevant.
+ if(CMAKE_CXX_COMPILER_ID MATCHES "AppleClang")
+ foreach(lang ASM C CXX)
+ # We have to tell 'ar' to not run ranlib by itself, by passing the 'S' option
+ set(CMAKE_${lang}_ARCHIVE_CREATE "<CMAKE_AR> qcS <TARGET> <LINK_FLAGS> <OBJECTS>")
+ set(CMAKE_${lang}_ARCHIVE_APPEND "<CMAKE_AR> qS <TARGET> <LINK_FLAGS> <OBJECTS>")
+ set(CMAKE_${lang}_ARCHIVE_FINISH "<CMAKE_RANLIB> -no_warning_for_no_symbols <TARGET>")
+ endforeach()
+ endif()
+endmacro()
+
+macro(qt_internal_set_apple_privacy_manifest target manifest_file)
+ set_target_properties(${target} PROPERTIES _qt_privacy_manifest "${manifest_file}")
+endmacro()
+
+macro(qt_internal_set_debug_extend_target)
+ option(QT_CMAKE_DEBUG_EXTEND_TARGET "Debug extend_target calls in Qt's build system" OFF)
+endmacro()
+
+# These upstream CMake modules will be automatically include()'d when doing
+# find_package(Qt6 COMPONENTS BuildInternals).
+function(qt_internal_get_qt_build_upstream_cmake_modules out_var)
+ set(${out_var}
+ CMakeFindBinUtils
+ CMakePackageConfigHelpers
+ CheckCXXSourceCompiles
+ FeatureSummary
+ PARENT_SCOPE
+ )
+endfunction()
+
+# These helpers will be installed when building qtbase, and they will be automatically include()'d
+# when doing find_package(Qt6 COMPONENTS BuildInternals).
+# The helpers are expected to exist under the qtbase/cmake sub-directory and their file name
+# extension should be '.cmake'.
+function(qt_internal_get_qt_build_private_helpers out_var)
+ set(${out_var}
+ Qt3rdPartyLibraryHelpers
+ QtAndroidHelpers
+ QtAppHelpers
+ QtAutoDetectHelpers
+ QtAutogenHelpers
+ QtBuildInformation
+ QtBuildOptionsHelpers
+ QtBuildPathsHelpers
+ QtBuildRepoExamplesHelpers
+ QtBuildRepoHelpers
+ QtCMakeHelpers
+ QtCMakeVersionHelpers
+ QtDbusHelpers
+ QtDeferredDependenciesHelpers
+ QtDocsHelpers
+ QtExecutableHelpers
+ QtFindPackageHelpers
+ QtFlagHandlingHelpers
+ QtFrameworkHelpers
+ QtGlobalStateHelpers
+ QtHeadersClean
+ QtInstallHelpers
+ QtJavaHelpers
+ QtLalrHelpers
+ QtMkspecHelpers
+ QtModuleHelpers
+ QtNoLinkTargetHelpers
+ QtPkgConfigHelpers
+ QtPlatformTargetHelpers
+ QtPluginHelpers
+ QtPostProcessHelpers
+ QtPrecompiledHeadersHelpers
+ QtPriHelpers
+ QtPrlHelpers
+ QtQmakeHelpers
+ QtResourceHelpers
+ QtRpathHelpers
+ QtSanitizerHelpers
+ QtScopeFinalizerHelpers
+ QtSeparateDebugInfo
+ QtSimdHelpers
+ QtSingleRepoTargetSetBuildHelpers
+ QtSyncQtHelpers
+ QtTargetHelpers
+ QtTestHelpers
+ QtToolHelpers
+ QtToolchainHelpers
+ QtUnityBuildHelpers
+ QtWasmHelpers
+ QtWrapperScriptHelpers
+ PARENT_SCOPE
+ )
+endfunction()
+
+# These files will be installed when building qtbase, but will NOT be automatically include()d
+# when doing find_package(Qt6 COMPONENTS BuildInternals).
+# The files are expected to exist under the qtbase/cmake sub-directory.
+function(qt_internal_get_qt_build_private_files_to_install out_var)
+ set(${out_var}
+ ModuleDescription.json.in
+ PkgConfigLibrary.pc.in
+ Qt3rdPartyLibraryConfig.cmake.in
+ QtBaseTopLevelHelpers.cmake
+ QtBuild.cmake
+ QtBuildHelpers.cmake
+ QtCMakePackageVersionFile.cmake.in
+ QtCompilerFlags.cmake
+ QtCompilerOptimization.cmake
+ QtConfigDependencies.cmake.in
+ QtConfigureTimeExecutableCMakeLists.txt.in
+ QtFileConfigure.txt.in
+ QtFindWrapConfigExtra.cmake.in
+ QtFindWrapHelper.cmake
+ QtFinishPkgConfigFile.cmake
+ QtFinishPrlFile.cmake
+ QtGenerateExtPri.cmake
+ QtGenerateLibHelpers.cmake
+ QtGenerateLibPri.cmake
+ QtGenerateVersionScript.cmake
+ QtModuleConfig.cmake.in
+ QtModuleDependencies.cmake.in
+ QtModuleHeadersCheck.cmake
+ QtModuleToolsConfig.cmake.in
+ QtModuleToolsDependencies.cmake.in
+ QtModuleToolsVersionlessTargets.cmake.in
+ QtPlatformAndroid.cmake
+ QtPlatformSupport.cmake
+ QtPluginConfig.cmake.in
+ QtPluginDependencies.cmake.in
+ QtPlugins.cmake.in
+ QtPostProcess.cmake
+ QtProcessConfigureArgs.cmake
+ QtSeparateDebugInfo.Info.plist.in
+ QtSetup.cmake
+ QtStandaloneTestsConfig.cmake.in
+ QtVersionlessAliasTargets.cmake.in
+ QtVersionlessTargets.cmake.in
+ QtWriteArgsFile.cmake
+ modulecppexports.h.in
+ qbatchedtestrunner.in.cpp
+ PARENT_SCOPE
+ )
+endfunction()
+
+# These helpers will be installed when building qtbase, and they will be automatically include()'d
+# when doing find_package(Qt6 COMPONENTS BuildInternals).
+# The helpers are expected to exist under the qtbase/cmake sub-directory and their file name
+# extension should be '.cmake'.
+# In addition, they are meant to be included when doing find_package(Qt6) as well.
+function(qt_internal_get_qt_build_public_helpers out_var)
+ set(${out_var}
+ QtFeature
+ QtFeatureCommon
+ QtPublicAppleHelpers
+ QtPublicCMakeHelpers
+ QtPublicCMakeVersionHelpers
+ QtPublicDependencyHelpers
+ QtPublicExternalProjectHelpers
+ QtPublicFinalizerHelpers
+ QtPublicFindPackageHelpers
+ QtPublicPluginHelpers
+ QtPublicTargetHelpers
+ QtPublicTestHelpers
+ QtPublicToolHelpers
+ QtPublicWalkLibsHelpers
+ PARENT_SCOPE
+ )
+endfunction()
+
+# These files will be installed when building qtbase, but will NOT be automatically include()d
+# when doing find_package(Qt6) nor find_package(Qt6 COMPONENTS BuildInternals).
+# The files are expected to exist under the qtbase/cmake sub-directory.
+function(qt_internal_get_qt_build_public_files_to_install out_var)
+ set(${out_var}
+ QtCopyFileIfDifferent.cmake
+ QtInitProject.cmake
+
+ # Public CMake files that are installed next Qt6Config.cmake, but are NOT included by it.
+ # Instead they are included by the generated CMake toolchain file.
+ QtPublicWasmToolchainHelpers.cmake
+
+ PARENT_SCOPE
+ )
+endfunction()
+
+# Includes all Qt CMake helper files that define functions and macros.
+macro(qt_internal_include_all_helpers)
+ # Upstream cmake modules.
+ qt_internal_get_qt_build_upstream_cmake_modules(__qt_upstream_helpers)
+ foreach(__qt_file_name IN LISTS __qt_upstream_helpers)
+ include("${__qt_file_name}")
+ endforeach()
+
+ # Internal helpers available only while building Qt itself.
+ qt_internal_get_qt_build_private_helpers(__qt_private_helpers)
+ foreach(__qt_file_name IN LISTS __qt_private_helpers)
+ include("${__qt_file_name}")
+ endforeach()
+
+ # Helpers that are available in public projects and while building Qt itself.
+ qt_internal_get_qt_build_public_helpers(__qt_public_helpers)
+ foreach(__qt_file_name IN LISTS __qt_public_helpers)
+ include("${__qt_file_name}")
+ endforeach()
+endmacro()
+
+function(qt_internal_check_host_path_set_for_cross_compiling)
+ if(CMAKE_CROSSCOMPILING)
+ if(NOT IS_DIRECTORY "${QT_HOST_PATH}")
+ message(FATAL_ERROR "You need to set QT_HOST_PATH to cross compile Qt.")
+ endif()
+ endif()
+endfunction()
+
+macro(qt_internal_setup_find_host_info_package)
+ _qt_internal_determine_if_host_info_package_needed(__qt_build_requires_host_info_package)
+ _qt_internal_find_host_info_package("${__qt_build_requires_host_info_package}")
+endmacro()
+
+macro(qt_internal_setup_poor_mans_scope_finalizer)
+ # This sets up the poor man's scope finalizer mechanism.
+ # For newer CMake versions, we use cmake_language(DEFER CALL) instead.
+ if(CMAKE_VERSION VERSION_LESS "3.19.0")
+ variable_watch(CMAKE_CURRENT_LIST_DIR qt_watch_current_list_dir)
+ endif()
+endmacro()
+
+macro(qt_internal_set_qt_namespace)
+ set(QT_NAMESPACE "" CACHE STRING "Qt Namespace")
+endmacro()
+
+macro(qt_internal_set_qt_coord_type)
+ if(PROJECT_NAME STREQUAL "QtBase")
+ set(QT_COORD_TYPE double CACHE STRING "Type of qreal")
+ endif()
+endmacro()
+
+function(qt_internal_check_macos_host_version)
+ # macOS versions 10.14 and less don't have the implementation of std::filesystem API.
+ if(CMAKE_HOST_APPLE AND CMAKE_HOST_SYSTEM_VERSION VERSION_LESS "19.0.0")
+ message(FATAL_ERROR "macOS versions less than 10.15 are not supported for building Qt.")
+ endif()
+endfunction()
+
+function(qt_internal_setup_tool_path_command)
+ if(NOT CMAKE_HOST_WIN32)
+ return()
+ endif()
+ set(bindir "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}/${INSTALL_BINDIR}")
+ file(TO_NATIVE_PATH "${bindir}" bindir)
+ list(APPEND command COMMAND)
+ list(APPEND command set PATH=${bindir}$<SEMICOLON>%PATH%)
+ set(QT_TOOL_PATH_SETUP_COMMAND "${command}" CACHE INTERNAL
+ "internal command prefix for tool invocations" FORCE)
+ # QT_TOOL_PATH_SETUP_COMMAND is deprecated. Please use _qt_internal_get_wrap_tool_script_path
+ # instead.
+endfunction()
+
+macro(qt_internal_setup_android_platform_specifics)
+ if(ANDROID)
+ qt_internal_setup_android_target_properties()
+ endif()
+endmacro()
+
+macro(qt_internal_setup_build_and_global_variables)
+ qt_internal_validate_cmake_generator()
+ qt_internal_set_qt_building_qt()
+ qt_internal_set_cmake_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_cmake_build_type
+ qt_internal_setup_cmake_config_postfix()
+
+ qt_internal_setup_position_independent_code()
+ qt_internal_set_link_depends_no_shared()
+ 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_set_configure_from_ide
+ qt_internal_set_sync_headers_at_configure_time()
+
+ qt_internal_setup_build_benchmarks()
+
+ # 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 qt_internal_setup_paths_and_prefixes
+ qt_internal_set_mkspecs_dir()
+ qt_internal_setup_platform_definitions_and_mkspec()
+
+ qt_internal_check_macos_host_version()
+ _qt_internal_check_apple_sdk_and_xcode_versions()
+ qt_internal_check_host_path_set_for_cross_compiling()
+ qt_internal_setup_android_platform_specifics()
+ qt_internal_setup_find_host_info_package()
+ qt_internal_setup_tool_path_command()
+ qt_internal_setup_default_target_function_options()
+ qt_internal_set_default_rpath_settings()
+ qt_internal_set_qt_namespace()
+ qt_internal_set_qt_coord_type()
+ qt_internal_set_qt_path_separator()
+ qt_internal_set_internals_extra_cmake_code()
+ qt_internal_set_top_level_source_dir()
+ 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 9d8a11cb2d..11fa9996b1 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)
@@ -11,7 +27,6 @@ function(qt_print_feature_summary)
endif()
endif()
- include(FeatureSummary)
# Show which packages were found.
feature_summary(INCLUDE_QUIET_PACKAGES
WHAT PACKAGES_FOUND
@@ -43,8 +58,7 @@ endfunction()
function(qt_print_build_instructions)
if((NOT PROJECT_NAME STREQUAL "QtBase" AND
- NOT PROJECT_NAME STREQUAL "Qt") OR
- QT_BUILD_STANDALONE_TESTS)
+ NOT PROJECT_NAME STREQUAL "Qt") OR QT_INTERNAL_BUILD_STANDALONE_PARTS)
return()
endif()
@@ -109,7 +123,7 @@ from the build directory")
set(QT_INTERNAL_BUILD_INSTRUCTIONS_SHOWN "TRUE" CACHE STRING "" FORCE)
if(QT_SUPERBUILD)
- qt_internal_save_previously_found_packages()
+ qt_internal_save_previously_visited_packages()
endif()
endfunction()
@@ -147,11 +161,23 @@ function(qt_configure_print_summary)
# Show Qt-specific configuration summary.
if(__qt_configure_reports)
+ # The summary will only be printed for log level STATUS or above.
+ # Check whether the log level is sufficient for printing the summary.
+ set(log_level_sufficient_for_printed_summary TRUE)
+ if(CMAKE_VERSION GREATER_EQUAL "3.25")
+ cmake_language(GET_MESSAGE_LOG_LEVEL log_level)
+ set(sufficient_log_levels STATUS VERBOSE DEBUG TRACE)
+ if(NOT log_level IN_LIST sufficient_log_levels)
+ set(log_level_sufficient_for_printed_summary FALSE)
+ endif()
+ endif()
+
# We want to show the configuration summary file and log level message only on
# first configuration or when we detect a feature change, to keep most
# reconfiguration output as quiet as possible.
# Currently feature change detection is not entirely reliable.
- if(NOT QT_INTERNAL_SUMMARY_INSTRUCTIONS_SHOWN OR features_possibly_changed)
+ if(log_level_sufficient_for_printed_summary
+ AND (NOT QT_INTERNAL_SUMMARY_INSTRUCTIONS_SHOWN OR features_possibly_changed))
set(force_show_summary TRUE)
message(
"\n"
diff --git a/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake b/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake
index 2ac1db6daf..129f1ebb77 100644
--- a/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake
+++ b/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake
@@ -4,66 +4,25 @@
# 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
-#
-###############################################
-
-# Recursively reads the dependencies section from dependencies.yaml in ${repo_dir} and returns the
-# list of dependencies, including transitive ones, in out_var.
-#
-# The returned dependencies are topologically sorted.
-#
-# Example output for qtdeclarative:
-# qtbase;qtimageformats;qtlanguageserver;qtshadertools;qtsvg
-#
-function(qt_internal_read_repo_dependencies out_var repo_dir)
- set(seen ${ARGN})
- set(dependencies "")
- set(in_dependencies_section FALSE)
- set(dependencies_file "${repo_dir}/dependencies.yaml")
- if(EXISTS "${dependencies_file}")
- file(STRINGS "${dependencies_file}" lines)
- foreach(line IN LISTS lines)
- if(line MATCHES "^([^ ]+):")
- if(CMAKE_MATCH_1 STREQUAL "dependencies")
- set(in_dependencies_section TRUE)
- else()
- set(in_dependencies_section FALSE)
- endif()
- elseif(in_dependencies_section AND line MATCHES "^ (.+):$")
- set(dependency "${CMAKE_MATCH_1}")
- set(dependency_repo_dir "${repo_dir}/${dependency}")
- string(REGEX MATCH "[^/]+$" dependency "${dependency}")
- if(NOT dependency IN_LIST seen)
- qt_internal_read_repo_dependencies(subdeps "${dependency_repo_dir}"
- ${seen} ${dependency})
- list(APPEND dependencies ${subdeps} ${dependency})
- endif()
- endif()
- endforeach()
- list(REMOVE_DUPLICATES dependencies)
- endif()
- 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
@@ -95,1330 +54,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)
-
-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
- if ((NOT DEFINED "FEATURE_pkg_config") AND (DEFINED "INPUT_pkg_config")
- AND (NOT "${INPUT_pkg_config}" STREQUAL "undefined")
- AND (NOT "${INPUT_pkg_config}" STREQUAL ""))
- if(INPUT_pkg_config)
- set(FEATURE_pkg_config ON)
- else()
- set(FEATURE_pkg_config OFF)
- endif()
- endif()
-
- # 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()
-
-macro(qt_build_internals_set_up_private_api)
- # Check for the minimum CMake version.
- include(QtCMakeVersionHelpers)
- qt_internal_require_suitable_cmake_version()
- qt_internal_upgrade_cmake_policies()
-
- # 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()
-
-# find all targets defined in $subdir by recursing through all added subdirectories
-# populates $qt_repo_targets with a ;-list of non-UTILITY targets
-macro(qt_build_internals_get_repo_targets subdir)
- get_directory_property(_targets DIRECTORY "${subdir}" BUILDSYSTEM_TARGETS)
- if(_targets)
- foreach(_target IN LISTS _targets)
- get_target_property(_type ${_target} TYPE)
- if(NOT ${_type} STREQUAL "UTILITY")
- list(APPEND qt_repo_targets "${_target}")
- endif()
- endforeach()
- endif()
-
- get_directory_property(_directories DIRECTORY "${subdir}" SUBDIRECTORIES)
- if (_directories)
- foreach(_directory IN LISTS _directories)
- qt_build_internals_get_repo_targets("${_directory}")
- endforeach()
- endif()
-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_build_internals_get_repo_targets("${directory}")
- 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.
- 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()
-
- 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)
- include(CheckLanguage)
- set(__qt_required_language_list C CXX)
- set(__qt_optional_language_list )
-
- # https://gitlab.kitware.com/cmake/cmake/-/issues/20545
- if(APPLE)
- list(APPEND __qt_optional_language_list OBJC OBJCXX)
- endif()
-
- foreach(__qt_lang ${__qt_required_language_list})
- enable_language(${__qt_lang})
- endforeach()
-
- foreach(__qt_lang ${__qt_optional_language_list})
- check_language(${__qt_lang})
- if(CMAKE_${__qt_lang}_COMPILER)
- enable_language(${__qt_lang})
- endif()
- 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)
- 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()
-
- # 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()
-
-macro(qt_build_repo_end)
- if(NOT QT_BUILD_STANDALONE_TESTS)
- # Delayed actions on some of the Qt targets:
- include(QtPostProcess)
-
- # 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_found_packages()
- endif()
-
- if(QT_INTERNAL_FRESH_REQUESTED)
- set(QT_INTERNAL_FRESH_REQUESTED "FALSE" CACHE INTERNAL "")
- endif()
-
- list(POP_BACK CMAKE_MESSAGE_CONTEXT)
-endmacro()
-
-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_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)
-
- 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)
- 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})
-
- # 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_EXAMPLES_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_EXAMPLES_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).
-
- # This function gets all targets below this directory (excluding custom targets and aliases)
- function(get_all_targets _result _dir)
- get_property(_subdirs DIRECTORY "${_dir}" PROPERTY SUBDIRECTORIES)
- foreach(_subdir IN LISTS _subdirs)
- get_all_targets(${_result} "${_subdir}")
- endforeach()
- get_property(_sub_targets DIRECTORY "${_dir}" PROPERTY BUILDSYSTEM_TARGETS)
- set(_real_targets "")
- if(_sub_targets)
- foreach(__target IN LISTS _sub_targets)
- get_target_property(target_type ${__target} TYPE)
- if(NOT target_type STREQUAL "UTILITY" AND NOT target_type STREQUAL "ALIAS")
- list(APPEND _real_targets ${__target})
- endif()
- endforeach()
- endif()
- set(${_result} ${${_result}} ${_real_targets} PARENT_SCOPE)
- endfunction()
-
- get_all_targets(targets "${CMAKE_CURRENT_SOURCE_DIR}")
-
- 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}\")
-")
-endmacro()
-
-function(qt_internal_add_example subdir)
- if(NOT QT_IS_EXTERNAL_EXAMPLES_BUILD)
- qt_internal_add_example_in_tree(${ARGV})
- else()
- qt_internal_add_example_external_project(${ARGV})
- endif()
-endfunction()
-
-# Use old non-ExternalProject approach, aka build in-tree with the Qt build.
-function(qt_internal_add_example_in_tree subdir)
- file(RELATIVE_PATH example_rel_path
- "${QT_EXAMPLE_BASE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/${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.
- # 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(CMAKE_INSTALL_PREFIX "${qt_example_install_prefix}/${example_rel_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} ${ARGN})
-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}")
-
- file(RELATIVE_PATH example_rel_path
- "${QT_EXAMPLE_BASE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/${subdir}")
-
- if(NOT arg_NAME)
- set(arg_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(arg_NAME MATCHES "/")
- string(REPLACE "/" ";" exploded_path "${arg_NAME}")
- list(POP_BACK exploded_path last_dir)
- if(NOT last_dir)
- message(FATAL_ERROR "Example subdirectory must have a name.")
- else()
- set(arg_NAME "${last_dir}")
- endif()
- endif()
- endif()
-
- # Likely a clash with an example subdir ExternalProject custom target of the same name.
- if(TARGET "${arg_NAME}")
- string(SHA1 rel_path_hash "${example_rel_path}")
- string(SUBSTRING "${rel_path_hash}" 0 4 short_hash)
- set(arg_NAME "${arg_NAME}-${short_hash}")
- endif()
-
- # TODO: Fix example builds when using Conan / install prefixes are different for each repo.
- if(QT_SUPERBUILD OR QtBase_BINARY_DIR)
- # When doing a top-level build or when building qtbase,
- # always use the Config file from the current build directory, even for prefix builds.
- # We strive to allow building examples without installing Qt first, which means we can't
- # use the install or staging Config files.
- set(qt_prefixes "${QT_BUILD_DIR}")
- set(qt_cmake_dir "${QT_CONFIG_BUILD_DIR}/${QT_CMAKE_EXPORT_NAMESPACE}")
- else()
- # This is a per-repo build that isn't the qtbase repo, so we know that
- # qtbase was found via find_package() and Qt6_DIR must be set
- set(qt_cmake_dir "${${QT_CMAKE_EXPORT_NAMESPACE}_DIR}")
-
- # In a prefix build of a non-qtbase repo, we want to pick up the installed Config files
- # for all repos except the one that is currently built. For the repo that is currently
- # built, we pick up the Config files from the current repo build dir instead.
- # For non-prefix builds, there's only one prefix, the main build dir.
- # Both are handled by this assignment.
- set(qt_prefixes "${QT_BUILD_DIR}")
-
- # Appending to QT_ADDITIONAL_PACKAGES_PREFIX_PATH helps find Qt6 components in
- # non-qtbase prefix builds because we use NO_DEFAULT_PATH in find_package calls.
- # It also handles the cross-compiling scenario where we need to adjust both the root path
- # and prefixes, with the prefixes containing lib/cmake. This leverages the infrastructure
- # previously added for Conan.
- list(APPEND QT_ADDITIONAL_PACKAGES_PREFIX_PATH ${qt_prefixes})
-
- # In a prefix build, look up all repo Config files in the install prefix,
- # except for the current repo, which will look in the build dir (handled above).
- if(QT_WILL_INSTALL)
- list(APPEND qt_prefixes "${QT6_INSTALL_PREFIX}")
- endif()
- endif()
-
- 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_EXAMPLES_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.
-
- # 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(example_install_prefix "${qt_example_install_prefix}/${example_rel_path}")
-
- 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_prefix}"
- 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()
-
-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()
+include(QtBuildHelpers)
-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()
+qt_internal_include_all_helpers()
+qt_internal_setup_build_internals()
diff --git a/cmake/QtBuildInternals/QtStandaloneTestTemplateProject/CMakeLists.txt b/cmake/QtBuildInternals/QtStandaloneTestTemplateProject/CMakeLists.txt
index 73ed57c1da..766e372666 100644
--- a/cmake/QtBuildInternals/QtStandaloneTestTemplateProject/CMakeLists.txt
+++ b/cmake/QtBuildInternals/QtStandaloneTestTemplateProject/CMakeLists.txt
@@ -2,11 +2,6 @@
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
-project(qt_single_test VERSION 6.0.0 LANGUAGES C CXX ASM)
-
-find_package(Qt6 REQUIRED COMPONENTS BuildInternals Core)
-
-include(${CMAKE_CURRENT_LIST_DIR}/Main.cmake)
# Get the absolute path of the passed-in project dir, relative to the current working directory
# of the calling script, rather than relative to this source directory.
@@ -18,6 +13,9 @@ else()
set(absolute_project_path "${QT_STANDALONE_TEST_PATH}")
endif()
+# If path does not include the drive letter, we try to add it.
+get_filename_component(absolute_project_path "." REALPATH BASE_DIR "${absolute_project_path}")
+
if(NOT IS_DIRECTORY "${absolute_project_path}")
get_filename_component(filename "${absolute_project_path}" NAME)
get_filename_component(directory "${absolute_project_path}" DIRECTORY)
@@ -27,5 +25,14 @@ if(NOT IS_DIRECTORY "${absolute_project_path}")
endif()
endif()
+# Get the project name base on test directory name
+get_filename_component(project_name "${absolute_project_path}" NAME)
+
+project(${project_name} VERSION 6.0.0 LANGUAGES C CXX ASM)
+
+find_package(Qt6 REQUIRED COMPONENTS BuildInternals Core)
+
+include(${CMAKE_CURRENT_LIST_DIR}/Main.cmake NO_POLICY_SCOPE)
+
# Add the test project path as a subdirectory project.
add_subdirectory("${absolute_project_path}" "build_dir")
diff --git a/cmake/QtBuildInternals/QtStandaloneTestTemplateProject/Main.cmake b/cmake/QtBuildInternals/QtStandaloneTestTemplateProject/Main.cmake
index 89bb2a1132..bd0984f314 100644
--- a/cmake/QtBuildInternals/QtStandaloneTestTemplateProject/Main.cmake
+++ b/cmake/QtBuildInternals/QtStandaloneTestTemplateProject/Main.cmake
@@ -2,15 +2,17 @@
# SPDX-License-Identifier: BSD-3-Clause
# Includes QtSetup and friends for private CMake API.
+set(QT_INTERNAL_IS_STANDALONE_TEST TRUE)
+qt_internal_project_setup()
qt_build_internals_set_up_private_api()
# Find all StandaloneTestsConfig.cmake files, and include them
# This will find all Qt packages that are required for standalone tests.
# It will find more packages that needed for a certain test, but will ensure any test can
# be built.
-qt_get_standalone_tests_config_files_path(standalone_tests_config_path)
+qt_get_standalone_parts_config_files_path(standalone_parts_config_path)
-file(GLOB config_files "${standalone_tests_config_path}/*")
+file(GLOB config_files "${standalone_parts_config_path}/*")
foreach(file ${config_files})
include("${file}")
endforeach()
@@ -21,5 +23,5 @@ qt_set_language_standards()
# Just before adding the test, change the local (non-cache) install prefix to something other than
# the Qt install prefix, so that tests don't try to install and pollute the Qt install prefix.
-# Needs to be called after qt_get_standalone_tests_confg_files_path().
-qt_set_up_fake_standalone_tests_install_prefix()
+# Needs to be called after qt_get_standalone_parts_config_files_path().
+qt_internal_set_up_fake_standalone_parts_install_prefix()
diff --git a/cmake/QtBuildInternalsExtra.cmake.in b/cmake/QtBuildInternalsExtra.cmake.in
index 2dc906b6c6..8985f8178a 100644
--- a/cmake/QtBuildInternalsExtra.cmake.in
+++ b/cmake/QtBuildInternalsExtra.cmake.in
@@ -1,3 +1,6 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
# Propagate common variables via BuildInternals package.
set(QT_BUILD_SHARED_LIBS @BUILD_SHARED_LIBS@)
option(BUILD_SHARED_LIBS "Build Qt statically or dynamically" @BUILD_SHARED_LIBS@)
@@ -103,6 +106,9 @@ set(QT_BUILD_EXAMPLES_AS_EXTERNAL "@QT_BUILD_EXAMPLES_AS_EXTERNAL@" CACHE BOOL
# Propagate usage of ccache.
set(QT_USE_CCACHE @QT_USE_CCACHE@ CACHE BOOL "Enable the use of ccache")
+# Propagate usage of vcpkg, ON by default.
+set(QT_USE_VCPKG @QT_USE_VCPKG@ CACHE BOOL "Enable the use of vcpkg")
+
# Propagate usage of unity build.
set(QT_UNITY_BUILD @QT_UNITY_BUILD@ CACHE BOOL "Enable unity (jumbo) build")
set(QT_UNITY_BUILD_BATCH_SIZE "@QT_UNITY_BUILD_BATCH_SIZE@" CACHE STRING "Unity build batch size")
@@ -129,42 +135,5 @@ if(NOT DEFINED QT_MAX_NEW_POLICY_CMAKE_VERSION)
set(QT_MAX_NEW_POLICY_CMAKE_VERSION "@max_new_policy_version@")
endif()
-get_property(__qt_internal_extras_is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
-
-# We want the same build type to be used when configuring all Qt repos or standalone
-# tests or single tests.
-# To do that, we need to force-set the CMAKE_BUILD_TYPE cache var because CMake itself
-# initializes it with the value of CMAKE_BUILD_TYPE_INIT at the start of project
-# configuration, so we need to override it.
-# Note the value of CMAKE_BUILD_TYPE_INIT is different based on the platform, most
-# Linux and macOS platforms will have it empty, but Windows platforms will have a value.
-#
-# We can't reliably differentiate between a value set on the command line by the user
-# and one set by CMake, so we use a few heuristics:
-# 1) When using a qt.toolchain.cmake file, we rely on the toolchain file to tell us
-# if a value was set by the user at initial configure time. On a 2nd run there will
-# always be a value in the cache, but at that point we've already set it to whatever it needs
-# to be.
-# 2) If a toolchain file is not used, we rely on the value of the CMake internal
-# CMAKE_BUILD_TYPE_INIT variable.
-# This won't work reliably on Windows where CMAKE_BUILD_TYPE_INIT is non-empty.
-#
-# Both cases won't handle an empty "" config set by the user, but we claim that's an
-# unsupported config when building Qt.
-#
-# Allow an opt out when QT_NO_FORCE_SET_CMAKE_BUILD_TYPE is set.
-# Finally, don't set the variable if a multi-config generator is used. This can happen
-# when qtbase is built with a single config, but a test is built with a multi-config generator.
-function(qt_internal_force_set_cmake_build_type_conditionally value)
- # STREQUAL check needs to be expanded variables because an undefined var is not equal to an
- # empty defined var.
- if("${CMAKE_BUILD_TYPE}" STREQUAL "${CMAKE_BUILD_TYPE_INIT}"
- AND NOT __qt_toolchain_cmake_build_type_before_project_call
- AND NOT QT_NO_FORCE_SET_CMAKE_BUILD_TYPE
- AND NOT __qt_internal_extras_is_multi_config)
- set(CMAKE_BUILD_TYPE "${value}" CACHE STRING "Choose the type of build." FORCE)
- endif()
-endfunction()
-
# Extra set of exported variables
@QT_EXTRA_BUILD_INTERNALS_VARS@
diff --git a/cmake/QtBuildOptionsHelpers.cmake b/cmake/QtBuildOptionsHelpers.cmake
new file mode 100644
index 0000000000..3879920f65
--- /dev/null
+++ b/cmake/QtBuildOptionsHelpers.cmake
@@ -0,0 +1,383 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+# Try to detect if CMAKE_BUILD_TYPE is default initialized by CMake, or it was set by the user.
+#
+# CMake initializes CMAKE_BUILD_TYPE to the value of CMAKE_BUILD_TYPE_INIT during the first
+# project() call if CMAKE_BUILD_TYPE is empty.
+#
+# Unfortunately on most Windows platforms, it defaults to 'Debug', so we can't differentiate
+# between a 'Debug' value set on the command line by the user, a value set by the project, or if it
+# was default initialized.
+# We need to rely on heuristics to determine that.
+#
+# We try to check the value of CMAKE_BUILD_TYPE before the first project() call by inspecting
+# various variables:
+# 1) When using a qt.toolchain.cmake file, we rely on the toolchain file to tell us
+# if a value was set by the user at initial configure time via the
+# __qt_toolchain_cmake_build_type_before_project_call variable. On a 2nd run there will
+# always be a value in the cache, but at that point we've already set it to whatever it needs
+# to be.
+# 2) Whe configuring qtbase, a top-level qt, or a standalone project we rely on one of the following
+# variables being set:
+# - __qt_auto_detect_cmake_build_type_before_project_call (e.g for qtbase)
+# - __qt_internal_standalone_project_cmake_build_type_before_project_call (e.g for sqldrivers)
+# 3) When using a multi-config generator, we assume that the CMAKE_BUILD_TYPE is not default
+# initialized.
+# 4) The user can also force the build type to be considered non-default-initialized by setting
+# QT_NO_FORCE_SET_CMAKE_BUILD_TYPE to TRUE. It has weird naming that doesn't quite correspond
+# to the meaning, but it's been called like that for a while now and I'm hesitant to change
+# the name in case it's used by various projects.
+#
+# The code doesn't handle an empty "" config set by the user, but we claim that's an
+# unsupported config when building Qt.
+function(qt_internal_is_cmake_build_type_default_initialized_heuristic out_var)
+ get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
+ get_cmake_property(aready_force_set _qt_build_internals_cmake_build_type_set)
+
+ if(
+ # Set by CMake's Platform/Windows-MSVC.cmake when CMAKE_BUILD_TYPE is empty
+ # The STREQUAL check needs to have expanded variables because an undefined var is not equal
+ # to an empty defined var.
+ "${CMAKE_BUILD_TYPE}" STREQUAL "${CMAKE_BUILD_TYPE_INIT}"
+
+ # Set by qt_internal_force_set_cmake_build_type()
+ AND aready_force_set MATCHES "NOTFOUND"
+
+ # Set by qt_auto_detect_cmake_build_type()
+ AND NOT __qt_auto_detect_cmake_build_type_before_project_call
+
+ # Set by sqldrivers project
+ AND NOT __qt_internal_standalone_project_cmake_build_type_before_project_call
+
+ # Set by qt.toolchain.cmake
+ AND NOT __qt_toolchain_cmake_build_type_before_project_call
+
+ # Set by user explicitily
+ AND NOT QT_NO_FORCE_SET_CMAKE_BUILD_TYPE
+
+ # Set in multi-config builds
+ AND NOT is_multi_config)
+
+ set(${out_var} TRUE PARENT_SCOPE)
+ else()
+ set(${out_var} FALSE PARENT_SCOPE)
+ endif()
+endfunction()
+
+function(qt_internal_force_set_cmake_build_type value)
+ cmake_parse_arguments(PARSE_ARGV 1 arg
+ "SHOW_MESSAGE"
+ ""
+ ""
+ )
+ _qt_internal_validate_all_args_are_parsed(arg)
+
+ set(CMAKE_BUILD_TYPE "${value}" 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.
+ if(arg_SHOW_MESSAGE)
+ message(STATUS "Force setting build type to '${value}'.")
+ endif()
+ set_property(GLOBAL PROPERTY _qt_build_internals_cmake_build_type_set "${value}")
+endfunction()
+
+# Only override the build type if it was default initialized by CMake.
+function(qt_internal_force_set_cmake_build_type_if_cmake_default_initialized value)
+ qt_internal_is_cmake_build_type_default_initialized_heuristic(is_default_cmake_build_type)
+ if(is_default_cmake_build_type)
+ qt_internal_force_set_cmake_build_type("${value}" SHOW_MESSAGE)
+ endif()
+endfunction()
+
+function(qt_internal_set_cmake_build_type)
+ # When building standalone tests against a multi-config Qt, we want to configure the
+ # tests / examples with
+ # the first multi-config configuration, rather than use CMake's default configuration.
+ # In the case of Windows, we definitely don't want it to default to Debug, because that causes
+ # issues in the CI.
+ if(QT_INTERNAL_BUILD_STANDALONE_PARTS AND QT_MULTI_CONFIG_FIRST_CONFIG)
+ qt_internal_force_set_cmake_build_type_if_cmake_default_initialized(
+ "${QT_MULTI_CONFIG_FIRST_CONFIG}")
+
+ # We want the same build type to be used when configuring all Qt repos or standalone
+ # tests or single tests, so we reuse the initial build type set by qtbase.
+ # __qt_internal_initial_qt_cmake_build_type is saved in QtBuildInternalsExtra.cmake.in.
+ elseif(__qt_internal_initial_qt_cmake_build_type)
+ qt_internal_force_set_cmake_build_type_if_cmake_default_initialized(
+ "${__qt_internal_initial_qt_cmake_build_type}")
+
+ # Default to something sensible when configuring qtbase / top-level.
+ else()
+ qt_internal_set_qt_appropriate_default_cmake_build_type()
+ endif()
+endfunction()
+
+# Sets a default cmake build type for qtbase / top-level.
+macro(qt_internal_set_qt_appropriate_default_cmake_build_type)
+ set(_default_build_type "Release")
+ if(FEATURE_developer_build)
+ set(_default_build_type "Debug")
+ endif()
+
+ qt_internal_is_cmake_build_type_default_initialized_heuristic(is_default_cmake_build_type)
+ if(is_default_cmake_build_type)
+ qt_internal_force_set_cmake_build_type("${_default_build_type}")
+ message(STATUS "Setting build type to '${_default_build_type}' as none was specified.")
+ 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 already explicitly 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_sync_headers_at_configure_time)
+ set(_qt_sync_headers_at_configure_time_default ${QT_INTERNAL_CONFIGURE_FROM_IDE})
+
+ if(FEATURE_developer_build)
+ # Sync headers during the initial configuration of a -developer-build to facilitate code
+ # navigation for code editors that use an LSP-based code model.
+ set(_qt_sync_headers_at_configure_time_default TRUE)
+ endif()
+
+ # Sync Qt header files at configure time
+ option(QT_SYNC_HEADERS_AT_CONFIGURE_TIME "Run syncqt at configure time already"
+ ${_qt_sync_headers_at_configure_time_default})
+ unset(_qt_sync_headers_at_configure_time_default)
+
+ # In static Ninja Multi-Config builds the sync_headers dependencies(and other autogen
+ # dependencies are not added to '_autogen/timestamp' targets. See QTBUG-113974.
+ if(CMAKE_GENERATOR STREQUAL "Ninja Multi-Config" AND NOT QT_BUILD_SHARED_LIBS)
+ set(QT_SYNC_HEADERS_AT_CONFIGURE_TIME TRUE CACHE BOOL "" FORCE)
+ 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 AND _qt_batch_tests)
+ set(_qt_wasm_and_batch_tests ON)
+ else()
+ set(_qt_wasm_and_batch_tests OFF)
+ endif()
+
+ option(QT_BUILD_MINIMAL_STATIC_TESTS "Build minimal subset of tests for static Qt builds" ${_qt_wasm_and_batch_tests})
+
+ option(QT_BUILD_WASM_BATCHED_TESTS "Build subset of tests for wasm batched tests" ${_qt_wasm_and_batch_tests})
+
+ 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)
+
+ # We need a way to force disable building in-tree examples in the CI, so that we instead build
+ # standalone examples. Because the Coin yaml instructions don't allow us to remove
+ # -make examples from from the configure args, we instead read a variable that only Coin sets.
+ if(QT_INTERNAL_CI_NO_BUILD_IN_TREE_EXAMPLES)
+ set(QT_BUILD_EXAMPLES OFF CACHE BOOL "Build Qt examples" FORCE)
+ endif()
+
+ if(QT_BUILD_STANDALONE_EXAMPLES)
+ # BuildInternals might have set it to OFF on initial configuration. So force it to ON when
+ # building standalone examples.
+ set(QT_BUILD_EXAMPLES ON CACHE BOOL "Build Qt examples" FORCE)
+
+ # Also force the examples to be built as part of the default build target.
+ set(QT_BUILD_EXAMPLES_BY_DEFAULT ON CACHE BOOL
+ "Should examples be built as part of the default 'all' target." FORCE)
+ endif()
+
+ option(QT_DEPLOY_MINIMAL_EXAMPLES
+ "Deploy minimal subset of examples to save time and space" OFF)
+
+ # FIXME: Support prefix builds as well QTBUG-96232
+ # We don't want to enable EP examples with -debug-and-release because starting with CMake 3.24
+ # ExternalProject_Add ends up creating build rules twice, once for each configuration, in the
+ # same build dir, which ends up causing various issues due to concurrent builds as well as
+ # clobbered CMakeCache.txt and ninja files.
+ if(QT_WILL_INSTALL OR QT_FEATURE_debug_and_release)
+ 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
new file mode 100644
index 0000000000..6431fa1937
--- /dev/null
+++ b/cmake/QtBuildPathsHelpers.cmake
@@ -0,0 +1,247 @@
+# 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_INTERNAL_BUILD_STANDALONE_PARTS)
+ 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,
+ # and whether it is a superbuild or non-superbuild.
+ # A third case is when another module or standalone tests/examples are built against a
+ # super-built Qt.
+ # The layout for the third case is the same as for non-superbuilds.
+ #
+ # These values should be prepended to file paths in commands or properties,
+ # in order to correctly place generated Config files, generated Targets files,
+ # executables / libraries, when copying / installing files, etc.
+ #
+ # The build dir variables will always be absolute paths.
+ # The QT_INSTALL_DIR variable will have a relative path in a prefix build,
+ # which means that it can be empty, so use qt_join_path to prevent accidental absolute paths.
+ if(QT_SUPERBUILD)
+ # In this case, we always copy all the build products in qtbase/{bin,lib,...}
+ if(QT_WILL_INSTALL)
+ set(QT_BUILD_DIR "${QtBase_BINARY_DIR}")
+ set(QT_INSTALL_DIR "")
+ else()
+ if("${CMAKE_STAGING_PREFIX}" STREQUAL "")
+ set(QT_BUILD_DIR "${QtBase_BINARY_DIR}")
+ set(QT_INSTALL_DIR "${QtBase_BINARY_DIR}")
+ else()
+ set(QT_BUILD_DIR "${CMAKE_STAGING_PREFIX}")
+ set(QT_INSTALL_DIR "${CMAKE_STAGING_PREFIX}")
+ endif()
+ endif()
+ else()
+ if(QT_WILL_INSTALL)
+ # In the usual prefix build case, the build dir is the current module build dir,
+ # and the install dir is the prefix, so we don't set it.
+ set(QT_BUILD_DIR "${CMAKE_BINARY_DIR}")
+ set(QT_INSTALL_DIR "")
+ else()
+ # When doing a non-prefix build, both the build dir and install dir are the same,
+ # pointing to the qtbase build dir.
+ set(QT_BUILD_DIR "${QT_STAGING_PREFIX}")
+ set(QT_INSTALL_DIR "${QT_BUILD_DIR}")
+ endif()
+ endif()
+
+ set(__config_path_part "${INSTALL_LIBDIR}/cmake")
+ set(QT_CONFIG_BUILD_DIR "${QT_BUILD_DIR}/${__config_path_part}")
+ set(QT_CONFIG_INSTALL_DIR "${QT_INSTALL_DIR}")
+ if(QT_CONFIG_INSTALL_DIR)
+ string(APPEND QT_CONFIG_INSTALL_DIR "/")
+ endif()
+ string(APPEND QT_CONFIG_INSTALL_DIR ${__config_path_part})
+
+ set(QT_BUILD_DIR "${QT_BUILD_DIR}" PARENT_SCOPE)
+ set(QT_INSTALL_DIR "${QT_INSTALL_DIR}" PARENT_SCOPE)
+ set(QT_CONFIG_BUILD_DIR "${QT_CONFIG_BUILD_DIR}" PARENT_SCOPE)
+ set(QT_CONFIG_INSTALL_DIR "${QT_CONFIG_INSTALL_DIR}" PARENT_SCOPE)
+endfunction()
+
+function(qt_configure_process_path name default docstring)
+ # Values are computed once for qtbase, and then exported and reused for other projects.
+ if(NOT PROJECT_NAME STREQUAL "QtBase")
+ return()
+ endif()
+
+ # No value provided, set the default.
+ if(NOT DEFINED "${name}")
+ set("${name}" "${default}" CACHE STRING "${docstring}")
+ else()
+ get_filename_component(given_path_as_abs "${${name}}" ABSOLUTE BASE_DIR
+ "${CMAKE_INSTALL_PREFIX}")
+ file(RELATIVE_PATH rel_path "${CMAKE_INSTALL_PREFIX}"
+ "${given_path_as_abs}")
+
+ # If absolute path given, check that it's inside the prefix (error out if not).
+ # TODO: Figure out if we need to support paths that are outside the prefix.
+ #
+ # If relative path given, it's relative to the install prefix (rather than the binary dir,
+ # which is what qmake does for some reason).
+ # In both cases, store the value as a relative path.
+ if("${rel_path}" STREQUAL "")
+ # file(RELATIVE_PATH) returns an empty string if the given absolute paths are equal
+ set(rel_path ".")
+ elseif(rel_path MATCHES "^\.\./")
+ # INSTALL_SYSCONFDIR is allowed to be outside the prefix.
+ if(NOT name STREQUAL "INSTALL_SYSCONFDIR")
+ message(FATAL_ERROR
+ "Path component '${name}' is outside computed install prefix: ${rel_path} ")
+ return()
+ endif()
+ set("${name}" "${${name}}" CACHE STRING "${docstring}" FORCE)
+ else()
+ set("${name}" "${rel_path}" CACHE STRING "${docstring}" FORCE)
+ endif()
+ endif()
+endfunction()
+
+macro(qt_internal_setup_configure_install_paths)
+ # Install locations:
+ qt_configure_process_path(INSTALL_BINDIR "bin" "Executables [PREFIX/bin]")
+ qt_configure_process_path(INSTALL_INCLUDEDIR "include" "Header files [PREFIX/include]")
+ qt_configure_process_path(INSTALL_LIBDIR "lib" "Libraries [PREFIX/lib]")
+ qt_configure_process_path(INSTALL_MKSPECSDIR "mkspecs" "Mkspecs files [PREFIX/mkspecs]")
+ qt_configure_process_path(INSTALL_ARCHDATADIR "." "Arch-dependent data [PREFIX]")
+ qt_configure_process_path(INSTALL_PLUGINSDIR
+ "${INSTALL_ARCHDATADIR}/plugins"
+ "Plugins [ARCHDATADIR/plugins]")
+
+ if(NOT INSTALL_MKSPECSDIR MATCHES "(^|/)mkspecs")
+ message(FATAL_ERROR "INSTALL_MKSPECSDIR must end with '/mkspecs'")
+ endif()
+
+ if (WIN32)
+ set(_default_libexec "${INSTALL_ARCHDATADIR}/bin")
+ else()
+ set(_default_libexec "${INSTALL_ARCHDATADIR}/libexec")
+ endif()
+
+ qt_configure_process_path(
+ INSTALL_LIBEXECDIR
+ "${_default_libexec}"
+ "Helper programs [ARCHDATADIR/bin on Windows, ARCHDATADIR/libexec otherwise]")
+ qt_configure_process_path(INSTALL_QMLDIR
+ "${INSTALL_ARCHDATADIR}/qml"
+ "QML imports [ARCHDATADIR/qml]")
+ qt_configure_process_path(INSTALL_DATADIR "." "Arch-independent data [PREFIX]")
+ qt_configure_process_path(INSTALL_DOCDIR "${INSTALL_DATADIR}/doc" "Documentation [DATADIR/doc]")
+ qt_configure_process_path(INSTALL_TRANSLATIONSDIR "${INSTALL_DATADIR}/translations"
+ "Translations [DATADIR/translations]")
+ if(APPLE)
+ set(QT_DEFAULT_SYS_CONF_DIR "/Library/Preferences/Qt")
+ else()
+ set(QT_DEFAULT_SYS_CONF_DIR "etc/xdg")
+ endif()
+ qt_configure_process_path(
+ INSTALL_SYSCONFDIR
+ "${QT_DEFAULT_SYS_CONF_DIR}"
+ "Settings used by Qt programs [PREFIX/etc/xdg]/[/Library/Preferences/Qt]")
+ qt_configure_process_path(INSTALL_EXAMPLESDIR "examples" "Examples [PREFIX/examples]")
+ qt_configure_process_path(INSTALL_TESTSDIR "tests" "Tests [PREFIX/tests]")
+ qt_configure_process_path(INSTALL_DESCRIPTIONSDIR
+ "${INSTALL_ARCHDATADIR}/modules"
+ "Module description files directory")
+endmacro()
+
+macro(qt_internal_set_cmake_install_libdir)
+ # Ensure that GNUInstallDirs's CMAKE_INSTALL_LIBDIR points to the same lib dir that Qt was
+ # configured with. Currently this is important for QML plugins, which embed an rpath based
+ # on that value.
+ set(CMAKE_INSTALL_LIBDIR "${INSTALL_LIBDIR}")
+endmacro()
+
+macro(qt_internal_set_qt_cmake_dir)
+ set(QT_CMAKE_DIR "${CMAKE_CURRENT_LIST_DIR}")
+endmacro()
+
+macro(qt_internal_set_qt_apple_support_files_path)
+ # This is analogous to what we have in QtConfig.cmake.in. It's copied here so that iOS
+ # tests can be built in tree.
+ if(APPLE)
+ if(NOT CMAKE_SYSTEM_NAME OR CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+ set(__qt_internal_cmake_apple_support_files_path "${QT_CMAKE_DIR}/macos")
+ elseif(CMAKE_SYSTEM_NAME STREQUAL "iOS")
+ set(__qt_internal_cmake_apple_support_files_path "${QT_CMAKE_DIR}/ios")
+ elseif(CMAKE_SYSTEM_NAME STREQUAL "visionOS")
+ set(__qt_internal_cmake_apple_support_files_path "${QT_CMAKE_DIR}/visionos")
+ endif()
+ endif()
+endmacro()
+
+macro(qt_internal_set_qt_staging_prefix)
+ if(NOT "${CMAKE_STAGING_PREFIX}" STREQUAL "")
+ set(QT_STAGING_PREFIX "${CMAKE_STAGING_PREFIX}")
+ else()
+ set(QT_STAGING_PREFIX "${CMAKE_INSTALL_PREFIX}")
+ endif()
+endmacro()
+
+macro(qt_internal_setup_paths_and_prefixes)
+ qt_internal_setup_configure_install_paths()
+
+ qt_internal_set_qt_staging_prefix()
+
+ # Depends on QT_STAGING_PREFIX being set.
+ qt_internal_setup_build_and_install_paths()
+
+ qt_get_relocatable_install_prefix(QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX)
+
+ # Depends on INSTALL_LIBDIR being set.
+ qt_internal_set_cmake_install_libdir()
+
+ qt_internal_set_qt_cmake_dir()
+
+ qt_internal_set_qt_apple_support_files_path()
+endmacro()
diff --git a/cmake/QtBuildRepoExamplesHelpers.cmake b/cmake/QtBuildRepoExamplesHelpers.cmake
new file mode 100644
index 0000000000..6802d81323
--- /dev/null
+++ b/cmake/QtBuildRepoExamplesHelpers.cmake
@@ -0,0 +1,652 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+macro(qt_examples_build_begin)
+ set(options EXTERNAL_BUILD)
+ set(singleOpts "")
+ set(multiOpts DEPENDS)
+
+ cmake_parse_arguments(arg "${options}" "${singleOpts}" "${multiOpts}" ${ARGN})
+
+ # Examples are not unity-ready.
+ set(CMAKE_UNITY_BUILD OFF)
+
+ # Skip running deployment steps when the developer asked to deploy a minimal subset of examples.
+ # Each example can then decide whether it wants to be deployed as part of the minimal subset
+ # by unsetting the QT_INTERNAL_SKIP_DEPLOYMENT variable before its qt_internal_add_example call.
+ # This will be used by our CI.
+ if(NOT DEFINED QT_INTERNAL_SKIP_DEPLOYMENT AND QT_DEPLOY_MINIMAL_EXAMPLES)
+ set(QT_INTERNAL_SKIP_DEPLOYMENT TRUE)
+ endif()
+
+ # Use by qt_internal_add_example.
+ set(QT_EXAMPLE_BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
+
+ if(QT_BUILD_STANDALONE_EXAMPLES)
+ # Find all qt packages, so that the various if(QT_FEATURE_foo) add_subdirectory()
+ # conditions have correct values, regardless whether we will use ExternalProjects or not.
+ qt_internal_find_standalone_parts_config_files()
+ endif()
+
+ 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)
+ # Don't show warnings for examples that were added via qt_internal_add_example.
+ # Those that are added via add_subdirectory will see the warning, due to the parent scope
+ # having the variable set to TRUE.
+ if(QT_FEATURE_developer_build AND NOT QT_NO_WARN_ABOUT_EXAMPLE_ADD_SUBDIRECTORY_WARNING)
+ set(QT_WARN_ABOUT_EXAMPLE_ADD_SUBDIRECTORY FALSE)
+ endif()
+
+ # 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}")
+ elseif(QT_BUILD_STANDALONE_EXAMPLES)
+ # TODO: We might need to reset and pipe through an empty CMAKE_STAGING_PREFIX if we ever
+ # try to run standalone examples in the CI when cross-compiling, similar how it's done in
+ # qt_internal_set_up_fake_standalone_parts_install_prefix.
+ qt_internal_get_fake_standalone_install_prefix(qt_example_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.
+# Also unset the deployment prefix, so it can be recomputed for each example subdirectory.
+unset(CMAKE_INSTALL_PREFIX)
+unset(QT_DEPLOY_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()
+
+ # We we need to augment the CMAKE_MODULE_PATH with the current repo cmake build dir, to find
+ # files like FindWrapBundledFooConfigExtra.cmake.
+ set(module_paths "${qt_prefixes}")
+ list(TRANSFORM module_paths APPEND "/${INSTALL_LIBDIR}/cmake/${QT_CMAKE_EXPORT_NAMESPACE}")
+ list(APPEND CMAKE_MODULE_PATH ${module_paths})
+
+ # Pass additional paths where qml plugin config files should be included by Qt6QmlPlugins.cmake.
+ # This is needed in prefix builds, where the cmake files are not installed yet.
+ set(glob_prefixes "${qt_prefixes}")
+ list(TRANSFORM glob_prefixes APPEND "/${INSTALL_LIBDIR}/cmake/${QT_CMAKE_EXPORT_NAMESPACE}Qml")
+
+ set(qml_plugin_cmake_config_file_glob_prefixes "")
+ foreach(glob_prefix IN LISTS glob_prefix)
+ if(EXISTS "${glob_prefix}")
+ list(APPEND qml_plugin_cmake_config_file_glob_prefixes "${glob_prefix}")
+ endif()
+ endforeach()
+
+ if(qml_plugin_cmake_config_file_glob_prefixes)
+ set(QT_ADDITIONAL_QML_PLUGIN_GLOB_PREFIXES ${qml_plugin_cmake_config_file_glob_prefixes})
+ 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
+ QT_ADDITIONAL_QML_PLUGIN_GLOB_PREFIXES:STRING
+ QT_INTERNAL_SKIP_DEPLOYMENT:BOOL
+ CMAKE_FIND_ROOT_PATH:STRING
+ CMAKE_MODULE_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
+ )
+
+ # QT_EXAMPLE_CMAKE_VARS_TO_PASS can be set by specific repos to pass any additional required
+ # CMake cache variables.
+ # One use case is passing locations of 3rd party package locations like Protobuf via _ROOT
+ # variables.
+ set(extra_vars_var_name "")
+ if(QT_EXAMPLE_CMAKE_VARS_TO_PASS)
+ set(extra_vars_var_name "QT_EXAMPLE_CMAKE_VARS_TO_PASS")
+ endif()
+ foreach(var_with_type IN LISTS vars_to_pass_if_defined ${extra_vars_var_name})
+ 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()
diff --git a/cmake/QtBuildRepoHelpers.cmake b/cmake/QtBuildRepoHelpers.cmake
new file mode 100644
index 0000000000..8bd0615090
--- /dev/null
+++ b/cmake/QtBuildRepoHelpers.cmake
@@ -0,0 +1,1079 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+# Macros and functions for building Qt submodules
+
+# 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.
+ qt_internal_require_suitable_cmake_version()
+ qt_internal_upgrade_cmake_policies()
+ qt_internal_promote_platform_targets_to_global()
+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)
+
+ # 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 qt_repo_targets_name)
+ 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/examples.
+ # 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()
+
+# There are three necessary copies of this macro in
+# qtbase/cmake/QtBaseHelpers.cmake
+# qtbase/cmake/QtBaseTopLevelHelpers.cmake
+# qtbase/cmake/QtBuildRepoHelpers.cmake
+macro(qt_internal_setup_standalone_parts)
+ # A generic marker for any kind of standalone builds, either tests or examples.
+ if(NOT DEFINED QT_INTERNAL_BUILD_STANDALONE_PARTS
+ AND (QT_BUILD_STANDALONE_TESTS OR QT_BUILD_STANDALONE_EXAMPLES))
+ set(QT_INTERNAL_BUILD_STANDALONE_PARTS TRUE CACHE INTERNAL
+ "Whether standalone tests or examples are being built")
+ endif()
+endmacro()
+
+macro(qt_build_repo_begin)
+ qt_internal_setup_standalone_parts()
+
+ 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_INTERNAL_BUILD_STANDALONE_PARTS)
+ include(QtPostProcess)
+ endif()
+ endif()
+endmacro()
+
+macro(qt_build_repo_end)
+ if(NOT QT_INTERNAL_BUILD_STANDALONE_PARTS)
+ 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(${qt_repo_targets_name})
+
+ qt_internal_show_extra_ide_sources()
+
+ 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(qt_internal_show_extra_ide_sources)
+ if(CMAKE_VERSION VERSION_LESS 3.20)
+ set(ide_sources_default OFF)
+ else()
+ set(ide_sources_default ON)
+ endif()
+
+ option(QT_SHOW_EXTRA_IDE_SOURCES "Generate CMake targets exposing non-source files to IDEs" ${ide_sources_default})
+ if(CMAKE_VERSION VERSION_LESS 3.20 AND QT_SHOW_EXTRA_IDE_SOURCES)
+ message(WARNING "QT_SHOW_EXTRA_IDE_SOURCES requires cmake-3.20")
+ return()
+ endif()
+
+ if(NOT QT_SHOW_EXTRA_IDE_SOURCES)
+ return()
+ endif()
+
+ # coin
+ set(coin_target_name ${qt_repo_targets_name}_coin_files)
+ file(GLOB_RECURSE coin_files LIST_DIRECTORIES false FOLLOW_SYMLINKS coin/*)
+ if(coin_files)
+ source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}/coin" FILES ${coin_files})
+ add_custom_target(${coin_target_name} SOURCES ${coin_files})
+ endif()
+
+ # config.test
+ set(config_tests_target_name ${qt_repo_targets_name}_config_tests)
+ file(GLOB_RECURSE config_tests_file LIST_DIRECTORIES false FOLLOW_SYMLINKS config.tests/*)
+ if(config_tests_file)
+ source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}/config.tests" FILES ${config_tests_file})
+ add_custom_target(${config_tests_target_name} SOURCES ${config_tests_file})
+ endif()
+
+ # cmake
+ set(cmake_target_name ${qt_repo_targets_name}_cmake_files)
+ file(GLOB_RECURSE cmake_files LIST_DIRECTORIES false FOLLOW_SYMLINKS
+ cmake/*
+ configure.cmake
+ qt_cmdline.cmake
+ .cmake.conf
+ *.cmake
+ *.cmake.in)
+ foreach(cmake_file IN LISTS cmake_files)
+ if(NOT ((cmake_file IN_LIST coin_files) OR (file IN_LIST config_tests_files)))
+ list(APPEND cmake_target_files ${cmake_file})
+ endif()
+ endforeach()
+
+ if(cmake_target_files)
+ source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" FILES ${cmake_target_files})
+ add_custom_target(${cmake_target_name} SOURCES ${cmake_target_files})
+ endif()
+
+ # licenses
+ set(licenses_target_name ${qt_repo_targets_name}_licenses)
+ file(GLOB licenses_files LIST_DIRECTORIES false LICENSES/*)
+ if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/licenseRule.json")
+ list(APPEND licenses_files "${CMAKE_CURRENT_SOURCE_DIR}/licenseRule.json")
+ endif()
+ if(licenses_files)
+ source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" FILES ${licenses_files})
+ add_custom_target(${licenses_target_name} SOURCES ${licenses_files})
+ endif()
+
+ # changelogs
+ set(changelogs_target_name ${qt_repo_targets_name}_changelogs)
+ file(GLOB change_logs_files LIST_DIRECTORIES false dist/*)
+ if(change_logs_files)
+ source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}/dist" FILES ${change_logs_files})
+ add_custom_target(${changelogs_target_name} SOURCES ${change_logs_files})
+ endif()
+
+ # extra files
+ set(target_name ${qt_repo_targets_name}_extra_files)
+ add_custom_target(${target_name})
+
+ set(recursive_glob_patterns
+ ${QT_BUILD_EXTRA_IDE_FILE_RECURSIVE_PATTERNS}
+ )
+ set(simple_glob_patterns
+ .gitattributes
+ .gitignore
+ .tag
+ config_help.txt
+ ${QT_BUILD_EXTRA_IDE_FILE_PATTERNS}
+ )
+
+ if(recursive_glob_patterns)
+ file(GLOB_RECURSE files LIST_DIRECTORIES false FOLLOW_SYMLINKS ${recursive_glob_patterns})
+ if(files)
+ source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" FILES ${files})
+ target_sources(${target_name} PRIVATE ${files})
+ endif()
+ endif()
+
+ file(GLOB files LIST_DIRECTORIES false ${simple_glob_patterns})
+ if(files)
+ source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" FILES ${files})
+ target_sources(${target_name} PRIVATE ${files})
+ endif()
+endfunction()
+
+
+# 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.
+ if(QT_INTERNAL_CALLED_FROM_CONFIGURE)
+ unset(QT_INTERNAL_CALLED_FROM_CONFIGURE CACHE)
+ endif()
+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_INTERNAL_BUILD_STANDALONE_PARTS)
+ # 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_INTERNAL_BUILD_STANDALONE_PARTS)
+ 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_INTERNAL_BUILD_STANDALONE_PARTS)
+ 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 OR QT_BUILD_STANDALONE_TESTS)
+ AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tests/CMakeLists.txt")
+ if(QT_BUILD_STANDALONE_EXAMPLES)
+ message(FATAL_ERROR
+ "Can't build both standalone tests and standalone examples at once.")
+ endif()
+ option(QT_BUILD_TESTS_PROJECT_${PROJECT_NAME} "Configure tests for project ${PROJECT_NAME}" TRUE)
+
+ if (QT_BUILD_TESTS_PROJECT_${PROJECT_NAME})
+ add_subdirectory(tests)
+ if(NOT QT_BUILD_TESTS_BY_DEFAULT)
+ set_property(DIRECTORY tests PROPERTY EXCLUDE_FROM_ALL TRUE)
+ endif()
+ endif()
+ endif()
+endmacro()
+
+macro(qt_build_repo_impl_examples)
+ if((QT_BUILD_EXAMPLES OR QT_BUILD_STANDALONE_EXAMPLES)
+ AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/examples/CMakeLists.txt")
+ if(QT_BUILD_STANDALONE_TESTS)
+ message(FATAL_ERROR
+ "Can't build both standalone tests and standalone examples at once.")
+ endif()
+
+ message(STATUS "Configuring examples.")
+
+ option(QT_BUILD_EXAMPLES_PROJECT_${PROJECT_NAME} "Configure examples for project ${PROJECT_NAME}" TRUE)
+ if(QT_BUILD_EXAMPLES_PROJECT_${PROJECT_NAME})
+
+ # Set this before any examples subdirectories are added, to warn about examples that are
+ # added via add_subdirectory() calls instead of qt_internal_add_example().
+ if(QT_FEATURE_developer_build
+ AND NOT QT_NO_WARN_ABOUT_EXAMPLE_ADD_SUBDIRECTORY_WARNING)
+ set(QT_WARN_ABOUT_EXAMPLE_ADD_SUBDIRECTORY TRUE)
+ endif()
+
+ add_subdirectory(examples)
+ endif()
+ 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_parts_config_files_path out_var)
+ # TODO: Rename this to StandaloneParts in some future Qt version, if it confuses people too
+ # much. Currently not renamed, not to break distro installation scripts that might exclude
+ # the files.
+ set(dir_name "StandaloneTests")
+
+ set(path_suffix "${INSTALL_LIBDIR}/cmake/${INSTALL_CMAKE_NAMESPACE}BuildInternals/${dir_name}")
+
+ # Each repo's standalone parts might be configured with a unique CMAKE_STAGING_PREFIX,
+ # different from any previous one, and it might not coincide with where the BuildInternals
+ # config file is.
+ if(QT_WILL_INSTALL AND CMAKE_STAGING_PREFIX)
+ qt_path_join(path "${CMAKE_STAGING_PREFIX}" "${path_suffix}")
+ else()
+ qt_path_join(path "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}" "${path_suffix}")
+ endif()
+
+ set("${out_var}" "${path}" PARENT_SCOPE)
+endfunction()
+
+function(qt_internal_get_standalone_parts_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()
+
+ # TODO: Rename this to StandalonePartsConfig.cmake in some future Qt version, if it confuses
+ # people too much. Currently not renamed, not to break distro installation scripts that might
+ # exclude # the files.
+ string(APPEND tests_config_file_name "TestsConfig.cmake")
+
+ set(${out_var} "${tests_config_file_name}" PARENT_SCOPE)
+endfunction()
+
+macro(qt_internal_find_standalone_test_config_file)
+ if(QT_INTERNAL_BUILD_STANDALONE_PARTS)
+ # 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)
+ endif()
+endmacro()
+
+# Used by standalone tests and standalone non-ExternalProject examples to find all installed qt
+# packages.
+macro(qt_internal_find_standalone_parts_config_files)
+ if(QT_INTERNAL_BUILD_STANDALONE_PARTS)
+ # Find location of TestsConfig.cmake. These contain the modules that need to be
+ # find_package'd when building tests or examples.
+ qt_get_standalone_parts_config_files_path(_qt_build_parts_install_prefix)
+
+ qt_internal_get_standalone_parts_config_file_name(_qt_parts_config_file_name)
+ set(_qt_standalone_parts_config_file_path
+ "${_qt_build_parts_install_prefix}/${_qt_parts_config_file_name}")
+ include("${_qt_standalone_parts_config_file_path}"
+ OPTIONAL
+ RESULT_VARIABLE _qt_standalone_parts_included)
+ if(NOT _qt_standalone_parts_included)
+ message(DEBUG
+ "Standalone parts config file not included because it does not exist: "
+ "${_qt_standalone_parts_config_file_path}"
+ )
+ else()
+ message(DEBUG
+ "Standalone parts config file included successfully: "
+ "${_qt_standalone_parts_config_file_path}"
+ )
+ endif()
+
+ unset(_qt_standalone_parts_config_file_path)
+ unset(_qt_standalone_parts_included)
+ unset(_qt_parts_config_file_name)
+ endif()
+endmacro()
+
+macro(qt_build_tests)
+ # Tests are not unity-ready.
+ 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")
+
+ qt_internal_find_standalone_parts_config_files()
+ qt_internal_find_standalone_test_config_file()
+
+ if(QT_BUILD_STANDALONE_TESTS)
+ # 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()
+
+ # Set up fake standalone parts install prefix, so we don't pollute the Qt install
+ # prefix with tests.
+ qt_internal_set_up_fake_standalone_parts_install_prefix()
+ 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_internal_get_fake_standalone_install_prefix out_var)
+ set(new_install_prefix "${CMAKE_BINARY_DIR}/fake_prefix")
+ set(${out_var} "${new_install_prefix}" PARENT_SCOPE)
+endfunction()
+
+function(qt_internal_set_up_fake_standalone_parts_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()
+ qt_internal_get_fake_standalone_install_prefix(new_install_prefix)
+
+ # It's IMPORTANT that this is not a cache variable. Otherwise
+ # qt_get_standalone_parts_config_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()
+
+# Meant to be called when configuring examples as part of the main build tree (unless standalone
+# examples are being built), 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.
+ if(NOT QT_BUILD_STANDALONE_EXAMPLES)
+ set(QT_NO_CREATE_TARGETS TRUE)
+ endif()
+endmacro()
+
+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()
+
+# 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()
+
+macro(qt_internal_setup_platform_support_variables)
+ # 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)
+endmacro()
+
+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()
+
+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()
+
+ # 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()
+
+macro(qt_build_internals_find_pkg_config)
+ # Find package config once before any system prefix modifications.
+ find_package(PkgConfig QUIET)
+endmacro()
+
+
+macro(qt_internal_setup_pkg_config_and_system_prefixes)
+ if(NOT QT_BUILD_INTERNALS_SKIP_PKG_CONFIG_ADJUSTMENT)
+ qt_build_internals_disable_pkg_config_if_needed()
+ endif()
+
+ if(NOT QT_BUILD_INTERNALS_SKIP_FIND_PKG_CONFIG)
+ qt_build_internals_find_pkg_config()
+ endif()
+
+ if(NOT QT_BUILD_INTERNALS_SKIP_SYSTEM_PREFIX_ADJUSTMENT)
+ qt_build_internals_set_up_system_prefixes()
+ endif()
+endmacro()
+
+macro(qt_internal_setup_standalone_test_when_called_as_a_find_package_component)
+ 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()
+endmacro()
+
+macro(qt_internal_setup_build_internals)
+ qt_internal_set_qt_repo_dependencies()
+ qt_internal_setup_platform_support_variables()
+ qt_internal_setup_pkg_config_and_system_prefixes()
+ qt_internal_setup_standalone_test_when_called_as_a_find_package_component()
+endmacro()
+
+# Recursively reads the dependencies section from dependencies.yaml in ${repo_dir} and returns the
+# list of dependencies, including transitive ones, in out_var.
+#
+# The returned dependencies are topologically sorted.
+#
+# Example output for qtdeclarative:
+# qtbase;qtimageformats;qtlanguageserver;qtshadertools;qtsvg
+#
+function(qt_internal_read_repo_dependencies out_var repo_dir)
+ set(seen ${ARGN})
+ set(dependencies "")
+ set(in_dependencies_section FALSE)
+ set(dependencies_file "${repo_dir}/dependencies.yaml")
+ if(EXISTS "${dependencies_file}")
+ file(STRINGS "${dependencies_file}" lines)
+ foreach(line IN LISTS lines)
+ if(line MATCHES "^([^ ]+):")
+ if(CMAKE_MATCH_1 STREQUAL "dependencies")
+ set(in_dependencies_section TRUE)
+ else()
+ set(in_dependencies_section FALSE)
+ endif()
+ elseif(in_dependencies_section AND line MATCHES "^ (.+):$")
+ set(dependency "${CMAKE_MATCH_1}")
+ set(dependency_repo_dir "${repo_dir}/${dependency}")
+ string(REGEX MATCH "[^/]+$" dependency "${dependency}")
+ if(NOT dependency IN_LIST seen)
+ qt_internal_read_repo_dependencies(subdeps "${dependency_repo_dir}"
+ ${seen} ${dependency})
+ if(dependency MATCHES "^tqtc-(.+)")
+ set(dependency "${CMAKE_MATCH_1}")
+ endif()
+ list(APPEND dependencies ${subdeps} ${dependency})
+ endif()
+ endif()
+ endforeach()
+ list(REMOVE_DUPLICATES dependencies)
+ endif()
+ set(${out_var} "${dependencies}" PARENT_SCOPE)
+endfunction()
+
+macro(qt_internal_set_qt_repo_dependencies)
+ # The top-level check needs to happen because it's possible
+ # to configure a top-level build with a few repos and then configure another repo
+ # using qt-configure-module in a separate build dir, where QT_SUPERBUILD will not
+ # be set anymore.
+ if(DEFINED QT_REPO_MODULE_VERSION AND NOT DEFINED QT_REPO_DEPENDENCIES AND NOT QT_SUPERBUILD)
+ qt_internal_read_repo_dependencies(QT_REPO_DEPENDENCIES "${PROJECT_SOURCE_DIR}")
+ endif()
+endmacro()
diff --git a/cmake/QtCMakeHelpers.cmake b/cmake/QtCMakeHelpers.cmake
index 142a003cbc..0fe95f32fd 100644
--- a/cmake/QtCMakeHelpers.cmake
+++ b/cmake/QtCMakeHelpers.cmake
@@ -61,14 +61,6 @@ macro(qt_parse_all_arguments result type flags options multiopts)
endif()
endmacro()
-# Checks whether any unparsed arguments have been passed to the function at the call site.
-# Use this right after `cmake_parse_arguments`.
-function(_qt_internal_validate_all_args_are_parsed prefix)
- if(DEFINED ${prefix}_UNPARSED_ARGUMENTS)
- message(FATAL_ERROR "Unknown arguments: (${${prefix}_UNPARSED_ARGUMENTS})")
- endif()
-endfunction()
-
# Print all variables defined in the current scope.
macro(qt_debug_print_variables)
cmake_parse_arguments(__arg "DEDUP" "" "MATCH;IGNORE" ${ARGN})
@@ -116,63 +108,12 @@ endmacro()
# Takes a list of path components and joins them into one path separated by forward slashes "/",
# and saves the path in out_var.
function(qt_path_join out_var)
- string(JOIN "/" path ${ARGN})
+ _qt_internal_path_join(path ${ARGN})
set(${out_var} ${path} PARENT_SCOPE)
endfunction()
-# qt_remove_args can remove arguments from an existing list of function
-# arguments in order to pass a filtered list of arguments to a different function.
-# Parameters:
-# out_var: result of remove all arguments specified by ARGS_TO_REMOVE from ALL_ARGS
-# ARGS_TO_REMOVE: Arguments to remove.
-# ALL_ARGS: All arguments supplied to cmake_parse_arguments
-# from which ARGS_TO_REMOVE should be removed from. We require all the
-# arguments or we can't properly identify the range of the arguments detailed
-# in ARGS_TO_REMOVE.
-# ARGS: Arguments passed into the function, usually ${ARGV}
-#
-# E.g.:
-# We want to forward all arguments from foo to bar, execpt ZZZ since it will
-# trigger an error in bar.
-#
-# foo(target BAR .... ZZZ .... WWW ...)
-# bar(target BAR.... WWW...)
-#
-# function(foo target)
-# cmake_parse_arguments(PARSE_ARGV 1 arg "" "" "BAR;ZZZ;WWW")
-# qt_remove_args(forward_args
-# ARGS_TO_REMOVE ${target} ZZZ
-# ALL_ARGS ${target} BAR ZZZ WWW
-# ARGS ${ARGV}
-# )
-# bar(${target} ${forward_args})
-# endfunction()
-#
function(qt_remove_args out_var)
- cmake_parse_arguments(arg "" "" "ARGS_TO_REMOVE;ALL_ARGS;ARGS" ${ARGN})
- set(result ${arg_ARGS})
- foreach(arg IN LISTS arg_ARGS_TO_REMOVE)
- # find arg
- list(FIND result ${arg} find_result)
- if (NOT find_result EQUAL -1)
- # remove arg
- list(REMOVE_AT result ${find_result})
- list(LENGTH result result_len)
- if(find_result EQUAL result_len)
- # We removed the last argument, could have been an option keyword
- continue()
- endif()
- list(GET result ${find_result} arg_current)
- # remove values until we hit another arg or the end of the list
- while(NOT "${arg_current}" IN_LIST arg_ALL_ARGS AND find_result LESS result_len)
- list(REMOVE_AT result ${find_result})
- list(LENGTH result result_len)
- if (NOT find_result EQUAL result_len)
- list(GET result ${find_result} arg_current)
- endif()
- endwhile()
- endif()
- endforeach()
+ _qt_internal_remove_args(result ${ARGN})
set(${out_var} "${result}" PARENT_SCOPE)
endfunction()
diff --git a/cmake/QtCMakePackageVersionFile.cmake.in b/cmake/QtCMakePackageVersionFile.cmake.in
index 185bdb491f..d4c30b33ac 100644
--- a/cmake/QtCMakePackageVersionFile.cmake.in
+++ b/cmake/QtCMakePackageVersionFile.cmake.in
@@ -1,3 +1,6 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
# Include the basic version config file to get results of regular version checking.
include("${CMAKE_CURRENT_LIST_DIR}/@package_name@ConfigVersionImpl.cmake")
diff --git a/cmake/QtCMakeVersionHelpers.cmake b/cmake/QtCMakeVersionHelpers.cmake
index c17a75e29f..322e58eed1 100644
--- a/cmake/QtCMakeVersionHelpers.cmake
+++ b/cmake/QtCMakeVersionHelpers.cmake
@@ -14,6 +14,8 @@ function(qt_internal_get_supported_min_cmake_version_for_building_qt out_var)
set(supported_version "${QT_SUPPORTED_MIN_CMAKE_VERSION_FOR_BUILDING_QT}")
# We're building qtbase so the values come from .cmake.conf.
+ elseif(APPLE)
+ set(supported_version "${QT_SUPPORTED_MIN_CMAKE_VERSION_FOR_BUILDING_QT_APPLE}")
elseif(BUILD_SHARED_LIBS)
set(supported_version "${QT_SUPPORTED_MIN_CMAKE_VERSION_FOR_BUILDING_QT_SHARED}")
else()
@@ -30,7 +32,9 @@ function(qt_internal_get_supported_min_cmake_version_for_using_qt out_var)
"It should have been set by this point.")
endif()
- if(BUILD_SHARED_LIBS)
+ if(APPLE)
+ set(supported_version "${QT_SUPPORTED_MIN_CMAKE_VERSION_FOR_USING_QT_APPLE}")
+ elseif(BUILD_SHARED_LIBS)
set(supported_version "${QT_SUPPORTED_MIN_CMAKE_VERSION_FOR_USING_QT_SHARED}")
else()
set(supported_version "${QT_SUPPORTED_MIN_CMAKE_VERSION_FOR_USING_QT_STATIC}")
diff --git a/cmake/QtCompilerFlags.cmake b/cmake/QtCompilerFlags.cmake
index 62bd63bd22..f58f36b7a2 100644
--- a/cmake/QtCompilerFlags.cmake
+++ b/cmake/QtCompilerFlags.cmake
@@ -8,18 +8,16 @@
# property checked below, and is equivalent to qmake's CONFIG += warn_off.
set(_qt_compiler_warning_flags_on "")
-set(_qt_compiler_warning_flags_off "")
+set(_qt_compiler_warning_flags_off -w)
if (MSVC)
list(APPEND _qt_compiler_warning_flags_on /W3)
- list(APPEND _qt_compiler_warning_flags_off -W0)
else()
if(CMAKE_CXX_COMPILER_ID STREQUAL "GHS") # There is no -Wextra flag for GHS compiler.
list(APPEND _qt_compiler_warning_flags_on -Wall)
else()
list(APPEND _qt_compiler_warning_flags_on -Wall -Wextra)
endif()
- list(APPEND _qt_compiler_warning_flags_off -w)
endif()
set(_qt_compiler_warning_flags_condition
@@ -27,8 +25,15 @@ set(_qt_compiler_warning_flags_condition
set(_qt_compiler_warning_flags_genex
"$<IF:${_qt_compiler_warning_flags_condition},${_qt_compiler_warning_flags_off},${_qt_compiler_warning_flags_on}>")
+set(_qt_compiler_warning_flags_language_condition
+ "$<COMPILE_LANGUAGE:CXX,C,OBJC,OBJCXX>")
+set(_qt_compiler_warning_flags_language_conditional_genex
+ "$<${_qt_compiler_warning_flags_language_condition}:${_qt_compiler_warning_flags_genex}>")
+
+
# Need to replace semicolons so that the list is not wrongly expanded in the add_compile_options
# call.
string(REPLACE ";" "$<SEMICOLON>"
- _qt_compiler_warning_flags_genex "${_qt_compiler_warning_flags_genex}")
-add_compile_options(${_qt_compiler_warning_flags_genex})
+ _qt_compiler_warning_flags_language_conditional_genex
+ "${_qt_compiler_warning_flags_language_conditional_genex}")
+add_compile_options(${_qt_compiler_warning_flags_language_conditional_genex})
diff --git a/cmake/QtCompilerOptimization.cmake b/cmake/QtCompilerOptimization.cmake
index b5b49ab78a..ac542e9451 100644
--- a/cmake/QtCompilerOptimization.cmake
+++ b/cmake/QtCompilerOptimization.cmake
@@ -35,35 +35,40 @@ if (MSVC)
endif()
if(GCC OR CLANG OR QCC)
- set(QT_CFLAGS_SSE2 "-msse2")
- set(QT_CFLAGS_SSE3 "-msse3")
- set(QT_CFLAGS_SSSE3 "-mssse3")
- set(QT_CFLAGS_SSE4_1 "-msse4.1")
- set(QT_CFLAGS_SSE4_2 "-msse4.2")
- set(QT_CFLAGS_F16C "-mf16c")
- set(QT_CFLAGS_RDRND "-mrdrnd")
- set(QT_CFLAGS_RDSEED "-mrdseed")
- set(QT_CFLAGS_AVX "-mavx")
- set(QT_CFLAGS_AVX2 "-mavx2")
- set(QT_CFLAGS_ARCH_HASWELL "-march=haswell")
- set(QT_CFLAGS_AVX512F "-mavx512f")
- set(QT_CFLAGS_AVX512ER "-mavx512er")
- set(QT_CFLAGS_AVX512CD "-mavx512cd")
- set(QT_CFLAGS_AVX512PF "-mavx512pf")
- set(QT_CFLAGS_AVX512DQ "-mavx512dq")
- set(QT_CFLAGS_AVX512BW "-mavx512bw")
- set(QT_CFLAGS_AVX512VL "-mavx512vl")
- set(QT_CFLAGS_AVX512IFMA "-mavx512ifma")
- set(QT_CFLAGS_AVX512VBMI "-mavx512vbmi")
- set(QT_CFLAGS_AVX512VBMI2 "-mavx512vbmi2")
- set(QT_CFLAGS_AESNI "-maes")
- set(QT_CFLAGS_SHANI "-msha")
- set(QT_CFLAGS_VAES "-mvaes")
+ set(__prefix)
+ if(MSVC AND CLANG)
+ set(__prefix "/clang:")
+ endif()
+ set(QT_CFLAGS_SSE2 "${__prefix}-msse2")
+ set(QT_CFLAGS_SSE3 "${__prefix}-msse3")
+ set(QT_CFLAGS_SSSE3 "${__prefix}-mssse3")
+ set(QT_CFLAGS_SSE4_1 "${__prefix}-msse4.1")
+ set(QT_CFLAGS_SSE4_2 "${__prefix}-msse4.2")
+ set(QT_CFLAGS_F16C "${__prefix}-mf16c")
+ set(QT_CFLAGS_RDRND "${__prefix}-mrdrnd")
+ set(QT_CFLAGS_RDSEED "${__prefix}-mrdseed")
+ set(QT_CFLAGS_AVX "${__prefix}-mavx")
+ set(QT_CFLAGS_AVX2 "${__prefix}-mavx2")
+ set(QT_CFLAGS_ARCH_HASWELL "${__prefix}-march=haswell")
+ set(QT_CFLAGS_AVX512F "${__prefix}-mavx512f")
+ set(QT_CFLAGS_AVX512ER "${__prefix}-mavx512er")
+ set(QT_CFLAGS_AVX512CD "${__prefix}-mavx512cd")
+ set(QT_CFLAGS_AVX512PF "${__prefix}-mavx512pf")
+ set(QT_CFLAGS_AVX512DQ "${__prefix}-mavx512dq")
+ set(QT_CFLAGS_AVX512BW "${__prefix}-mavx512bw")
+ set(QT_CFLAGS_AVX512VL "${__prefix}-mavx512vl")
+ set(QT_CFLAGS_AVX512IFMA "${__prefix}-mavx512ifma")
+ set(QT_CFLAGS_AVX512VBMI "${__prefix}-mavx512vbmi")
+ set(QT_CFLAGS_AVX512VBMI2 "${__prefix}-mavx512vbmi2")
+ set(QT_CFLAGS_AESNI "${__prefix}-maes")
+ set(QT_CFLAGS_SHANI "${__prefix}-msha")
+ set(QT_CFLAGS_VAES "${__prefix}-mvaes")
if(NOT UIKIT AND NOT QT_64BIT)
- set(QT_CFLAGS_NEON "-mfpu=neon")
+ set(QT_CFLAGS_NEON "${__prefix}-mfpu=neon")
endif()
- set(QT_CFLAGS_MIPS_DSP "-mdsp")
- set(QT_CFLAGS_MIPS_DSPR2 "-mdspr2")
+ set(QT_CFLAGS_MIPS_DSP "${__prefix}-mdsp")
+ set(QT_CFLAGS_MIPS_DSPR2 "${__prefix}-mdspr2")
+ unset(__prefix)
endif()
# Fall through is important, so that more specific flags that might be missing are set by the
@@ -93,9 +98,14 @@ endif()
# Windows MSVC
if(MSVC)
set(QT_CFLAGS_OPTIMIZE "-O2")
+ if(NOT CLANG)
+ # -Ob3 was introduced in Visual Studio 2019 version 16.0
+ # However clang-cl can't recognize it.
+ string(APPEND QT_CFLAGS_OPTIMIZE " -Ob3 ")
+ endif()
set(QT_CFLAGS_OPTIMIZE_DEBUG "-Od")
set(QT_CFLAGS_OPTIMIZE_SIZE "-O1")
- set(QT_CFLAGS_OPTIMIZE_VALID_VALUES "/O2" "/O1" "/Od" "/Ob0" "/Ob1" "/Ob2" "/O0" "-O0")
+ set(QT_CFLAGS_OPTIMIZE_VALID_VALUES "/O2" "/O1" "/Od" "/Ob0" "/Ob1" "/Ob2" "/Ob3" "/O0" "-O0")
if(CLANG)
set(QT_CFLAGS_OPTIMIZE_FULL "/clang:-O3")
@@ -124,5 +134,5 @@ endif()
# Emscripten Clang
if(WASM)
set(QT_CFLAGS_OPTIMIZE_DEBUG "-O2 -g") # -Og is not supported
- set(QT_CFLAGS_SSE2 -O2 -msimd128 -msse -msse2)
+ set(QT_CFLAGS_SSE2 "-O2 -msimd128 -msse -msse2")
endif()
diff --git a/cmake/QtConfig.cmake.in b/cmake/QtConfig.cmake.in
index 2e49828472..b5a21e391d 100644
--- a/cmake/QtConfig.cmake.in
+++ b/cmake/QtConfig.cmake.in
@@ -1,9 +1,15 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
@PACKAGE_INIT@
cmake_minimum_required(VERSION @min_new_policy_version@...@max_new_policy_version@)
include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@ConfigExtras.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/QtPublicCMakeVersionHelpers.cmake")
+include("${CMAKE_CURRENT_LIST_DIR}/QtPublicCMakeHelpers.cmake")
+include("${CMAKE_CURRENT_LIST_DIR}/QtInstallPaths.cmake")
+
__qt_internal_require_suitable_cmake_version_for_using_qt()
get_filename_component(_qt_cmake_dir "${CMAKE_CURRENT_LIST_DIR}/.." ABSOLUTE)
@@ -12,7 +18,11 @@ set(_qt_@PROJECT_VERSION_MAJOR@_config_cmake_dir "${CMAKE_CURRENT_LIST_DIR}")
if (NOT QT_NO_CREATE_TARGETS)
include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@Targets.cmake")
if(NOT QT_NO_CREATE_VERSIONLESS_TARGETS)
- include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@VersionlessTargets.cmake")
+ if(CMAKE_VERSION VERSION_LESS 3.18 OR QT_USE_OLD_VERSION_LESS_TARGETS)
+ include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@VersionlessTargets.cmake")
+ else()
+ include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@VersionlessAliasTargets.cmake")
+ endif()
endif()
else()
# For examples using `find_package(...)` inside their CMakeLists.txt files:
@@ -29,27 +39,27 @@ list(APPEND CMAKE_MODULE_PATH "${_qt_import_prefix}")
list(APPEND CMAKE_MODULE_PATH "${_qt_import_prefix}/3rdparty/extra-cmake-modules/find-modules")
list(APPEND CMAKE_MODULE_PATH "${_qt_import_prefix}/3rdparty/kwin")
-if(APPLE AND (NOT CMAKE_SYSTEM_NAME OR CMAKE_SYSTEM_NAME STREQUAL "Darwin"))
- # Add module directory to pick up custom Info.plist template for macOS
- list(APPEND CMAKE_MODULE_PATH "${_qt_import_prefix}/macos")
-elseif(APPLE AND CMAKE_SYSTEM_NAME STREQUAL "iOS")
- # Add module directory to pick up custom Info.plist template for iOS
- set(__qt_internal_cmake_ios_support_files_path "${_qt_import_prefix}/ios")
- list(APPEND CMAKE_MODULE_PATH "${__qt_internal_cmake_ios_support_files_path}")
+if(APPLE)
+ if(NOT CMAKE_SYSTEM_NAME OR CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+ set(__qt_internal_cmake_apple_support_files_path "${_qt_import_prefix}/macos")
+ elseif(CMAKE_SYSTEM_NAME STREQUAL "iOS")
+ set(__qt_internal_cmake_apple_support_files_path "${_qt_import_prefix}/ios")
+ elseif(CMAKE_SYSTEM_NAME STREQUAL "visionOS")
+ set(__qt_internal_cmake_apple_support_files_path "${_qt_import_prefix}/visionos")
+ endif()
endif()
# Public helpers available to all Qt packages.
-include("${CMAKE_CURRENT_LIST_DIR}/QtFeature.cmake")
-include("${CMAKE_CURRENT_LIST_DIR}/QtPublicAppleHelpers.cmake")
-include("${CMAKE_CURRENT_LIST_DIR}/QtPublicFinalizerHelpers.cmake")
-include("${CMAKE_CURRENT_LIST_DIR}/QtPublicPluginHelpers.cmake")
-include("${CMAKE_CURRENT_LIST_DIR}/QtPublicTargetHelpers.cmake")
-include("${CMAKE_CURRENT_LIST_DIR}/QtPublicWalkLibsHelpers.cmake")
-include("${CMAKE_CURRENT_LIST_DIR}/QtPublicFindPackageHelpers.cmake")
-include("${CMAKE_CURRENT_LIST_DIR}/QtPublicDependencyHelpers.cmake")
-include("${CMAKE_CURRENT_LIST_DIR}/QtPublicTestHelpers.cmake")
-include("${CMAKE_CURRENT_LIST_DIR}/QtPublicToolHelpers.cmake")
-include("${CMAKE_CURRENT_LIST_DIR}/QtPublicCMakeHelpers.cmake")
+set(__qt_public_files_to_include
+ @QT_PUBLIC_FILES_TO_INCLUDE@
+)
+foreach(__qt_public_file_to_include IN LISTS __qt_public_files_to_include)
+ include("${__qt_public_file_to_include}")
+endforeach()
+
+if(NOT DEFINED QT_CMAKE_EXPORT_NAMESPACE)
+ set(QT_CMAKE_EXPORT_NAMESPACE @QT_CMAKE_EXPORT_NAMESPACE@)
+endif()
set(QT_ADDITIONAL_PACKAGES_PREFIX_PATH "" CACHE STRING
"Additional directories where find(Qt6 ...) components are searched")
@@ -64,9 +74,7 @@ __qt_internal_collect_additional_prefix_paths(_qt_additional_host_packages_prefi
__qt_internal_prefix_paths_to_roots(_qt_additional_host_packages_root_paths
"${_qt_additional_host_packages_prefix_paths}")
-if(NOT DEFINED QT_CMAKE_EXPORT_NAMESPACE)
- set(QT_CMAKE_EXPORT_NAMESPACE @QT_CMAKE_EXPORT_NAMESPACE@)
-endif()
+__qt_internal_collect_additional_module_paths()
# Propagate sanitizer flags to both internal Qt builds and user projects.
# Allow opt-out in case if downstream projects handle it in a different way.
@@ -134,9 +142,9 @@ foreach(module ${@INSTALL_CMAKE_NAMESPACE@_FIND_COMPONENTS})
${@INSTALL_CMAKE_NAMESPACE@_FIND_VERSION}
${_@INSTALL_CMAKE_NAMESPACE@_FIND_PARTS_QUIET}
PATHS
+ ${QT_BUILD_CMAKE_PREFIX_PATH}
${_qt_cmake_dir}
${_qt_additional_packages_prefix_paths}
- ${QT_EXAMPLES_CMAKE_PREFIX_PATH}
${__qt_find_package_host_qt_path}
${_qt_additional_host_packages_prefix_paths}
${__qt_use_no_default_path_for_qt_packages}
diff --git a/cmake/QtConfigDependencies.cmake.in b/cmake/QtConfigDependencies.cmake.in
index c17ae28bac..9824f8525c 100644
--- a/cmake/QtConfigDependencies.cmake.in
+++ b/cmake/QtConfigDependencies.cmake.in
@@ -1,3 +1,6 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
set(@INSTALL_CMAKE_NAMESPACE@_FOUND FALSE)
set(__qt_platform_requires_host_info_package "@platform_requires_host_info_package@")
diff --git a/cmake/QtConfigExtras.cmake.in b/cmake/QtConfigExtras.cmake.in
index bde3460cdc..06acd33c82 100644
--- a/cmake/QtConfigExtras.cmake.in
+++ b/cmake/QtConfigExtras.cmake.in
@@ -1,2 +1,7 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
set(QT_SUPPORTED_MIN_CMAKE_VERSION_FOR_USING_QT "@supported_min_version_for_using_qt@")
set(QT_COMPUTED_MIN_CMAKE_VERSION_FOR_USING_QT "@computed_min_version_for_using_qt@")
+
+@QT_CONFIG_EXTRAS_CODE@
diff --git a/cmake/QtConfigureTimeExecutableCMakeLists.txt.in b/cmake/QtConfigureTimeExecutableCMakeLists.txt.in
index a36299706c..17acb37f0e 100644
--- a/cmake/QtConfigureTimeExecutableCMakeLists.txt.in
+++ b/cmake/QtConfigureTimeExecutableCMakeLists.txt.in
@@ -1,3 +1,6 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
cmake_minimum_required(VERSION 3.16)
project(@configure_time_target@ LANGUAGES CXX)
diff --git a/cmake/QtDocsHelpers.cmake b/cmake/QtDocsHelpers.cmake
index 48ed5a324b..8b631e88ca 100644
--- a/cmake/QtDocsHelpers.cmake
+++ b/cmake/QtDocsHelpers.cmake
@@ -21,12 +21,37 @@ function(qt_internal_add_docs)
# Function called from old generated CMakeLists.txt that was missing the target parameter
return()
endif()
- if(NOT ${ARGC} EQUAL 2)
- message(FATAL_ERROR "qt_add_docs called with the wrong number of arguments. Should be qt_add_docs(target path_to_project.qdocconf).")
+ set(error_msg "qt_add_docs called with wrong number of arguments. ")
+ list(APPEND error_msg
+ "Should be qt_add_docs\(target_name qdocconf "
+ "\[INDEX_DIRECTORIES EXTRA_INDEX_DIRS_LIST_TO_ENABLE_QDOC_RESOLVE_LINKS\]\)")
+ if(NOT ${ARGC} GREATER_EQUAL 2)
+ message(FATAL_ERROR ${error_msg})
return()
endif()
+
set(target ${ARGV0})
set(doc_project ${ARGV1})
+ set(qdoc_extra_args "")
+ # Check if there are more than 2 arguments and pass them
+ # as extra --indexdir arguments to qdoc in prepare and
+ # generate phases.
+ if (${ARGC} GREATER 2)
+ # The INDEX_DIRECTORIES key should enable passing a list of index
+ # directories as extra command-line arguments to qdoc.
+ set(qdocExtraArgs INDEX_DIRECTORIES)
+ cmake_parse_arguments(PARSE_ARGV 2 arg "" "" "${qdocExtraArgs}")
+ if(arg_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR ${error_msg})
+ return()
+ endif()
+ if(arg_INDEX_DIRECTORIES)
+ foreach(index_directory ${arg_INDEX_DIRECTORIES})
+ list(APPEND qdoc_extra_args "--indexdir" ${index_directory})
+ endforeach()
+ endif()
+ endif()
+
# If a target is not built (which can happen for tools when crosscompiling), we shouldn't try
# to generate docs.
@@ -114,13 +139,14 @@ function(qt_internal_add_docs)
if(NOT QT_BUILD_ONLINE_DOCS)
list(PREPEND prepare_qdoc_args
-installdir "${QT_INSTALL_DIR}/${INSTALL_DOCDIR}"
+ ${qdoc_extra_args}
)
endif()
- if(QT_SUPERBUILD)
+ if(DEFINED ENV{QT_INSTALL_DOCS})
+ set(qt_install_docs_env "$ENV{QT_INSTALL_DOCS}")
+ elseif(QT_SUPERBUILD OR "${PROJECT_NAME}" STREQUAL "QtBase")
set(qt_install_docs_env "${QtBase_BINARY_DIR}/${INSTALL_DOCDIR}")
- elseif(QT_WILL_INSTALL)
- set(qt_install_docs_env "${CMAKE_INSTALL_PREFIX}/${INSTALL_DOCDIR}")
else()
set(qt_install_docs_env "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}/${INSTALL_DOCDIR}")
endif()
@@ -156,6 +182,7 @@ function(qt_internal_add_docs)
if(NOT QT_BUILD_ONLINE_DOCS)
list(PREPEND generate_qdoc_args
-installdir "${QT_INSTALL_DIR}/${INSTALL_DOCDIR}"
+ ${qdoc_extra_args}
)
endif()
diff --git a/cmake/QtExecutableHelpers.cmake b/cmake/QtExecutableHelpers.cmake
index 5efeb2a245..08da17b7e0 100644
--- a/cmake/QtExecutableHelpers.cmake
+++ b/cmake/QtExecutableHelpers.cmake
@@ -30,6 +30,7 @@ function(qt_internal_add_executable name)
endif()
_qt_internal_create_executable(${name})
+ qt_internal_mark_as_internal_target(${name})
if(ANDROID)
_qt_internal_android_executable_finalizer(${name})
endif()
@@ -64,12 +65,12 @@ function(qt_internal_add_executable name)
QT_DELAYED_TARGET_COPYRIGHT "${arg_TARGET_COPYRIGHT}"
)
else()
- if("${arg_TARGET_DESCRIPTION}" STREQUAL "")
+ if(NOT arg_TARGET_DESCRIPTION)
set(arg_TARGET_DESCRIPTION "Qt ${name}")
endif()
qt_set_target_info_properties(${name} ${ARGN}
- TARGET_DESCRIPTION "${arg_TARGET_DESCRIPTION}"
- TARGET_VERSION "${arg_VERSION}")
+ TARGET_DESCRIPTION ${arg_TARGET_DESCRIPTION}
+ TARGET_VERSION ${arg_VERSION})
endif()
if (WIN32 AND NOT arg_DELAY_RC)
@@ -116,14 +117,11 @@ function(qt_internal_add_executable name)
set(arg_NO_UNITY_BUILD "")
endif()
- if(arg_NO_UNITY_BUILD_SOURCES)
- set(arg_NO_UNITY_BUILD_SOURCES "NO_UNITY_BUILD_SOURCES ${arg_NO_UNITY_BUILD_SOURCES}")
- else()
- set(arg_NO_UNITY_BUILD_SOURCES "")
- endif()
-
qt_internal_extend_target("${name}"
+ ${arg_NO_UNITY_BUILD}
SOURCES ${arg_SOURCES}
+ NO_PCH_SOURCES ${arg_NO_PCH_SOURCES}
+ NO_UNITY_BUILD_SOURCES ${arg_NO_UNITY_BUILD_SOURCES}
INCLUDE_DIRECTORIES ${private_includes}
DEFINES ${arg_DEFINES}
LIBRARIES
@@ -140,8 +138,6 @@ function(qt_internal_add_executable name)
MOC_OPTIONS ${arg_MOC_OPTIONS}
ENABLE_AUTOGEN_TOOLS ${arg_ENABLE_AUTOGEN_TOOLS}
DISABLE_AUTOGEN_TOOLS ${arg_DISABLE_AUTOGEN_TOOLS}
- ${arg_NO_UNITY_BUILD_SOURCES}
- ${arg_NO_UNITY_BUILD}
)
set_target_properties("${name}" PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${arg_OUTPUT_DIRECTORY}"
@@ -150,12 +146,7 @@ function(qt_internal_add_executable name)
MACOSX_BUNDLE "${arg_GUI}"
)
- if(WASM)
- # WASM unconditionally sets DISABLE_EXCEPTION_CATCHING=1
- qt_internal_set_exceptions_flags("${name}" NO_EXCEPTIONS)
- else()
- qt_internal_set_exceptions_flags("${name}" ${arg_EXCEPTIONS})
- endif()
+ qt_internal_set_exceptions_flags("${name}" ${arg_EXCEPTIONS})
if(WASM)
qt_internal_wasm_add_finalizers("${name}")
@@ -186,7 +177,7 @@ function(qt_internal_add_executable name)
qt_get_install_target_default_args(
OUT_VAR install_targets_default_args
CMAKE_CONFIG "${cmake_config}"
- ALL_CMAKE_CONFIGS "${cmake_configs}"
+ ALL_CMAKE_CONFIGS ${cmake_configs}
RUNTIME "${arg_INSTALL_DIRECTORY}"
LIBRARY "${arg_INSTALL_DIRECTORY}"
BUNDLE "${arg_INSTALL_DIRECTORY}")
@@ -216,103 +207,6 @@ function(qt_internal_add_executable name)
ADDITIONAL_INSTALL_ARGS ${additional_install_args})
qt_internal_install_pdb_files(${name} "${arg_INSTALL_DIRECTORY}")
endif()
-
- # If linking against Gui, make sure to also build the default QPA plugin.
- # This makes the experience of an initial Qt configuration to build and run one single
- # test / executable nicer.
- get_target_property(linked_libs "${name}" LINK_LIBRARIES)
- if("Qt::Gui" IN_LIST linked_libs AND TARGET qpa_default_plugins)
- add_dependencies("${name}" qpa_default_plugins)
- endif()
-
- # For static plugins, we need to explicitly link to plugins we want to be
- # loaded with the executable. User projects get that automatically, but
- # for tools built as part of Qt, we can't use that mechanism because it
- # would pollute the targets we export as part of an install and lead to
- # circular dependencies. The logic here is a simpler equivalent of the
- # more dynamic logic in QtPlugins.cmake.in, but restricted to only
- # adding plugins that are provided by the same module as the module
- # libraries the executable links to.
- set(libs
- ${arg_LIBRARIES}
- ${arg_PUBLIC_LIBRARIES}
- ${extra_libraries}
- Qt::PlatformCommonInternal
- )
-
- set(deduped_libs "")
- foreach(lib IN LISTS libs)
- if(NOT TARGET "${lib}")
- continue()
- endif()
-
- # Normalize module by stripping any leading "Qt::", because properties are set on the
- # versioned target (either Gui when building the module, or Qt6::Gui when it's
- # imported).
- if(lib MATCHES "Qt::([-_A-Za-z0-9]+)")
- set(new_lib "${QT_CMAKE_EXPORT_NAMESPACE}::${CMAKE_MATCH_1}")
- if(TARGET "${new_lib}")
- set(lib "${new_lib}")
- endif()
- endif()
-
- # Unalias the target.
- get_target_property(aliased_target ${lib} ALIASED_TARGET)
- if(aliased_target)
- set(lib ${aliased_target})
- endif()
-
- list(APPEND deduped_libs "${lib}")
- endforeach()
-
- list(REMOVE_DUPLICATES deduped_libs)
-
- foreach(lib IN LISTS deduped_libs)
- string(MAKE_C_IDENTIFIER "${name}_plugin_imports_${lib}" out_file)
- string(APPEND out_file .cpp)
-
- # Initialize plugins that are built in the same repository as the Qt module 'lib'.
- set(class_names_regular
- "$<GENEX_EVAL:$<TARGET_PROPERTY:${lib},_qt_initial_repo_plugin_class_names>>")
-
- # Initialize plugins that are built in the current Qt repository, but are associated
- # with a Qt module from a different repository (qtsvg's QSvgPlugin associated with
- # qtbase's QtGui).
- string(MAKE_C_IDENTIFIER "${PROJECT_NAME}" current_project_name)
- set(prop_prefix "_qt_repo_${current_project_name}")
- set(class_names_current_project
- "$<GENEX_EVAL:$<TARGET_PROPERTY:${lib},${prop_prefix}_plugin_class_names>>")
-
- # Only add separator if first list is not empty, so we don't trigger the file generation
- # when all lists are empty.
- set(class_names_separator "$<$<NOT:$<STREQUAL:${class_names_regular},>>:;>" )
- set(class_names
- "${class_names_regular}${class_names_separator}${class_names_current_project}")
-
- set(out_file_path "${CMAKE_CURRENT_BINARY_DIR}/${out_file}")
-
- file(GENERATE OUTPUT "${out_file_path}" CONTENT
-"// This file is auto-generated. Do not edit.
-#include <QtPlugin>
-
-Q_IMPORT_PLUGIN($<JOIN:${class_names},)\nQ_IMPORT_PLUGIN(>)
-"
- CONDITION "$<NOT:$<STREQUAL:${class_names},>>"
- )
-
- # CMake versions earlier than 3.18.0 can't find the generated file for some reason,
- # failing at generation phase.
- # Explicitly marking the file as GENERATED fixes the issue.
- set_source_files_properties("${out_file_path}" PROPERTIES GENERATED TRUE)
-
- target_sources(${name} PRIVATE
- "$<$<NOT:$<STREQUAL:${class_names},>>:${out_file_path}>"
- )
- target_link_libraries(${name} PRIVATE
- "$<TARGET_PROPERTY:${lib},_qt_initial_repo_plugins>"
- "$<TARGET_PROPERTY:${lib},${prop_prefix}_plugins>")
- endforeach()
-
endfunction()
# This function compiles the target at configure time the very first time and creates the custom
@@ -375,6 +269,7 @@ function(qt_internal_add_configure_time_executable target)
set(target_binary_dir "${CMAKE_CURRENT_BINARY_DIR}/configure_time_bins")
if(arg_CONFIG)
set(CMAKE_TRY_COMPILE_CONFIGURATION "${arg_CONFIG}")
+ string(TOUPPER "_${arg_CONFIG}" config_suffix)
endif()
get_cmake_property(is_multi_config GENERATOR_IS_MULTI_CONFIG)
@@ -393,9 +288,15 @@ function(qt_internal_add_configure_time_executable target)
if(arg_INSTALL_DIRECTORY)
set(install_dir "${arg_INSTALL_DIRECTORY}")
endif()
+
+ set(output_directory_relative "${install_dir}")
set(output_directory "${QT_BUILD_DIR}/${install_dir}")
+
+ set(target_binary_path_relative
+ "${output_directory_relative}/${configuration_path}${target_binary}")
set(target_binary_path
"${output_directory}/${configuration_path}${target_binary}")
+
get_filename_component(target_binary_path "${target_binary_path}" ABSOLUTE)
if(NOT DEFINED arg_SOURCES)
@@ -408,7 +309,7 @@ function(qt_internal_add_configure_time_executable target)
set(timestamp_file "${target_binary_dir}/${target_binary}_timestamp")
add_custom_command(OUTPUT "${target_binary_path}" "${timestamp_file}"
COMMAND
- ${CMAKE_COMMAND} --build "${target_binary_dir}" ${config_build_arg}
+ ${CMAKE_COMMAND} --build "${target_binary_dir}" --clean-first ${config_build_arg}
COMMAND
${CMAKE_COMMAND} -E touch "${timestamp_file}"
DEPENDS
@@ -425,7 +326,8 @@ function(qt_internal_add_configure_time_executable target)
)
set(should_build_at_configure_time TRUE)
- if(EXISTS "${target_binary_path}")
+ if(QT_INTERNAL_HAVE_CONFIGURE_TIME_${target} AND
+ EXISTS "${target_binary_path}" AND EXISTS "${timestamp_file}")
set(last_ts 0)
foreach(source IN LISTS sources)
file(TIMESTAMP "${source}" ts "%s")
@@ -440,6 +342,37 @@ function(qt_internal_add_configure_time_executable target)
endif()
endif()
+ set(cmake_flags_arg "")
+ if(arg_CMAKE_FLAGS)
+ set(cmake_flags_arg CMAKE_FLAGS "${arg_CMAKE_FLAGS}")
+ endif()
+
+ qt_internal_get_enabled_languages_for_flag_manipulation(enabled_languages)
+ foreach(lang IN LISTS enabled_languages)
+ set(compiler_flags_var "CMAKE_${lang}_FLAGS")
+ list(APPEND cmake_flags_arg "-D${compiler_flags_var}:STRING=${${compiler_flags_var}}")
+ if(arg_CONFIG)
+ set(compiler_flags_var_config "${compiler_flags_var}${config_suffix}")
+ list(APPEND cmake_flags_arg
+ "-D${compiler_flags_var_config}:STRING=${${compiler_flags_var_config}}")
+ endif()
+ endforeach()
+
+ qt_internal_get_target_link_types_for_flag_manipulation(target_link_types)
+ foreach(linker_type IN LISTS target_link_types)
+ set(linker_flags_var "CMAKE_${linker_type}_LINKER_FLAGS")
+ list(APPEND cmake_flags_arg "-D${linker_flags_var}:STRING=${${linker_flags_var}}")
+ if(arg_CONFIG)
+ set(linker_flags_var_config "${linker_flags_var}${config_suffix}")
+ list(APPEND cmake_flags_arg
+ "-D${linker_flags_var_config}:STRING=${${linker_flags_var_config}}")
+ endif()
+ endforeach()
+
+ if(NOT "${QT_INTERNAL_CMAKE_FLAGS_CONFIGURE_TIME_TOOL_${target}}" STREQUAL "${cmake_flags_arg}")
+ set(should_build_at_configure_time TRUE)
+ endif()
+
if(should_build_at_configure_time)
foreach(arg IN LISTS multi_value_args)
string(TOLOWER "${arg}" template_arg_name)
@@ -463,11 +396,12 @@ function(qt_internal_add_configure_time_executable target)
set(template "${arg_CMAKELISTS_TEMPLATE}")
endif()
- set(cmake_flags_arg)
- if(arg_CMAKE_FLAGS)
- set(cmake_flags_arg CMAKE_FLAGS "${arg_CMAKE_FLAGS}")
- endif()
configure_file("${template}" "${target_binary_dir}/CMakeLists.txt" @ONLY)
+
+ if(EXISTS "${target_binary_dir}/CMakeCache.txt")
+ file(REMOVE "${target_binary_dir}/CMakeCache.txt")
+ endif()
+
try_compile(result
"${target_binary_dir}"
"${target_binary_dir}"
@@ -476,6 +410,12 @@ function(qt_internal_add_configure_time_executable target)
OUTPUT_VARIABLE try_compile_output
)
+ set(QT_INTERNAL_CMAKE_FLAGS_CONFIGURE_TIME_TOOL_${target}
+ "${cmake_flags_arg}" CACHE INTERNAL "")
+
+ file(WRITE "${timestamp_file}" "")
+ set(QT_INTERNAL_HAVE_CONFIGURE_TIME_${target} ${result} CACHE INTERNAL
+ "Indicates that the configure-time target ${target} was built")
if(NOT result)
message(FATAL_ERROR "Unable to build ${target}: ${try_compile_output}")
endif()
@@ -485,7 +425,9 @@ function(qt_internal_add_configure_time_executable target)
add_executable(${QT_CMAKE_EXPORT_NAMESPACE}::${target} ALIAS ${target})
set_target_properties(${target} PROPERTIES
_qt_internal_configure_time_target TRUE
- IMPORTED_LOCATION "${target_binary_path}")
+ _qt_internal_configure_time_target_build_location "${target_binary_path_relative}"
+ IMPORTED_LOCATION "${target_binary_path}"
+ )
if(NOT arg_NO_INSTALL)
set_target_properties(${target} PROPERTIES
diff --git a/cmake/QtFeature.cmake b/cmake/QtFeature.cmake
index 199b844cf8..96cb308b2c 100644
--- a/cmake/QtFeature.cmake
+++ b/cmake/QtFeature.cmake
@@ -1,7 +1,6 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-include(QtFeatureCommon)
include(CheckCXXCompilerFlag)
function(qt_feature_module_begin)
@@ -81,45 +80,25 @@ function(qt_evaluate_to_boolean expressionVar)
endif()
endfunction()
-function(qt_evaluate_config_expression resultVar)
+function(qt_internal_evaluate_config_expression resultVar outIdx startIdx)
set(result "")
- set(nestingLevel 0)
- set(skipNext OFF)
set(expression "${ARGN}")
list(LENGTH expression length)
+ math(EXPR memberIdx "${startIdx} - 1")
math(EXPR length "${length}-1")
- foreach(memberIdx RANGE ${length})
- if(${skipNext})
- set(skipNext OFF)
- continue()
- endif()
-
+ while(memberIdx LESS ${length})
+ math(EXPR memberIdx "${memberIdx} + 1")
list(GET expression ${memberIdx} member)
if("${member}" STREQUAL "(")
- if(${nestingLevel} GREATER 0)
- list(APPEND result ${member})
- endif()
- math(EXPR nestingLevel "${nestingLevel} + 1")
- continue()
+ math(EXPR memberIdx "${memberIdx} + 1")
+ qt_internal_evaluate_config_expression(sub_result memberIdx ${memberIdx} ${expression})
+ list(APPEND result ${sub_result})
elseif("${member}" STREQUAL ")")
- math(EXPR nestingLevel "${nestingLevel} - 1")
- if(nestingLevel LESS 0)
- break()
- endif()
- if(${nestingLevel} EQUAL 0)
- qt_evaluate_config_expression(result ${result})
- else()
- list(APPEND result ${member})
- endif()
- continue()
- elseif(${nestingLevel} GREATER 0)
- list(APPEND result ${member})
- continue()
+ break()
elseif("${member}" STREQUAL "NOT")
list(APPEND result ${member})
- continue()
elseif("${member}" STREQUAL "AND")
qt_evaluate_to_boolean(result)
if(NOT ${result})
@@ -144,7 +123,7 @@ function(qt_evaluate_config_expression resultVar)
set(lhs "${${lhs}}")
math(EXPR rhsIndex "${memberIdx}+1")
- set(skipNext ON)
+ set(memberIdx ${rhsIndex})
list(GET expression ${rhsIndex} rhs)
# We can't pass through an empty string with double quotes through various
@@ -164,7 +143,7 @@ function(qt_evaluate_config_expression resultVar)
list(APPEND result ${member})
endif()
- endforeach()
+ endwhile()
# The 'TARGET Gui' case is handled by qt_evaluate_to_boolean, by passing those tokens verbatim
# to if().
@@ -174,18 +153,48 @@ function(qt_evaluate_config_expression resultVar)
qt_evaluate_to_boolean(result)
endif()
+ # When in recursion, we must skip to the next closing parenthesis on nesting level 0. The outIdx
+ # must point to the matching closing parenthesis, and that's not the case if we're early exiting
+ # in AND/OR.
+ if(startIdx GREATER 0)
+ set(nestingLevel 1)
+ while(TRUE)
+ list(GET expression ${memberIdx} member)
+ if("${member}" STREQUAL ")")
+ math(EXPR nestingLevel "${nestingLevel} - 1")
+ if(nestingLevel EQUAL 0)
+ break()
+ endif()
+ elseif("${member}" STREQUAL "(")
+ math(EXPR nestingLevel "${nestingLevel} + 1")
+ endif()
+ math(EXPR memberIdx "${memberIdx} + 1")
+ endwhile()
+ endif()
+
+ set(${outIdx} ${memberIdx} PARENT_SCOPE)
set(${resultVar} ${result} PARENT_SCOPE)
endfunction()
-function(_qt_internal_dump_expression_values expression_dump expression)
- set(dump "")
- set(skipNext FALSE)
- set(isTargetExpression FALSE)
+function(qt_evaluate_config_expression resultVar)
+ qt_internal_evaluate_config_expression(result unused 0 ${ARGN})
+ set("${resultVar}" "${result}" PARENT_SCOPE)
+endfunction()
+function(_qt_internal_get_feature_condition_keywords out_var)
set(keywords "EQUAL" "LESS" "LESS_EQUAL" "GREATER" "GREATER_EQUAL" "STREQUAL" "STRLESS"
"STRLESS_EQUAL" "STRGREATER" "STRGREATER_EQUAL" "VERSION_EQUAL" "VERSION_LESS"
"VERSION_LESS_EQUAL" "VERSION_GREATER" "VERSION_GREATER_EQUAL" "MATCHES"
"EXISTS" "COMMAND" "DEFINED" "NOT" "AND" "OR" "TARGET" "EXISTS" "IN_LIST" "(" ")")
+ set(${out_var} "${keywords}" PARENT_SCOPE)
+endfunction()
+
+function(_qt_internal_dump_expression_values expression_dump expression)
+ set(dump "")
+ set(skipNext FALSE)
+ set(isTargetExpression FALSE)
+
+ _qt_internal_get_feature_condition_keywords(keywords)
list(LENGTH expression length)
math(EXPR length "${length}-1")
@@ -239,19 +248,44 @@ endfunction()
# ${computed} is also stored when reconfiguring and the condition does not align with the user
# provided value.
#
-function(qt_feature_check_and_save_user_provided_value resultVar feature condition computed label)
+function(qt_feature_check_and_save_user_provided_value
+ resultVar feature condition condition_expression computed label)
if (DEFINED "FEATURE_${feature}")
# Revisit new user provided value
set(user_value "${FEATURE_${feature}}")
- string(TOUPPER "${user_value}" result)
+ string(TOUPPER "${user_value}" user_value_upper)
+ set(result "${user_value_upper}")
- # If the build is marked as dirty and the user_value doesn't meet the new condition,
- # reset it to the computed one.
+ # If ${feature} depends on another dirty feature, reset the ${feature} value to
+ # ${computed}.
get_property(dirty_build GLOBAL PROPERTY _qt_dirty_build)
- if(NOT condition AND result AND dirty_build)
- set(result "${computed}")
- message(WARNING "Reset FEATURE_${feature} value to ${result}, because it doesn't \
-meet its condition after reconfiguration.")
+ if(dirty_build)
+ _qt_internal_feature_compute_feature_dependencies(deps "${feature}")
+ if(deps)
+ get_property(dirty_features GLOBAL PROPERTY _qt_dirty_features)
+ foreach(dirty_feature ${dirty_features})
+ if(dirty_feature IN_LIST deps AND NOT "${result}" STREQUAL "${computed}")
+ set(result "${computed}")
+ message(WARNING
+ "Auto-resetting 'FEATURE_${feature}' from '${user_value_upper}' to "
+ "'${computed}', "
+ "because the dependent feature '${dirty_feature}' was marked dirty.")
+
+ # Append ${feature} as a new dirty feature.
+ set_property(GLOBAL APPEND PROPERTY _qt_dirty_features "${feature}")
+ break()
+ endif()
+ endforeach()
+ endif()
+
+ # If the build is marked as dirty and the feature doesn't meet its condition,
+ # reset its value to the computed one, which is likely OFF.
+ if(NOT condition AND result)
+ set(result "${computed}")
+ message(WARNING "Resetting 'FEATURE_${feature}' from '${user_value_upper}' to "
+ "'${computed}' because it doesn't meet its condition after reconfiguration. "
+ "Condition expression is: '${condition_expression}'")
+ endif()
endif()
set(bool_values OFF NO FALSE N ON YES TRUE Y)
@@ -299,13 +333,21 @@ condition:\n ${conditionString}\nCondition values dump:\n ${conditionDump}
set(QT_KNOWN_FEATURES "${QT_KNOWN_FEATURES}" CACHE INTERNAL "" FORCE)
endmacro()
+macro(_qt_internal_parse_feature_definition feature)
+ cmake_parse_arguments(arg
+ "PRIVATE;PUBLIC"
+ "LABEL;PURPOSE;SECTION;"
+ "AUTODETECT;CONDITION;ENABLE;DISABLE;EMIT_IF"
+ ${_QT_FEATURE_DEFINITION_${feature}})
+endmacro()
+
# The build system stores 2 CMake cache variables for each feature, to allow detecting value changes
# during subsequent reconfigurations.
#
#
# `FEATURE_foo` stores the user provided feature value for the current configuration run.
-# It can be set directly by the user, or derived from INPUT_foo (also set by the user).
+# It can be set directly by the user.
#
# If a value is not provided on initial configuration, the value will be auto-computed based on the
# various conditions of the feature.
@@ -334,9 +376,7 @@ function(qt_evaluate_feature feature)
message(FATAL_ERROR "Attempting to evaluate feature ${feature} but its definition is missing. Either the feature does not exist or a dependency to the module that defines it is missing")
endif()
- cmake_parse_arguments(arg
- "PRIVATE;PUBLIC"
- "LABEL;PURPOSE;SECTION;" "AUTODETECT;CONDITION;ENABLE;DISABLE;EMIT_IF" ${_QT_FEATURE_DEFINITION_${feature}})
+ _qt_internal_parse_feature_definition("${feature}")
if("${arg_ENABLE}" STREQUAL "")
set(arg_ENABLE OFF)
@@ -374,17 +414,6 @@ function(qt_evaluate_feature feature)
qt_evaluate_config_expression(emit_if ${arg_EMIT_IF})
endif()
- # If FEATURE_ is not defined trying to use INPUT_ variable to enable/disable feature.
- if ((NOT DEFINED "FEATURE_${feature}") 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()
- endif()
-
# Warn about a feature which is not emitted, but the user explicitly provided a value for it.
if(NOT emit_if AND DEFINED FEATURE_${feature})
set(msg "")
@@ -401,7 +430,8 @@ function(qt_evaluate_feature feature)
# Only save the user provided value if the feature was emitted.
if(emit_if)
qt_feature_check_and_save_user_provided_value(
- saved_user_value "${feature}" "${condition}" "${computed}" "${arg_LABEL}")
+ saved_user_value
+ "${feature}" "${condition}" "${arg_CONDITION}" "${computed}" "${arg_LABEL}")
else()
# Make sure the feature internal value is OFF if not emitted.
set(saved_user_value OFF)
@@ -414,6 +444,60 @@ function(qt_evaluate_feature feature)
set(QT_FEATURE_LABEL_${feature} "${arg_LABEL}" CACHE INTERNAL "")
endfunction()
+# Collect feature names that ${feature} depends on, by inspecting the given expression.
+function(_qt_internal_feature_extract_feature_dependencies_from_expression out_var expression)
+ list(LENGTH expression length)
+ math(EXPR length "${length}-1")
+
+ if(length LESS 0)
+ set(${out_var} "" PARENT_SCOPE)
+ return()
+ endif()
+
+ set(deps "")
+
+ foreach(memberIdx RANGE ${length})
+ list(GET expression ${memberIdx} member)
+ if(member MATCHES "^QT_FEATURE_(.+)")
+ list(APPEND deps "${CMAKE_MATCH_1}")
+ endif()
+ endforeach()
+ set(${out_var} "${deps}" PARENT_SCOPE)
+endfunction()
+
+# Collect feature names that ${feature} depends on, based on feature names that appear
+# in the ${feature}'s condition expressions.
+function(_qt_internal_feature_compute_feature_dependencies out_var feature)
+ # Only compute the deps once per feature.
+ get_property(deps_computed GLOBAL PROPERTY _qt_feature_deps_computed_${feature})
+ if(deps_computed)
+ get_property(deps GLOBAL PROPERTY _qt_feature_deps_${feature})
+ set(${out_var} "${deps}" PARENT_SCOPE)
+ return()
+ endif()
+
+ _qt_internal_parse_feature_definition("${feature}")
+
+ set(options_to_check AUTODETECT CONDITION ENABLE DISABLE EMIT_IF)
+ set(deps "")
+
+ # Go through each option that takes condition expressions and collect the feature names.
+ foreach(option ${options_to_check})
+ set(option_value "${arg_${option}}")
+ if(option_value)
+ _qt_internal_feature_extract_feature_dependencies_from_expression(
+ option_deps "${option_value}")
+ if(option_deps)
+ list(APPEND deps ${option_deps})
+ endif()
+ endif()
+ endforeach()
+
+ set_property(GLOBAL PROPERTY _qt_feature_deps_computed_${feature} TRUE)
+ set_property(GLOBAL PROPERTY _qt_feature_deps_${feature} "${deps}")
+ set(${out_var} "${deps}" PARENT_SCOPE)
+endfunction()
+
function(qt_feature_config feature config_var_name)
qt_feature_normalize_name("${feature}" feature)
cmake_parse_arguments(PARSE_ARGV 2 arg
@@ -786,6 +870,40 @@ function(qt_feature_copy_global_config_features_to_core target)
endif()
endfunction()
+function(qt_internal_detect_dirty_features)
+ # We need to clean up QT_FEATURE_*, but only once per configuration cycle
+ get_property(qt_feature_clean GLOBAL PROPERTY _qt_feature_clean)
+ if(NOT qt_feature_clean AND NOT QT_NO_FEATURE_AUTO_RESET)
+ message(STATUS "Checking for feature set changes")
+ set_property(GLOBAL PROPERTY _qt_feature_clean TRUE)
+ foreach(feature ${QT_KNOWN_FEATURES})
+ if(DEFINED "FEATURE_${feature}" AND
+ NOT "${QT_FEATURE_${feature}}" STREQUAL "${FEATURE_${feature}}")
+ message(" '${feature}' was changed from ${QT_FEATURE_${feature}} "
+ "to ${FEATURE_${feature}}")
+ set(dirty_build TRUE)
+ set_property(GLOBAL APPEND PROPERTY _qt_dirty_features "${feature}")
+ endif()
+ unset("QT_FEATURE_${feature}" CACHE)
+ endforeach()
+
+ set(QT_KNOWN_FEATURES "" CACHE INTERNAL "" FORCE)
+
+ if(dirty_build)
+ set_property(GLOBAL PROPERTY _qt_dirty_build TRUE)
+ message(WARNING
+ "Due to detected feature set changes, dependent features "
+ "will be re-computed automatically. This might cause a lot of files to be rebuilt. "
+ "To disable this behavior, configure with -DQT_NO_FEATURE_AUTO_RESET=ON")
+ endif()
+ endif()
+endfunction()
+
+# Builds either a string of source code or a whole project to determine whether the build is
+# successful.
+#
+# Sets a TEST_${name}_OUTPUT variable with the build output, to the scope of the calling function.
+# Sets a TEST_${name} cache variable to either TRUE or FALSE if the build is successful or not.
function(qt_config_compile_test name)
if(DEFINED "TEST_${name}")
return()
@@ -908,8 +1026,11 @@ function(qt_config_compile_test name)
get_filename_component(arg_PROJECT_PATH "${arg_PROJECT_PATH}" REALPATH)
endif()
- try_compile(HAVE_${name} "${CMAKE_BINARY_DIR}/config.tests/${name}" "${arg_PROJECT_PATH}"
- "${name}" CMAKE_FLAGS ${flags} ${arg_CMAKE_FLAGS})
+ try_compile(
+ HAVE_${name} "${CMAKE_BINARY_DIR}/config.tests/${name}" "${arg_PROJECT_PATH}" "${name}"
+ CMAKE_FLAGS ${flags} ${arg_CMAKE_FLAGS}
+ OUTPUT_VARIABLE try_compile_output
+ )
if(${HAVE_${name}})
set(status_label "Success")
@@ -954,7 +1075,7 @@ function(qt_config_compile_test name)
set(CMAKE_REQUIRED_FLAGS ${arg_COMPILE_OPTIONS})
# Pass -stdlib=libc++ on if necessary
- if (INPUT_stdlib_libcpp OR QT_FEATURE_stdlib_libcpp)
+ if (QT_FEATURE_stdlib_libcpp)
list(APPEND CMAKE_REQUIRED_FLAGS "-stdlib=libc++")
endif()
@@ -975,7 +1096,19 @@ function(qt_config_compile_test name)
set(_save_CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES}")
set(CMAKE_REQUIRED_LIBRARIES "${arg_LIBRARIES}")
- check_cxx_source_compiles("${arg_UNPARSED_ARGUMENTS} ${arg_CODE}" HAVE_${name})
+
+ # OUTPUT_VARIABLE is an internal undocumented variable of check_cxx_source_compiles
+ # since 3.23. Allow an opt out in case this breaks in the future.
+ set(try_compile_output "")
+ set(output_var "")
+ if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.23"
+ AND NOT QT_INTERNAL_NO_TRY_COMPILE_OUTPUT_VARIABLE)
+ set(output_var OUTPUT_VARIABLE try_compile_output)
+ endif()
+
+ check_cxx_source_compiles(
+ "${arg_UNPARSED_ARGUMENTS} ${arg_CODE}" HAVE_${name} ${output_var}
+ )
set(CMAKE_REQUIRED_LIBRARIES "${_save_CMAKE_REQUIRED_LIBRARIES}")
set(CMAKE_C_STANDARD "${_save_CMAKE_C_STANDARD}")
@@ -987,6 +1120,7 @@ function(qt_config_compile_test name)
endif()
endif()
+ set(TEST_${name}_OUTPUT "${try_compile_output}" PARENT_SCOPE)
set(TEST_${name} "${HAVE_${name}}" CACHE INTERNAL "${arg_LABEL}")
endfunction()
@@ -1024,7 +1158,7 @@ function(qt_get_platform_try_compile_vars out_var)
list(APPEND flags "CMAKE_CXX_STANDARD_REQUIRED")
# Pass -stdlib=libc++ on if necessary
- if (INPUT_stdlib_libcpp OR QT_FEATURE_stdlib_libcpp)
+ if (QT_FEATURE_stdlib_libcpp)
if(CMAKE_CXX_FLAGS)
string(APPEND CMAKE_CXX_FLAGS " -stdlib=libc++")
else()
@@ -1058,8 +1192,8 @@ function(qt_get_platform_try_compile_vars out_var)
if(UIKIT)
# Specify the sysroot, but only if not doing a simulator_and_device build.
# So keep the sysroot empty for simulator_and_device builds.
- if(QT_UIKIT_SDK)
- list(APPEND flags_cmd_line "-DCMAKE_OSX_SYSROOT:STRING=${QT_UIKIT_SDK}")
+ if(QT_APPLE_SDK)
+ list(APPEND flags_cmd_line "-DCMAKE_OSX_SYSROOT:STRING=${QT_APPLE_SDK}")
endif()
endif()
if(QT_NO_USE_FIND_PACKAGE_SYSTEM_ENVIRONMENT_PATH)
@@ -1225,7 +1359,16 @@ function(qt_config_linker_supports_flag_test name)
endif()
cmake_parse_arguments(arg "" "LABEL;FLAG" "" ${ARGN})
- set(flags "-Wl,${arg_FLAG}")
+ if(GCC OR CLANG)
+ set(flags "-Wl,--fatal-warnings,${arg_FLAG}")
+ elseif(MSVC)
+ set(flags "${arg_FLAG}")
+ else()
+ # We don't know how to pass linker options in a way that
+ # it reliably fails, so assume the detection failed.
+ set(TEST_${name} "0" CACHE INTERNAL "${label}")
+ return()
+ endif()
# Pass the linker that the main project uses to the compile test.
qt_internal_get_active_linker_flags(linker_flags)
diff --git a/cmake/QtFindPackageHelpers.cmake b/cmake/QtFindPackageHelpers.cmake
index 407e41b833..af6057bf51 100644
--- a/cmake/QtFindPackageHelpers.cmake
+++ b/cmake/QtFindPackageHelpers.cmake
@@ -16,6 +16,15 @@ function(qt_find_package_promote_targets_to_global_scope target)
"qt_find_package_targets_dict" "promote_global")
endfunction()
+# As an optimization when using -developer-build, qt_find_package records which
+# packages were found during the initial configuration. Then on subsequent
+# reconfigurations it skips looking for packages that were not found on the
+# initial run.
+# For the build system to pick up a newly added qt_find_package call, you need to:
+# - Start with a clean build dir
+# - Or remove the <builddir>/CMakeCache.txt file and configure from scratch
+# - Or remove the QT_INTERNAL_PREVIOUSLY_FOUND_PACKAGES cache variable (by
+# editing CMakeCache.txt) and reconfigure.
macro(qt_find_package)
# Get the target names we expect to be provided by the package.
set(find_package_options CONFIG NO_MODULE MODULE REQUIRED)
@@ -41,10 +50,13 @@ macro(qt_find_package)
# Due to this behavior being different from what general CMake projects expect, it is only
# done for -developer-builds.
if(QT_INTERNAL_PREVIOUSLY_FOUND_PACKAGES AND
- NOT "${ARGV0}" IN_LIST QT_INTERNAL_PREVIOUSLY_FOUND_PACKAGES)
+ NOT "${ARGV0}" IN_LIST QT_INTERNAL_PREVIOUSLY_FOUND_PACKAGES
+ AND "${ARGV0}" IN_LIST QT_INTERNAL_PREVIOUSLY_SEARCHED_PACKAGES)
set(_qt_find_package_skip_find_package TRUE)
endif()
+ set_property(GLOBAL APPEND PROPERTY _qt_previously_searched_packages "${ARGV0}")
+
if(QT_DEBUG_QT_FIND_PACKAGE AND ${ARGV0}_FOUND AND arg_PROVIDED_TARGETS)
set(_qt_find_package_skip_find_package TRUE)
foreach(qt_find_package_target_name ${arg_PROVIDED_TARGETS})
@@ -178,6 +190,15 @@ macro(qt_find_package)
PROPERTIES INTERFACE_QT_PACKAGE_VERSION ${ARGV1})
endif()
+ # Save the retrieved package version.
+ set(_qt_find_package_found_version "")
+ if(${ARGV0}_VERSION)
+ set(_qt_find_package_found_version "${${ARGV0}_VERSION}")
+ set_target_properties(${qt_find_package_target_name}
+ PROPERTIES
+ _qt_package_found_version "${_qt_find_package_found_version}")
+ endif()
+
if(arg_COMPONENTS)
string(REPLACE ";" " " components_as_string "${arg_COMPONENTS}")
set_property(TARGET ${qt_find_package_target_name}
@@ -191,6 +212,18 @@ macro(qt_find_package)
${components_as_string})
endif()
+ # Work around: QTBUG-125371
+ if(NOT "${ARGV0}" STREQUAL "Qt6")
+ # Record the package + component + optional component provided targets.
+ qt_internal_record_package_component_provided_targets(
+ PACKAGE_NAME "${ARGV0}"
+ ON_TARGET ${qt_find_package_target_name}
+ PROVIDED_TARGETS ${arg_PROVIDED_TARGETS}
+ COMPONENTS ${arg_COMPONENTS}
+ OPTIONAL_COMPONENTS ${arg_OPTIONAL_COMPONENTS}
+ )
+ endif()
+
get_property(is_global TARGET ${qt_find_package_target_name} PROPERTY
IMPORTED_GLOBAL)
qt_internal_should_not_promote_package_target_to_global(
@@ -216,12 +249,62 @@ macro(qt_find_package)
endif()
endmacro()
+# Records information about a package's provided targets, given a specific list of components.
+#
+# A package might contain multiple components, and create only a subset of targets based on which
+# components are looked for.
+# This function computes a unique key / id using the package name and the components that are
+# passed.
+# Then it saves the id in a property on the ON_TARGET target. The ON_TARGET target is one
+# of the provided targets for that package id. This allows us to create a relationship to find
+# the package id, given a target.
+# The function also appends the list of provided targets for that package id to a global property.
+# This information will later be saved into the module Dependencies.cmake file.
+function(qt_internal_record_package_component_provided_targets)
+ set(opt_args "")
+ set(single_args
+ PACKAGE_NAME
+ ON_TARGET
+ )
+ set(multi_args
+ COMPONENTS
+ OPTIONAL_COMPONENTS
+ PROVIDED_TARGETS
+ )
+ cmake_parse_arguments(PARSE_ARGV 0 arg "${opt_args}" "${single_args}" "${multi_args}")
+ _qt_internal_validate_all_args_are_parsed(arg)
+
+ if(NOT arg_PACKAGE_NAME)
+ message(FATAL_ERROR "PACKAGE_NAME is required.")
+ endif()
+
+ if(NOT arg_ON_TARGET)
+ message(FATAL_ERROR "ON_TARGET is required.")
+ endif()
+
+ _qt_internal_get_package_components_id(
+ PACKAGE_NAME "${arg_PACKAGE_NAME}"
+ COMPONENTS ${arg_COMPONENTS}
+ OPTIONAL_COMPONENTS ${arg_OPTIONAL_COMPONENTS}
+ OUT_VAR_KEY package_key
+ )
+
+ set_target_properties(${arg_ON_TARGET} PROPERTIES
+ _qt_package_components_id "${package_key}"
+ )
+
+ _qt_internal_append_to_cmake_property_without_duplicates(
+ _qt_find_package_${package_key}_provided_targets
+ "${arg_PROVIDED_TARGETS}"
+ )
+endfunction()
+
# Save found packages in the cache. They will be read on next reconfiguration to skip looking
# for packages that were not previously found.
# Only applies to -developer-builds by default.
# Can also be opted in or opted out via QT_INTERNAL_SAVE_PREVIOUSLY_FOUND_PACKAGES.
# Opting out will need two reconfigurations to take effect.
-function(qt_internal_save_previously_found_packages)
+function(qt_internal_save_previously_visited_packages)
if(DEFINED QT_INTERNAL_SAVE_PREVIOUSLY_FOUND_PACKAGES)
set(should_save "${QT_INTERNAL_SAVE_PREVIOUSLY_FOUND_PACKAGES}")
else()
@@ -235,6 +318,7 @@ function(qt_internal_save_previously_found_packages)
if(NOT should_save)
# When the value is flipped to OFF, remove any previously saved packages.
unset(QT_INTERNAL_PREVIOUSLY_FOUND_PACKAGES CACHE)
+ unset(QT_INTERNAL_PREVIOUSLY_SEARCHED_PACKAGES CACHE)
return()
endif()
@@ -244,6 +328,15 @@ function(qt_internal_save_previously_found_packages)
set(QT_INTERNAL_PREVIOUSLY_FOUND_PACKAGES "${_qt_previously_found_packages}" CACHE INTERNAL
"List of CMake packages found during configuration using qt_find_package.")
endif()
+
+ get_property(_qt_previously_searched_packages GLOBAL PROPERTY _qt_previously_searched_packages)
+ if(_qt_previously_searched_packages)
+ list(REMOVE_DUPLICATES _qt_previously_searched_packages)
+ set(QT_INTERNAL_PREVIOUSLY_SEARCHED_PACKAGES
+ "${_qt_previously_searched_packages}" CACHE INTERNAL
+ "List of CMake packages searched during configuration using qt_find_package."
+ )
+ endif()
endfunction()
# Return qmake library name for the given target, e.g. return "vulkan" for "Vulkan::Vulkan".
@@ -493,8 +586,15 @@ function(qt_register_target_dependencies target public_libs private_libs)
endif()
foreach(lib IN LISTS lib_list)
- if ("${lib}" MATCHES "^Qt::(.*)")
+ if("${lib}" MATCHES "^Qt::(.*)")
+ set(lib "${CMAKE_MATCH_1}")
+ elseif("${lib}" MATCHES "^${QT_CMAKE_EXPORT_NAMESPACE}::(.*)")
set(lib "${CMAKE_MATCH_1}")
+ else()
+ set(lib "")
+ endif()
+
+ if(lib)
qt_internal_get_package_name_of_target("${lib}" package_name)
qt_internal_get_package_version_of_target("${lib}" package_version)
list(APPEND target_deps "${package_name}\;${package_version}")
@@ -510,8 +610,16 @@ function(qt_register_target_dependencies target public_libs private_libs)
# INTERFACE libraries. INTERFACE libraries in most cases will be FooPrivate libraries.
if(target_is_shared AND private_libs)
foreach(lib IN LISTS private_libs)
- if ("${lib}" MATCHES "^Qt::(.*)")
- set(lib_namespaced "${lib}")
+ set(lib_namespaced "${lib}")
+ if("${lib}" MATCHES "^Qt::(.*)")
+ set(lib "${CMAKE_MATCH_1}")
+ elseif("${lib}" MATCHES "^${QT_CMAKE_EXPORT_NAMESPACE}::(.*)")
+ set(lib "${CMAKE_MATCH_1}")
+ else()
+ set(lib "")
+ endif()
+
+ if(lib)
set(lib "${CMAKE_MATCH_1}")
qt_internal_is_lib_part_of_qt6_package("${lib}" is_part_of_qt6)
diff --git a/cmake/QtFindWrapConfigExtra.cmake.in b/cmake/QtFindWrapConfigExtra.cmake.in
index 6ecf43512c..d1706d7cab 100644
--- a/cmake/QtFindWrapConfigExtra.cmake.in
+++ b/cmake/QtFindWrapConfigExtra.cmake.in
@@ -1 +1,4 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
@extra_cmake_code@
diff --git a/cmake/QtFindWrapHelper.cmake b/cmake/QtFindWrapHelper.cmake
index a8d3da49d1..b17f2133bb 100644
--- a/cmake/QtFindWrapHelper.cmake
+++ b/cmake/QtFindWrapHelper.cmake
@@ -80,10 +80,39 @@ macro(qt_find_package_system_or_bundled _unique_prefix)
INTERFACE_QT_3RD_PARTY_PACKAGE_TYPE
"${${_unique_prefix}_qt_package_type}")
+
+ # This might not be set, because qt_find_package() is called from a configure.cmake file via
+ # qt_feature_evaluate_features, which means the _VERSION var is confined to the function
+ # scope.
+ if(${${_unique_prefix}_qt_package_name_to_use}_VERSION)
+ set(_qfwrap_${_unique_prefix}_package_version
+ "${${${_unique_prefix}_qt_package_name_to_use}_VERSION}"
+ )
+ else()
+ # We set this in qt_find_package, so try to retrieve it.
+ get_target_property(_qfwrap_${_unique_prefix}_package_version_from_prop
+ "${${_unique_prefix}_qt_package_target_to_use}" _qt_package_found_version)
+ if(_qfwrap_${_unique_prefix}_package_version_from_prop)
+ set(_qfwrap_${_unique_prefix}_package_version
+ "${_qfwrap_${_unique_prefix}_package_version_from_prop}"
+ )
+ else()
+ set(_qfwrap_${_unique_prefix}_package_version "")
+ endif()
+ endif()
+
+ if(_qfwrap_${_unique_prefix}_package_version)
+ set(_qfwrap_${_unique_prefix}_package_version_option
+ VERSION_VAR "_qfwrap_${_unique_prefix}_package_version"
+ )
+ endif()
+
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
Wrap${_qfwrap_${_unique_prefix}_FRIENDLY_PACKAGE_NAME}
- DEFAULT_MSG ${_qfwrap_${_unique_prefix}_WRAP_PACKAGE_FOUND_VAR_NAME})
+ REQUIRED_VARS ${_qfwrap_${_unique_prefix}_WRAP_PACKAGE_FOUND_VAR_NAME}
+ ${_qfwrap_${_unique_prefix}_package_version_option}
+ )
elseif(${_unique_prefix}_qt_package_type STREQUAL "bundled")
message(FATAL_ERROR "Can't find ${${_unique_prefix}_qt_package_target_to_use}.")
endif()
diff --git a/cmake/QtFlagHandlingHelpers.cmake b/cmake/QtFlagHandlingHelpers.cmake
index d8597326cc..251a356df0 100644
--- a/cmake/QtFlagHandlingHelpers.cmake
+++ b/cmake/QtFlagHandlingHelpers.cmake
@@ -1,6 +1,23 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+# Sets '${var}' to a genex that extracts the target's property.
+# Sets 'have_${var}' to a genex that checks that the property has a
+# non-empty value.
+macro(qt_internal_genex_get_property var target property)
+ set(${var} "$<TARGET_PROPERTY:${target},${property}>")
+ set(have_${var} "$<BOOL:${${var}}>")
+endmacro()
+
+# Sets '${var}' to a genex that will join the given property values
+# using '${glue}' and will surround the entire output with '${prefix}'
+# and '${suffix}'.
+macro(qt_internal_genex_get_joined_property var target property prefix suffix glue)
+ qt_internal_genex_get_property("${var}" "${target}" "${property}")
+ set(${var}
+ "$<${have_${var}}:${prefix}$<JOIN:${${var}},${glue}>${suffix}>")
+endmacro()
+
# This function generates LD version script for the target and uses it in the target linker line.
# Function has two modes dependending on the specified arguments.
# Arguments:
@@ -23,7 +40,40 @@ function(qt_internal_add_linker_version_script target)
endif()
if(TEST_ld_version_script)
- set(contents "Qt_${PROJECT_VERSION_MAJOR}_PRIVATE_API {\n qt_private_api_tag*;\n")
+ # Create a list of mangled symbol matches for all "std::" symbols. This
+ # list will catch most symbols, but will miss global-namespace symbols
+ # that only have std parameters.
+ # See https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangle.name for reference
+ set(contents "NonQt {\nlocal:")
+
+ # For types: vtable, VTT, typeinfo, typeinfo name
+ foreach(ptrqualifier "" "P" "PK") # T, T *, const T * (volatile ignored)
+ string(APPEND contents "\n _ZT[VTIS]${ptrqualifier}S*;"
+ "_ZT[VTIS]${ptrqualifier}NS*;")
+ endforeach()
+
+ # For functions and variables
+ foreach(special ""
+ "G[VR]" # guard variables, extended-lifetime references
+ "GTt") # transaction entry points
+ foreach(cvqualifier "" "[VK]" "VK") # plain, const|volatile, const volatile
+ string(APPEND contents "\n ")
+ foreach(refqualifier "" "[RO]") # plain, & or &&
+ # For names in the std:: namespace, compression applies
+ # (https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling-compression)
+ string(APPEND contents
+ " _Z${special}${cvqualifier}${refqualifier}S*;" # plain
+ " _Z${special}N${cvqualifier}${refqualifier}S*;" # nested name
+ )
+ endforeach()
+ endforeach()
+ endforeach()
+
+ string(APPEND contents "\n};\nQt_${PROJECT_VERSION_MAJOR}")
+ if(QT_FEATURE_elf_private_full_version)
+ string(APPEND contents ".${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
+ endif()
+ string(APPEND contents "_PRIVATE_API { qt_private_api_tag*;\n")
if(arg_PRIVATE_HEADERS)
foreach(ph ${arg_PRIVATE_HEADERS})
string(APPEND contents " @FILE:${ph}@\n")
@@ -33,22 +83,27 @@ function(qt_internal_add_linker_version_script target)
endif()
string(APPEND contents "};\n")
set(current "Qt_${PROJECT_VERSION_MAJOR}")
- if (QT_NAMESPACE STREQUAL "")
- set(tag_symbol "qt_version_tag")
- else()
- set(tag_symbol "qt_version_tag_${QT_NAMESPACE}")
+ string(APPEND contents "${current} {\n *;")
+
+ get_target_property(target_type ${target} TYPE)
+ if(NOT target_type STREQUAL "INTERFACE_LIBRARY")
+ set(genex_prefix "\n ")
+ set(genex_glue "$<SEMICOLON>\n ")
+ set(genex_suffix "$<SEMICOLON>")
+ qt_internal_genex_get_joined_property(
+ linker_exports "${target}" _qt_extra_linker_script_exports
+ "${genex_prefix}" "${genex_suffix}" "${genex_glue}"
+ )
+ string(APPEND contents "${linker_exports}")
+ endif()
+ string(APPEND contents "\n};\n")
+
+ if(NOT target_type STREQUAL "INTERFACE_LIBRARY")
+ set(property_genex "$<TARGET_PROPERTY:${target},_qt_extra_linker_script_content>")
+ set(check_genex "$<BOOL:${property_genex}>")
+ string(APPEND contents
+ "$<${check_genex}:${property_genex}>")
endif()
- string(APPEND contents "${current} { *; };\n")
-
- foreach(minor_version RANGE ${PROJECT_VERSION_MINOR})
- set(previous "${current}")
- set(current "Qt_${PROJECT_VERSION_MAJOR}.${minor_version}")
- if (minor_version EQUAL ${PROJECT_VERSION_MINOR})
- string(APPEND contents "${current} { ${tag_symbol}; } ${previous};\n")
- else()
- string(APPEND contents "${current} {} ${previous};\n")
- endif()
- endforeach()
set(infile "${CMAKE_CURRENT_BINARY_DIR}/${target}.version.in")
set(outfile "${CMAKE_CURRENT_BINARY_DIR}/${target}.version")
@@ -87,6 +142,17 @@ function(qt_internal_add_link_flags_no_undefined target)
if (NOT QT_BUILD_SHARED_LIBS OR WASM)
return()
endif()
+ if (VXWORKS)
+ # VxWorks requires thread_local-related symbols to be found at
+ # runtime, resulting in linker error when no-undefined flag is
+ # set and thread_local is used
+ return()
+ endif()
+ if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
+ # ld64 defaults to -undefined,error, and in Xcode 15
+ # passing this option is deprecated, causing a warning.
+ return()
+ endif()
if ((GCC OR CLANG) AND NOT MSVC)
if(CLANG AND QT_FEATURE_sanitizer)
return()
@@ -124,11 +190,20 @@ endfunction()
function(qt_internal_apply_gc_binaries target visibility)
set(possible_visibilities PRIVATE INTERFACE PUBLIC)
- list(FIND possible_visibilities "${visibility}" known_visibility)
- if (known_visibility EQUAL "-1")
+ if(NOT visibility IN_LIST possible_visibilities)
message(FATAL_ERROR "Visibitily setting must be one of PRIVATE, INTERFACE or PUBLIC.")
endif()
+ string(JOIN "" clang_or_gcc_begin
+ "$<$<OR:"
+ "$<CXX_COMPILER_ID:GNU>,"
+ "$<CXX_COMPILER_ID:Clang>,"
+ "$<CXX_COMPILER_ID:AppleClang>,"
+ "$<CXX_COMPILER_ID:IntelLLVM>"
+ ">:"
+ )
+ set(clang_or_gcc_end ">")
+
if ((GCC OR CLANG) AND NOT WASM AND NOT UIKIT AND NOT MSVC)
if(APPLE)
set(gc_sections_flag "-Wl,-dead_strip")
@@ -137,16 +212,26 @@ function(qt_internal_apply_gc_binaries target visibility)
elseif(LINUX OR BSD OR WIN32 OR ANDROID)
set(gc_sections_flag "-Wl,--gc-sections")
endif()
+
+ # Save the flag value with and without genex wrapping, so we can remove the wrapping
+ # when generating .pc pkgconfig files.
+ set_property(GLOBAL PROPERTY _qt_internal_gc_sections_without_genex "${gc_sections_flag}")
+
+ set(gc_sections_flag
+ "${clang_or_gcc_begin}${gc_sections_flag}${clang_or_gcc_end}")
+
+ set_property(GLOBAL PROPERTY _qt_internal_gc_sections_with_genex "${gc_sections_flag}")
endif()
if(gc_sections_flag)
target_link_options("${target}" ${visibility} "${gc_sections_flag}")
endif()
if((GCC OR CLANG) AND NOT WASM AND NOT UIKIT AND NOT MSVC)
- set(split_sections_flags "-ffunction-sections" "-fdata-sections")
+ set(split_sections_flags
+ "${clang_or_gcc_begin}-ffunction-sections;-fdata-sections${clang_or_gcc_end}")
endif()
if(split_sections_flags)
- target_compile_options("${target}" ${visibility} ${split_sections_flags})
+ target_compile_options("${target}" ${visibility} "${split_sections_flags}")
endif()
endfunction()
@@ -156,42 +241,23 @@ function(qt_internal_apply_intel_cet target visibility)
endif()
set(possible_visibilities PRIVATE INTERFACE PUBLIC)
- list(FIND possible_visibilities "${visibility}" known_visibility)
- if (known_visibility EQUAL "-1")
+ if(NOT visibility IN_LIST possible_visibilities)
message(FATAL_ERROR "Visibitily setting must be one of PRIVATE, INTERFACE or PUBLIC.")
endif()
if(GCC)
- set(flags "-mshstk")
+ string(JOIN "" flags
+ "$<$<OR:"
+ "$<CXX_COMPILER_ID:GNU>,"
+ "$<CXX_COMPILER_ID:Clang>,"
+ "$<CXX_COMPILER_ID:AppleClang>"
+ ">:-mshstk>")
endif()
if(flags)
target_compile_options("${target}" ${visibility} "${flags}")
endif()
endfunction()
-function(qt_internal_library_deprecation_level result)
- # QT_DISABLE_DEPRECATED_UP_TO controls which version we use as a cut-off
- # compiling in to the library. E.g. if it is set to QT_VERSION then no
- # code which was deprecated before QT_VERSION will be compiled in.
- if (NOT DEFINED QT_DISABLE_DEPRECATED_UP_TO)
- if(WIN32)
- # On Windows, due to the way DLLs work, we need to export all functions,
- # including the inlines
- list(APPEND deprecations "QT_DISABLE_DEPRECATED_UP_TO=0x040800")
- else()
- # On other platforms, Qt's own compilation does need to compile the Qt 5.0 API
- list(APPEND deprecations "QT_DISABLE_DEPRECATED_UP_TO=0x050000")
- endif()
- else()
- list(APPEND deprecations "QT_DISABLE_DEPRECATED_UP_TO=${QT_DISABLE_DEPRECATED_UP_TO}")
- endif()
- # QT_WARN_DEPRECATED_UP_TO controls the upper-bound of deprecation
- # warnings that are emitted. E.g. if it is set to 0x060500 then all use of
- # things deprecated in or before 6.5.0 will be warned against.
- list(APPEND deprecations "QT_WARN_DEPRECATED_UP_TO=0x070000")
- set("${result}" "${deprecations}" PARENT_SCOPE)
-endfunction()
-
# Sets the exceptions flags for the given target according to exceptions_on
function(qt_internal_set_exceptions_flags target exceptions_on)
set(_defs "")
@@ -200,21 +266,21 @@ function(qt_internal_set_exceptions_flags target exceptions_on)
if(MSVC)
set(_flag "/EHsc")
if((MSVC_VERSION GREATER_EQUAL 1929) AND NOT CLANG)
+ # Use the undocumented compiler flag to make our binary smaller on x64.
+ # https://devblogs.microsoft.com/cppblog/making-cpp-exception-handling-smaller-x64/
+ # NOTE: It seems we'll use this new exception handling model unconditionally without
+ # this hack since some unknown MSVC version.
set(_flag ${_flag} "/d2FH4")
endif()
+ else()
+ set(_flag "-fexceptions")
endif()
else()
set(_defs "QT_NO_EXCEPTIONS")
- if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
+ if(MSVC)
set(_flag "/EHs-c-" "/wd4530" "/wd4577")
- elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU|AppleClang|InteLLLVM")
+ else()
set(_flag "-fno-exceptions")
- elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
- if (MSVC)
- set(_flag "/EHs-c-" "/wd4530" "/wd4577")
- else()
- set(_flag "-fno-exceptions")
- endif()
endif()
endif()
@@ -287,14 +353,15 @@ function(qt_set_msvc_cplusplus_options target visibility)
# Check qt_config_compile_test for more info.
if(MSVC AND MSVC_VERSION GREATER_EQUAL 1913)
set(flags "-Zc:__cplusplus" "-permissive-")
- target_compile_options("${target}" ${visibility} "$<$<COMPILE_LANGUAGE:CXX>:${flags}>")
+ target_compile_options("${target}" ${visibility}
+ "$<$<AND:$<CXX_COMPILER_ID:MSVC>,$<COMPILE_LANGUAGE:CXX>>:${flags}>")
endif()
endfunction()
function(qt_enable_utf8_sources target)
set(utf8_flags "")
if(MSVC)
- list(APPEND utf8_flags "-utf-8")
+ list(APPEND utf8_flags "$<$<CXX_COMPILER_ID:MSVC>:-utf-8>")
endif()
if(utf8_flags)
@@ -314,7 +381,7 @@ function(qt_internal_enable_unicode_defines)
set(no_unicode_condition
"$<NOT:$<BOOL:$<TARGET_PROPERTY:QT_NO_UNICODE_DEFINES>>>")
target_compile_definitions(Platform
- INTERFACE "$<${no_unicode_condition}:UNICODE;_UNICODE>")
+ INTERFACE "$<${no_unicode_condition}:UNICODE$<SEMICOLON>_UNICODE>")
endif()
endfunction()
@@ -557,12 +624,20 @@ endfunction()
# Removes specified flags from CMAKE_<LANGUAGES>_FLAGS[_CONFIGS] variables
#
-# IN_CACHE enables flags removal from CACHE
-# CONFIGS list of configurations that need to clear flags. Clears all configs by default if not
-# specified.
-# LANGUAGES list of LANGUAGES that need clear flags. Clears all languages by default if not
-# specified.
-# REGEX enables the flag processing as a regular expression.
+# Option Arguments:
+# IN_CACHE
+# Enables flags removal from CACHE
+# REGEX
+# Enables the flag processing as a regular expression.
+#
+# Multi-value Arguments:
+# CONFIGS
+# List of configurations that need to clear flags. Clears all configs by default if not
+# specified.
+#
+# LANGUAGES
+# List of LANGUAGES that need clear flags. Clears all languages by default if not
+# specified.
function(qt_internal_remove_compiler_flags flags)
cmake_parse_arguments(PARSE_ARGV 1 arg
"IN_CACHE;REGEX"
@@ -585,8 +660,7 @@ function(qt_internal_remove_compiler_flags flags)
if(arg_CONFIGS)
set(configs "${arg_CONFIGS}")
else()
- message(FATAL_ERROR
- "You must specify at least one configuration for which to remove the flags.")
+ qt_internal_get_configs_for_flag_manipulation(configs)
endif()
if(arg_REGEX)
@@ -992,14 +1066,42 @@ function(qt_internal_set_up_config_optimizations_like_in_qmake)
IN_CACHE)
endif()
+ # Legacy Android toolchain file adds the `-g` flag to CMAKE_<LANG>_FLAGS, as a
+ # result, our release build ends up containing debug symbols. To avoid that, we
+ # remove the flag from CMAKE_<LANGL>_FLAGS and add
+ # it to CMAKE_<LANG>_FLAGS_DEBUG.
+ #
+ # Note:
+ # The new `android.toolchain.cmake` file does not have this problem, but
+ # it has other issues, eg., https://github.com/android/ndk/issues/1693, so we
+ # cannot force it. While we do load the new toolchain, it automatically falls
+ # back to the legacy toolchain, ie., `android-legacy.toolchain.cmake` which
+ # has the problem described above.
+ #
+ # Todo:
+ # When the new toolchain is fixed, and it doesn't fall back to the legacy
+ # anymore by default, then we should be able to remove this workaround.
+ if(ANDROID AND ANDROID_COMPILER_FLAGS MATCHES "(^| )-g")
+ qt_internal_remove_compiler_flags("-g")
+ qt_internal_add_compiler_flags(FLAGS "-g" CONFIGS DEBUG RELWITHDEBINFO)
+ endif()
+
# Update all relevant flags in the calling scope
- foreach(config ${configs})
- foreach(lang ${enabled_languages})
+ foreach(lang ${enabled_languages})
+ set(flag_var_name "CMAKE_${lang}_FLAGS")
+ set(${flag_var_name} "${${flag_var_name}}" PARENT_SCOPE)
+
+ foreach(config ${configs})
set(flag_var_name "CMAKE_${lang}_FLAGS_${config}")
set(${flag_var_name} "${${flag_var_name}}" PARENT_SCOPE)
endforeach()
+ endforeach()
- foreach(t ${target_link_types})
+ foreach(t ${target_link_types})
+ set(flag_var_name "CMAKE_${t}_LINKER_FLAGS")
+ set(${flag_var_name} "${${flag_var_name}}" PARENT_SCOPE)
+
+ foreach(config ${configs})
set(flag_var_name "CMAKE_${t}_LINKER_FLAGS_${config}")
set(${flag_var_name} "${${flag_var_name}}" PARENT_SCOPE)
endforeach()
diff --git a/cmake/QtFrameworkHelpers.cmake b/cmake/QtFrameworkHelpers.cmake
index 1eed9df379..0a37573ff6 100644
--- a/cmake/QtFrameworkHelpers.cmake
+++ b/cmake/QtFrameworkHelpers.cmake
@@ -6,6 +6,7 @@ macro(qt_find_apple_system_frameworks)
qt_internal_find_apple_system_framework(FWAppKit AppKit)
qt_internal_find_apple_system_framework(FWCFNetwork CFNetwork)
qt_internal_find_apple_system_framework(FWAssetsLibrary AssetsLibrary)
+ qt_internal_find_apple_system_framework(FWPhotos Photos)
qt_internal_find_apple_system_framework(FWAudioToolbox AudioToolbox)
qt_internal_find_apple_system_framework(FWApplicationServices ApplicationServices)
qt_internal_find_apple_system_framework(FWCarbon Carbon)
@@ -36,6 +37,7 @@ macro(qt_find_apple_system_frameworks)
qt_internal_find_apple_system_framework(FWContacts Contacts)
qt_internal_find_apple_system_framework(FWEventKit EventKit)
qt_internal_find_apple_system_framework(FWHealthKit HealthKit)
+ qt_internal_find_apple_system_framework(FWUniformTypeIdentifiers UniformTypeIdentifiers)
endif()
endmacro()
@@ -71,7 +73,7 @@ function(qt_copy_framework_headers target)
set(options)
set(oneValueArgs)
- set(multiValueArgs PUBLIC PRIVATE QPA)
+ set(multiValueArgs PUBLIC PRIVATE QPA RHI SSG)
cmake_parse_arguments(arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
qt_internal_get_framework_info(fw ${target})
@@ -79,27 +81,82 @@ function(qt_copy_framework_headers target)
set(output_dir_PUBLIC "${output_dir}/${fw_versioned_header_dir}")
set(output_dir_PRIVATE "${output_dir}/${fw_private_module_header_dir}/private")
set(output_dir_QPA "${output_dir}/${fw_private_module_header_dir}/qpa")
+ set(output_dir_RHI "${output_dir}/${fw_private_module_header_dir}/rhi")
+ set(output_dir_SSG "${output_dir}/${fw_private_module_header_dir}/ssg")
+ qt_internal_module_info(module "${target}")
- set(out_files)
- foreach(type IN ITEMS PUBLIC PRIVATE QPA)
+ set(out_files "")
+ set(in_files "")
+ set(out_dirs "")
+ set(copy_commands "")
+ foreach(type IN ITEMS PUBLIC PRIVATE QPA RHI SSG)
+ set(in_files_${type} "")
set(fw_output_header_dir "${output_dir_${type}}")
+ list(APPEND out_dirs "${fw_output_header_dir}")
foreach(hdr IN LISTS arg_${type})
get_filename_component(in_file_path ${hdr} ABSOLUTE)
get_filename_component(in_file_name ${hdr} NAME)
set(out_file_path "${fw_output_header_dir}/${in_file_name}")
- add_custom_command(
- OUTPUT ${out_file_path}
- DEPENDS ${in_file_path}
- COMMAND ${CMAKE_COMMAND} -E make_directory "${fw_output_header_dir}"
- COMMAND ${CMAKE_COMMAND} -E copy "${in_file_path}" "${fw_output_header_dir}"
- VERBATIM)
list(APPEND out_files ${out_file_path})
+ list(APPEND in_files_${type} "${in_file_path}")
endforeach()
+ if(in_files_${type})
+ list(APPEND copy_commands
+ COMMAND ${CMAKE_COMMAND} -E copy ${in_files_${type}} "${fw_output_header_dir}")
+ list(APPEND in_files ${in_files_${type}})
+ endif()
endforeach()
- set_property(TARGET ${target} APPEND PROPERTY
- QT_COPIED_FRAMEWORK_HEADERS "${out_files}")
+ list(REMOVE_DUPLICATES out_files)
+ list(REMOVE_DUPLICATES in_files)
+
+ set(copy_fw_sync_headers_command
+ "${CMAKE_COMMAND}" -E copy_directory
+ "${module_build_interface_include_dir}/.syncqt_staging"
+ "${output_dir}/${fw_versioned_header_dir}"
+ )
+
+ set(copy_fw_sync_headers_marker_file
+ "${CMAKE_CURRENT_BINARY_DIR}/${target}_fw_sync_headers_marker_file"
+ )
+
+ set(copy_fw_sync_headers_marker_file_command
+ "${CMAKE_COMMAND}" -E touch "${copy_fw_sync_headers_marker_file}"
+ )
+
+ if(CMAKE_GENERATOR MATCHES "^Ninja")
+ add_custom_command(
+ OUTPUT
+ "${output_dir}/${fw_versioned_header_dir}"
+ "${copy_fw_sync_headers_marker_file}"
+ DEPENDS ${target}_sync_headers
+ COMMAND ${copy_fw_sync_headers_command}
+ COMMAND ${copy_fw_sync_headers_marker_file_command}
+ VERBATIM
+ )
+ add_custom_target(${target}_copy_fw_sync_headers
+ DEPENDS "${output_dir}/${fw_versioned_header_dir}")
+ else()
+ add_custom_target(${target}_copy_fw_sync_headers
+ COMMAND ${copy_fw_sync_headers_command}
+ COMMAND ${copy_fw_sync_headers_marker_file_command}
+ )
+ endif()
+
+ if(out_files)
+ add_custom_command(
+ OUTPUT ${out_files}
+ DEPENDS ${target}_copy_fw_sync_headers ${in_files}
+ COMMAND
+ ${CMAKE_COMMAND} -E make_directory ${out_dirs}
+ ${copy_commands}
+ VERBATIM
+ COMMENT "Copy the ${target} header files to the framework directory"
+ )
+ set_property(TARGET ${target} APPEND PROPERTY
+ QT_COPIED_FRAMEWORK_HEADERS "${out_files}")
+ endif()
endfunction()
function(qt_internal_generate_fake_framework_header target)
@@ -141,6 +198,8 @@ endfunction()
# <out_var>_version framework version, e.g. 'A', 'B' etc.
# <out_var>_bundle_version framework bundle version, same as the PROJECT_VERSION, e.g. '6.0.0'.
# <out_var>_header_dir top-level header directory, e.g. 'QtCore.framework/Headers'.
+# <out_var>_versioned_binary_dir versioned directory that contains the framework binary,
+# e.g. 'QtCore.framework/Versions/A'
# <out_var>_versioned_header_dir header directory for specific framework version,
# e.g. 'QtCore.framework/Versions/A/Headers'
# <out_var>_private_header_dir header directory for the specific framework version and
@@ -149,6 +208,12 @@ endfunction()
# version, framework bundle version and tailing module name, e.g.
# 'QtCore.framework/Versions/A/Headers/6.0.0/Core'
function(qt_internal_get_framework_info out_var target)
+ # Avoid "INTERFACE_LIBRARY targets may only have whitelisted properties" error on CMake < 3.17.
+ get_target_property(target_type ${target} TYPE)
+ if("${target_type}" STREQUAL "INTERFACE_LIBRARY")
+ return()
+ endif()
+
get_target_property(${out_var}_version ${target} FRAMEWORK_VERSION)
get_target_property(${out_var}_bundle_version ${target} MACOSX_FRAMEWORK_BUNDLE_VERSION)
@@ -164,11 +229,14 @@ function(qt_internal_get_framework_info out_var target)
set(${out_var}_name "${module}")
set(${out_var}_dir "${${out_var}_name}.framework")
set(${out_var}_header_dir "${${out_var}_dir}/Headers")
+
if(UIKIT)
- # iOS frameworks do not version their headers
+ # iOS frameworks do not have a Versions sub-directory
+ set(${out_var}_versioned_binary_dir "${${out_var}_dir}")
set(${out_var}_versioned_header_dir "${${out_var}_header_dir}")
else()
- set(${out_var}_versioned_header_dir "${${out_var}_dir}/Versions/${${out_var}_version}/Headers")
+ set(${out_var}_versioned_binary_dir "${${out_var}_dir}/Versions/${${out_var}_version}")
+ set(${out_var}_versioned_header_dir "${${out_var}_versioned_binary_dir}/Headers")
endif()
set(${out_var}_private_header_dir "${${out_var}_versioned_header_dir}/${${out_var}_bundle_version}")
set(${out_var}_private_module_header_dir "${${out_var}_private_header_dir}/${module}")
@@ -178,6 +246,7 @@ function(qt_internal_get_framework_info out_var target)
set(${out_var}_header_dir "${${out_var}_header_dir}" PARENT_SCOPE)
set(${out_var}_version "${${out_var}_version}" PARENT_SCOPE)
set(${out_var}_bundle_version "${${out_var}_bundle_version}" PARENT_SCOPE)
+ set(${out_var}_versioned_binary_dir "${${out_var}_versioned_binary_dir}" PARENT_SCOPE)
set(${out_var}_versioned_header_dir "${${out_var}_versioned_header_dir}" PARENT_SCOPE)
set(${out_var}_private_header_dir "${${out_var}_private_header_dir}" PARENT_SCOPE)
set(${out_var}_private_module_header_dir "${${out_var}_private_module_header_dir}" PARENT_SCOPE)
diff --git a/cmake/QtHeadersClean.cmake b/cmake/QtHeadersClean.cmake
index a0adbfcfab..a1ebfcef28 100644
--- a/cmake/QtHeadersClean.cmake
+++ b/cmake/QtHeadersClean.cmake
@@ -5,6 +5,10 @@
# ${module_headers} with a custom set of defines. This makes sure our public headers
# are self-contained, and also compile with more strict compiler options.
function(qt_internal_add_headersclean_target module_target module_headers)
+ if(INPUT_headersclean AND WASM)
+ message(FATAL_ERROR "The headersclean targets are not supported on WASM platform.")
+ endif()
+
get_target_property(no_headersclean_check ${module_target} _qt_no_headersclean_check)
if(no_headersclean_check)
return()
@@ -23,6 +27,7 @@ function(qt_internal_add_headersclean_target module_target module_headers)
-DQT_NO_CAST_FROM_ASCII
-DQT_NO_URL_CAST_FROM_STRING
-DQT_NO_CAST_FROM_BYTEARRAY
+ -DQT_NO_CONTEXTLESS_CONNECT
-DQT_NO_KEYWORDS
-DQT_TYPESAFE_FLAGS
-DQT_USE_QSTRINGBUILDER
@@ -100,42 +105,35 @@ function(qt_internal_add_headersclean_target module_target module_headers)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU"
OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang|IntelLLVM")
- # Turn on some extra warnings not found in -Wall -Wextra.
- set(hcleanFLAGS -Wall -Wextra -Werror -Woverloaded-virtual -Wshadow -Wundef -Wfloat-equal
- -Wnon-virtual-dtor -Wpointer-arith -Wformat-security -Wno-long-long -Wno-variadic-macros
- -fno-operator-names
- -pedantic-errors)
+ # Compile header in strict C++20 mode. Enable further warnings.
+ set(hcleanFLAGS -std=c++2a
+ -Wall -Wextra -Werror -pedantic-errors
+ -Woverloaded-virtual -Wshadow -Wundef -Wfloat-equal
+ -Wnon-virtual-dtor -Wpointer-arith -Wformat-security
+ -Wchar-subscripts -Wold-style-cast
+ -Wredundant-decls # QTBUG-115583
+ -fno-operator-names)
if(QT_FEATURE_reduce_relocations AND UNIX)
list(APPEND hcleanFLAGS -fPIC)
endif()
- # options accepted by GCC and Clang
- list(APPEND hcleanFLAGS -Wchar-subscripts -Wold-style-cast)
-
if (NOT ((TEST_architecture_arch STREQUAL arm)
OR (TEST_architecture_arch STREQUAL mips)))
list(APPEND hcleanFLAGS -Wcast-align)
endif()
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
- list(APPEND hcleanFLAGS -Wzero-as-null-pointer-constant)
- if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 4.5)
- list(APPEND hcleanFLAGS -Wdouble-promotion)
- endif()
- if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 4.9)
- list(APPEND hcleanFLAGS -Wfloat-conversion)
- endif()
+ list(APPEND hcleanFLAGS -Wzero-as-null-pointer-constant
+ -Wdouble-promotion -Wfloat-conversion)
endif()
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang|IntelLLVM")
- list(APPEND hcleanFLAGS -Wshorten-64-to-32)
+ list(APPEND hcleanFLAGS -Wshorten-64-to-32
+ -Wweak-vtables)
endif()
- # Use strict mode C++20, with no GNU extensions (see -pedantic-errors above).
- list(APPEND hcleanFLAGS -std=c++2a)
-
separate_arguments(cxx_flags NATIVE_COMMAND ${CMAKE_CXX_FLAGS})
if(APPLE AND CMAKE_OSX_SYSROOT)
@@ -151,10 +149,7 @@ function(qt_internal_add_headersclean_target module_target module_headers)
# If additional package prefixes are provided, we consider they can contain frameworks
# as well.
foreach(prefix IN LISTS _qt_additional_packages_prefix_paths)
- if(prefix MATCHES "/lib/cmake$") # Cut CMake files path
- string(APPEND prefix "/../..")
- endif()
- get_filename_component(prefix "${prefix}" ABSOLUTE)
+ __qt_internal_reverse_prefix_path_from_cmake_dir(path "${path}")
set(libdir "${prefix}/${INSTALL_LIBDIR}")
if(EXISTS "${libdir}")
@@ -182,7 +177,13 @@ function(qt_internal_add_headersclean_target module_target module_headers)
)
set(input_header_path_type ABSOLUTE)
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
- set(hcleanFLAGS -std:c++latest -Zc:__cplusplus -Za -WX -W3)
+ # Note we can't enable -Za, as it does not support certain key Microsoft SDK header files
+ # we use. Microsoft suggests to use /permissive- instead, which is implicity set by
+ # -std:c++latest.
+ set(hcleanFLAGS -std:c++latest -Zc:__cplusplus -WX -W4 -EHsc)
+
+ # Because we now add `-DNOMINMAX` to `PlatformCommonInternal`.
+ set(hcleanUDEFS -UNOMINMAX)
# cl.exe needs a source path
get_filename_component(source_path "${QT_MKSPECS_DIR}/features/data/dummy.cpp" REALPATH)
@@ -194,6 +195,7 @@ function(qt_internal_add_headersclean_target module_target module_headers)
"${hcleanFLAGS}"
"${target_includes_joined_genex}"
"${hcleanDEFS}"
+ "${hcleanUDEFS}"
)
string(JOIN " " compiler_command_line_variables
"-FI"
@@ -226,7 +228,7 @@ function(qt_internal_add_headersclean_target module_target module_headers)
file(GENERATE OUTPUT "${headers_check_parameters}"
CONTENT "${headers_check_parameters_content}")
- set(sync_headers_dep "sync_headers")
+ set(sync_headers_dep "${module_target}_sync_headers")
foreach(header ${hclean_headers})
# We need realpath here to make sure path starts with drive letter
diff --git a/cmake/QtHostInfoConfig.cmake.in b/cmake/QtHostInfoConfig.cmake.in
index 7933b8b500..a1d069ec01 100644
--- a/cmake/QtHostInfoConfig.cmake.in
+++ b/cmake/QtHostInfoConfig.cmake.in
@@ -1,3 +1,6 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
@PACKAGE_INIT@
set(@var_prefix@BINDIR "@INSTALL_BINDIR@")
diff --git a/cmake/QtInitProject.cmake b/cmake/QtInitProject.cmake
index 3a8d11459f..a42f59f5c8 100644
--- a/cmake/QtInitProject.cmake
+++ b/cmake/QtInitProject.cmake
@@ -95,7 +95,7 @@ handle_type(qml EXTENSIONS .qml .js .mjs MODULES Gui Qml Quick TEMPLATE
URI ${project_name}
OUTPUT_DIRECTORY qml
VERSION 1.0
- AUTO_RESOURCE_PREFIX
+ RESOURCE_PREFIX /qt/qml
QML_FILES
@files@
)"
diff --git a/cmake/QtInstallPaths.cmake.in b/cmake/QtInstallPaths.cmake.in
new file mode 100644
index 0000000000..977fffd0e4
--- /dev/null
+++ b/cmake/QtInstallPaths.cmake.in
@@ -0,0 +1,16 @@
+# install layout information, following what qmake -query provides
+get_filename_component(QT@PROJECT_VERSION_MAJOR@_INSTALL_PREFIX
+ ${CMAKE_CURRENT_LIST_DIR}/../@QT_INVERSE_CONFIG_INSTALL_DIR@ ABSOLUTE)
+set(QT@PROJECT_VERSION_MAJOR@_INSTALL_ARCHDATA "@INSTALL_ARCHDATADIR@")
+set(QT@PROJECT_VERSION_MAJOR@_INSTALL_BINS "@INSTALL_BINDIR@")
+set(QT@PROJECT_VERSION_MAJOR@_INSTALL_CONFIGURATION "@INSTALL_SYSCONFDIR@")
+set(QT@PROJECT_VERSION_MAJOR@_INSTALL_DATA "@INSTALL_DATADIR@")
+set(QT@PROJECT_VERSION_MAJOR@_INSTALL_DOCS "@INSTALL_DOCDIR@")
+set(QT@PROJECT_VERSION_MAJOR@_INSTALL_EXAMPLES "@INSTALL_EXAMPLESDIR@")
+set(QT@PROJECT_VERSION_MAJOR@_INSTALL_HEADERS "@INSTALL_INCLUDEDIR@")
+set(QT@PROJECT_VERSION_MAJOR@_INSTALL_LIBS "@INSTALL_LIBDIR@")
+set(QT@PROJECT_VERSION_MAJOR@_INSTALL_LIBEXECS "@INSTALL_LIBEXECDIR@")
+set(QT@PROJECT_VERSION_MAJOR@_INSTALL_PLUGINS "@INSTALL_PLUGINSDIR@")
+set(QT@PROJECT_VERSION_MAJOR@_INSTALL_QML "@INSTALL_QMLDIR@")
+set(QT@PROJECT_VERSION_MAJOR@_INSTALL_TESTS "@INSTALL_TESTSDIR@")
+set(QT@PROJECT_VERSION_MAJOR@_INSTALL_TRANSLATIONS "@INSTALL_TRANSLATIONSDIR@")
diff --git a/cmake/QtInternalTargets.cmake b/cmake/QtInternalTargets.cmake
index 21730457d8..d7eadc1a73 100644
--- a/cmake/QtInternalTargets.cmake
+++ b/cmake/QtInternalTargets.cmake
@@ -48,6 +48,11 @@ function(qt_internal_set_warnings_are_errors_flags target target_scope)
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "11.0.0")
# We do mixed enum arithmetic all over the place:
list(APPEND flags -Wno-error=deprecated-enum-enum-conversion -Wno-error=deprecated-enum-float-conversion)
+
+ # GCC has some false positive, and it specifically comes through in MINGW
+ if (MINGW)
+ list(APPEND flags -Wno-error=stringop-overread)
+ endif()
endif()
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "11.0.0" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "11.2.0")
@@ -97,7 +102,7 @@ function(qt_internal_add_global_definition definition)
set(optional_args)
set(single_value_args VALUE)
set(multi_value_args SCOPE)
- cmake_parse_arguments(args
+ cmake_parse_arguments(arg
"${optional_args}"
"${single_value_args}"
"${multi_value_args}"
@@ -151,10 +156,12 @@ qt_internal_add_target_aliases(PlatformToolInternal)
target_link_libraries(PlatformToolInternal INTERFACE PlatformAppInternal)
qt_internal_add_global_definition(QT_NO_JAVA_STYLE_ITERATORS)
-qt_internal_add_global_definition(QT_NO_AS_CONST)
+qt_internal_add_global_definition(QT_NO_QASCONST)
qt_internal_add_global_definition(QT_NO_QEXCHANGE)
qt_internal_add_global_definition(QT_NO_NARROWING_CONVERSIONS_IN_CONNECT)
qt_internal_add_global_definition(QT_EXPLICIT_QFILE_CONSTRUCTION_FROM_PATH)
+qt_internal_add_global_definition(QT_USE_QSTRINGBUILDER SCOPE PLUGIN TOOL MODULE)
+qt_internal_add_global_definition(QT_NO_FOREACH)
if(WARNINGS_ARE_ERRORS)
qt_internal_set_warnings_are_errors_flags(PlatformModuleInternal INTERFACE)
@@ -165,6 +172,8 @@ if(WIN32)
# Needed for M_PI define. Same as mkspecs/features/qt_module.prf.
# It's set for every module being built, but it's not propagated to user apps.
target_compile_definitions(PlatformModuleInternal INTERFACE _USE_MATH_DEFINES)
+ # Not disabling min/max macros may result in unintended substitutions of std::min/max
+ target_compile_definitions(PlatformCommonInternal INTERFACE NOMINMAX)
endif()
if(FEATURE_largefile AND UNIX)
target_compile_definitions(PlatformCommonInternal
@@ -202,6 +211,14 @@ function(qt_internal_apply_bitcode_flags target)
target_compile_options("${target}" INTERFACE ${bitcode_flags})
endfunction()
+# Function guards linker options that are applicable for internal Qt targets only from propagating
+# them to user projects.
+function(qt_internal_platform_link_options target scope)
+ set(options ${ARGN})
+ set(is_internal_target_genex "$<BOOL:$<TARGET_PROPERTY:_qt_is_internal_target>>")
+ target_link_options(${target} ${scope} "$<${is_internal_target_genex}:${options}>")
+endfunction()
+
# Apple deprecated the entire OpenGL API in favor of Metal, which
# we are aware of, so silence the deprecation warnings in code.
# This does not apply to user-code, which will need to silence
@@ -212,6 +229,31 @@ elseif(UIKIT)
target_compile_definitions(PlatformCommonInternal INTERFACE GLES_SILENCE_DEPRECATION)
endif()
+if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang")
+ if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "14.0.0")
+ # Xcode 14's Clang will emit objc_msgSend stubs by default, which ld
+ # from earlier Xcode versions will fail to understand when linking
+ # against static libraries with these stubs. Disable the stubs explicitly,
+ # for as long as we do support Xcode < 14.
+ set(is_static_lib "$<STREQUAL:$<TARGET_PROPERTY:TYPE>,STATIC_LIBRARY>")
+ set(is_objc "$<COMPILE_LANGUAGE:OBJC,OBJCXX>")
+ set(is_static_and_objc "$<AND:${is_static_lib},${is_objc}>")
+ target_compile_options(PlatformCommonInternal INTERFACE
+ "$<${is_static_and_objc}:-fno-objc-msgsend-selector-stubs>"
+ )
+ endif()
+
+ # A bug in Xcode 15 adds duplicate flags to the linker. In addition, the
+ # `-warn_duplicate_libraries` is now enabled by default which may result
+ # in several 'duplicate libraries warning'.
+ # - https://gitlab.kitware.com/cmake/cmake/-/issues/25297 and
+ # - https://indiestack.com/2023/10/xcode-15-duplicate-library-linker-warnings/
+ set(is_xcode15 "$<VERSION_GREATER_EQUAL:$<CXX_COMPILER_VERSION>,15>")
+ set(not_disabled "$<NOT:$<BOOL:$<TARGET_PROPERTY:QT_NO_DISABLE_WARN_DUPLICATE_LIBRARIES>>>")
+ target_link_options(PlatformCommonInternal INTERFACE
+ "$<$<AND:${not_disabled},${is_xcode15}>:LINKER:-no_warn_duplicate_libraries>")
+endif()
+
if(MSVC)
target_compile_definitions(PlatformCommonInternal INTERFACE
"_CRT_SECURE_NO_WARNINGS"
@@ -224,7 +266,7 @@ if(WASM AND QT_FEATURE_sse2)
endif()
# Taken from mkspecs/common/msvc-version.conf and mkspecs/common/msvc-desktop.conf
-if (MSVC)
+if (MSVC AND NOT CLANG)
if (MSVC_VERSION GREATER_EQUAL 1799)
target_compile_options(PlatformCommonInternal INTERFACE
-FS
@@ -235,20 +277,16 @@ if (MSVC)
if (MSVC_VERSION GREATER_EQUAL 1899)
target_compile_options(PlatformCommonInternal INTERFACE
-Zc:strictStrings
+ -Zc:throwingNew
)
- if (NOT CLANG)
- target_compile_options(PlatformCommonInternal INTERFACE
- -Zc:throwingNew
- )
- endif()
endif()
- if (MSVC_VERSION GREATER_EQUAL 1909 AND NOT CLANG) # MSVC 2017
+ if (MSVC_VERSION GREATER_EQUAL 1909) # MSVC 2017
target_compile_options(PlatformCommonInternal INTERFACE
-Zc:referenceBinding
-Zc:ternary
)
endif()
- if (MSVC_VERSION GREATER_EQUAL 1919 AND NOT CLANG) # MSVC 2019
+ if (MSVC_VERSION GREATER_EQUAL 1919) # MSVC 2019
target_compile_options(PlatformCommonInternal INTERFACE
-Zc:externConstexpr
#-Zc:lambda # Buggy. TODO: Enable again when stable enough.
@@ -265,7 +303,7 @@ if (MSVC)
$<$<NOT:$<CONFIG:Debug>>:-guard:cf -Gw>
)
- target_link_options(PlatformCommonInternal INTERFACE
+ qt_internal_platform_link_options(PlatformCommonInternal INTERFACE
-DYNAMICBASE -NXCOMPAT -LARGEADDRESSAWARE
$<$<NOT:$<CONFIG:Debug>>:-OPT:REF -OPT:ICF -GUARD:CF>
)
@@ -279,18 +317,52 @@ if (GCC AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "9.2")
target_compile_options(PlatformCommonInternal INTERFACE $<$<COMPILE_LANGUAGE:CXX>:-Wsuggest-override>)
endif()
+# Hardening options
if(QT_FEATURE_intelcet)
if(MSVC)
- target_link_options(PlatformCommonInternal INTERFACE
- -CETCOMPAT
- )
+ qt_internal_platform_link_options(PlatformCommonInternal INTERFACE -CETCOMPAT)
else()
- target_compile_options(PlatformCommonInternal INTERFACE
- -fcf-protection=full
- )
+ target_compile_options(PlatformCommonInternal INTERFACE -fcf-protection=full)
endif()
endif()
+if(QT_FEATURE_glibc_fortify_source)
+ set(is_optimized_build "$<OR:$<NOT:$<CONFIG:Debug>>,$<BOOL:${QT_FEATURE_optimize_debug}>>")
+ # Some compilers may define _FORTIFY_SOURCE by default when optimizing, remove it
+ # before defining our own
+ target_compile_options(PlatformCommonInternal BEFORE INTERFACE "$<${is_optimized_build}:-U_FORTIFY_SOURCE>")
+ if(TEST_glibc_234)
+ target_compile_options(PlatformCommonInternal INTERFACE "$<${is_optimized_build}:-D_FORTIFY_SOURCE=3>")
+ else()
+ target_compile_options(PlatformCommonInternal INTERFACE "$<${is_optimized_build}:-D_FORTIFY_SOURCE=2>")
+ endif()
+endif()
+
+if(QT_FEATURE_trivial_auto_var_init_pattern)
+ target_compile_options(PlatformCommonInternal INTERFACE -ftrivial-auto-var-init=pattern)
+endif()
+
+if(QT_FEATURE_stack_protector)
+ target_compile_options(PlatformCommonInternal INTERFACE -fstack-protector-strong)
+endif()
+
+if(QT_FEATURE_stack_clash_protection)
+ target_compile_options(PlatformCommonInternal INTERFACE -fstack-clash-protection)
+endif()
+
+if(QT_FEATURE_libstdcpp_assertions)
+ target_compile_definitions(PlatformCommonInternal INTERFACE _GLIBCXX_ASSERTIONS)
+endif()
+
+if(QT_FEATURE_libcpp_hardening)
+ target_compile_definitions(PlatformCommonInternal INTERFACE -D_LIBCPP_HARDENING_MODE=$<IF:$<CONFIG:Debug>,_LIBCPP_HARDENING_MODE_EXTENSIVE,_LIBCPP_HARDENING_MODE_FAST>)
+endif()
+
+if(QT_FEATURE_relro_now_linker)
+ qt_internal_platform_link_options(PlatformCommonInternal INTERFACE "-Wl,-z,relro,-z,now")
+endif()
+
+
if(QT_FEATURE_force_asserts)
target_compile_definitions(PlatformCommonInternal INTERFACE QT_FORCE_ASSERTS)
endif()
@@ -310,30 +382,40 @@ endif()
if(DEFINED QT_EXTRA_FRAMEWORKPATHS AND APPLE)
list(TRANSFORM QT_EXTRA_FRAMEWORKPATHS PREPEND "-F" OUTPUT_VARIABLE __qt_fw_flags)
target_compile_options(PlatformCommonInternal INTERFACE ${__qt_fw_flags})
- target_link_options(PlatformCommonInternal INTERFACE ${__qt_fw_flags})
+ qt_internal_platform_link_options(PlatformCommonInternal INTERFACE ${__qt_fw_flags})
unset(__qt_fw_flags)
endif()
qt_internal_get_active_linker_flags(__qt_internal_active_linker_flags)
if(__qt_internal_active_linker_flags)
- target_link_options(PlatformCommonInternal INTERFACE "${__qt_internal_active_linker_flags}")
+ qt_internal_platform_link_options(PlatformCommonInternal INTERFACE
+ "${__qt_internal_active_linker_flags}")
endif()
unset(__qt_internal_active_linker_flags)
if(QT_FEATURE_enable_gdb_index)
- target_link_options(PlatformCommonInternal INTERFACE "-Wl,--gdb-index")
+ qt_internal_platform_link_options(PlatformCommonInternal INTERFACE "-Wl,--gdb-index")
endif()
if(QT_FEATURE_enable_new_dtags)
- target_link_options(PlatformCommonInternal INTERFACE "-Wl,--enable-new-dtags")
+ qt_internal_platform_link_options(PlatformCommonInternal INTERFACE "-Wl,--enable-new-dtags")
endif()
+function(qt_internal_apply_coverage_flags)
+ if(QT_FEATURE_coverage_gcov)
+ target_compile_options(PlatformCommonInternal INTERFACE
+ "$<$<CONFIG:Debug>:--coverage>")
+ target_link_options(PlatformCommonInternal INTERFACE "$<$<CONFIG:Debug>:--coverage>")
+ endif()
+endfunction()
+qt_internal_apply_coverage_flags()
+
function(qt_get_implicit_sse2_genex_condition out_var)
set(is_shared_lib "$<STREQUAL:$<TARGET_PROPERTY:TYPE>,SHARED_LIBRARY>")
set(is_static_lib "$<STREQUAL:$<TARGET_PROPERTY:TYPE>,STATIC_LIBRARY>")
set(is_static_qt_build "$<NOT:$<BOOL:${QT_BUILD_SHARED_LIBS}>>")
- set(is_staitc_lib_during_static_qt_build "$<AND:${is_static_qt_build},${is_static_lib}>")
- set(enable_sse2_condition "$<OR:${is_shared_lib},${is_staitc_lib_during_static_qt_build}>")
+ set(is_static_lib_during_static_qt_build "$<AND:${is_static_qt_build},${is_static_lib}>")
+ set(enable_sse2_condition "$<OR:${is_shared_lib},${is_static_lib_during_static_qt_build}>")
set(${out_var} "${enable_sse2_condition}" PARENT_SCOPE)
endfunction()
diff --git a/cmake/QtJavaHelpers.cmake b/cmake/QtJavaHelpers.cmake
index edf4f54b9a..ec9b611c5e 100644
--- a/cmake/QtJavaHelpers.cmake
+++ b/cmake/QtJavaHelpers.cmake
@@ -4,6 +4,10 @@
# This function can be used to compile java sources into a jar package.
function(qt_internal_add_jar target)
+ set(options)
+ set(oneValueArgs OUTPUT_DIR)
+ set(multiValueArgs INCLUDE_JARS SOURCES)
+ cmake_parse_arguments(arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
set(javac_target_version "${QT_ANDROID_JAVAC_TARGET}")
if (NOT javac_target_version)
@@ -15,7 +19,12 @@ function(qt_internal_add_jar target)
set(javac_source_version "8")
endif()
- set(CMAKE_JAVA_COMPILE_FLAGS -source "${javac_source_version}" -target "${javac_target_version}" -Xlint:unchecked -bootclasspath "${QT_ANDROID_JAR}")
+ set(CMAKE_JAVA_COMPILE_FLAGS -source "${javac_source_version}" -target "${javac_target_version}"
+ -Xlint:unchecked,cast,divzero,fallthrough,overrides,path -classpath "${QT_ANDROID_JAR}")
add_jar(${ARGV})
+ foreach(f IN LISTS arg_SOURCES)
+ _qt_internal_expose_source_file_to_ide(${target} "${f}")
+ endforeach()
+
endfunction()
diff --git a/cmake/QtMkspecHelpers.cmake b/cmake/QtMkspecHelpers.cmake
new file mode 100644
index 0000000000..cd08daa2c4
--- /dev/null
+++ b/cmake/QtMkspecHelpers.cmake
@@ -0,0 +1,146 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+macro(qt_internal_set_mkspecs_dir)
+ # Find the path to mkspecs/, depending on whether we are building as part of a standard qtbuild,
+ # or a module against an already installed version of qt.
+ if(NOT QT_MKSPECS_DIR)
+ if("${QT_BUILD_INTERNALS_PATH}" STREQUAL "")
+ get_filename_component(QT_MKSPECS_DIR "${CMAKE_CURRENT_LIST_DIR}/../mkspecs" ABSOLUTE)
+ else()
+ # We can rely on QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX being set by
+ # QtBuildInternalsExtra.cmake.
+ get_filename_component(
+ QT_MKSPECS_DIR
+ "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}/${INSTALL_MKSPECSDIR}" ABSOLUTE)
+ endif()
+ set(QT_MKSPECS_DIR "${QT_MKSPECS_DIR}" CACHE INTERNAL "")
+ endif()
+endmacro()
+
+macro(qt_internal_setup_platform_definitions_and_mkspec)
+ # Platform define path, etc.
+ if(WIN32)
+ set(QT_DEFAULT_PLATFORM_DEFINITIONS WIN32 _ENABLE_EXTENDED_ALIGNED_STORAGE)
+ if(QT_64BIT)
+ list(APPEND QT_DEFAULT_PLATFORM_DEFINITIONS WIN64 _WIN64)
+ endif()
+
+ if(CLANG)
+ if(CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC" OR MSVC)
+ set(QT_DEFAULT_MKSPEC win32-clang-msvc)
+ elseif(CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "GNU" OR MINGW)
+ set(QT_DEFAULT_MKSPEC win32-clang-g++)
+ endif()
+ elseif(MSVC)
+ if(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
+ set(QT_DEFAULT_MKSPEC win32-arm64-msvc)
+ else()
+ set(QT_DEFAULT_MKSPEC win32-msvc)
+ endif()
+ elseif(MINGW)
+ set(QT_DEFAULT_MKSPEC win32-g++)
+ list(APPEND QT_DEFAULT_PLATFORM_DEFINITIONS MINGW_HAS_SECURE_API=1)
+ endif()
+ elseif(LINUX)
+ if(GCC)
+ set(QT_DEFAULT_MKSPEC linux-g++)
+ elseif(CLANG)
+ set(QT_DEFAULT_MKSPEC linux-clang)
+ endif()
+ elseif(ANDROID)
+ if(GCC)
+ set(QT_DEFAULT_MKSPEC android-g++)
+ elseif(CLANG)
+ set(QT_DEFAULT_MKSPEC android-clang)
+ endif()
+ elseif(IOS)
+ set(QT_DEFAULT_MKSPEC macx-ios-clang)
+ elseif(APPLE)
+ set(QT_DEFAULT_MKSPEC macx-clang)
+ elseif(WASM)
+ if(WASM64)
+ set(QT_DEFAULT_MKSPEC wasm-emscripten-64)
+ else()
+ set(QT_DEFAULT_MKSPEC wasm-emscripten)
+ endif()
+ elseif(QNX)
+ # Certain POSIX defines are not set if we don't compile with -std=gnuXX
+ set(QT_ENABLE_CXX_EXTENSIONS ON)
+
+ list(APPEND QT_DEFAULT_PLATFORM_DEFINITIONS _FORTIFY_SOURCE=2 _REENTRANT)
+
+ set(compiler_aarch64le aarch64le)
+ set(compiler_armle-v7 armv7le)
+ set(compiler_x86-64 x86_64)
+ set(compiler_x86 x86)
+ foreach(arch aarch64le armle-v7 x86-64 x86)
+ if (CMAKE_CXX_COMPILER_TARGET MATCHES "${compiler_${arch}}$")
+ set(QT_DEFAULT_MKSPEC qnx-${arch}-qcc)
+ endif()
+ endforeach()
+ elseif(FREEBSD)
+ if(CLANG)
+ set(QT_DEFAULT_MKSPEC freebsd-clang)
+ elseif(GCC)
+ set(QT_DEFAULT_MKSPEC freebsd-g++)
+ endif()
+ elseif(NETBSD)
+ set(QT_DEFAULT_MKSPEC netbsd-g++)
+ elseif(OPENBSD)
+ set(QT_DEFAULT_MKSPEC openbsd-g++)
+ elseif(SOLARIS)
+ if(GCC)
+ if(QT_64BIT)
+ set(QT_DEFAULT_MKSPEC solaris-g++-64)
+ else()
+ set(QT_DEFAULT_MKSPEC solaris-g++)
+ endif()
+ else()
+ if(QT_64BIT)
+ set(QT_DEFAULT_MKSPEC solaris-cc-64)
+ else()
+ set(QT_DEFAULT_MKSPEC solaris-cc)
+ endif()
+ endif()
+ elseif(HURD)
+ set(QT_DEFAULT_MKSPEC hurd-g++)
+ endif()
+
+ if(NOT QT_QMAKE_TARGET_MKSPEC)
+ set(QT_QMAKE_TARGET_MKSPEC "${QT_DEFAULT_MKSPEC}" CACHE STRING "QMake target mkspec")
+ endif()
+
+ if(CMAKE_CROSSCOMPILING)
+ set(QT_QMAKE_HOST_MKSPEC "${QT${PROJECT_VERSION_MAJOR}_HOST_INFO_QMAKE_MKSPEC}")
+ else()
+ set(QT_QMAKE_HOST_MKSPEC "${QT_QMAKE_TARGET_MKSPEC}")
+ endif()
+
+ if(NOT QT_QMAKE_TARGET_MKSPEC OR NOT EXISTS "${QT_MKSPECS_DIR}/${QT_QMAKE_TARGET_MKSPEC}")
+ if(NOT QT_QMAKE_TARGET_MKSPEC)
+ set(reason
+ "Platform is not detected. Please make sure your build environment is configured"
+ " properly or specify it manually using QT_QMAKE_TARGET_MKSPEC variable and one of"
+ " the known platforms.")
+ else()
+ set(reason "Unknown platform ${QT_QMAKE_TARGET_MKSPEC}")
+ endif()
+
+ file(GLOB known_platforms
+ LIST_DIRECTORIES true
+ RELATIVE "${QT_MKSPECS_DIR}"
+ "${QT_MKSPECS_DIR}/*"
+ )
+ list(JOIN known_platforms "\n " known_platforms)
+ message(FATAL_ERROR "${reason}\n"
+ "Known platforms:\n ${known_platforms}")
+ endif()
+
+ if(NOT DEFINED QT_DEFAULT_PLATFORM_DEFINITIONS)
+ set(QT_DEFAULT_PLATFORM_DEFINITIONS "")
+ endif()
+
+ set(QT_PLATFORM_DEFINITIONS ${QT_DEFAULT_PLATFORM_DEFINITIONS}
+ CACHE STRING "Qt platform specific pre-processor defines")
+endmacro()
diff --git a/cmake/QtModuleConfig.cmake.in b/cmake/QtModuleConfig.cmake.in
index cdb79f4bbb..06a7daad71 100644
--- a/cmake/QtModuleConfig.cmake.in
+++ b/cmake/QtModuleConfig.cmake.in
@@ -1,3 +1,6 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
@PACKAGE_INIT@
cmake_minimum_required(VERSION @min_new_policy_version@...@max_new_policy_version@)
@@ -29,9 +32,6 @@ if (NOT QT_NO_CREATE_TARGETS AND @INSTALL_CMAKE_NAMESPACE@@target@_FOUND)
include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target@AdditionalTargetInfo.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target@ExtraProperties.cmake"
OPTIONAL)
- if(NOT QT_NO_CREATE_VERSIONLESS_TARGETS)
- include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target@VersionlessTargets.cmake")
- endif()
# DEPRECATED
# Provide old style variables for includes, compile definitions, etc.
@@ -74,15 +74,25 @@ if (NOT QT_NO_CREATE_TARGETS AND @INSTALL_CMAKE_NAMESPACE@@target@_FOUND)
${_@QT_CMAKE_EXPORT_NAMESPACE@@target@_OWN_PRIVATE_INCLUDE_DIRS})
foreach(_module_dep ${_@QT_CMAKE_EXPORT_NAMESPACE@@target@_MODULE_DEPENDENCIES})
- list(APPEND @QT_CMAKE_EXPORT_NAMESPACE@@target@_INCLUDE_DIRS
+ if(_module_dep MATCHES ".+Private$")
+ set(_private_suffix "Private")
+ else()
+ set(_private_suffix "")
+ endif()
+ list(APPEND @QT_CMAKE_EXPORT_NAMESPACE@@target@${_private_suffix}_INCLUDE_DIRS
${@QT_CMAKE_EXPORT_NAMESPACE@${_module_dep}_INCLUDE_DIRS})
- list(APPEND @QT_CMAKE_EXPORT_NAMESPACE@@target@_PRIVATE_INCLUDE_DIRS
+ list(APPEND @QT_CMAKE_EXPORT_NAMESPACE@@target@${_private_suffix}_PRIVATE_INCLUDE_DIRS
${@QT_CMAKE_EXPORT_NAMESPACE@${_module_dep}_PRIVATE_INCLUDE_DIRS})
- list(APPEND @QT_CMAKE_EXPORT_NAMESPACE@@target@_DEFINITIONS
+ if(_private_suffix)
+ list(APPEND @QT_CMAKE_EXPORT_NAMESPACE@@target@_PRIVATE_INCLUDE_DIRS
+ ${@QT_CMAKE_EXPORT_NAMESPACE@${_module_dep}_PRIVATE_INCLUDE_DIRS})
+ endif()
+ list(APPEND @QT_CMAKE_EXPORT_NAMESPACE@@target@${_private_suffix}_DEFINITIONS
${@QT_CMAKE_EXPORT_NAMESPACE@${_module_dep}_DEFINITIONS})
- list(APPEND @QT_CMAKE_EXPORT_NAMESPACE@@target@_COMPILE_DEFINITIONS
+ list(APPEND @QT_CMAKE_EXPORT_NAMESPACE@@target@${_private_suffix}_COMPILE_DEFINITIONS
${@QT_CMAKE_EXPORT_NAMESPACE@${_module_dep}_COMPILE_DEFINITIONS})
endforeach()
+ unset(_private_suffix)
list(REMOVE_DUPLICATES @QT_CMAKE_EXPORT_NAMESPACE@@target@_INCLUDE_DIRS)
list(REMOVE_DUPLICATES @QT_CMAKE_EXPORT_NAMESPACE@@target@_PRIVATE_INCLUDE_DIRS)
@@ -118,6 +128,14 @@ if (TARGET @QT_CMAKE_EXPORT_NAMESPACE@::@target@)
EXISTS "${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target@BuildInternals.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target@BuildInternals.cmake")
endif()
+
+ if(NOT QT_NO_CREATE_VERSIONLESS_TARGETS)
+ if(CMAKE_VERSION VERSION_LESS 3.18 OR QT_USE_OLD_VERSION_LESS_TARGETS)
+ include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target@VersionlessTargets.cmake")
+ else()
+ include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target@VersionlessAliasTargets.cmake")
+ endif()
+ endif()
else()
set(@INSTALL_CMAKE_NAMESPACE@@target@_FOUND FALSE)
diff --git a/cmake/QtModuleDependencies.cmake.in b/cmake/QtModuleDependencies.cmake.in
index c6c68ceb49..4a82ad3bd3 100644
--- a/cmake/QtModuleDependencies.cmake.in
+++ b/cmake/QtModuleDependencies.cmake.in
@@ -1,3 +1,6 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
# Make sure @INSTALL_CMAKE_NAMESPACE@ is found before anything else.
set(@INSTALL_CMAKE_NAMESPACE@@target@_FOUND FALSE)
@@ -16,10 +19,10 @@ set(${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED FALSE)
if(NOT @INSTALL_CMAKE_NAMESPACE@_FOUND)
find_dependency(@INSTALL_CMAKE_NAMESPACE@ @main_qt_package_version@
PATHS
+ ${QT_BUILD_CMAKE_PREFIX_PATH}
"${CMAKE_CURRENT_LIST_DIR}/.."
"${_qt_cmake_dir}"
${_qt_additional_packages_prefix_paths}
- ${QT_EXAMPLES_CMAKE_PREFIX_PATH}
${__qt_use_no_default_path_for_qt_packages}
)
endif()
@@ -27,6 +30,7 @@ endif()
# note: _third_party_deps example: "ICU\\;FALSE\\;1.0\\;i18n uc data;ZLIB\\;FALSE\\;\\;"
set(__qt_@target@_third_party_deps "@third_party_deps@")
+@third_party_deps_extra_info@
_qt_internal_find_third_party_dependencies("@target@" __qt_@target@_third_party_deps)
# Find Qt tool package.
diff --git a/cmake/QtModuleHeadersCheck.cmake b/cmake/QtModuleHeadersCheck.cmake
index d241f5bb55..39053f3e10 100644
--- a/cmake/QtModuleHeadersCheck.cmake
+++ b/cmake/QtModuleHeadersCheck.cmake
@@ -11,7 +11,8 @@ if(EXISTS ${HEADER_CHECK_EXCEPTIONS})
file(READ ${HEADER_CHECK_EXCEPTIONS} header_check_exception_list)
endif()
-file(TO_CMAKE_PATH "${INPUT_HEADER_FILE}" header)
+get_filename_component(header "${INPUT_HEADER_FILE}" REALPATH)
+file(TO_CMAKE_PATH "${header}" header)
foreach(exception IN LISTS header_check_exception_list)
file(TO_CMAKE_PATH "${exception}" exception)
if(exception STREQUAL header)
diff --git a/cmake/QtModuleHelpers.cmake b/cmake/QtModuleHelpers.cmake
index 15a49df84b..d7957fa4bc 100644
--- a/cmake/QtModuleHelpers.cmake
+++ b/cmake/QtModuleHelpers.cmake
@@ -16,8 +16,8 @@ macro(qt_internal_get_internal_add_module_keywords option_args single_args multi
NO_ADDITIONAL_TARGET_INFO
NO_GENERATE_METATYPES
NO_HEADERSCLEAN_CHECK
- GENERATE_CPP_EXPORTS
- GENERATE_PRIVATE_CPP_EXPORTS
+ GENERATE_CPP_EXPORTS # deprecated
+ NO_GENERATE_CPP_EXPORTS
NO_UNITY_BUILD
)
set(${single_args}
@@ -30,6 +30,8 @@ macro(qt_internal_get_internal_add_module_keywords option_args single_args multi
EXTERNAL_HEADERS_DIR
PRIVATE_HEADER_FILTERS
QPA_HEADER_FILTERS
+ RHI_HEADER_FILTERS
+ SSG_HEADER_FILTERS
HEADER_SYNC_SOURCE_DIRECTORY
${__default_target_info_args}
)
@@ -37,7 +39,6 @@ macro(qt_internal_get_internal_add_module_keywords option_args single_args multi
QMAKE_MODULE_CONFIG
EXTRA_CMAKE_FILES
EXTRA_CMAKE_INCLUDES
- NO_PCH_SOURCES
EXTERNAL_HEADERS
POLICIES
${__default_private_args}
@@ -115,6 +116,14 @@ endfunction()
# The regular expressions that filter QPA header files out of target sources.
# The value must use the following format 'regex1|regex2|regex3'.
#
+# RHI_HEADER_FILTERS
+# The regular expressions that filter RHI header files out of target sources.
+# The value must use the following format 'regex1|regex2|regex3'.
+#
+# SSG_HEADER_FILTERS
+# The regular expressions that filter ssg header files out of target sources.
+# The value must use the following format 'regex1|regex2|regex3'.
+#
# HEADER_SYNC_SOURCE_DIRECTORY
# The source directory for header sync procedure. Header files outside this directory will be
# ignored by syncqt. The specifying this directory allows to skip the parsing of the whole
@@ -414,18 +423,15 @@ function(qt_internal_add_module target)
# We should not generate export headers if module is defined as pure STATIC.
# Static libraries don't need to export their symbols, and corner cases when sources are
# also used in shared libraries, should be handled manually.
- if(arg_GENERATE_CPP_EXPORTS AND NOT arg_STATIC)
+ if((NOT arg_NO_GENERATE_CPP_EXPORTS OR arg_GENERATE_CPP_EXPORTS) AND NOT arg_STATIC
+ AND NOT arg_HEADER_MODULE)
if(arg_CPP_EXPORT_HEADER_BASE_NAME)
set(cpp_export_header_base_name
"CPP_EXPORT_HEADER_BASE_NAME;${arg_CPP_EXPORT_HEADER_BASE_NAME}"
)
endif()
- if(arg_GENERATE_PRIVATE_CPP_EXPORTS)
- set(generate_private_cpp_export "GENERATE_PRIVATE_CPP_EXPORTS")
- endif()
qt_internal_generate_cpp_global_exports(${target} ${module_define_infix}
"${cpp_export_header_base_name}"
- "${generate_private_cpp_export}"
)
endif()
@@ -447,6 +453,20 @@ function(qt_internal_add_module target)
set_target_properties(${target}
PROPERTIES _qt_module_qpa_headers_filter_regex "${qpa_filter_regex}")
+ set(rhi_filter_regex "")
+ if(arg_RHI_HEADER_FILTERS)
+ set(rhi_filter_regex "${arg_RHI_HEADER_FILTERS}")
+ endif()
+ set_target_properties(${target}
+ PROPERTIES _qt_module_rhi_headers_filter_regex "${rhi_filter_regex}")
+
+ set(ssg_filter_regex "")
+ if(arg_SSG_HEADER_FILTERS)
+ set(ssg_filter_regex "${arg_SSG_HEADER_FILTERS}")
+ endif()
+ set_target_properties(${target}
+ PROPERTIES _qt_module_ssg_headers_filter_regex "${ssg_filter_regex}")
+
set(private_filter_regex ".+_p(ch)?\\.h")
if(arg_PRIVATE_HEADER_FILTERS)
set(private_filter_regex "${private_filter_regex}|${arg_PRIVATE_HEADER_FILTERS}")
@@ -457,6 +477,8 @@ function(qt_internal_add_module target)
# If EXTERNAL_HEADERS_DIR is set we install the specified directory and keep the structure
# without taking into the account the CMake source tree and syncqt outputs.
if(arg_EXTERNAL_HEADERS_DIR)
+ set_property(TARGET ${target}
+ PROPERTY _qt_external_headers_dir "${arg_EXTERNAL_HEADERS_DIR}")
qt_install(DIRECTORY "${arg_EXTERNAL_HEADERS_DIR}/"
DESTINATION "${module_install_interface_include_dir}"
)
@@ -464,7 +486,7 @@ function(qt_internal_add_module target)
endif()
if(arg_NO_HEADERSCLEAN_CHECK OR arg_NO_MODULE_HEADERS OR arg_NO_SYNC_QT
- OR NOT QT_FEATURE_headersclean)
+ OR NOT INPUT_headersclean)
set_target_properties("${target}" PROPERTIES _qt_no_headersclean_check ON)
endif()
@@ -475,8 +497,6 @@ function(qt_internal_add_module target)
endif()
endif()
- qt_internal_library_deprecation_level(deprecation_define)
-
if(NOT arg_HEADER_MODULE)
qt_autogen_tools_initial_setup(${target})
endif()
@@ -562,7 +582,6 @@ function(qt_internal_add_module target)
list(APPEND defines_for_extend_target
QT_NO_CAST_TO_ASCII QT_ASCII_CAST_WARNINGS
QT_MOC_COMPAT #we don't need warnings from calling moc code in our generated code
- QT_USE_QSTRINGBUILDER
QT_DEPRECATED_WARNINGS
QT_BUILDING_QT
QT_BUILD_${module_define_infix}_LIB ### FIXME: use QT_BUILD_ADDON for Add-ons or remove if we don't have add-ons anymore
@@ -579,19 +598,17 @@ function(qt_internal_add_module target)
set(arg_NO_UNITY_BUILD "")
endif()
- if(arg_NO_UNITY_BUILD_SOURCES)
- set(arg_NO_UNITY_BUILD_SOURCES "NO_UNITY_BUILD_SOURCES ${arg_NO_UNITY_BUILD_SOURCES}")
- else()
- set(arg_NO_UNITY_BUILD_SOURCES "")
- endif()
-
if(NOT arg_EXTERNAL_HEADERS)
set(arg_EXTERNAL_HEADERS "")
endif()
+
qt_internal_extend_target("${target}"
+ ${arg_NO_UNITY_BUILD}
SOURCES
${arg_SOURCES}
${arg_EXTERNAL_HEADERS}
+ NO_UNITY_BUILD_SOURCES
+ ${arg_NO_UNITY_BUILD_SOURCES}
INCLUDE_DIRECTORIES
${private_includes}
SYSTEM_INCLUDE_DIRECTORIES
@@ -620,8 +637,6 @@ function(qt_internal_add_module target)
DISABLE_AUTOGEN_TOOLS ${arg_DISABLE_AUTOGEN_TOOLS}
PRECOMPILED_HEADER ${arg_PRECOMPILED_HEADER}
NO_PCH_SOURCES ${arg_NO_PCH_SOURCES}
- ${arg_NO_UNITY_BUILD_SOURCES}
- ${arg_NO_UNITY_BUILD}
)
# The public module define is not meant to be used when building the module itself,
@@ -668,8 +683,21 @@ function(qt_internal_add_module target)
list(APPEND extra_cmake_files "${CMAKE_CURRENT_LIST_DIR}/${INSTALL_CMAKE_NAMESPACE}${target}Macros.cmake")
list(APPEND extra_cmake_includes "${INSTALL_CMAKE_NAMESPACE}${target}Macros.cmake")
endif()
+
if (EXISTS "${CMAKE_CURRENT_LIST_DIR}/${INSTALL_CMAKE_NAMESPACE}${target}ConfigExtras.cmake.in")
if(target STREQUAL Core)
+ if(NOT "${QT_NAMESPACE}" STREQUAL "")
+ string(MAKE_C_IDENTIFIER "${QT_NAMESPACE}" qt_namespace_sanity)
+ if(NOT "${QT_NAMESPACE}" STREQUAL "${qt_namespace_sanity}")
+ message(FATAL_ERROR "QT_NAMESPACE is not a valid C++ identifier: "
+ "${QT_NAMESPACE}.")
+ endif()
+ string(JOIN "" qtcore_namespace_definition
+ "set_property(TARGET \${__qt_core_target} "
+ "APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS QT_NAMESPACE=${QT_NAMESPACE})"
+ )
+ endif()
+
set(extra_cmake_code "")
# Add some variables for compatibility with Qt5 config files.
if(QT_FEATURE_reduce_exports)
@@ -699,6 +727,9 @@ set(QT_ALLOW_MISSING_TOOLS_PACKAGES TRUE)")
get_filename_component(basename ${cmake_file} NAME)
file(COPY ${cmake_file} DESTINATION ${config_build_dir})
list(APPEND extra_cmake_files "${config_build_dir}/${basename}")
+
+ # Make sure touched extra cmake files cause a reconfigure, so they get re-copied.
+ set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${cmake_file}")
endforeach()
list(APPEND extra_cmake_includes ${arg_EXTRA_CMAKE_INCLUDES})
@@ -804,7 +835,9 @@ set(QT_ALLOW_MISSING_TOOLS_PACKAGES TRUE)")
qt_internal_export_modern_cmake_config_targets_file(
TARGETS ${exported_targets}
EXPORT_NAME_PREFIX ${INSTALL_CMAKE_NAMESPACE}${target}
- CONFIG_INSTALL_DIR "${config_install_dir}")
+ CONFIG_BUILD_DIR "${config_build_dir}"
+ CONFIG_INSTALL_DIR "${config_install_dir}"
+ )
qt_internal_export_genex_properties(TARGETS ${target}
EXPORT_NAME_PREFIX ${INSTALL_CMAKE_NAMESPACE}${target}
@@ -824,7 +857,7 @@ set(QT_ALLOW_MISSING_TOOLS_PACKAGES TRUE)")
if(NOT arg_NO_SYNC_QT AND NOT arg_NO_MODULE_HEADERS)
list(APPEND interface_includes "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>")
- # syncqt.pl does not create a private header directory like 'include/6.0/QtFoo' unless
+ # syncqt does not create a private header directory like 'include/6.0/QtFoo' unless
# the module has foo_p.h header files. For QtZlib, there are no such private headers, so we
# need to make sure not to add such include paths unless the directory exists, otherwise
# consumers of the module will fail at CMake generation time stating that
@@ -881,6 +914,28 @@ set(QT_ALLOW_MISSING_TOOLS_PACKAGES TRUE)")
qt_add_list_file_finalizer(qt_finalize_module ${target} ${arg_INTERNAL_MODULE} ${arg_NO_PRIVATE_MODULE})
endfunction()
+function(qt_internal_apply_apple_privacy_manifest target)
+ # Avoid "INTERFACE_LIBRARY targets may only have whitelisted properties" error on CMake < 3.17.
+ get_target_property(target_type ${target} TYPE)
+ if("${target_type}" STREQUAL "INTERFACE_LIBRARY")
+ return()
+ endif()
+
+ if(APPLE)
+ # Privacy manifest
+ get_target_property(is_framework ${target} FRAMEWORK)
+ if(is_framework)
+ get_target_property(privacy_manifest ${target} _qt_privacy_manifest)
+ if(NOT privacy_manifest)
+ set(privacy_manifest
+ "${__qt_internal_cmake_apple_support_files_path}/PrivacyInfo.xcprivacy")
+ endif()
+ target_sources("${target}" PRIVATE "${privacy_manifest}")
+ set_property(TARGET "${target}" APPEND PROPERTY RESOURCE "${privacy_manifest}")
+ endif()
+ endif()
+endfunction()
+
function(qt_finalize_module target)
qt_internal_collect_module_headers(module_headers ${target})
@@ -896,12 +951,15 @@ function(qt_finalize_module target)
PUBLIC ${module_headers_public} "${module_depends_header}"
PRIVATE ${module_headers_private}
QPA ${module_headers_qpa}
+ RHI ${module_headers_rhi}
+ SSG ${module_headers_ssg}
)
qt_finalize_framework_headers_copy(${target})
qt_generate_prl_file(${target} "${INSTALL_LIBDIR}")
qt_generate_module_pri_file("${target}" ${ARGN})
qt_internal_generate_pkg_config_file(${target})
+ qt_internal_apply_apple_privacy_manifest(${target})
endfunction()
# Get a set of Qt module related values based on the target.
@@ -928,6 +986,8 @@ endfunction()
# * foo_versioned_inner_include_dir with the value "QtCore/6.2.0/QtCore"
# * foo_private_include_dir with the value "QtCore/6.2.0/QtCore/private"
# * foo_qpa_include_dir with the value "QtCore/6.2.0/QtCore/qpa"
+# * foo_rhi_include_dir with the value "QtCore/6.2.0/QtCore/rhi"
+# * foo_ssg_include_dir with the value "QtQuick3D/6.2.0/QtQuick3D/ssg"
# * foo_interface_name the interface name of the module stored in _qt_module_interface_name
# property, e.g. Core.
#
@@ -950,6 +1010,12 @@ endfunction()
# * foo_<build|install>_qpa_include_dir with
# qtbase_build_dir/include/QtCore/6.2.0/QtCore/qpa for build interface and
# include/QtCore/6.2.0/QtCore/qpa for install interface.
+# * foo_<build|install>_rhi_include_dir with
+# qtbase_build_dir/include/QtCore/6.2.0/QtCore/rhi for build interface and
+# include/QtCore/6.2.0/QtCore/rhi for install interface.
+# * foo_<build|install>_ssg_include_dir with
+# qtbase_build_dir/include/<module>/x.y.z/<module>/ssg for build interface and
+# include/<module>/x.y.z/<module>/ssg for install interface.
# The following values are set by the function and might be useful in caller's scope:
# * repo_install_interface_include_dir contains path to the top-level repository include directory,
# e.g. qtbase_build_dir/include
@@ -984,6 +1050,10 @@ the different base name for the module info variables.")
"${${result}_versioned_inner_include_dir}/private")
set("${result}_qpa_include_dir"
"${${result}_versioned_inner_include_dir}/qpa")
+ set("${result}_rhi_include_dir"
+ "${${result}_versioned_inner_include_dir}/rhi")
+ set("${result}_ssg_include_dir"
+ "${${result}_versioned_inner_include_dir}/ssg")
# Module build interface directories
set(repo_build_interface_include_dir "${QT_BUILD_DIR}/include")
@@ -997,6 +1067,10 @@ the different base name for the module info variables.")
"${repo_build_interface_include_dir}/${${result}_private_include_dir}")
set("${result}_build_interface_qpa_include_dir"
"${repo_build_interface_include_dir}/${${result}_qpa_include_dir}")
+ set("${result}_build_interface_rhi_include_dir"
+ "${repo_build_interface_include_dir}/${${result}_rhi_include_dir}")
+ set("${result}_build_interface_ssg_include_dir"
+ "${repo_build_interface_include_dir}/${${result}_ssg_include_dir}")
# Module install interface directories
set(repo_install_interface_include_dir "${INSTALL_INCLUDEDIR}")
@@ -1010,6 +1084,10 @@ the different base name for the module info variables.")
"${repo_install_interface_include_dir}/${${result}_private_include_dir}")
set("${result}_install_interface_qpa_include_dir"
"${repo_install_interface_include_dir}/${${result}_qpa_include_dir}")
+ set("${result}_install_interface_rhi_include_dir"
+ "${repo_install_interface_include_dir}/${${result}_rhi_include_dir}")
+ set("${result}_install_interface_ssg_include_dir"
+ "${repo_install_interface_include_dir}/${${result}_ssg_include_dir}")
set("${result}" "${module}" PARENT_SCOPE)
set("${result}_versioned" "${module_versioned}" PARENT_SCOPE)
@@ -1023,6 +1101,8 @@ the different base name for the module info variables.")
"${${result}_versioned_inner_include_dir}" PARENT_SCOPE)
set("${result}_private_include_dir" "${${result}_private_include_dir}" PARENT_SCOPE)
set("${result}_qpa_include_dir" "${${result}_qpa_include_dir}" PARENT_SCOPE)
+ set("${result}_rhi_include_dir" "${${result}_rhi_include_dir}" PARENT_SCOPE)
+ set("${result}_ssg_include_dir" "${${result}_ssg_include_dir}" PARENT_SCOPE)
set("${result}_interface_name" "${module_interface_name}" PARENT_SCOPE)
# Setting module build interface directories in parent scope
@@ -1037,6 +1117,10 @@ the different base name for the module info variables.")
"${${result}_build_interface_private_include_dir}" PARENT_SCOPE)
set("${result}_build_interface_qpa_include_dir"
"${${result}_build_interface_qpa_include_dir}" PARENT_SCOPE)
+ set("${result}_build_interface_rhi_include_dir"
+ "${${result}_build_interface_rhi_include_dir}" PARENT_SCOPE)
+ set("${result}_build_interface_ssg_include_dir"
+ "${${result}_build_interface_ssg_include_dir}" PARENT_SCOPE)
# Setting module install interface directories in parent scope
set(repo_install_interface_include_dir "${repo_install_interface_include_dir}" PARENT_SCOPE)
@@ -1050,6 +1134,10 @@ the different base name for the module info variables.")
"${${result}_install_interface_private_include_dir}" PARENT_SCOPE)
set("${result}_install_interface_qpa_include_dir"
"${${result}_install_interface_qpa_include_dir}" PARENT_SCOPE)
+ set("${result}_install_interface_rhi_include_dir"
+ "${${result}_install_interface_rhi_include_dir}" PARENT_SCOPE)
+ set("${result}_install_interface_ssg_include_dir"
+ "${${result}_install_interface_ssg_include_dir}" PARENT_SCOPE)
endfunction()
function(qt_internal_list_to_json_array out_var list_var)
@@ -1080,7 +1168,7 @@ function(qt_describe_module target)
get_target_property(target_type ${target} TYPE)
if(NOT target_type STREQUAL "INTERFACE_LIBRARY")
- get_target_property(plugin_types ${target} MODULE_PLUGIN_TYPES)
+ get_target_property(plugin_types ${target} QMAKE_MODULE_PLUGIN_TYPES)
if(plugin_types)
qt_internal_list_to_json_array(plugin_types plugin_types)
string(APPEND extra_module_information "\n \"plugin_types\": ${plugin_types},")
@@ -1113,7 +1201,7 @@ endfunction()
function(qt_internal_generate_cpp_global_exports target module_define_infix)
cmake_parse_arguments(arg
- "GENERATE_PRIVATE_CPP_EXPORTS"
+ ""
"CPP_EXPORT_HEADER_BASE_NAME"
"" ${ARGN}
)
@@ -1138,26 +1226,12 @@ function(qt_internal_generate_cpp_global_exports target module_define_infix)
set(${out_public_header} "${generated_header_path}" PARENT_SCOPE)
target_sources(${target} PRIVATE "${generated_header_path}")
set_source_files_properties("${generated_header_path}" PROPERTIES GENERATED TRUE)
-
- if(arg_GENERATE_PRIVATE_CPP_EXPORTS)
- set(generated_private_header_path
- "${module_build_interface_private_include_dir}/${header_base_name}_p.h"
- )
-
- configure_file("${QT_CMAKE_DIR}/modulecppexports_p.h.in"
- "${generated_private_header_path}" @ONLY
- )
-
- set(${out_private_header} "${generated_private_header_path}" PARENT_SCOPE)
- target_sources(${target} PRIVATE "${generated_private_header_path}")
- set_source_files_properties("${generated_private_header_path}" PROPERTIES GENERATED TRUE)
- endif()
endfunction()
function(qt_internal_install_module_headers target)
set(options)
set(one_value_args)
- set(multi_value_args PUBLIC PRIVATE QPA)
+ set(multi_value_args PUBLIC PRIVATE QPA RHI SSG)
cmake_parse_arguments(arg "${options}" "${one_value_args}" "${multi_value_args}" ${ARGN})
qt_internal_module_info(module ${target})
@@ -1182,6 +1256,8 @@ function(qt_internal_install_module_headers target)
PUBLIC ${arg_PUBLIC}
PRIVATE ${arg_PRIVATE}
QPA ${arg_QPA}
+ RHI ${arg_RHI}
+ SSG ${arg_SSG}
)
else()
if(arg_PUBLIC)
@@ -1195,6 +1271,12 @@ function(qt_internal_install_module_headers target)
if(arg_QPA)
qt_install(FILES ${arg_QPA} DESTINATION "${module_install_interface_qpa_include_dir}")
endif()
+ if(arg_RHI)
+ qt_install(FILES ${arg_RHI} DESTINATION "${module_install_interface_rhi_include_dir}")
+ endif()
+ if(arg_SSG)
+ qt_install(FILES ${arg_SSG} DESTINATION "${module_install_interface_ssg_include_dir}")
+ endif()
endif()
endfunction()
@@ -1202,13 +1284,30 @@ function(qt_internal_collect_module_headers out_var target)
set(${out_var}_public "")
set(${out_var}_private "")
set(${out_var}_qpa "")
+ set(${out_var}_rhi "")
+ set(${out_var}_ssg "")
set(${out_var}_all "")
qt_internal_get_target_sources(sources ${target})
+ get_target_property(target_type ${target} TYPE)
+ if(target_type STREQUAL "INTERFACE_LIBRARY")
+ set(source_dir "${CMAKE_CURRENT_SOURCE_DIR}")
+ set(binary_dir "${CMAKE_CURRENT_BINARY_DIR}")
+ else()
+ get_target_property(source_dir ${target} SOURCE_DIR)
+ get_target_property(binary_dir ${target} BINARY_DIR)
+ endif()
+ get_filename_component(source_dir "${source_dir}" ABSOLUTE)
+ get_filename_component(binary_dir "${binary_dir}" ABSOLUTE)
+
+ get_target_property(is_3rdparty_library ${target} _qt_module_is_3rdparty_header_library)
+
get_target_property(public_filter ${target} _qt_module_public_headers_filter_regex)
get_target_property(private_filter ${target} _qt_module_private_headers_filter_regex)
get_target_property(qpa_filter ${target} _qt_module_qpa_headers_filter_regex)
+ get_target_property(rhi_filter ${target} _qt_module_rhi_headers_filter_regex)
+ get_target_property(ssg_filter ${target} _qt_module_ssg_headers_filter_regex)
set(condition_independent_headers_warning "")
foreach(file_path IN LISTS sources)
@@ -1216,6 +1315,27 @@ function(qt_internal_collect_module_headers out_var target)
if(NOT file_name MATCHES ".+\\.h$")
continue()
endif()
+
+ get_source_file_property(non_module_header ${file_path} _qt_non_module_header)
+ if(non_module_header)
+ continue()
+ endif()
+
+ get_filename_component(file_path "${file_path}" ABSOLUTE)
+
+ string(FIND "${file_path}" "${source_dir}" source_dir_pos)
+ if(source_dir_pos EQUAL 0)
+ set(is_outside_module_source_dir FALSE)
+ else()
+ set(is_outside_module_source_dir TRUE)
+ endif()
+
+ get_source_file_property(is_generated "${file_path}" GENERATED)
+ # Skip all header files outside the module source directory, except the generated files.
+ if(is_outside_module_source_dir AND NOT is_generated)
+ continue()
+ endif()
+
get_source_file_property(condition ${file_path} _qt_extend_target_condition)
if(NOT condition STREQUAL "" AND NOT condition STREQUAL "NOTFOUND")
list(JOIN condition " " condition_string)
@@ -1224,15 +1344,29 @@ function(qt_internal_collect_module_headers out_var target)
"\nCondition:\n ${condition_string}")
endif()
- get_source_file_property(is_generated "${file_path}" GENERATED)
- get_filename_component(file_path "${file_path}" ABSOLUTE)
- get_filename_component(file_path "${file_path}" REALPATH)
+ if(is_outside_module_source_dir)
+ set(base_dir "${binary_dir}")
+ else()
+ set(base_dir "${source_dir}")
+ endif()
+
+ file(RELATIVE_PATH file_path_rel "${base_dir}" "${file_path}")
+ if(file_path_rel MATCHES "3rdparty/.+" AND NOT is_3rdparty_library)
+ set(is_3rdparty_header TRUE)
+ else()
+ set(is_3rdparty_header FALSE)
+ endif()
list(APPEND ${out_var}_all "${file_path}")
if(qpa_filter AND file_name MATCHES "${qpa_filter}")
list(APPEND ${out_var}_qpa "${file_path}")
+ elseif(rhi_filter AND file_name MATCHES "${rhi_filter}")
+ list(APPEND ${out_var}_rhi "${file_path}")
+ elseif(ssg_filter AND file_name MATCHES "${ssg_filter}")
+ list(APPEND ${out_var}_ssg "${file_path}")
elseif(private_filter AND file_name MATCHES "${private_filter}")
list(APPEND ${out_var}_private "${file_path}")
- elseif(NOT public_filter OR file_name MATCHES "${public_filter}")
+ elseif((NOT public_filter OR file_name MATCHES "${public_filter}")
+ AND NOT is_3rdparty_header)
list(APPEND ${out_var}_public "${file_path}")
endif()
if(is_generated)
@@ -1252,7 +1386,7 @@ function(qt_internal_collect_module_headers out_var target)
endif()
- set(header_types public private qpa)
+ set(header_types public private qpa rhi ssg)
set(has_header_types_properties "")
foreach(header_type IN LISTS header_types)
get_target_property(current_propety_value ${target} _qt_module_has_${header_type}_headers)
@@ -1274,5 +1408,7 @@ function(qt_internal_collect_module_headers out_var target)
_qt_module_has_public_headers
_qt_module_has_private_headers
_qt_module_has_qpa_headers
+ _qt_module_has_rhi_headers
+ _qt_module_has_ssg_headers
)
endfunction()
diff --git a/cmake/QtModuleToolsConfig.cmake.in b/cmake/QtModuleToolsConfig.cmake.in
index 4d852dc98e..ec447aa55b 100644
--- a/cmake/QtModuleToolsConfig.cmake.in
+++ b/cmake/QtModuleToolsConfig.cmake.in
@@ -1,3 +1,6 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
@PACKAGE_INIT@
cmake_minimum_required(VERSION @min_new_policy_version@...@max_new_policy_version@)
diff --git a/cmake/QtModuleToolsDependencies.cmake.in b/cmake/QtModuleToolsDependencies.cmake.in
index 2eaaf74976..b2504a0943 100644
--- a/cmake/QtModuleToolsDependencies.cmake.in
+++ b/cmake/QtModuleToolsDependencies.cmake.in
@@ -1,3 +1,6 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
# Find "ModuleTools" dependencies, which are other ModuleTools packages.
set(@INSTALL_CMAKE_NAMESPACE@@target@_FOUND FALSE)
set(__qt_@target@_tool_deps "@package_deps@")
diff --git a/cmake/QtModuleToolsVersionlessTargets.cmake.in b/cmake/QtModuleToolsVersionlessTargets.cmake.in
index 0cf554c34a..bc861a77b6 100644
--- a/cmake/QtModuleToolsVersionlessTargets.cmake.in
+++ b/cmake/QtModuleToolsVersionlessTargets.cmake.in
@@ -1,3 +1,6 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
foreach(__qt_tool @tool_targets_non_prefixed@)
if(NOT TARGET Qt::${__qt_tool} AND TARGET Qt6::${__qt_tool})
add_executable(Qt::${__qt_tool} IMPORTED GLOBAL)
diff --git a/cmake/QtPkgConfigHelpers.cmake b/cmake/QtPkgConfigHelpers.cmake
index 370ff607c4..ea28516941 100644
--- a/cmake/QtPkgConfigHelpers.cmake
+++ b/cmake/QtPkgConfigHelpers.cmake
@@ -51,6 +51,17 @@ function(qt_internal_generate_pkg_config_file module)
list(TRANSFORM loose_include_dirs REPLACE "${INSTALL_INCLUDEDIR}" "\${includedir}")
list(TRANSFORM loose_include_dirs REPLACE "${INSTALL_MKSPECSDIR}" "\${mkspecsdir}")
+ # Remove genex wrapping around gc_sections flag because we can't evaluate genexes like
+ # $<CXX_COMPILER_ID> in file(GENERATE). And given that .pc files don't support dynamic
+ # evaluation like the $<CXX_COMPILER_ID> genex, distros will be expected to patch the .pc
+ # files according to which compiler they intend to be used with.
+ get_property(gc_sections_with_genex GLOBAL PROPERTY _qt_internal_gc_sections_with_genex)
+ get_property(gc_sections_without_genex GLOBAL PROPERTY _qt_internal_gc_sections_without_genex)
+ if(loose_link_options AND gc_sections_with_genex AND gc_sections_without_genex)
+ string(REPLACE "${gc_sections_with_genex}" "${gc_sections_without_genex}"
+ loose_link_options "${loose_link_options}")
+ endif()
+
qt_internal_set_pkg_config_cpp_flags(link_options "${loose_link_options}" "")
qt_internal_set_pkg_config_cpp_flags(compile_defs "${loose_compile_defs}" -D)
qt_internal_set_pkg_config_cpp_flags(include_dirs "${loose_include_dirs}" -I)
@@ -63,7 +74,7 @@ function(qt_internal_generate_pkg_config_file module)
foreach(dep IN LISTS loose_target_requires)
if(dep MATCHES "^Qt::")
string(REGEX REPLACE "Qt" "${QT_CMAKE_EXPORT_NAMESPACE}" dep ${dep})
- else()
+ elseif(NOT dep MATCHES "^${QT_CMAKE_EXPORT_NAMESPACE}::")
# TODO: Figure out a way to get non-Qt requirements PkgConfig files.
continue()
endif()
diff --git a/cmake/QtPlatformAndroid.cmake b/cmake/QtPlatformAndroid.cmake
index 65095de329..6b8bd744c1 100644
--- a/cmake/QtPlatformAndroid.cmake
+++ b/cmake/QtPlatformAndroid.cmake
@@ -36,7 +36,7 @@ function(qt_get_android_sdk_jar_for_api api out_jar_location)
endfunction()
# Minimum recommend android SDK api version
-set(QT_ANDROID_API_VERSION "android-33")
+set(QT_ANDROID_API_VERSION "android-34")
function(qt_internal_sort_android_platforms out_var)
if(CMAKE_VERSION GREATER_EQUAL 3.18)
@@ -185,7 +185,7 @@ define_property(TARGET
)
# Returns test execution arguments for Android targets
-function(qt_internal_android_test_arguments target out_test_runner out_test_arguments)
+function(qt_internal_android_test_arguments target timeout out_test_runner out_test_arguments)
set(${out_test_runner} "${QT_HOST_PATH}/${QT${PROJECT_VERSION_MAJOR}_HOST_INFO_BINDIR}/androidtestrunner" PARENT_SCOPE)
set(deployment_tool "${QT_HOST_PATH}/${QT${PROJECT_VERSION_MAJOR}_HOST_INFO_BINDIR}/androiddeployqt")
@@ -195,15 +195,19 @@ function(qt_internal_android_test_arguments target out_test_runner out_test_argu
endif()
set(target_binary_dir "$<TARGET_PROPERTY:${target},BINARY_DIR>")
- set(apk_dir "${target_binary_dir}/android-build")
-
+ if(QT_USE_TARGET_ANDROID_BUILD_DIR)
+ set(apk_dir "${target_binary_dir}/android-build-${target}")
+ else()
+ set(apk_dir "${target_binary_dir}/android-build")
+ endif()
set(${out_test_arguments}
"--path" "${apk_dir}"
"--adb" "${ANDROID_SDK_ROOT}/platform-tools/adb"
"--skip-install-root"
- "--make" "${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target ${target}_make_apk"
+ "--make" "\"${CMAKE_COMMAND}\" --build ${CMAKE_BINARY_DIR} --target ${target}_make_apk"
"--apk" "${apk_dir}/${target}.apk"
- "--timeout" "-1"
+ "--ndk-stack" "${ANDROID_NDK_ROOT}/ndk-stack"
+ "--timeout" "${timeout}"
"--verbose"
PARENT_SCOPE
)
diff --git a/cmake/QtPlatformSupport.cmake b/cmake/QtPlatformSupport.cmake
index 16a5a1fe0a..9f8498e42c 100644
--- a/cmake/QtPlatformSupport.cmake
+++ b/cmake/QtPlatformSupport.cmake
@@ -12,7 +12,6 @@ endfunction()
qt_set01(LINUX CMAKE_SYSTEM_NAME STREQUAL "Linux")
qt_set01(HPUX CMAKE_SYSTEM_NAME STREQUAL "HPUX")
qt_set01(ANDROID CMAKE_SYSTEM_NAME STREQUAL "Android") # FIXME: How to identify this?
-qt_set01(NACL CMAKE_SYSTEM_NAME STREQUAL "NaCl") # FIXME: How to identify this?
qt_set01(INTEGRITY CMAKE_SYSTEM_NAME STREQUAL "Integrity") # FIXME: How to identify this?
qt_set01(VXWORKS CMAKE_SYSTEM_NAME STREQUAL "VxWorks") # FIXME: How to identify this?
qt_set01(QNX CMAKE_SYSTEM_NAME STREQUAL "QNX") # FIXME: How to identify this?
@@ -33,7 +32,8 @@ qt_set01(BSD APPLE OR OPENBSD OR FREEBSD OR NETBSD)
qt_set01(IOS APPLE AND CMAKE_SYSTEM_NAME STREQUAL "iOS")
qt_set01(TVOS APPLE AND CMAKE_SYSTEM_NAME STREQUAL "tvOS")
qt_set01(WATCHOS APPLE AND CMAKE_SYSTEM_NAME STREQUAL "watchOS")
-qt_set01(UIKIT APPLE AND (IOS OR TVOS OR WATCHOS))
+qt_set01(VISIONOS APPLE AND CMAKE_SYSTEM_NAME STREQUAL "visionOS")
+qt_set01(UIKIT APPLE AND (IOS OR TVOS OR WATCHOS OR VISIONOS))
qt_set01(MACOS APPLE AND NOT UIKIT)
qt_set01(GCC CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
diff --git a/cmake/QtPlatformTargetHelpers.cmake b/cmake/QtPlatformTargetHelpers.cmake
index 54d1916f9e..f1976b9975 100644
--- a/cmake/QtPlatformTargetHelpers.cmake
+++ b/cmake/QtPlatformTargetHelpers.cmake
@@ -49,6 +49,15 @@ function(qt_internal_setup_public_platform_target)
target_compile_options(Platform INTERFACE "$<$<CXX_COMPILER_ID:Clang>:-fno-direct-access-external-data>")
endif()
+ # Qt checks if a given platform supports 128 bit integers
+ # by checking if __SIZEOF_128__ is defined
+ # VXWORKS doesn't support 128 bit integers
+ # but it uses clang which defines __SIZEOF_128__
+ # which breaks the detection mechanism
+ if(VXWORKS)
+ target_compile_definitions(Platform INTERFACE "-DQT_NO_INT128")
+ endif()
+
qt_set_msvc_cplusplus_options(Platform INTERFACE)
# Propagate minimum C++ 17 via Platform to Qt consumers (apps), after the global features
diff --git a/cmake/QtPluginConfig.cmake.in b/cmake/QtPluginConfig.cmake.in
index 7bd9a1d579..1dc30b0338 100644
--- a/cmake/QtPluginConfig.cmake.in
+++ b/cmake/QtPluginConfig.cmake.in
@@ -1,6 +1,9 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
include_guard(DIRECTORY)
-if(DEFINED QT_REPO_DEPENDENCIES AND NOT QT_BUILD_STANDALONE_TESTS)
+if(DEFINED QT_REPO_DEPENDENCIES AND NOT QT_INTERNAL_BUILD_STANDALONE_PARTS)
# We're building a Qt repository.
# Skip this plugin if it has not been provided by one of this repo's dependencies.
string(TOLOWER "@PROJECT_NAME@" lower_case_project_name)
diff --git a/cmake/QtPluginDependencies.cmake.in b/cmake/QtPluginDependencies.cmake.in
index c9dd1873d8..bcbb9bb5db 100644
--- a/cmake/QtPluginDependencies.cmake.in
+++ b/cmake/QtPluginDependencies.cmake.in
@@ -1,3 +1,6 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
set(@target@_FOUND FALSE)
# note: _third_party_deps example: "ICU\\;FALSE\\;1.0\\;i18n uc data;ZLIB\\;FALSE\\;\\;"
diff --git a/cmake/QtPluginHelpers.cmake b/cmake/QtPluginHelpers.cmake
index 835541fe09..a4188b7289 100644
--- a/cmake/QtPluginHelpers.cmake
+++ b/cmake/QtPluginHelpers.cmake
@@ -91,6 +91,11 @@ function(qt_internal_add_plugin target)
qt6_add_plugin(${target} ${plugin_args})
qt_internal_mark_as_internal_library(${target})
+ get_target_property(target_type "${target}" TYPE)
+ if(plugin_init_target AND TARGET "${plugin_init_target}")
+ qt_internal_add_target_aliases("${plugin_init_target}")
+ endif()
+
set(plugin_type "")
# TODO: Transitional: Remove the TYPE option handling after all repos have been converted to use
# PLUGIN_TYPE.
@@ -165,8 +170,6 @@ function(qt_internal_add_plugin target)
qt_handle_multi_config_output_dirs("${target}")
- qt_internal_library_deprecation_level(deprecation_define)
-
qt_autogen_tools_initial_setup(${target})
unset(plugin_install_package_suffix)
@@ -211,73 +214,17 @@ function(qt_internal_add_plugin target)
# This QT_PLUGINS assignment is only used by QtPostProcessHelpers to decide if a
# QtModulePlugins.cmake file should be generated.
set_property(TARGET "${qt_module_target}" APPEND PROPERTY QT_PLUGINS "${target}")
+ else()
+ # The _qt_plugins property is considered when collecting the plugins in
+ # deployment process. The usecase is following:
+ # QtModuleX is built separately and installed, so it's imported.
+ # The plugin is built in some application build tree and its PLUGIN_TYPE is associated
+ # with QtModuleX.
+ set_property(TARGET "${qt_module_target}" APPEND PROPERTY _qt_plugins "${target}")
endif()
set(plugin_target_versioned "${QT_CMAKE_EXPORT_NAMESPACE}::${target}")
get_target_property(type "${plugin_target_versioned}" TYPE)
- if(type STREQUAL STATIC_LIBRARY)
- # Associate plugin with its Qt module when both are both built in the same repository.
- # Check that by comparing the PROJECT_NAME of each.
- # This covers auto-linking of the majority of plugins to executables and in-tree tests.
- # Linking of plugins in standalone tests (when the Qt module will be an imported target)
- # is handled instead by the complicated genex logic in QtModulePlugins.cmake.in.
- set(is_plugin_and_module_in_same_project FALSE)
- if(NOT is_imported_qt_module)
- get_target_property(module_source_dir ${qt_module_target} SOURCE_DIR)
- get_directory_property(module_project_name
- DIRECTORY ${module_source_dir}
- DEFINITION PROJECT_NAME
- )
- if(module_project_name STREQUAL PROJECT_NAME)
- set(is_plugin_and_module_in_same_project TRUE)
- endif()
-
- # When linking static plugins with the special logic in qt_internal_add_executable,
- # make sure to skip non-default plugins.
- if(is_plugin_and_module_in_same_project AND _default_plugin)
- set_property(TARGET ${qt_module_target} APPEND PROPERTY
- _qt_initial_repo_plugins
- "${target}")
- set_property(TARGET ${qt_module_target} APPEND PROPERTY
- _qt_initial_repo_plugin_class_names
- "$<TARGET_PROPERTY:${target},QT_PLUGIN_CLASS_NAME>"
- )
- endif()
- endif()
-
- # Associate plugin with its Qt module when the plugin is built in the current repository
- # but the module is built in a different repository (qtsvg's QSvgPlugin associated with
- # qtbase's QtGui).
- # The association is done in a separate property, to ensure that reconfiguring in-tree tests
- # in qtbase doesn't accidentally cause linking to a plugin from a previously built qtsvg.
- # Needed for in-tree tests like in qtsvg, qtimageformats.
- # This is done for each Qt module regardless if it's an imported target or not, to handle
- # both per-repo and top-level builds (in per-repo build of qtsvg QtGui is imported, in a
- # top-level build Gui is not imported, but in both cases qtsvg tests need to link to
- # QSvgPlugin).
- #
- # TODO: Top-level in-tree tests and qdeclarative per-repo in-tree tests that depend on
- # static Qml plugins won't work due to the requirement of running qmlimportscanner
- # at configure time, but qmlimportscanner is not built at that point. Moving the
- # execution of qmlimportscanner to build time is non-trivial because qmlimportscanner
- # not only generates a cpp file to compile but also outputs a list of static plugins
- # that should be linked and there is no straightforward way to tell CMake to link
- # against a list of libraries that was discovered at build time (apart from
- # response files, which apparently might not work on all platforms).
- # qmake doesn't have this problem because each project is configured separately so
- # qmlimportscanner is always built by the time it needs to be run for a test.
- if(NOT is_plugin_and_module_in_same_project AND _default_plugin)
- string(MAKE_C_IDENTIFIER "${PROJECT_NAME}" current_project_name)
- set(prop_prefix "_qt_repo_${current_project_name}")
- set_property(TARGET ${qt_module_target} APPEND PROPERTY
- ${prop_prefix}_plugins "${target}")
- set_property(TARGET ${qt_module_target} APPEND PROPERTY
- ${prop_prefix}_plugin_class_names
- "$<TARGET_PROPERTY:${target},QT_PLUGIN_CLASS_NAME>"
- )
- endif()
- endif()
-
qt_internal_add_autogen_sync_header_dependencies(${target} ${qt_module_target})
endif()
@@ -333,14 +280,13 @@ function(qt_internal_add_plugin target)
set(arg_NO_UNITY_BUILD "")
endif()
- if(arg_NO_UNITY_BUILD_SOURCES)
- set(arg_NO_UNITY_BUILD_SOURCES "NO_UNITY_BUILD_SOURCES ${arg_NO_UNITY_BUILD_SOURCES}")
- else()
- set(arg_NO_UNITY_BUILD_SOURCES "")
- endif()
-
qt_internal_extend_target("${target}"
+ ${arg_NO_UNITY_BUILD}
SOURCES ${arg_SOURCES}
+ NO_PCH_SOURCES
+ ${arg_NO_PCH_SOURCES}
+ NO_UNITY_BUILD_SOURCES
+ ${arg_NO_UNITY_BUILD_SOURCES}
INCLUDE_DIRECTORIES
${private_includes}
SYSTEM_INCLUDE_DIRECTORIES
@@ -366,8 +312,6 @@ function(qt_internal_add_plugin target)
MOC_OPTIONS ${arg_MOC_OPTIONS}
ENABLE_AUTOGEN_TOOLS ${arg_ENABLE_AUTOGEN_TOOLS}
DISABLE_AUTOGEN_TOOLS ${arg_DISABLE_AUTOGEN_TOOLS}
- ${arg_NO_UNITY_BUILD_SOURCES}
- ${arg_NO_UNITY_BUILD}
)
qt_internal_add_repo_local_defines("${target}")
@@ -386,7 +330,6 @@ function(qt_internal_add_plugin target)
qt_register_target_dependencies("${target}" "${arg_PUBLIC_LIBRARIES}" "${qt_libs_private}")
- get_target_property(target_type "${target}" TYPE)
if(target_type STREQUAL STATIC_LIBRARY)
if(qt_module_target)
qt_internal_link_internal_platform_for_object_library("${plugin_init_target}")
@@ -550,6 +493,7 @@ function(qt_internal_add_darwin_permission_plugin permission)
Qt::Core
Qt::CorePrivate
${FWFoundation}
+ NO_UNITY_BUILD # disable unity build: the same file is built with two different preprocessor defines.
)
# Disable PCH since CMake falls over on single .mm source targets
@@ -590,10 +534,12 @@ function(qt_internal_add_darwin_permission_plugin permission)
)
if(CMAKE_VERSION VERSION_LESS "3.18")
set_property(SOURCE "${separate_request_source_file}" PROPERTY GENERATED TRUE)
+ set_property(SOURCE "${separate_request_source_file}" PROPERTY SKIP_UNITY_BUILD_INCLUSION TRUE)
endif()
target_sources(${plugin_target} PRIVATE
"$<${separate_request_genex}:${separate_request_source_file}>"
)
+
set_property(TARGET ${plugin_target} APPEND PROPERTY
EXPORT_PROPERTIES _qt_darwin_permissison_separate_request
)
@@ -612,3 +558,48 @@ function(qt_internal_add_darwin_permission_plugin permission)
QT_PLUGIN_PRI_EXTRA_CONTENT ${extra_plugin_pri_content}
)
endfunction()
+
+# The function looks and links the static plugins that the target depends on. The function behaves
+# similar to qt_import_plugins, but should be used when building Qt executable or shared libraries.
+# It's expected that all dependencies are valid targets at the time when the function is called.
+# If not their plugins will be not collected for linking.
+function(qt_internal_import_plugins target)
+ set(plugin_targets "")
+ foreach(dep_target IN LISTS ARGN)
+ if(dep_target AND TARGET ${dep_target})
+ get_target_property(plugins ${dep_target} _qt_plugins)
+ if(plugins)
+ list(APPEND plugin_targets ${plugins})
+ else()
+ # Fallback should be remove in Qt 7.
+ get_target_property(target_type ${dep_target} TYPE)
+ if(NOT "${target_type}" STREQUAL "INTERFACE_LIBRARY")
+ get_target_property(plugins ${dep_target} QT_PLUGINS)
+ if(plugins)
+ list(APPEND plugin_targets ${plugins})
+ endif()
+ endif()
+ endif()
+ endif()
+ endforeach()
+
+ set(non_imported_plugin_targets "")
+ foreach(plugin_target IN LISTS plugin_targets)
+ if(NOT TARGET ${plugin_target} OR "${plugin_target}" IN_LIST non_imported_plugin_targets)
+ continue()
+ endif()
+
+ get_target_property(is_imported ${plugin_target} IMPORTED)
+ if(NOT is_imported)
+ list(APPEND non_imported_plugin_targets "${plugin_target}")
+ endif()
+ endforeach()
+
+ if(plugin_targets)
+ __qt_internal_collect_plugin_init_libraries("${non_imported_plugin_targets}" init_libraries)
+ __qt_internal_collect_plugin_libraries("${non_imported_plugin_targets}" plugin_libraries)
+ if(plugin_libraries OR init_libraries)
+ target_link_libraries(${target} PRIVATE ${plugin_libraries} ${init_libraries})
+ endif()
+ endif()
+endfunction()
diff --git a/cmake/QtPlugins.cmake.in b/cmake/QtPlugins.cmake.in
index 405d5f37b9..e668a4cbef 100644
--- a/cmake/QtPlugins.cmake.in
+++ b/cmake/QtPlugins.cmake.in
@@ -1,6 +1,14 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
include_guard(DIRECTORY)
@QT_MODULE_PLUGIN_INCLUDES@
+# Distributions should probably change this default.
+if(NOT DEFINED QT_SKIP_AUTO_PLUGIN_INCLUSION)
+ set(QT_SKIP_AUTO_PLUGIN_INCLUSION OFF)
+endif()
+
if(NOT QT_NO_CREATE_TARGETS AND NOT QT_SKIP_AUTO_PLUGIN_INCLUSION)
__qt_internal_include_plugin_packages(@QT_MODULE@)
endif()
diff --git a/cmake/QtPostProcess.cmake b/cmake/QtPostProcess.cmake
index b178372c60..f69448c14a 100644
--- a/cmake/QtPostProcess.cmake
+++ b/cmake/QtPostProcess.cmake
@@ -1,8 +1,6 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-include(QtPostProcessHelpers)
-
qt_internal_create_depends_files()
qt_generate_build_internals_extra_cmake_code()
qt_internal_create_plugins_auto_inclusion_files()
diff --git a/cmake/QtPostProcessHelpers.cmake b/cmake/QtPostProcessHelpers.cmake
index 83bcabe49b..9654b18664 100644
--- a/cmake/QtPostProcessHelpers.cmake
+++ b/cmake/QtPostProcessHelpers.cmake
@@ -67,6 +67,11 @@ macro(qt_collect_third_party_deps target)
set(package_optional_components "")
endif()
+ get_target_property(package_components_id ${dep} _qt_package_components_id)
+ if(package_components_id)
+ list(APPEND third_party_deps_package_components_ids ${package_components_id})
+ endif()
+
list(APPEND third_party_deps
"${package_name}\;${package_is_optional}\;${package_version}\;${package_components}\;${package_optional_components}")
endif()
@@ -74,6 +79,42 @@ macro(qt_collect_third_party_deps target)
endforeach()
endmacro()
+# Collect provided targets for the given list of package component ids.
+#
+# ${target} is merely used as a key infix to avoid name clashes in the Dependencies.cmake files.
+# package_component_ids is a list of '${package_name}-${components}-${optional_components}' keys
+# that are sanitized not to contain spaces or semicolons.
+#
+# The output is a list of variable assignments to add to the dependencies file.
+# Each variable assignment is the list of provided targets for a given package component id.
+#
+# We use these extra assignments instead of adding the info to the existing 'third_party_deps' list
+# to make the information more readable. That list already has 5 items per package, making it
+# quite hard to read.
+function(qt_internal_collect_third_party_dep_packages_info
+ target
+ package_components_ids
+ out_packages_info)
+
+ # There might be multiple calls to find the same package, so remove the duplicates.
+ list(REMOVE_DUPLICATES package_components_ids)
+
+ set(packages_info "")
+
+ foreach(package_key IN LISTS package_components_ids)
+ get_cmake_property(provided_targets _qt_find_package_${package_key}_provided_targets)
+ if(provided_targets)
+ set(key "__qt_${target}_third_party_package_${package_key}_provided_targets")
+
+ # Escape the semicolon, so it is preserved in the list(JOIN) below
+ string(REPLACE ";" "\;" provided_targets "${provided_targets}")
+ string(APPEND packages_info "set(${key} \"${provided_targets}\")\n")
+ endif()
+ endforeach()
+
+ set(${out_packages_info} "${packages_info}" PARENT_SCOPE)
+endfunction()
+
# Filter the dependency targets to collect unique set of the dependencies.
# non-Private and Private targets are treated as the single object in this context
# since they are defined by the same CMake package. For internal modules
@@ -149,6 +190,7 @@ function(qt_internal_create_module_depends_file target)
# ModuleDependencies.cmake.
set(third_party_deps "")
set(third_party_deps_seen "")
+ set(third_party_deps_package_components_ids "")
# Used for collecting Qt tool dependencies that should be find_package()'d in
# ModuleToolsDependencies.cmake.
@@ -216,6 +258,14 @@ function(qt_internal_create_module_depends_file target)
endforeach()
qt_collect_third_party_deps(${target})
+ qt_internal_collect_third_party_dep_packages_info(${target}
+ "${third_party_deps_package_components_ids}"
+ packages_info)
+
+ set(third_party_deps_extra_info "")
+ if(packages_info)
+ string(APPEND third_party_deps_extra_info "${packages_info}")
+ endif()
# Add dependency to the main ModuleTool package to ModuleDependencies file.
if(${target} IN_LIST QT_KNOWN_MODULES_WITH_TOOLS)
@@ -446,7 +496,33 @@ function(qt_internal_create_plugins_auto_inclusion_files)
# TODO: Find a better way to deal with this, perhaps by using find_package() instead of include
# for the Qml PluginConfig.cmake files.
-file(GLOB __qt_qml_plugins_config_file_list \"\${CMAKE_CURRENT_LIST_DIR}/QmlPlugins/${INSTALL_CMAKE_NAMESPACE}*Config.cmake\")
+# Distributions should probably change this default.
+if(NOT DEFINED QT_SKIP_AUTO_QML_PLUGIN_INCLUSION)
+ set(QT_SKIP_AUTO_QML_PLUGIN_INCLUSION OFF)
+endif()
+
+set(__qt_qml_plugins_config_file_list \"\")
+set(__qt_qml_plugins_glob_prefixes \"\${CMAKE_CURRENT_LIST_DIR}\")
+
+# Allow passing additional prefixes where we will glob for PluginConfig.cmake files.
+if(QT_ADDITIONAL_QML_PLUGIN_GLOB_PREFIXES)
+ foreach(__qt_qml_plugin_glob_prefix IN LISTS QT_ADDITIONAL_QML_PLUGIN_GLOB_PREFIXES)
+ if(__qt_qml_plugin_glob_prefix)
+ list(APPEND __qt_qml_plugins_glob_prefixes \"\${__qt_qml_plugin_glob_prefix}\")
+ endif()
+ endforeach()
+endif()
+
+list(REMOVE_DUPLICATES __qt_qml_plugins_glob_prefixes)
+
+foreach(__qt_qml_plugin_glob_prefix IN LISTS __qt_qml_plugins_glob_prefixes)
+ file(GLOB __qt_qml_plugins_glob_config_file_list
+ \"\${__qt_qml_plugin_glob_prefix}/QmlPlugins/${INSTALL_CMAKE_NAMESPACE}*Config.cmake\")
+ if(__qt_qml_plugins_glob_config_file_list)
+ list(APPEND __qt_qml_plugins_config_file_list \${__qt_qml_plugins_glob_config_file_list})
+ endif()
+endforeach()
+
if (__qt_qml_plugins_config_file_list AND NOT QT_SKIP_AUTO_QML_PLUGIN_INCLUSION)
# First round of inclusions ensure all qml plugin targets are brought into scope.
foreach(__qt_qml_plugin_config_file \${__qt_qml_plugins_config_file_list})
@@ -472,8 +548,8 @@ if (__qt_qml_plugins_config_file_list AND NOT QT_SKIP_AUTO_QML_PLUGIN_INCLUSION)
endif()")
endif()
- get_target_property(qt_plugins "${QT_MODULE}" QT_PLUGINS)
- if(qt_plugins OR QT_MODULE_PLUGIN_INCLUDES)
+ get_target_property(module_plugin_types "${QT_MODULE}" MODULE_PLUGIN_TYPES)
+ if(module_plugin_types OR QT_MODULE_PLUGIN_INCLUDES)
list(APPEND modules_with_plugins "${QT_MODULE}")
configure_file(
"${QT_CMAKE_DIR}/QtPlugins.cmake.in"
@@ -551,9 +627,8 @@ function(qt_generate_build_internals_extra_cmake_code)
if(CMAKE_BUILD_TYPE)
string(APPEND QT_EXTRA_BUILD_INTERNALS_VARS
"
+# Used by qt_internal_set_cmake_build_type.
set(__qt_internal_initial_qt_cmake_build_type \"${CMAKE_BUILD_TYPE}\")
-qt_internal_force_set_cmake_build_type_conditionally(
- \"\${__qt_internal_initial_qt_cmake_build_type}\")
")
endif()
if(CMAKE_CONFIGURATION_TYPES)
@@ -575,17 +650,6 @@ qt_internal_force_set_cmake_build_type_conditionally(
string(APPEND QT_EXTRA_BUILD_INTERNALS_VARS
"\nset(QT_MULTI_CONFIG_FIRST_CONFIG \"${QT_MULTI_CONFIG_FIRST_CONFIG}\")\n")
endif()
- # When building standalone tests against a multi-config Qt, we want to choose the first
- # configuration, rather than use CMake's default value.
- # In the case of Windows, we definitely don't it to default to Debug, because that causes
- # issues in the CI.
- if(multi_config_specific)
- string(APPEND QT_EXTRA_BUILD_INTERNALS_VARS "
-if(QT_BUILD_STANDALONE_TESTS)
- qt_internal_force_set_cmake_build_type_conditionally(
- \"\${QT_MULTI_CONFIG_FIRST_CONFIG}\")
-endif()\n")
- endif()
if(CMAKE_CROSS_CONFIGS)
string(APPEND ninja_multi_config_specific
@@ -616,9 +680,9 @@ endif()\n")
"set(QT_IS_MACOS_UNIVERSAL \"${QT_IS_MACOS_UNIVERSAL}\" CACHE BOOL \"\")\n")
endif()
- if(DEFINED QT_UIKIT_SDK)
+ if(DEFINED QT_APPLE_SDK)
string(APPEND QT_EXTRA_BUILD_INTERNALS_VARS
- "set(QT_UIKIT_SDK \"${QT_UIKIT_SDK}\" CACHE BOOL \"\")\n")
+ "set(QT_APPLE_SDK \"${QT_APPLE_SDK}\" CACHE BOOL \"\")\n")
endif()
if(QT_FORCE_FIND_TOOLS)
@@ -639,13 +703,19 @@ endif()\n")
endif()
# Save the default qpa platform.
- # Used by qtwayland/src/plugins/platforms/qwayland-generic/CMakeLists.txt. Otherwise
- # the DEFAULT_IF condition is evaluated incorrectly.
if(DEFINED QT_QPA_DEFAULT_PLATFORM)
string(APPEND QT_EXTRA_BUILD_INTERNALS_VARS
"set(QT_QPA_DEFAULT_PLATFORM \"${QT_QPA_DEFAULT_PLATFORM}\" CACHE STRING \"\")\n")
endif()
+ # Save the list of default qpa platforms.
+ # Used by qtwayland/src/plugins/platforms/qwayland-generic/CMakeLists.txt. Otherwise
+ # the DEFAULT_IF condition is evaluated incorrectly.
+ if(DEFINED QT_QPA_PLATFORMS)
+ string(APPEND QT_EXTRA_BUILD_INTERNALS_VARS
+ "set(QT_QPA_PLATFORMS \"${QT_QPA_PLATFORMS}\" CACHE STRING \"\")\n")
+ endif()
+
# Save minimum and policy-related CMake versions to ensure the same minimum is
# checked for when building other downstream repos (qtsvg, etc) and the policy settings
# will be consistent unless the downstream repos explicitly override them.
@@ -713,17 +783,6 @@ endif()\n")
string(APPEND QT_EXTRA_BUILD_INTERNALS_VARS "${install_prefix_content}")
- # The top-level check needs to happen inside QtBuildInternals, because it's possible
- # to configure a top-level build with a few repos and then configure another repo
- # using qt-configure-module in a separate build dir, where QT_SUPERBUILD will not
- # be set anymore.
- string(APPEND QT_EXTRA_BUILD_INTERNALS_VARS
- "
-if(DEFINED QT_REPO_MODULE_VERSION AND NOT DEFINED QT_REPO_DEPENDENCIES AND NOT QT_SUPERBUILD)
- qt_internal_read_repo_dependencies(QT_REPO_DEPENDENCIES \"$\{PROJECT_SOURCE_DIR}\")
-endif()
-")
-
if(DEFINED OpenGL_GL_PREFERENCE)
string(APPEND QT_EXTRA_BUILD_INTERNALS_VARS
"
@@ -734,10 +793,22 @@ set(OpenGL_GL_PREFERENCE \"${OpenGL_GL_PREFERENCE}\" CACHE STRING \"\")
string(APPEND QT_EXTRA_BUILD_INTERNALS_VARS
"
-set(QT_COPYRIGHT_YEAR \"${QT_COPYRIGHT_YEAR}\" CACHE STRING \"\")
set(QT_COPYRIGHT \"${QT_COPYRIGHT}\" CACHE STRING \"\")
")
+ # Add the apple version requirements to the BuildInternals extra code, so the info is
+ # available when configuring a standalone test.
+ # Otherwise when QtSetup is included after a
+ # find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+ # call, Qt6ConfigExtras.cmake is not included yet, the requirements are not available and
+ # _qt_internal_check_apple_sdk_and_xcode_versions() would fail.
+ _qt_internal_export_apple_sdk_and_xcode_version_requirements(apple_requirements)
+ if(apple_requirements)
+ string(APPEND QT_EXTRA_BUILD_INTERNALS_VARS "
+${apple_requirements}
+")
+ endif()
+
qt_compute_relative_path_from_cmake_config_dir_to_prefix()
configure_file(
"${CMAKE_CURRENT_LIST_DIR}/QtBuildInternalsExtra.cmake.in"
@@ -804,7 +875,7 @@ function(qt_internal_create_config_file_for_standalone_tests)
# Create a Config file that calls find_package on the modules that were built as part
# of the current repo. This is used for standalone tests.
- qt_internal_get_standalone_tests_config_file_name(tests_config_file_name)
+ qt_internal_get_standalone_parts_config_file_name(tests_config_file_name)
# Standalone tests Config files should follow the main versioning scheme.
qt_internal_get_package_version_of_target(Platform main_qt_package_version)
@@ -848,8 +919,15 @@ function(qt_internal_generate_user_facing_tools_info)
if(NOT filename)
set(filename ${target})
endif()
+ set(linkname ${filename})
+ if(APPLE)
+ get_target_property(is_macos_bundle ${target} MACOSX_BUNDLE )
+ if(is_macos_bundle)
+ set(filename "${filename}.app/Contents/MacOS/${filename}")
+ endif()
+ endif()
qt_path_join(tool_target_path "${CMAKE_INSTALL_PREFIX}" "${INSTALL_BINDIR}" "${filename}")
- qt_path_join(tool_link_path "${INSTALL_PUBLICBINDIR}" "${filename}${PROJECT_VERSION_MAJOR}")
+ qt_path_join(tool_link_path "${INSTALL_PUBLICBINDIR}" "${linkname}${PROJECT_VERSION_MAJOR}")
list(APPEND lines "${tool_target_path} ${tool_link_path}")
endforeach()
string(REPLACE ";" "\n" content "${lines}")
diff --git a/cmake/QtPriHelpers.cmake b/cmake/QtPriHelpers.cmake
index c619a50f30..f29b55b349 100644
--- a/cmake/QtPriHelpers.cmake
+++ b/cmake/QtPriHelpers.cmake
@@ -26,9 +26,14 @@ function(qt_generate_qmake_libraries_pri_content module_name output_root_dir out
set(lib_incdir "")
set(lib_libdir "")
set(lib_libs "")
+ set(seen_targets "")
while(lib_targets)
list(POP_BACK lib_targets lib_target)
if(TARGET ${lib_target})
+ if(${lib_target} IN_LIST seen_targets)
+ continue()
+ endif()
+ list(APPEND seen_targets ${lib_target})
get_target_property(lib_target_type ${lib_target} TYPE)
if(lib_target_type STREQUAL "INTERFACE_LIBRARY")
get_target_property(iface_libs ${lib_target} INTERFACE_LINK_LIBRARIES)
@@ -139,13 +144,10 @@ function(qt_get_direct_module_dependencies target out_var)
continue()
endif()
get_target_property(lib_type ${lib} TYPE)
- get_target_property(is_versionless_target ${lib} _qt_is_versionless_target)
- if (lib_type STREQUAL "INTERFACE_LIBRARY" AND is_versionless_target)
- # Found a version-less target like Qt::Core outside of qtbase.
- # Skip this one and use what this target points to, e.g. Qt6::Core.
- # Make sure to process Private interface libraries as-is.
- get_target_property(ifacelibs ${lib} INTERFACE_LINK_LIBRARIES)
- list(PREPEND libs ${ifacelibs})
+ get_target_property(aliased_target ${lib} ALIASED_TARGET)
+ if(TARGET "${aliased_target}")
+ # If versionless target is alias, use what the alias points to.
+ list(PREPEND libs "${aliased_target}")
continue()
endif()
if(lib_type STREQUAL "OBJECT_LIBRARY")
@@ -776,8 +778,23 @@ QT_PATCH_VERSION = ${PROJECT_VERSION_PATCH}
if(APPLE)
list(APPEND extra_statements "QT_MAC_SDK_VERSION = ${QT_MAC_SDK_VERSION}")
- list(APPEND extra_statements
- "QMAKE_MACOSX_DEPLOYMENT_TARGET = ${CMAKE_OSX_DEPLOYMENT_TARGET}")
+ if(NOT CMAKE_SYSTEM_NAME OR CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+ # macOS
+ list(APPEND extra_statements
+ "QMAKE_MACOSX_DEPLOYMENT_TARGET = ${CMAKE_OSX_DEPLOYMENT_TARGET}")
+ list(APPEND extra_statements
+ "QT_MAC_SDK_VERSION_MIN = ${QT_SUPPORTED_MIN_MACOS_SDK_VERSION}")
+ list(APPEND extra_statements
+ "QT_MAC_SDK_VERSION_MAX = ${QT_SUPPORTED_MAX_MACOS_SDK_VERSION}")
+ elseif(CMAKE_SYSTEM_NAME STREQUAL iOS)
+ list(APPEND extra_statements
+ "QMAKE_IOS_DEPLOYMENT_TARGET = ${CMAKE_OSX_DEPLOYMENT_TARGET}")
+ list(APPEND extra_statements
+ "QT_MAC_SDK_VERSION_MIN = ${QT_SUPPORTED_MIN_IOS_SDK_VERSION}")
+ list(APPEND extra_statements
+ "QT_MAC_SDK_VERSION_MAX = ${QT_SUPPORTED_MAX_IOS_SDK_VERSION}")
+ endif()
+
if (CMAKE_OSX_ARCHITECTURES)
list(APPEND architectures "${CMAKE_OSX_ARCHITECTURES}")
string (REPLACE ";" " " architectures "${architectures}")
@@ -787,8 +804,6 @@ QT_PATCH_VERSION = ${PROJECT_VERSION_PATCH}
list(APPEND extra_statements "QT_ARCHS = ${architectures}")
endif()
- list(APPEND extra_statements "QT_EDITION = Open Source")
-
if(WASM)
list(APPEND extra_statements
"QT_EMCC_VERSION = ${EMCC_VERSION}")
@@ -826,7 +841,7 @@ function(qt_generate_global_device_pri_file)
file(TO_CMAKE_PATH ${ANDROID_NDK} ANDROID_NDK)
string(APPEND content "DEFAULT_ANDROID_NDK_ROOT = ${ANDROID_NDK}\n")
- set(android_platform "android-23")
+ set(android_platform "android-28")
if(ANDROID_PLATFORM)
set(android_platform "${ANDROID_PLATFORM}")
elseif(ANDROID_NATIVE_API_LEVEL)
@@ -847,8 +862,8 @@ function(qt_generate_global_device_pri_file)
endif()
endif()
- if(QT_UIKIT_SDK)
- string(APPEND content "QMAKE_MAC_SDK = ${QT_UIKIT_SDK}\n")
+ if(QT_APPLE_SDK)
+ string(APPEND content "QMAKE_MAC_SDK = ${QT_APPLE_SDK}\n")
endif()
set(gcc_machine_dump "")
diff --git a/cmake/QtProcessConfigureArgs.cmake b/cmake/QtProcessConfigureArgs.cmake
index 0572fbbd5b..df0dfe48de 100644
--- a/cmake/QtProcessConfigureArgs.cmake
+++ b/cmake/QtProcessConfigureArgs.cmake
@@ -54,7 +54,11 @@ if("${MODULE_ROOT}" STREQUAL "")
get_filename_component(MODULE_ROOT ".." ABSOLUTE BASE_DIR "${CMAKE_CURRENT_LIST_DIR}")
set(qtbase_or_top_level_build TRUE)
else()
- file(TO_CMAKE_PATH "${MODULE_ROOT}" MODULE_ROOT)
+ # If MODULE_ROOT is passed without drive letter, we try to add it to the path.
+ # The check is necessary; otherwise, `get_filename_component` returns an empty string.
+ if(NOT MODULE_ROOT STREQUAL ".")
+ get_filename_component(MODULE_ROOT "." REALPATH BASE_DIR "${MODULE_ROOT}")
+ endif()
set(qtbase_or_top_level_build FALSE)
endif()
set(configure_filename "configure.cmake")
@@ -81,11 +85,16 @@ list(TRANSFORM configure_args STRIP)
unset(generator)
set(auto_detect_compiler TRUE)
set(auto_detect_generator ${qtbase_or_top_level_build})
+set(no_prefix_option FALSE)
unset(device_options)
unset(options_json_file)
set_property(GLOBAL PROPERTY UNHANDLED_ARGS "")
while(NOT "${configure_args}" STREQUAL "")
- list(POP_FRONT configure_args arg)
+ list(POP_FRONT configure_args raw_arg)
+
+ # Condense '--foo-bar' arguments into '-foo-bar'.
+ string(REGEX REPLACE "^--([^-])" "-\\1" arg "${raw_arg}")
+
if(arg STREQUAL "-cmake-generator")
list(POP_FRONT configure_args generator)
elseif(arg STREQUAL "-cmake-use-default-generator")
@@ -106,6 +115,20 @@ while(NOT "${configure_args}" STREQUAL "")
foreach(qtrepo IN LISTS qtrepos)
push("-DBUILD_${qtrepo}=OFF")
endforeach()
+ elseif(arg STREQUAL "-skip-tests")
+ list(POP_FRONT configure_args qtrepos)
+ is_non_empty_valid_arg("${arg}" "${qtrepos}")
+ list(TRANSFORM qtrepos REPLACE "," ";")
+ foreach(qtrepo IN LISTS qtrepos)
+ push("-DQT_BUILD_TESTS_PROJECT_${qtrepo}=OFF")
+ endforeach()
+ elseif(arg STREQUAL "-skip-examples")
+ list(POP_FRONT configure_args qtrepos)
+ is_non_empty_valid_arg("${arg}" "${qtrepos}")
+ list(TRANSFORM qtrepos REPLACE "," ";")
+ foreach(qtrepo IN LISTS qtrepos)
+ push("-DQT_BUILD_EXAMPLES_PROJECT_${qtrepo}=OFF")
+ endforeach()
elseif(arg STREQUAL "-submodules")
warn_in_per_repo_build("${arg}")
list(POP_FRONT configure_args submodules)
@@ -123,8 +146,10 @@ while(NOT "${configure_args}" STREQUAL "")
push("-DINSTALL_MKSPECSDIR=${path}")
elseif(arg STREQUAL "-developer-build")
set(developer_build TRUE)
- # Treat this argument as "unhandled" to process it further.
- set_property(GLOBAL APPEND PROPERTY UNHANDLED_ARGS "${arg}")
+ push("-DFEATURE_developer_build=ON")
+ elseif(arg STREQUAL "-no-prefix")
+ set(no_prefix_option TRUE)
+ push("-DFEATURE_no_prefix=ON")
elseif(arg STREQUAL "-cmake-file-api")
set(cmake_file_api TRUE)
elseif(arg STREQUAL "-no-cmake-file-api")
@@ -135,14 +160,7 @@ while(NOT "${configure_args}" STREQUAL "")
list(POP_FRONT configure_args version)
is_valid_qt_hex_version("${arg}" "${version}")
push("-DQT_DISABLE_DEPRECATED_UP_TO=${version}")
- elseif(arg STREQUAL "-unity-build")
- push("-DQT_UNITY_BUILD=ON")
- # QT_UNITY_BUILD_BATCH_SIZE will be set to 8, CMake's default.
- elseif(arg STREQUAL "-unity-build-batch-size")
- list(POP_FRONT configure_args unity_build_batch_size)
- is_non_empty_valid_arg("${arg}" "${unity_build_batch_size}")
- push("-DQT_UNITY_BUILD_BATCH_SIZE=${unity_build_batch_size}")
- elseif(arg STREQUAL "--")
+ elseif(raw_arg STREQUAL "--")
# Everything after this argument will be passed to CMake verbatim.
list(APPEND cmake_args "${configure_args}")
break()
@@ -151,6 +169,41 @@ while(NOT "${configure_args}" STREQUAL "")
endif()
endwhile()
+# Read the specified manually generator value from CMake command line.
+# The '-cmake-generator' argument has higher priority than CMake command line.
+if(NOT generator)
+ set(is_next_arg_generator_name FALSE)
+ foreach(arg IN LISTS cmake_args)
+ if(is_next_arg_generator_name)
+ set(is_next_arg_generator_name FALSE)
+ if(NOT arg MATCHES "^-.*")
+ set(generator "${arg}")
+ set(auto_detect_generator FALSE)
+ endif()
+ elseif(arg MATCHES "^-G(.*)")
+ set(generator "${CMAKE_MATCH_1}")
+ if(generator)
+ set(auto_detect_generator FALSE)
+ else()
+ set(is_next_arg_generator_name TRUE)
+ endif()
+ endif()
+ endforeach()
+endif()
+
+# Attempt to detect the generator type, either single or multi-config
+if("${generator}" STREQUAL "Xcode"
+ OR "${generator}" STREQUAL "Ninja Multi-Config"
+ OR "${generator}" MATCHES "^Visual Studio")
+ set(multi_config ON)
+else()
+ set(multi_config OFF)
+endif()
+
+# Tell the build system we are configuring via the configure script so we can act on that.
+# The cache variable is unset at the end of configuration.
+push("-DQT_INTERNAL_CALLED_FROM_CONFIGURE:BOOL=TRUE")
+
if(FRESH_REQUESTED)
push("-DQT_INTERNAL_FRESH_REQUESTED:BOOL=TRUE")
if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.24")
@@ -226,16 +279,23 @@ macro(qt_commandline_custom handler)
endmacro()
function(qt_commandline_option name)
- set(options)
+ set(options CONTROLS_FEATURE)
set(oneValueArgs TYPE NAME VALUE)
set(multiValueArgs VALUES MAPPING)
cmake_parse_arguments(arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
set(commandline_known_options "${commandline_known_options};${name}" PARENT_SCOPE)
set(commandline_option_${name} "${arg_TYPE}" PARENT_SCOPE)
+ set(input_name ${name})
if(NOT "${arg_NAME}" STREQUAL "")
+ set(input_name ${arg_NAME})
set(commandline_option_${name}_variable "${arg_NAME}" PARENT_SCOPE)
endif()
+ set(mapping_type "${arg_TYPE}")
+ if(arg_CONTROLS_FEATURE)
+ set(mapping_type "boolean")
+ endif()
+ set_property(GLOBAL PROPERTY INPUTTYPE_${input_name} "${mapping_type}")
if(NOT "${arg_VALUE}" STREQUAL "")
set(commandline_option_${name}_value "${arg_VALUE}" PARENT_SCOPE)
endif()
@@ -246,6 +306,11 @@ function(qt_commandline_option name)
endif()
endfunction()
+# Add the common command line options for every qt repo.
+macro(qt_add_common_commandline_options)
+ qt_commandline_option(headersclean TYPE boolean)
+endmacro()
+
function(qt_commandline_prefix arg var)
set(idx ${commandline_nr_of_prefixes})
set(commandline_prefix_${idx} "${arg}" "${var}" PARENT_SCOPE)
@@ -262,6 +327,8 @@ set(QT_CONFIGURE_RUNNING ON)
# Load qt_cmdline.cmake files
####################################################################################################
+qt_add_common_commandline_options()
+
while(commandline_files)
list(POP_FRONT commandline_files commandline_file)
get_filename_component(commandline_file_directory "${commandline_file}" DIRECTORY)
@@ -326,6 +393,23 @@ function(qtConfCommandlineAppendInput name val)
qtConfCommandlineSetInput(${name} "${val}")
endfunction()
+function(qtConfCommandlineSetInputType input_name type_name)
+ set_property(GLOBAL PROPERTY INPUTTYPE_${input_name} "${type_name}")
+endfunction()
+
+function(qtConfCommandlineSetBooleanInput name val)
+ qtConfCommandlineSetInput(${name} ${val})
+ qtConfCommandlineSetInputType(${name} boolean)
+endfunction()
+
+function(qtConfCommandlineEnableFeature name)
+ qtConfCommandlineSetBooleanInput(${name} yes)
+endfunction()
+
+function(qtConfCommandlineDisableFeature name)
+ qtConfCommandlineSetBooleanInput(${name} no)
+endfunction()
+
function(qtConfValidateValue opt val out_var)
set(${out_var} TRUE PARENT_SCOPE)
@@ -342,7 +426,9 @@ function(qtConfValidateValue opt val out_var)
endforeach()
set(${out_var} FALSE PARENT_SCOPE)
- qtConfAddError("Invalid value '${val}' supplied to command line option '${opt}'.")
+ list(JOIN valid_values " " valid_values_str)
+ qtConfAddError("Invalid value '${val}' supplied to command line option '${opt}'."
+ "\nAllowed values: ${valid_values_str}\n")
endfunction()
function(qt_commandline_mapped_enum_value opt key out_var)
@@ -630,10 +716,20 @@ while(1)
if(arg MATCHES "^--?enable-(.*)")
set(opt "${CMAKE_MATCH_1}")
set(val "yes")
- # Handle -no-prefix so it's not interpreted as the negation of -prefix
- elseif(arg MATCHES "-(no-prefix)")
- set(opt "${CMAKE_MATCH_1}")
- set(val "")
+ # Handle builtin [-no]-feature-xxx
+ elseif(arg MATCHES "^--?(no-)?feature-(.*)")
+ set(opt "${CMAKE_MATCH_2}")
+ if(NOT opt IN_LIST commandline_known_features)
+ qtConfAddError("Enabling/Disabling unknown feature '${opt}'.")
+ endif()
+ if("${CMAKE_MATCH_1}" STREQUAL "")
+ set(val "ON")
+ else()
+ set(val "OFF")
+ endif()
+ qt_feature_normalize_name("${opt}" normalized_feature_name)
+ push(-DFEATURE_${normalized_feature_name}=${val})
+ continue()
elseif(arg MATCHES "^--?(disable|no)-(.*)")
set(opt "${CMAKE_MATCH_2}")
set(val "no")
@@ -650,7 +746,6 @@ while(1)
if(NOT DEFINED commandline_option_${opt} AND opt MATCHES "(qt|system)-(.*)")
set(opt "${CMAKE_MATCH_2}")
set(val "${CMAKE_MATCH_1}")
- message("opt: ${opt} val: ${val}")
endif()
else()
qtConfAddError("Invalid command line parameter '${arg}'.")
@@ -671,15 +766,6 @@ while(1)
endforeach()
endif()
- # Handle builtin [-no]-feature-xxx
- if("${type}" STREQUAL "" AND opt MATCHES "^feature-(.*)")
- set(opt "${CMAKE_MATCH_1}")
- if(NOT opt IN_LIST commandline_known_features)
- qtConfAddError("Enabling/Disabling unknown feature '${opt}'.")
- endif()
- set(type boolean)
- endif()
-
if("${type}" STREQUAL "")
qtConfAddError("Unknown command line option '${arg}'.")
endif()
@@ -699,6 +785,9 @@ get_property(config_inputs GLOBAL PROPERTY CONFIG_INPUTS)
list(REMOVE_DUPLICATES config_inputs)
foreach(var ${config_inputs})
get_property(INPUT_${var} GLOBAL PROPERTY INPUT_${var})
+ if("${commandline_input_type}" STREQUAL "")
+ get_property(commandline_input_${var}_type GLOBAL PROPERTY INPUTTYPE_${var})
+ endif()
endforeach()
macro(drop_input name)
@@ -794,7 +883,7 @@ function(guess_compiler_from_mkspec)
push("-DCMAKE_CXX_COMPILER=${cxx_compiler}")
endif()
if(mkspec MATCHES "-libc\\+\\+$")
- push("-DINPUT_stdlib_libcpp=ON")
+ push("-DFEATURE_stdlib_libcpp=ON")
endif()
set(cmake_args "${cmake_args}" PARENT_SCOPE)
endfunction()
@@ -826,9 +915,13 @@ endfunction()
drop_input(commercial)
drop_input(confirm-license)
translate_boolean_input(precompile_header BUILD_WITH_PCH)
+translate_boolean_input(unity_build QT_UNITY_BUILD)
+translate_string_input(unity_build_batch_size QT_UNITY_BUILD_BATCH_SIZE)
translate_boolean_input(ccache QT_USE_CCACHE)
+translate_boolean_input(vcpkg QT_USE_VCPKG)
translate_boolean_input(shared BUILD_SHARED_LIBS)
translate_boolean_input(warnings_are_errors WARNINGS_ARE_ERRORS)
+translate_boolean_input(qtinlinenamespace QT_INLINE_NAMESPACE)
translate_string_input(qt_namespace QT_NAMESPACE)
translate_string_input(qt_libinfix QT_LIBINFIX)
translate_string_input(qreal QT_COORD_TYPE)
@@ -850,6 +943,7 @@ translate_string_input(platform QT_QMAKE_TARGET_MKSPEC)
translate_string_input(xplatform QT_QMAKE_TARGET_MKSPEC)
guess_compiler_from_mkspec()
translate_string_input(qpa_default_platform QT_QPA_DEFAULT_PLATFORM)
+translate_list_input(qpa_platforms QT_QPA_PLATFORMS)
translate_path_input(android-sdk ANDROID_SDK_ROOT)
translate_path_input(android-ndk ANDROID_NDK_ROOT)
@@ -867,15 +961,11 @@ endif()
translate_string_input(android-javac-source QT_ANDROID_JAVAC_SOURCE)
translate_string_input(android-javac-target QT_ANDROID_JAVAC_TARGET)
-# FIXME: config_help.txt says -sdk should apply to macOS as well.
-translate_string_input(sdk QT_UIKIT_SDK)
-if(DEFINED INPUT_sdk OR (DEFINED INPUT_xplatform AND INPUT_xplatform STREQUAL "macx-ios-clang")
- OR (DEFINED INPUT_platform AND INPUT_platform STREQUAL "macx-ios-clang"))
- push("-DCMAKE_SYSTEM_NAME=iOS")
-endif()
+translate_string_input(sdk QT_APPLE_SDK)
drop_input(make)
drop_input(nomake)
+translate_boolean_input(install-examples-sources QT_INSTALL_EXAMPLES_SOURCES)
check_qt_build_parts(nomake)
check_qt_build_parts(make)
@@ -896,10 +986,33 @@ if(INPUT_force_debug_info)
list(TRANSFORM build_configs REPLACE "^Release$" "RelWithDebInfo")
endif()
+# Code coverage handling
+drop_input(gcov)
+if(INPUT_gcov)
+ if(NOT "${INPUT_coverage}" STREQUAL "")
+ if(NOT "${INPUT_coverage}" STREQUAL "gcov")
+ qtConfAddError("The -gcov argument is provided, but -coverage is set"
+ " to ${INPUT_coverage}")
+ endif()
+ else()
+ set(INPUT_coverage "gcov")
+ list(APPEND config_inputs coverage)
+ endif()
+endif()
+if(NOT "${INPUT_coverage}" STREQUAL "")
+ if(build_configs)
+ if(NOT "Debug" IN_LIST build_configs)
+ qtConfAddError("The -coverage argument requires Qt configured with 'Debug' config.")
+ endif()
+ else()
+ set(build_configs "Debug")
+ endif()
+endif()
+
list(LENGTH build_configs nr_of_build_configs)
-if(nr_of_build_configs EQUAL 1)
+if(nr_of_build_configs EQUAL 1 AND NOT multi_config)
push("-DCMAKE_BUILD_TYPE=${build_configs}")
-elseif(nr_of_build_configs GREATER 1)
+elseif(nr_of_build_configs GREATER 1 OR multi_config)
set(multi_config ON)
string(REPLACE ";" "[[;]]" escaped_build_configs "${build_configs}")
# We must not use the push macro here to avoid variable expansion.
@@ -930,12 +1043,20 @@ if(cmake_file_api OR (developer_build AND NOT DEFINED cmake_file_api))
endforeach()
endif()
+# Translate unhandled input variables to either -DINPUT_foo=value or -DFEATURE_foo=ON/OFF. If the
+# input's name matches a feature name and the corresponding command-line option's type is boolean
+# then we assume it's controlling a feature.
foreach(input ${config_inputs})
qt_feature_normalize_name("${input}" cmake_input)
- push("-DINPUT_${cmake_input}=${INPUT_${input}}")
+ if("${commandline_input_${input}_type}" STREQUAL "boolean"
+ AND input IN_LIST commandline_known_features)
+ translate_boolean_input("${input}" "FEATURE_${cmake_input}")
+ else()
+ push("-DINPUT_${cmake_input}=${INPUT_${input}}")
+ endif()
endforeach()
-if(DEFINED INPUT_no-prefix AND DEFINED INPUT_prefix)
+if(no_prefix_option AND DEFINED INPUT_prefix)
qtConfAddError("Can't specify both -prefix and -no-prefix options at the same time.")
endif()
@@ -984,6 +1105,14 @@ endforeach()
push("${MODULE_ROOT}")
+if(INPUT_sysroot)
+ qtConfAddWarning("The -sysroot option is deprecated and no longer has any effect. "
+ "It is recommended to use a toolchain file instead, i.e., "
+ "-DCMAKE_TOOLCHAIN_FILE=<filename>. "
+ "Alternatively, you may use -DCMAKE_SYSROOT option "
+ "to pass the sysroot to CMake.\n")
+endif()
+
# Restore the escaped semicolons in arguments that are lists
list(TRANSFORM cmake_args REPLACE "\\[\\[;\\]\\]" "\\\\;")
diff --git a/cmake/QtPublicAppleHelpers.cmake b/cmake/QtPublicAppleHelpers.cmake
index b60ef5e448..5f7a7719b5 100644
--- a/cmake/QtPublicAppleHelpers.cmake
+++ b/cmake/QtPublicAppleHelpers.cmake
@@ -27,7 +27,7 @@ function(_qt_internal_handle_ios_launch_screen target)
if(NOT launch_screen AND NOT QT_NO_SET_DEFAULT_IOS_LAUNCH_SCREEN)
set(is_default_launch_screen TRUE)
set(launch_screen
- "${__qt_internal_cmake_ios_support_files_path}/LaunchScreen.storyboard")
+ "${__qt_internal_cmake_apple_support_files_path}/LaunchScreen.storyboard")
endif()
# Check that the launch screen exists.
@@ -61,13 +61,7 @@ function(_qt_internal_handle_ios_launch_screen target)
file(MAKE_DIRECTORY "${launch_screen_out_dir}")
- # Replaces the value in the default template.
- set(QT_IOS_LAUNCH_SCREEN_TEXT "${target}")
- configure_file(
- "${launch_screen_in_path}"
- "${launch_screen_out_path}"
- @ONLY
- )
+ configure_file("${launch_screen_in_path}" "${launch_screen_out_path}" COPYONLY)
set(final_launch_screen_path "${launch_screen_out_path}")
else()
@@ -221,7 +215,7 @@ function(_qt_internal_find_ios_development_team_id out_var)
endif()
endfunction()
-function(_qt_internal_get_ios_bundle_identifier_prefix out_var)
+function(_qt_internal_get_apple_bundle_identifier_prefix out_var)
get_property(prefix GLOBAL PROPERTY _qt_internal_ios_bundle_identifier_prefix)
get_property(prefix_computed GLOBAL PROPERTY
_qt_internal_ios_bundle_identifier_prefix_computed)
@@ -269,8 +263,8 @@ function(_qt_internal_escape_rfc_1034_identifier value out_var)
set("${out_var}" "${value}" PARENT_SCOPE)
endfunction()
-function(_qt_internal_get_default_ios_bundle_identifier out_var)
- _qt_internal_get_ios_bundle_identifier_prefix(prefix)
+function(_qt_internal_get_default_apple_bundle_identifier target out_var)
+ _qt_internal_get_apple_bundle_identifier_prefix(prefix)
if(NOT prefix)
set(prefix "com.yourcompany")
@@ -281,14 +275,16 @@ function(_qt_internal_get_default_ios_bundle_identifier out_var)
string(SHA1 hash "${team_id}")
string(SUBSTRING "${hash}" 0 8 infix)
string(APPEND prefix ".${infix}")
- else()
+ endif()
+
+ if(CMAKE_GENERATOR STREQUAL "Xcode")
message(WARNING
- "No organization bundle identifier prefix could be retrieved from Xcode "
- "preferences. This can lead to code signing issues due to a non-unique bundle "
- "identifier. Please set up an organization prefix by creating a new project within "
- "Xcode, or consider providing a custom bundle identifier by specifying the "
- "XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER property."
- )
+ "No organization bundle identifier prefix could be retrieved from Xcode preferences. \
+ This can lead to code signing issues due to a non-unique bundle \
+ identifier. Please set up an organization prefix by creating a new project within \
+ Xcode, or consider providing a custom bundle identifier by specifying the \
+ MACOSX_BUNDLE_GUI_IDENTIFIER or XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER property."
+ )
endif()
endif()
@@ -299,7 +295,12 @@ function(_qt_internal_get_default_ios_bundle_identifier out_var)
# that the identifier is invalid.
_qt_internal_escape_rfc_1034_identifier("${prefix}" prefix)
- set(identifier "${prefix}.\${PRODUCT_NAME:rfc1034identifier}")
+ if(CMAKE_GENERATOR STREQUAL "Xcode")
+ set(identifier "${prefix}.$(PRODUCT_NAME:rfc1034identifier)")
+ else()
+ set(identifier "${prefix}.${target}")
+ endif()
+
set("${out_var}" "${identifier}" PARENT_SCOPE)
endfunction()
@@ -384,56 +385,72 @@ function(_qt_internal_set_xcode_development_team_id target)
endif()
endfunction()
-function(_qt_internal_set_xcode_bundle_identifier target)
+function(_qt_internal_set_apple_bundle_identifier target)
# Skip all logic if requested.
if(QT_NO_SET_XCODE_BUNDLE_IDENTIFIER)
return()
endif()
- # There are two fields to consider: the CFBundleIdentifier key (CFBI) to be written to
- # Info.plist
- # and the PRODUCT_BUNDLE_IDENTIFIER (PBI) property to set in the Xcode project.
- # The following logic enables the best out-of-the-box experience combined with maximum
- # customization.
- # 1) If values for both fields are not provided, assign ${PRODUCT_BUNDLE_IDENTIFIER} to CFBI
- # (which is expanded by xcodebuild at build time and will use the value of PBI) and
- # auto-compute a default PBI from Xcode's ${PRODUCT_NAME}.
- # 2) If CFBI is set and PBI isn't, use given CFBI and keep PBI empty.
- # 3) If PBI is set and CFBI isn't, assign ${PRODUCT_BUNDLE_IDENTIFIER} to CFBI and use
- # the given PBI.
- # 4) If both are set, use both given values.
- # TLDR:
- # cfbi pbi -> result_cfbi result_pbi
- # unset unset computed computed
- # set unset given_val unset
- # unset set computed given_val
- # set set given_val given_val
-
- get_target_property(existing_cfbi "${target}" MACOSX_BUNDLE_GUI_IDENTIFIER)
- if(NOT MACOSX_BUNDLE_GUI_IDENTIFIER AND NOT existing_cfbi)
- set(is_cfbi_given FALSE)
- else()
- set(is_cfbi_given TRUE)
+ # There are two fields to consider: the CFBundleIdentifier key (ie., cmake_bundle_identifier)
+ # to be written to Info.plist and the PRODUCT_BUNDLE_IDENTIFIER (ie., xcode_bundle_identifier)
+ # property to set in the Xcode project. The `cmake_bundle_identifier` set by
+ # MACOSX_BUNDLE_GUI_IDENTIFIER applies to both Xcode, and other generators, while
+ # `xcode_bundle_identifier` set by XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER is
+ # Xcode specific.
+ #
+ # If Ninja is the generator, we set the value of `MACOSX_BUNDLE_GUI_IDENTIFIER`
+ # and don't touch the `XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER`.
+ # If Xcode is the generator, we set the value of `XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER`,
+ # and additionally, to silence a Xcode's warning, we set the `MACOSX_BUNDLE_GUI_IDENTIFIER` to
+ # `${PRODUCT_BUNDLE_IDENTIFIER}` so that Xcode could sort it out.
+
+ get_target_property(existing_cmake_bundle_identifier "${target}"
+ MACOSX_BUNDLE_GUI_IDENTIFIER)
+ get_target_property(existing_xcode_bundle_identifier "${target}"
+ XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER)
+
+ set(is_cmake_bundle_identifier_given FALSE)
+ if(existing_cmake_bundle_identifier)
+ set(is_cmake_bundle_identifier_given TRUE)
+ elseif(MACOSX_BUNDLE_GUI_IDENTIFIER)
+ set(is_cmake_bundle_identifier_given TRUE)
+ set(existing_cmake_bundle_identifier ${MACOSX_BUNDLE_GUI_IDENTIFIER})
+ endif()
+
+ set(is_xcode_bundle_identifier_given FALSE)
+ if(existing_xcode_bundle_identifier)
+ set(is_xcode_bundle_identifier_given TRUE)
+ elseif(CMAKE_XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER)
+ set(is_xcode_bundle_identifier_given TRUE)
+ set(existing_xcode_bundle_identifier ${CMAKE_XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER})
+ endif()
+
+ if(is_cmake_bundle_identifier_given
+ AND is_xcode_bundle_identifier_given
+ AND NOT existing_cmake_bundle_identifier STREQUAL existing_xcode_bundle_identifier)
+ message(WARNING
+ "MACOSX_BUNDLE_GUI_IDENTIFIER and XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "
+ "are set to different values. You only need to set one of them. ")
+ endif()
+
+ if(NOT is_xcode_bundle_identifier_given
+ AND NOT is_cmake_bundle_identifier_given)
+ _qt_internal_get_default_apple_bundle_identifier("${target}" bundle_id)
+ elseif(is_cmake_bundle_identifier_given)
+ set(bundle_id ${existing_cmake_bundle_identifier})
+ elseif(is_xcode_bundle_identifier_given)
+ set(bundle_id ${existing_xcode_bundle_identifier})
endif()
- if(NOT is_cfbi_given)
+ if(CMAKE_GENERATOR STREQUAL "Xcode")
set_target_properties("${target}"
PROPERTIES
- MACOSX_BUNDLE_GUI_IDENTIFIER "\${PRODUCT_BUNDLE_IDENTIFIER}")
- endif()
-
- get_target_property(existing_pbi "${target}" XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER)
- if(NOT CMAKE_XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER AND NOT existing_pbi)
- set(is_pbi_given FALSE)
+ XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "${bundle_id}"
+ MACOSX_BUNDLE_GUI_IDENTIFIER "$(PRODUCT_BUNDLE_IDENTIFIER)")
else()
- set(is_pbi_given TRUE)
- endif()
-
- if(NOT is_pbi_given AND NOT is_cfbi_given)
- _qt_internal_get_default_ios_bundle_identifier(bundle_id)
set_target_properties("${target}"
PROPERTIES
- XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "${bundle_id}")
+ MACOSX_BUNDLE_GUI_IDENTIFIER "${bundle_id}")
endif()
endfunction()
@@ -503,7 +520,7 @@ function(_qt_internal_set_xcode_bundle_name target)
if(CMAKE_GENERATOR STREQUAL Xcode)
set_target_properties("${target}"
PROPERTIES
- MACOSX_BUNDLE_BUNDLE_NAME "\${PRODUCT_NAME}")
+ MACOSX_BUNDLE_BUNDLE_NAME "$(PRODUCT_NAME)")
else()
set_target_properties("${target}"
PROPERTIES
@@ -531,15 +548,13 @@ function(_qt_internal_set_xcode_bitcode_enablement target)
"NO")
endfunction()
-function(_qt_internal_generate_ios_info_plist target)
+function(_qt_internal_copy_info_plist target)
# If the project already specifies a custom file, we don't override it.
- get_target_property(existing_plist "${target}" MACOSX_BUNDLE_INFO_PLIST)
- if(existing_plist)
- return()
+ get_target_property(info_plist_in "${target}" MACOSX_BUNDLE_INFO_PLIST)
+ if(NOT info_plist_in)
+ set(info_plist_in "${__qt_internal_cmake_apple_support_files_path}/Info.plist.app.in")
endif()
- set(info_plist_in "${__qt_internal_cmake_ios_support_files_path}/Info.plist.app.in")
-
string(MAKE_C_IDENTIFIER "${target}" target_identifier)
set(info_plist_out_dir
"${CMAKE_CURRENT_BINARY_DIR}/.qt/info_plist/${target_identifier}")
@@ -569,6 +584,65 @@ function(_qt_internal_generate_ios_info_plist target)
set_target_properties("${target}" PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${info_plist_out}")
endfunction()
+function(_qt_internal_plist_buddy plist_file)
+ cmake_parse_arguments(PARSE_ARGV 1 arg
+ "" "OUTPUT_VARIABLE;ERROR_VARIABLE" "COMMANDS")
+ foreach(command ${arg_COMMANDS})
+ execute_process(COMMAND "/usr/libexec/PlistBuddy"
+ -c "${command}" "${plist_file}"
+ OUTPUT_VARIABLE plist_buddy_output
+ ERROR_VARIABLE plist_buddy_error)
+ string(STRIP "${plist_buddy_output}" plist_buddy_output)
+ if(arg_OUTPUT_VARIABLE)
+ list(APPEND ${arg_OUTPUT_VARIABLE} ${plist_buddy_output})
+ set(${arg_OUTPUT_VARIABLE} ${${arg_OUTPUT_VARIABLE}} PARENT_SCOPE)
+ endif()
+ if(arg_ERROR_VARIABLE)
+ list(APPEND ${arg_ERROR_VARIABLE} ${plist_buddy_error})
+ set(${arg_ERROR_VARIABLE} ${${arg_ERROR_VARIABLE}} PARENT_SCOPE)
+ endif()
+ if(plist_buddy_error)
+ return()
+ endif()
+ endforeach()
+endfunction()
+
+function(_qt_internal_set_apple_localizations target)
+ if(QT_NO_SET_PLIST_LOCALIZATIONS)
+ return()
+ endif()
+
+ set(supported_languages "${QT_I18N_TRANSLATED_LANGUAGES}")
+ if("${QT_I18N_TRANSLATED_LANGUAGES}" STREQUAL "")
+ get_target_property(supported_languages "${target}" _qt_apple_supported_languages)
+ if("${supported_languages}" STREQUAL "supported_languages-NOTFOUND")
+ return()
+ endif()
+ endif()
+ get_target_property(plist_file "${target}" MACOSX_BUNDLE_INFO_PLIST)
+ if (NOT plist_file)
+ return()
+ endif()
+
+ _qt_internal_plist_buddy("${plist_file}"
+ COMMANDS "print CFBundleLocalizations"
+ OUTPUT_VARIABLE existing_localizations
+ )
+ if(existing_localizations)
+ return()
+ endif()
+
+ list(TRANSFORM supported_languages PREPEND
+ "Add CFBundleLocalizations: string ")
+
+ _qt_internal_plist_buddy("${plist_file}"
+ COMMANDS
+ "Add CFBundleLocalizations array"
+ ${supported_languages}
+ "Delete CFBundleAllowMixedLocalizations"
+ )
+endfunction()
+
function(_qt_internal_set_ios_simulator_arch target)
if(CMAKE_XCODE_ATTRIBUTE_ARCHS
OR QT_NO_SET_XCODE_ARCHS)
@@ -595,30 +669,269 @@ function(_qt_internal_set_ios_simulator_arch target)
"x86_64")
endfunction()
+# Export Apple platform sdk and xcode version requirements to Qt6ConfigExtras.cmake.
+function(_qt_internal_export_apple_sdk_and_xcode_version_requirements out_var)
+ if(NOT APPLE)
+ return()
+ endif()
+
+ if(IOS)
+ set(vars_to_assign
+ QT_SUPPORTED_MIN_IOS_SDK_VERSION
+ QT_SUPPORTED_MAX_IOS_SDK_VERSION
+ QT_SUPPORTED_MIN_IOS_XCODE_VERSION
+ )
+ elseif(VISIONOS)
+ set(vars_to_assign
+ QT_SUPPORTED_MIN_VISIONOS_SDK_VERSION
+ QT_SUPPORTED_MAX_VISIONOS_SDK_VERSION
+ QT_SUPPORTED_MIN_VISIONOS_XCODE_VERSION
+ )
+ else()
+ set(vars_to_assign
+ QT_SUPPORTED_MIN_MACOS_SDK_VERSION
+ QT_SUPPORTED_MAX_MACOS_SDK_VERSION
+ QT_SUPPORTED_MIN_MACOS_XCODE_VERSION
+ )
+ endif()
+
+ set(assignments "")
+ foreach(var IN LISTS vars_to_assign)
+ set(value "${${var}}")
+ list(APPEND assignments
+ "
+if(NOT ${var})
+ set(${var} \"${value}\")
+endif()")
+ endforeach()
+
+ list(JOIN assignments "\n" assignments)
+ set(${out_var} "${assignments}" PARENT_SCOPE)
+endfunction()
+
+function(_qt_internal_get_apple_sdk_version out_var)
+ if(APPLE)
+ if(CMAKE_SYSTEM_NAME STREQUAL iOS)
+ set(sdk_name "iphoneos")
+ elseif(CMAKE_SYSTEM_NAME STREQUAL visionOS)
+ set(sdk_name "xros")
+ else()
+ # Default to macOS
+ set(sdk_name "macosx")
+ endif()
+ set(xcrun_version_arg "--show-sdk-version")
+ execute_process(COMMAND /usr/bin/xcrun --sdk ${sdk_name} ${xcrun_version_arg}
+ OUTPUT_VARIABLE sdk_version
+ ERROR_VARIABLE xcrun_error)
+ if(NOT sdk_version)
+ message(FATAL_ERROR
+ "Can't determine darwin ${sdk_name} SDK version. Error: ${xcrun_error}")
+ endif()
+ string(STRIP "${sdk_version}" sdk_version)
+ set(${out_var} "${sdk_version}" PARENT_SCOPE)
+ endif()
+endfunction()
+
+function(_qt_internal_get_xcode_version_raw out_var)
+ if(APPLE)
+ execute_process(COMMAND /usr/bin/xcrun xcodebuild -version
+ OUTPUT_VARIABLE xcode_version
+ ERROR_VARIABLE xcrun_error)
+ string(REPLACE "\n" " " xcode_version "${xcode_version}")
+ string(STRIP "${xcode_version}" xcode_version)
+ set(${out_var} "${xcode_version}" PARENT_SCOPE)
+ endif()
+endfunction()
+
+function(_qt_internal_get_xcode_version out_var)
+ if(APPLE)
+ _qt_internal_get_xcode_version_raw(xcode_version_raw)
+
+ # The raw output is something like after the newlines are replaced with spaces:
+ # Xcode 14.3 Build version 14E222b
+ # We want only the '14.3' part. We could be more specific with the regex to match only
+ # digits separated by dots, but you never know how Apple might change the format.
+ string(REGEX REPLACE "Xcode (([^ ])+)" "\\2" xcode_version "${xcode_version_raw}")
+ if(xcode_version_raw MATCHES "Xcode ([^ ]+)")
+ set(xcode_version "${CMAKE_MATCH_1}")
+ else()
+ message(DEBUG "Failed to extract Xcode version from '${xcode_version_raw}'")
+ set(xcode_version "${xcode_version_raw}")
+ endif()
+
+ set(${out_var} "${xcode_version}" PARENT_SCOPE)
+ endif()
+endfunction()
+
+function(_qt_internal_get_cached_apple_sdk_version out_var)
+ if(QT_INTERNAL_APPLE_SDK_VERSION)
+ set(sdk_version "${QT_INTERNAL_APPLE_SDK_VERSION}")
+ else()
+ _qt_internal_get_apple_sdk_version(sdk_version)
+ set(QT_INTERNAL_APPLE_SDK_VERSION "${sdk_version}" CACHE STRING "Apple SDK version")
+ endif()
+
+ set(${out_var} "${sdk_version}" PARENT_SCOPE)
+endfunction()
+
+function(_qt_internal_get_cached_xcode_version out_var)
+ if(QT_INTERNAL_XCODE_VERSION)
+ set(xcode_version "${QT_INTERNAL_XCODE_VERSION}")
+ else()
+ _qt_internal_get_xcode_version(xcode_version)
+ set(QT_INTERNAL_XCODE_VERSION "${xcode_version}" CACHE STRING "Xcode version")
+ endif()
+
+ set(${out_var} "${xcode_version}" PARENT_SCOPE)
+endfunction()
+
+# Warn when the platform SDK or Xcode version are not supported.
+#
+# The warnings are currently only shown when building Qt, not when building user projects
+# with CMake.
+# The warnings ARE shown for qmake user projects.
+#
+# The qmake equivalent for user projects is in mkspecs/features/mac/default_post.prf.
+function(_qt_internal_check_apple_sdk_and_xcode_versions)
+ if(NOT APPLE)
+ return()
+ endif()
+
+ if(QT_NO_APPLE_SDK_AND_XCODE_CHECK)
+ return()
+ endif()
+
+ # Only run the check once in a top-level build.
+ get_property(check_done GLOBAL PROPERTY _qt_internal_apple_sdk_and_xcode_check_done)
+ if(check_done)
+ return()
+ endif()
+ set_property(GLOBAL PROPERTY _qt_internal_apple_sdk_and_xcode_check_done "TRUE")
+
+ if(IOS)
+ set(min_sdk_version "${QT_SUPPORTED_MIN_IOS_SDK_VERSION}")
+ set(max_sdk_version "${QT_SUPPORTED_MAX_IOS_SDK_VERSION}")
+ set(min_xcode_version "${QT_SUPPORTED_MIN_IOS_XCODE_VERSION}")
+ elseif(VISIONOS)
+ set(min_sdk_version "${QT_SUPPORTED_MIN_VISIONOS_SDK_VERSION}")
+ set(max_sdk_version "${QT_SUPPORTED_MAX_VISIONOS_SDK_VERSION}")
+ set(min_xcode_version "${QT_SUPPORTED_MIN_VISIONOS_XCODE_VERSION}")
+ else()
+ set(min_sdk_version "${QT_SUPPORTED_MIN_MACOS_SDK_VERSION}")
+ set(max_sdk_version "${QT_SUPPORTED_MAX_MACOS_SDK_VERSION}")
+ set(min_xcode_version "${QT_SUPPORTED_MIN_MACOS_XCODE_VERSION}")
+ endif()
+
+ _qt_internal_get_cached_apple_sdk_version(sdk_version)
+ _qt_internal_get_cached_xcode_version(xcode_version)
+
+ if(NOT max_sdk_version MATCHES "^[0-9]+$")
+ message(FATAL_ERROR
+ "Invalid max SDK version: ${max_sdk_version} "
+ "It should be a major version number, without minor or patch version components.")
+ endif()
+
+ # The default differs in different branches.
+ set(failed_check_should_error FALSE)
+
+ if(failed_check_should_error)
+ # Allow downgrading the error into a warning.
+ if(QT_FORCE_WARN_APPLE_SDK_AND_XCODE_CHECK)
+ set(message_type WARNING)
+ set(extra_message " Due to QT_FORCE_WARN_APPLE_SDK_AND_XCODE_CHECK being ON "
+ "the build will continue, but it will likely fail. Use at your own risk.")
+ else()
+ set(message_type FATAL_ERROR)
+ set(extra_message " You can turn this error into a warning by configuring with "
+ "-DQT_FORCE_WARN_APPLE_SDK_AND_XCODE_CHECK=ON, but the build will likely fail. "
+ "Use at your own risk.")
+ endif()
+ else()
+ # Allow upgrading the warning into an error.
+ if(QT_FORCE_FATAL_APPLE_SDK_AND_XCODE_CHECK)
+ set(message_type FATAL_ERROR)
+ set(extra_message " Erroring out due to QT_FORCE_FATAL_APPLE_SDK_AND_XCODE_CHECK "
+ "being ON.")
+ else()
+ set(message_type WARNING)
+ set(extra_message " You can turn this warning into an error by configuring with "
+ "-DQT_FORCE_FATAL_APPLE_SDK_AND_XCODE_CHECK=ON. ")
+ endif()
+ endif()
+
+ if(sdk_version VERSION_LESS min_sdk_version AND NOT QT_NO_APPLE_SDK_MIN_VERSION_CHECK)
+ message(${message_type}
+ "Qt requires at least version ${min_sdk_version} of the platform SDK, "
+ "you're building against version ${sdk_version}. Please upgrade."
+ ${extra_message}
+ )
+ endif()
+
+ if(xcode_version VERSION_LESS min_xcode_version AND NOT QT_NO_XCODE_MIN_VERSION_CHECK)
+ message(${message_type}
+ "Qt requires at least version ${min_xcode_version} of Xcode, "
+ "you're building against version ${xcode_version}. Please upgrade."
+ ${extra_message}
+ )
+ endif()
+
+ if(QT_NO_APPLE_SDK_MAX_VERSION_CHECK)
+ return()
+ endif()
+
+ # Make sure we warn only when the current version is greater than the max supported version.
+ math(EXPR next_after_max_sdk_version "${max_sdk_version} + 1")
+ if(sdk_version VERSION_GREATER_EQUAL next_after_max_sdk_version)
+ message(WARNING
+ "Qt has only been tested with version ${max_sdk_version} "
+ "of the platform SDK, you're using ${sdk_version}. "
+ "This is an unsupported configuration. You may experience build issues, "
+ "and by using "
+ "the ${sdk_version} SDK you are opting in to new features "
+ "that Qt has not been prepared for. "
+ "Please downgrade the SDK you use to build your app to version "
+ "${max_sdk_version}, or configure "
+ "with -DQT_NO_APPLE_SDK_MAX_VERSION_CHECK=ON to silence this warning."
+ )
+ endif()
+endfunction()
+
function(_qt_internal_finalize_apple_app target)
- # Shared between macOS and iOS apps
+ # Shared between macOS and UIKit apps
+
+ _qt_internal_copy_info_plist("${target}")
+ _qt_internal_set_apple_localizations("${target}")
# Only set the various properties if targeting the Xcode generator, otherwise the various
# Xcode tokens are embedded as-is instead of being dynamically evaluated.
# This affects things like the version number or application name as reported by Qt API.
if(CMAKE_GENERATOR STREQUAL "Xcode")
_qt_internal_set_xcode_development_team_id("${target}")
- _qt_internal_set_xcode_bundle_identifier("${target}")
_qt_internal_set_xcode_code_sign_style("${target}")
_qt_internal_set_xcode_bundle_display_name("${target}")
_qt_internal_set_xcode_install_path("${target}")
endif()
+
_qt_internal_set_xcode_bundle_name("${target}")
+ _qt_internal_set_apple_bundle_identifier("${target}")
_qt_internal_set_placeholder_apple_bundle_version("${target}")
endfunction()
+function(_qt_internal_finalize_uikit_app target)
+ if(CMAKE_SYSTEM_NAME STREQUAL iOS)
+ _qt_internal_finalize_ios_app("${target}")
+ else()
+ _qt_internal_finalize_apple_app("${target}")
+ endif()
+endfunction()
+
function(_qt_internal_finalize_ios_app target)
- _qt_internal_finalize_apple_app("${target}")
+ # Must be called before we generate the Info.plist
+ _qt_internal_handle_ios_launch_screen("${target}")
+ _qt_internal_finalize_apple_app("${target}")
_qt_internal_set_xcode_targeted_device_family("${target}")
_qt_internal_set_xcode_bitcode_enablement("${target}")
- _qt_internal_handle_ios_launch_screen("${target}")
- _qt_internal_generate_ios_info_plist("${target}")
_qt_internal_set_ios_simulator_arch("${target}")
endfunction()
diff --git a/cmake/QtPublicCMakeHelpers.cmake b/cmake/QtPublicCMakeHelpers.cmake
index 2e469da8cb..1a9cdc5a07 100644
--- a/cmake/QtPublicCMakeHelpers.cmake
+++ b/cmake/QtPublicCMakeHelpers.cmake
@@ -25,10 +25,13 @@ endfunction()
# The function checks if add_custom_command has the support of the DEPFILE argument.
function(_qt_internal_check_depfile_support out_var)
if(CMAKE_GENERATOR MATCHES "Ninja" OR
- CMAKE_VERSION VERSION_GREATER_EQUAL 3.20 AND CMAKE_GENERATOR MATCHES "Makefiles"
- OR CMAKE_VERSION VERSION_GREATER_EQUAL 3.21
+ (CMAKE_VERSION VERSION_GREATER_EQUAL 3.20 AND CMAKE_GENERATOR MATCHES "Makefiles")
+ OR (CMAKE_VERSION VERSION_GREATER_EQUAL 3.21
AND (CMAKE_GENERATOR MATCHES "Xcode"
- OR CMAKE_GENERATOR MATCHES "Visual Studio ([0-9]+)" AND CMAKE_MATCH_1 GREATER_EQUAL 12))
+ OR (CMAKE_GENERATOR MATCHES "Visual Studio ([0-9]+)" AND CMAKE_MATCH_1 GREATER_EQUAL 12)
+ )
+ )
+ )
set(${out_var} TRUE)
else()
set(${out_var} FALSE)
@@ -36,6 +39,65 @@ function(_qt_internal_check_depfile_support out_var)
set(${out_var} "${${out_var}}" PARENT_SCOPE)
endfunction()
+# Checks if the path points to the cmake directory, like lib/cmake.
+function(__qt_internal_check_path_points_to_cmake_dir result path)
+ string(TOUPPER "${QT_CMAKE_EXPORT_NAMESPACE}" export_namespace_upper)
+ if((INSTALL_LIBDIR AND path MATCHES "/${INSTALL_LIBDIR}/cmake$") OR
+ (${export_namespace_upper}_INSTALL_LIBS AND
+ path MATCHES "/${${export_namespace_upper}_INSTALL_LIBS}/cmake$") OR
+ path MATCHES "/lib/cmake$"
+ )
+ set(${result} TRUE PARENT_SCOPE)
+ else()
+ set(${result} FALSE PARENT_SCOPE)
+ endif()
+endfunction()
+
+# Creates a reverse path to prefix from possible cmake directories. Returns the unchanged path
+# if it doesn't point to cmake directory.
+function(__qt_internal_reverse_prefix_path_from_cmake_dir result cmake_path)
+ string(TOUPPER "${QT_CMAKE_EXPORT_NAMESPACE}" export_namespace_upper)
+ if(INSTALL_LIBDIR AND cmake_path MATCHES "(.+)/${INSTALL_LIBDIR}/cmake$")
+ if(CMAKE_MATCH_1)
+ set(${result} "${CMAKE_MATCH_1}" PARENT_SCOPE)
+ endif()
+ elseif(${export_namespace_upper}_INSTALL_LIBS AND
+ cmake_path MATCHES "(.+)/${${export_namespace_upper}_INSTALL_LIBS}/cmake$")
+ if(CMAKE_MATCH_1)
+ set(${result} "${CMAKE_MATCH_1}" PARENT_SCOPE)
+ endif()
+ elseif(result MATCHES "(.+)/lib/cmake$")
+ if(CMAKE_MATCH_1)
+ set(${result} "${CMAKE_MATCH_1}" PARENT_SCOPE)
+ endif()
+ else()
+ set(${result} "${cmake_path}" PARENT_SCOPE)
+ endif()
+endfunction()
+
+# Returns the possible cmake directories based on prefix_path.
+function(__qt_internal_get_possible_cmake_dirs out_paths prefix_path)
+ set(${out_paths} "")
+
+ if(EXISTS "${prefix_path}/lib/cmake")
+ list(APPEND ${out_paths} "${prefix_path}/lib/cmake")
+ endif()
+
+ string(TOUPPER "${QT_CMAKE_EXPORT_NAMESPACE}" export_namespace_upper)
+ set(next_path "${prefix_path}/${${export_namespace_upper}_INSTALL_LIBS}/cmake")
+ if(${export_namespace_upper}_INSTALL_LIBS AND EXISTS "${next_path}")
+ list(APPEND ${out_paths} "${next_path}")
+ endif()
+
+ set(next_path "${prefix_path}/${INSTALL_LIBDIR}/cmake")
+ if(INSTALL_LIBDIR AND EXISTS "${next_path}")
+ list(APPEND ${out_paths} "${next_path}")
+ endif()
+
+ list(REMOVE_DUPLICATES ${out_paths})
+ set(${out_paths} "${${out_paths}}" PARENT_SCOPE)
+endfunction()
+
# Collect additional package prefix paths to look for Qt packages, both from command line and the
# env variable ${prefixes_var}. The result is stored in ${out_var} and is a list of paths ending
# with "/lib/cmake".
@@ -69,25 +131,530 @@ function(__qt_internal_collect_additional_prefix_paths out_var prefixes_var)
# NO_DEFAULT_PATH, and thus CMAKE_PREFIX_PATH values are discarded.
# CMAKE_FIND_ROOT_PATH values are not discarded and togegher with the PATHS option, it
# ensures packages from additional prefixes are found.
- if(NOT additional_path MATCHES "/lib/cmake$")
- string(APPEND additional_path "/lib/cmake")
+ __qt_internal_check_path_points_to_cmake_dir(is_path_to_cmake "${additional_path}")
+ if(is_path_to_cmake)
+ list(APPEND additional_packages_prefix_paths "${additional_path}")
+ else()
+ __qt_internal_get_possible_cmake_dirs(additional_cmake_dirs "${additional_path}")
+ list(APPEND additional_packages_prefix_paths ${additional_cmake_dirs})
endif()
- list(APPEND additional_packages_prefix_paths "${additional_path}")
endforeach()
set("${out_var}" "${additional_packages_prefix_paths}" PARENT_SCOPE)
endfunction()
+# Collects CMAKE_MODULE_PATH from QT_ADDITIONAL_PACKAGES_PREFIX_PATH
+function(__qt_internal_collect_additional_module_paths)
+ if(__qt_additional_module_paths_set)
+ return()
+ endif()
+ foreach(prefix_path IN LISTS QT_ADDITIONAL_PACKAGES_PREFIX_PATH)
+ __qt_internal_check_path_points_to_cmake_dir(is_path_to_cmake "${prefix_path}")
+ if(is_path_to_cmake)
+ list(APPEND CMAKE_MODULE_PATH "${prefix_path}/${QT_CMAKE_EXPORT_NAMESPACE}")
+ else()
+ __qt_internal_get_possible_cmake_dirs(additional_cmake_dirs "${additional_path}")
+ list(TRANSFORM additional_cmake_dirs APPEND "/${QT_CMAKE_EXPORT_NAMESPACE}")
+ list(APPEND CMAKE_MODULE_PATH ${additional_cmake_dirs})
+ endif()
+ endforeach()
+ list(REMOVE_DUPLICATES CMAKE_MODULE_PATH)
+ set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" PARENT_SCOPE)
+ set(__qt_additional_module_paths_set TRUE PARENT_SCOPE)
+endfunction()
+
# Take a list of prefix paths ending with "/lib/cmake", and return a list of absolute paths with
# "/lib/cmake" removed.
function(__qt_internal_prefix_paths_to_roots out_var prefix_paths)
set(result "")
foreach(path IN LISTS prefix_paths)
- if(path MATCHES "/lib/cmake$")
- string(APPEND path "/../..")
- endif()
- get_filename_component(path "${path}" ABSOLUTE)
+ __qt_internal_reverse_prefix_path_from_cmake_dir(path "${path}")
list(APPEND result "${path}")
endforeach()
set("${out_var}" "${result}" PARENT_SCOPE)
endfunction()
+
+# This function gets all targets below this directory
+#
+# Multi-value Arguments:
+# EXCLUDE list of target types that should be filtered from resulting list.
+#
+# INCLUDE list of target types that should be filtered from resulting list.
+# EXCLUDE has higher priority than INCLUDE.
+function(_qt_internal_collect_buildsystem_targets result dir)
+ cmake_parse_arguments(arg "" "" "EXCLUDE;INCLUDE" ${ARGN})
+
+ if(NOT _qt_internal_collect_buildsystem_targets_inner)
+ set(${result} "")
+ set(_qt_internal_collect_buildsystem_targets_inner TRUE)
+ endif()
+
+ set(forward_args "")
+ if(arg_EXCLUDE)
+ set(forward_args APPEND EXCLUDE ${arg_EXCLUDE})
+ endif()
+
+ if(arg_INCLUDE)
+ set(forward_args APPEND INCLUDE ${arg_INCLUDE})
+ endif()
+
+ get_property(subdirs DIRECTORY "${dir}" PROPERTY SUBDIRECTORIES)
+
+ # Make sure that we don't hit endless recursion when running qt-cmake-standalone-test on a
+ # in-source test dir, where the currently processed directory lists itself in its SUBDIRECTORIES
+ # property.
+ # See https://bugreports.qt.io/browse/QTBUG-119998
+ # and https://gitlab.kitware.com/cmake/cmake/-/issues/25489
+ # Do it only when QT_INTERNAL_IS_STANDALONE_TEST is set, to avoid the possible slowdown when
+ # processing many subdirectores when configuring all standalone tests rather than just one.
+ if(QT_INTERNAL_IS_STANDALONE_TEST)
+ list(REMOVE_ITEM subdirs "${dir}")
+ endif()
+
+ foreach(subdir IN LISTS subdirs)
+ _qt_internal_collect_buildsystem_targets(${result} "${subdir}" ${forward_args})
+ endforeach()
+ get_property(sub_targets DIRECTORY "${dir}" PROPERTY BUILDSYSTEM_TARGETS)
+ set(real_targets "")
+ if(sub_targets)
+ foreach(target IN LISTS sub_targets)
+ get_target_property(target_type ${target} TYPE)
+ if((NOT arg_INCLUDE OR target_type IN_LIST arg_INCLUDE) AND
+ (NOT arg_EXCLUDE OR (NOT target_type IN_LIST arg_EXCLUDE)))
+ list(APPEND real_targets ${target})
+ endif()
+ endforeach()
+ endif()
+ set(${result} ${${result}} ${real_targets} PARENT_SCOPE)
+endfunction()
+
+# Add a custom target ${target} that is *not* added to the default build target in a safe way.
+# Dependencies must then be added with _qt_internal_add_phony_target_dependencies.
+#
+# What's "safe" in this context? For the Visual Studio generators, we cannot use add_dependencies,
+# because this would enable the dependencies in the default build of the solution. See QTBUG-115166
+# and upstream CMake issue #16668 for details. Instead, we record the dependencies (added with
+# _qt_internal_add_phony_target_dependencies) and create the target at the end of the top-level
+# directory scope.
+#
+# This only works if at least CMake 3.19 is used. Older CMake versions will trigger a warning that
+# can be turned off with the variable ${WARNING_VARIABLE}.
+#
+# For other generators, this is just a call to add_custom_target, unless the target already exists,
+# followed by add_dependencies.
+#
+# Use this function for targets that are not part of the default build, i.e. that should be
+# triggered by the user.
+#
+# TARGET_CREATED_HOOK is the name of a function that is called after the target has been created.
+# It takes the target's name as first and only argument.
+#
+# Example:
+# _qt_internal_add_phony_target(update_translations
+# WARNING_VARIABLE QT_NO_GLOBAL_LUPDATE_TARGET_CREATED_WARNING
+# )
+# _qt_internal_add_phony_target_dependencies(update_translations
+# narf_lupdate_zort_lupdate
+# )
+#
+function(_qt_internal_add_phony_target target)
+ set(no_value_options "")
+ set(single_value_options
+ TARGET_CREATED_HOOK
+ WARNING_VARIABLE
+ )
+ set(multi_value_options "")
+ cmake_parse_arguments(PARSE_ARGV 0 arg
+ "${no_value_options}" "${single_value_options}" "${multi_value_options}"
+ )
+ if("${arg_WARNING_VARIABLE}" STREQUAL "")
+ message(FATAL_ERROR "WARNING_VARIABLE must be provided.")
+ endif()
+ if(CMAKE_GENERATOR MATCHES "^Visual Studio ")
+ if(${CMAKE_VERSION} VERSION_LESS "3.19.0")
+ if(NOT ${${arg_WARNING_VARIABLE}})
+ message(WARNING
+ "Cannot create target ${target} with this CMake version. "
+ "Please upgrade to CMake 3.19.0 or newer. "
+ "Set ${WARNING_VARIABLE} to ON to disable this warning."
+ )
+ endif()
+ return()
+ endif()
+
+ get_property(already_deferred GLOBAL PROPERTY _qt_target_${target}_creation_deferred)
+ if(NOT already_deferred)
+ cmake_language(EVAL CODE
+ "cmake_language(DEFER DIRECTORY \"${CMAKE_SOURCE_DIR}\" CALL _qt_internal_add_phony_target_deferred \"${target}\")"
+ )
+ if(DEFINED arg_TARGET_CREATED_HOOK)
+ set_property(GLOBAL
+ PROPERTY _qt_target_${target}_creation_hook ${arg_TARGET_CREATED_HOOK}
+ )
+ endif()
+ endif()
+ set_property(GLOBAL APPEND PROPERTY _qt_target_${target}_creation_deferred ON)
+ else()
+ if(NOT TARGET ${target})
+ add_custom_target(${target})
+ if(DEFINED arg_TARGET_CREATED_HOOK)
+ if(CMAKE_VERSION VERSION_LESS "3.19")
+ set(incfile
+ "${CMAKE_CURRENT_BINARY_DIR}/.qt_internal_add_phony_target.cmake"
+ )
+ file(WRITE "${incfile}" "${arg_TARGET_CREATED_HOOK}(${target})")
+ include("${incfile}")
+ file(REMOVE "${incfile}")
+ else()
+ cmake_language(CALL "${arg_TARGET_CREATED_HOOK}" "${target}")
+ endif()
+ endif()
+ endif()
+ endif()
+endfunction()
+
+# Adds dependencies to a custom target that has been created with
+# _qt_internal_add_phony_target. See the docstring at _qt_internal_add_phony_target for
+# more details.
+function(_qt_internal_add_phony_target_dependencies target)
+ set(dependencies ${ARGN})
+ if(CMAKE_GENERATOR MATCHES "^Visual Studio ")
+ set_property(GLOBAL APPEND PROPERTY _qt_target_${target}_dependencies ${dependencies})
+
+ # Exclude the dependencies from the solution's default build to avoid them being enabled
+ # accidentally should the user add another dependency to them.
+ set_target_properties(${dependencies} PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD ON)
+ else()
+ add_dependencies(${target} ${dependencies})
+ endif()
+endfunction()
+
+# Hack for the Visual Studio generator. Create the custom target named ${target} and work
+# around the lack of a working add_dependencies by calling 'cmake --build' for every dependency.
+function(_qt_internal_add_phony_target_deferred target)
+ get_property(target_dependencies GLOBAL PROPERTY _qt_target_${target}_dependencies)
+ set(target_commands "")
+ foreach(dependency IN LISTS target_dependencies)
+ list(APPEND target_commands
+ COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_BINARY_DIR}" -t ${dependency}
+ )
+ endforeach()
+ add_custom_target(${target} ${target_commands})
+ get_property(creation_hook GLOBAL PROPERTY _qt_target_${target}_creation_hook)
+ if(creation_hook)
+ cmake_language(CALL ${creation_hook} ${target})
+ endif()
+endfunction()
+
+# The helper function that checks if module was included multiple times, and has the inconsistent
+# set of targets that belong to the module. It's expected that either all 'targets' or none of them
+# will be written to the 'targets_not_defined' variable, if the module was not or was
+# searched before accordingly.
+function(_qt_internal_check_multiple_inclusion targets_not_defined targets)
+ set(targets_defined "")
+ set(${targets_not_defined} "")
+ set(expected_targets "")
+ foreach(expected_target ${targets})
+ list(APPEND expected_targets ${expected_target})
+ if(NOT TARGET Qt::${expected_target})
+ list(APPEND ${targets_not_defined} ${expected_target})
+ endif()
+ if(TARGET Qt::${expected_target})
+ list(APPEND targets_defined ${expected_target})
+ endif()
+ endforeach()
+ if("${targets_defined}" STREQUAL "${expected_targets}")
+ set(${targets_not_defined} "" PARENT_SCOPE)
+ return()
+ endif()
+ if(NOT "${targets_defined}" STREQUAL "")
+ message(FATAL_ERROR "Some (but not all) targets in this export set were already defined."
+ "\nTargets Defined: ${targets_defined}\nTargets not yet defined: "
+ "${${targets_not_defined}}\n"
+ )
+ endif()
+ set(${targets_not_defined} "${${targets_not_defined}}" PARENT_SCOPE)
+endfunction()
+
+# The function is used when creating version less targets using ALIASes.
+function(_qt_internal_create_versionless_alias_targets targets install_namespace)
+ foreach(target IN LISTS targets)
+ add_library(Qt::${target} ALIAS ${install_namespace}::${target})
+ endforeach()
+endfunction()
+
+# The function is used when creating version less targets from scratch but not using ALIASes.
+# It assigns the known properties from the versioned targets to the versionless created in this
+# function. This allows versionless targets mimic the versioned.
+function(_qt_internal_create_versionless_targets targets install_namespace)
+ set(known_interface_properties
+ QT_MAJOR_VERSION
+ AUTOMOC_MACRO_NAMES
+ AUTOUIC_OPTIONS
+ COMPILE_DEFINITIONS
+ COMPILE_FEATURES
+ COMPILE_OPTIONS
+ CXX_MODULE_SETS
+ HEADER_SETS
+ HEADER_SETS_TO_VERIFY
+ INCLUDE_DIRECTORIES
+ LINK_DEPENDS
+ LINK_DIRECTORIES
+ LINK_LIBRARIES
+ LINK_LIBRARIES_DIRECT
+ LINK_LIBRARIES_DIRECT_EXCLUDE
+ LINK_OPTIONS
+ POSITION_INDEPENDENT_CODE
+ PRECOMPILE_HEADERS
+ SOURCES
+ SYSTEM_INCLUDE_DIRECTORIES
+ )
+
+ set(known_qt_exported_properties
+ MODULE_PLUGIN_TYPES
+ QT_DISABLED_PRIVATE_FEATURES
+ QT_DISABLED_PUBLIC_FEATURES
+ QT_ENABLED_PRIVATE_FEATURES
+ QT_ENABLED_PUBLIC_FEATURES
+ QT_QMAKE_PRIVATE_CONFIG
+ QT_QMAKE_PUBLIC_CONFIG
+ QT_QMAKE_PUBLIC_QT_CONFIG
+ )
+
+ set(known_qt_exported_properties_interface_allowed
+ _qt_config_module_name
+ _qt_is_public_module
+ _qt_module_has_headers
+ _qt_module_has_private_headers
+ _qt_module_has_public_headers
+ _qt_module_has_qpa_headers
+ _qt_module_has_rhi_headers
+ _qt_module_include_name
+ _qt_module_interface_name
+ _qt_package_name
+ _qt_package_version
+ _qt_private_module_target_name
+ )
+
+ set(supported_target_types STATIC_LIBRARY MODULE_LIBRARY SHARED_LIBRARY OBJECT_LIBRARY
+ INTERFACE_LIBRARY)
+
+ foreach(target IN LISTS targets)
+ if(NOT TARGET ${install_namespace}::${target})
+ message(FATAL_ERROR "${install_namespace}::${target} is not a target, can not extend"
+ " an alias target")
+ endif()
+
+ get_target_property(type ${install_namespace}::${target} TYPE)
+ if(NOT type)
+ message(FATAL_ERROR "Cannot get the ${install_namespace}::${target} target type.")
+ endif()
+
+ if(NOT "${type}" IN_LIST supported_target_types)
+ message(AUTHOR_WARNING "${install_namespace}::${target} requires the versionless"
+ " target creation, but it has incompatible type ${type}.")
+ continue()
+ endif()
+
+ string(REPLACE "_LIBRARY" "" creation_type "${type}")
+ add_library(Qt::${target} ${creation_type} IMPORTED)
+
+ if(NOT "${type}" STREQUAL "INTERFACE_LIBRARY")
+ foreach(config "" _RELEASE _DEBUG _RELWITHDEBINFO _MINSIZEREL)
+ get_target_property(target_imported_location
+ ${install_namespace}::${target} IMPORTED_LOCATION${config})
+ if(NOT target_imported_location)
+ if("${config}" STREQUAL "")
+ message(FATAL_ERROR "Cannot create versionless target for"
+ " ${install_namespace}::${target}. IMPORTED_LOCATION property is "
+ "missing."
+ )
+ else()
+ continue()
+ endif()
+ endif()
+ set_property(TARGET Qt::${target} PROPERTY
+ IMPORTED_LOCATION${config} "${target_imported_location}")
+ endforeach()
+
+ foreach(property IN LISTS known_qt_exported_properties)
+ get_target_property(exported_property_value
+ ${install_namespace}::${target} ${property})
+ if(exported_property_value)
+ set_property(TARGET Qt::${target} APPEND PROPERTY
+ ${property} "${exported_property_value}")
+ endif()
+ endforeach()
+ endif()
+
+ foreach(property IN LISTS known_interface_properties)
+ get_target_property(interface_property_value
+ ${install_namespace}::${target} INTERFACE_${property})
+ if(interface_property_value)
+ set_property(TARGET Qt::${target} APPEND PROPERTY
+ INTERFACE_${property} "${interface_property_value}")
+ endif()
+ endforeach()
+
+ foreach(property IN LISTS known_qt_exported_properties_interface_allowed)
+ get_target_property(exported_property_value
+ ${install_namespace}::${target} ${property})
+ if(exported_property_value)
+ set_property(TARGET Qt::${target} APPEND PROPERTY
+ ${property} "${exported_property_value}")
+ endif()
+ endforeach()
+
+ set_property(TARGET Qt::${target} PROPERTY _qt_is_versionless_target TRUE)
+ endforeach()
+endfunction()
+
+# Checks whether any unparsed arguments have been passed to the function at the call site.
+# Use this right after `cmake_parse_arguments`.
+function(_qt_internal_validate_all_args_are_parsed prefix)
+ if(DEFINED ${prefix}_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "Unknown arguments: (${${prefix}_UNPARSED_ARGUMENTS})")
+ endif()
+endfunction()
+
+# Takes a list of path components and joins them into one path separated by forward slashes "/",
+# and saves the path in out_var.
+function(_qt_internal_path_join out_var)
+ string(JOIN "/" path ${ARGN})
+ set(${out_var} ${path} PARENT_SCOPE)
+endfunction()
+
+# _qt_internal_qt_remove_args can remove arguments from an existing list of function
+# arguments in order to pass a filtered list of arguments to a different function.
+# Parameters:
+# out_var: result of remove all arguments specified by ARGS_TO_REMOVE from ALL_ARGS
+# ARGS_TO_REMOVE: Arguments to remove.
+# ALL_ARGS: All arguments supplied to cmake_parse_arguments
+# from which ARGS_TO_REMOVE should be removed from. We require all the
+# arguments or we can't properly identify the range of the arguments detailed
+# in ARGS_TO_REMOVE.
+# ARGS: Arguments passed into the function, usually ${ARGV}
+#
+# E.g.:
+# We want to forward all arguments from foo to bar, execpt ZZZ since it will
+# trigger an error in bar.
+#
+# foo(target BAR .... ZZZ .... WWW ...)
+# bar(target BAR.... WWW...)
+#
+# function(foo target)
+# cmake_parse_arguments(PARSE_ARGV 1 arg "" "" "BAR;ZZZ;WWW")
+# qt_remove_args(forward_args
+# ARGS_TO_REMOVE ${target} ZZZ
+# ALL_ARGS ${target} BAR ZZZ WWW
+# ARGS ${ARGV}
+# )
+# bar(${target} ${forward_args})
+# endfunction()
+#
+function(_qt_internal_remove_args out_var)
+ cmake_parse_arguments(arg "" "" "ARGS_TO_REMOVE;ALL_ARGS;ARGS" ${ARGN})
+ set(result ${arg_ARGS})
+ foreach(arg IN LISTS arg_ARGS_TO_REMOVE)
+ # find arg
+ list(FIND result ${arg} find_result)
+ if (NOT find_result EQUAL -1)
+ # remove arg
+ list(REMOVE_AT result ${find_result})
+ list(LENGTH result result_len)
+ if(find_result EQUAL result_len)
+ # We removed the last argument, could have been an option keyword
+ continue()
+ endif()
+ list(GET result ${find_result} arg_current)
+ # remove values until we hit another arg or the end of the list
+ while(NOT "${arg_current}" IN_LIST arg_ALL_ARGS AND find_result LESS result_len)
+ list(REMOVE_AT result ${find_result})
+ list(LENGTH result result_len)
+ if (NOT find_result EQUAL result_len)
+ list(GET result ${find_result} arg_current)
+ endif()
+ endwhile()
+ endif()
+ endforeach()
+ set(${out_var} "${result}" PARENT_SCOPE)
+endfunction()
+
+# Append ${ARGN} to ${target}'s ${property_name} property, removing duplicates.
+function(_qt_internal_append_to_target_property_without_duplicates target property_name)
+ get_target_property(property "${target}" "${property_name}")
+ if(NOT property)
+ set(property "")
+ endif()
+ list(APPEND property ${ARGN})
+ list(REMOVE_DUPLICATES property)
+ set_property(TARGET "${target}" PROPERTY "${property_name}" "${property}")
+endfunction()
+
+# Append ${ARGN} to global CMake ${property_name} property, removing duplicates.
+function(_qt_internal_append_to_cmake_property_without_duplicates property_name)
+ get_cmake_property(property "${property_name}")
+ if(NOT property)
+ set(property "")
+ endif()
+ list(APPEND property ${ARGN})
+ list(REMOVE_DUPLICATES property)
+ set_property(GLOBAL PROPERTY "${property_name}" "${property}")
+endfunction()
+
+# Helper function to forward options from one function to another.
+#
+# This is somewhat the opposite of _qt_internal_remove_args.
+#
+# Parameters:
+# FORWARD_PREFIX is usually arg because we pass cmake_parse_arguments(PARSE_ARGV 0 arg) in most code
+# FORWARD_OPTIONS, FORWARD_SINGLE, FORWARD_MULTI are the options that should be forwarded.
+#
+# The forwarded args will be either set in arg_FORWARD_OUT_VAR or appended if FORWARD_APPEND is set.
+#
+# The function reads the options like ${arg_FORWARD_PREFIX}_${option} in the parent scope.
+function(_qt_internal_forward_function_args)
+ set(opt_args
+ FORWARD_APPEND
+ )
+ set(single_args
+ FORWARD_PREFIX
+ )
+ set(multi_args
+ FORWARD_OPTIONS
+ FORWARD_SINGLE
+ FORWARD_MULTI
+ FORWARD_OUT_VAR
+ )
+ cmake_parse_arguments(PARSE_ARGV 0 arg "${opt_args}" "${single_args}" "${multi_args}")
+ _qt_internal_validate_all_args_are_parsed(arg)
+
+ if(NOT arg_FORWARD_OUT_VAR)
+ message(FATAL_ERROR "FORWARD_OUT_VAR must be provided.")
+ endif()
+
+ set(forward_args "")
+ foreach(option_name IN LISTS arg_FORWARD_OPTIONS)
+ if(${arg_FORWARD_PREFIX}_${option_name})
+ list(APPEND forward_args "${option_name}")
+ endif()
+ endforeach()
+
+ foreach(option_name IN LISTS arg_FORWARD_SINGLE)
+ if(${arg_FORWARD_PREFIX}_${option_name})
+ list(APPEND forward_args "${option_name}" "${${arg_FORWARD_PREFIX}_${option_name}}")
+ endif()
+ endforeach()
+
+ foreach(option_name IN LISTS arg_FORWARD_MULTI)
+ if(${arg_FORWARD_PREFIX}_${option_name})
+ list(APPEND forward_args "${option_name}" ${${arg_FORWARD_PREFIX}_${option_name}})
+ endif()
+ endforeach()
+
+ if(arg_FORWARD_APPEND)
+ set(forward_args ${${arg_FORWARD_OUT_VAR}} "${forward_args}")
+ endif()
+
+ set(${arg_FORWARD_OUT_VAR} "${forward_args}" PARENT_SCOPE)
+endfunction()
diff --git a/cmake/QtPublicDependencyHelpers.cmake b/cmake/QtPublicDependencyHelpers.cmake
index de62eb1c10..bd8b4a55c4 100644
--- a/cmake/QtPublicDependencyHelpers.cmake
+++ b/cmake/QtPublicDependencyHelpers.cmake
@@ -112,9 +112,9 @@ macro(_qt_internal_find_qt_dependencies target target_dep_list find_dependency_p
NAMES
${__qt_${target}_pkg_names}
PATHS
+ ${QT_BUILD_CMAKE_PREFIX_PATH}
${${find_dependency_path_list}}
${_qt_additional_packages_prefix_paths}
- ${QT_EXAMPLES_CMAKE_PREFIX_PATH}
${__qt_use_no_default_path_for_qt_packages}
)
endif()
diff --git a/cmake/QtPublicExternalProjectHelpers.cmake b/cmake/QtPublicExternalProjectHelpers.cmake
new file mode 100644
index 0000000000..07096523d0
--- /dev/null
+++ b/cmake/QtPublicExternalProjectHelpers.cmake
@@ -0,0 +1,86 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+include_guard()
+
+# Get CMake variables that are needed to build external projects such as examples or CMake test
+# projects.
+#
+# CMAKE_DIR_VAR: Variable name to store the path to the Qt6 CMake config module.
+#
+# PREFIXES_VAR: Variable name to store the prefixes that can be passed as CMAKE_PREFIX_PATH.
+#
+# ADDITIONAL_PACKAGES_PREFIXES_VAR: Variable name to store the prefixes that can be appended to
+# QT_ADDITIONAL_PACKAGES_PREFIX_PATH.
+function(_qt_internal_get_build_vars_for_external_projects)
+ set(no_value_options "")
+ set(single_value_options
+ CMAKE_DIR_VAR
+ PREFIXES_VAR
+ ADDITIONAL_PACKAGES_PREFIXES_VAR
+ )
+ set(multi_value_options "")
+ cmake_parse_arguments(PARSE_ARGV 0 arg
+ "${no_value_options}" "${single_value_options}" "${multi_value_options}"
+ )
+
+ # Standalone tests and examples have QT_BUILD_DIR pointing to the fake standalone prefix.
+ # Use instead the relocatable prefix, because qt must have been built / installed by this point.
+ if(QT_INTERNAL_BUILD_STANDALONE_PARTS)
+ qt_path_join(qt_cmake_dir
+ "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}"
+ "${INSTALL_LIBDIR}/cmake/${QT_CMAKE_EXPORT_NAMESPACE}"
+ )
+
+ set(qt_prefixes "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}")
+ set(qt_additional_packages_prefixes "${qt_prefixes}")
+
+ if(QT_WILL_INSTALL)
+ list(APPEND qt_prefixes "${QT6_INSTALL_PREFIX}")
+ endif()
+ # TODO: Fix example/test builds when using Conan / install prefixes are different for each repo.
+ elseif(QT_SUPERBUILD OR QtBase_BINARY_DIR)
+ # When doing a top-level build or when building qtbase,
+ # always use the Config file from the current build directory, even for prefix builds.
+ # We strive to allow building examples without installing Qt first, which means we can't
+ # use the install or staging Config files.
+ set(qt_prefixes "${QT_BUILD_DIR}")
+ set(qt_cmake_dir "${QT_CONFIG_BUILD_DIR}/${QT_CMAKE_EXPORT_NAMESPACE}")
+ set(qt_additional_packages_prefixes "")
+ else()
+ # This is a per-repo build that isn't the qtbase repo, so we know that
+ # qtbase was found via find_package() and Qt6_DIR must be set
+ set(qt_cmake_dir "${${QT_CMAKE_EXPORT_NAMESPACE}_DIR}")
+
+ # In a prefix build of a non-qtbase repo, we want to pick up the installed Config files
+ # for all repos except the one that is currently built. For the repo that is currently
+ # built, we pick up the Config files from the current repo build dir instead.
+ # For non-prefix builds, there's only one prefix, the main build dir.
+ # Both are handled by this assignment.
+ set(qt_prefixes "${QT_BUILD_DIR}")
+
+ # Appending to QT_ADDITIONAL_PACKAGES_PREFIX_PATH helps find Qt6 components in
+ # non-qtbase prefix builds because we use NO_DEFAULT_PATH in find_package calls.
+ # It also handles the cross-compiling scenario where we need to adjust both the root path
+ # and prefixes, with the prefixes containing lib/cmake. This leverages the infrastructure
+ # previously added for Conan.
+ set(qt_additional_packages_prefixes "${qt_prefixes}")
+
+ # In a prefix build, look up all repo Config files in the install prefix,
+ # except for the current repo, which will look in the build dir (handled above).
+ if(QT_WILL_INSTALL)
+ list(APPEND qt_prefixes "${QT6_INSTALL_PREFIX}")
+ endif()
+ endif()
+
+ if(arg_CMAKE_DIR_VAR)
+ set("${arg_CMAKE_DIR_VAR}" "${qt_cmake_dir}" PARENT_SCOPE)
+ endif()
+ if(arg_PREFIXES_VAR)
+ set("${arg_PREFIXES_VAR}" "${qt_prefixes}" PARENT_SCOPE)
+ endif()
+ if(arg_ADDITIONAL_PACKAGES_PREFIXES_VAR)
+ set("${arg_ADDITIONAL_PACKAGES_PREFIXES_VAR}" "${qt_additional_packages_prefixes}"
+ PARENT_SCOPE)
+ endif()
+endfunction()
diff --git a/cmake/QtPublicFindPackageHelpers.cmake b/cmake/QtPublicFindPackageHelpers.cmake
index 69f4f69e40..e463ea8d5d 100644
--- a/cmake/QtPublicFindPackageHelpers.cmake
+++ b/cmake/QtPublicFindPackageHelpers.cmake
@@ -4,3 +4,52 @@
function(qt_internal_disable_find_package_global_promotion target)
set_target_properties("${target}" PROPERTIES _qt_no_promote_global TRUE)
endfunction()
+
+# Transforms a list of package components into a string, so it can serve as a valid infix
+# in a property name.
+function(_qt_internal_get_package_components_as_valid_key_infix value out_var)
+ string(REPLACE ";" "_" valid_value "${value}")
+ set(${out_var} "${valid_value}" PARENT_SCOPE)
+endfunction()
+
+# This function computes a unique key / id using the package name and the components that are
+# passed.
+# The result is later used as property name, to store provided targets for a specific
+# package + components combination.
+function(_qt_internal_get_package_components_id)
+ set(opt_args "")
+ set(single_args
+ PACKAGE_NAME
+ OUT_VAR_KEY
+ )
+ set(multi_args
+ COMPONENTS
+ OPTIONAL_COMPONENTS
+ )
+ cmake_parse_arguments(PARSE_ARGV 0 arg "${opt_args}" "${single_args}" "${multi_args}")
+ _qt_internal_validate_all_args_are_parsed(arg)
+
+ if(NOT arg_PACKAGE_NAME)
+ message(FATAL_ERROR "PACKAGE_NAME is required")
+ endif()
+
+ if(NOT arg_OUT_VAR_KEY)
+ message(FATAL_ERROR "OUT_VAR_KEY is required")
+ endif()
+
+ set(key "${arg_PACKAGE_NAME}")
+
+ if(arg_COMPONENTS)
+ _qt_internal_get_package_components_as_valid_key_infix("${arg_COMPONENTS}"
+ components_as_string)
+ string(APPEND key "-${components_as_string}")
+ endif()
+
+ if(arg_OPTIONAL_COMPONENTS)
+ _qt_internal_get_package_components_as_valid_key_infix("${arg_OPTIONAL_COMPONENTS}"
+ components_as_string)
+ string(APPEND key "-${components_as_string}")
+ endif()
+
+ set(${arg_OUT_VAR_KEY} "${key}" PARENT_SCOPE)
+endfunction()
diff --git a/cmake/QtPublicPluginHelpers.cmake b/cmake/QtPublicPluginHelpers.cmake
index 5a4777a076..7087c31234 100644
--- a/cmake/QtPublicPluginHelpers.cmake
+++ b/cmake/QtPublicPluginHelpers.cmake
@@ -187,7 +187,7 @@ function(__qt_internal_get_plugin_import_macro plugin_target out_var)
set(class_name "${class_name_prefixed}")
endif()
- set(${out_var} "Q_IMPORT_PLUGIN(${class_name})" PARENT_SCOPE)
+ set(${out_var} "Q_IMPORT_PLUGIN(${class_name})\n" PARENT_SCOPE)
endfunction()
function(__qt_internal_get_plugin_include_prelude out_var)
diff --git a/cmake/QtPublicTargetHelpers.cmake b/cmake/QtPublicTargetHelpers.cmake
index 6f0d3bb2c9..02d5546560 100644
--- a/cmake/QtPublicTargetHelpers.cmake
+++ b/cmake/QtPublicTargetHelpers.cmake
@@ -307,7 +307,31 @@ function(_qt_internal_set_up_static_runtime_library target)
set_property(TARGET ${target} PROPERTY
MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
elseif(MINGW)
- target_link_options(${target} INTERFACE "LINKER:-Bstatic")
+ get_target_property(target_type ${target} TYPE)
+ if(target_type STREQUAL "EXECUTABLE")
+ set(link_option PRIVATE)
+ else()
+ set(link_option INTERFACE)
+ endif()
+ if(CLANG)
+ target_link_options(${target} ${link_option} "LINKER:-Bstatic")
+ else()
+ target_link_options(${target} ${link_option} "-static")
+ endif()
endif()
endif()
endfunction()
+
+function(_qt_internal_warn_about_example_add_subdirectory)
+ # This is set by qt_build_repo_impl_examples() in QtBuildRepoHelpers.cmake, only for developer
+ # builds, to catch examples that are added via add_subdirectory instead of via
+ # qt_internal_add_example.
+ if(QT_WARN_ABOUT_EXAMPLE_ADD_SUBDIRECTORY)
+ get_filename_component(dir_name "${PROJECT_SOURCE_DIR}" NAME)
+ message(AUTHOR_WARNING
+ "It looks like this example project was added via add_subdirectory instead of via "
+ "qt_internal_add_example. This causes issues in certain build configurations. Please "
+ "change the code to use\n qt_internal_add_example(${dir_name})\ninstead."
+ )
+ endif()
+endfunction()
diff --git a/cmake/QtPublicTestHelpers.cmake b/cmake/QtPublicTestHelpers.cmake
index 0cfbfab404..771911c5d5 100644
--- a/cmake/QtPublicTestHelpers.cmake
+++ b/cmake/QtPublicTestHelpers.cmake
@@ -64,7 +64,7 @@ is not specified")
#Escaping environment variables before expand them by file GENERATE
string(REPLACE "\\" "\\\\" environment_extras "${environment_extras}")
- if(WIN32)
+ if(CMAKE_HOST_WIN32)
# It's necessary to call actual test inside 'cmd.exe', because 'execute_process' uses
# SW_HIDE to avoid showing a console window, it affects other GUI as well.
# See https://gitlab.kitware.com/cmake/cmake/-/issues/17690 for details.
@@ -97,7 +97,7 @@ execute_process(COMMAND ${extra_runner} ${arg_COMMAND}
)
${post_run}
if(NOT result EQUAL 0)
- string(JOIN \" \" full_command ${arg_COMMAND})
+ string(JOIN \" \" full_command ${extra_runner} ${arg_COMMAND})
message(FATAL_ERROR \"\${full_command} execution failed with exit code \${result}.\")
endif()"
)
diff --git a/cmake/QtPublicWalkLibsHelpers.cmake b/cmake/QtPublicWalkLibsHelpers.cmake
index f0d9280637..959283aca1 100644
--- a/cmake/QtPublicWalkLibsHelpers.cmake
+++ b/cmake/QtPublicWalkLibsHelpers.cmake
@@ -184,13 +184,13 @@ function(__qt_internal_walk_libs
if(lib_target MATCHES "^::@")
continue()
elseif(TARGET ${lib_target})
- if ("${lib_target}" MATCHES "^Qt::(.*)")
- # If both, Qt::Foo and Foo targets exist, prefer the target name without
+ if(NOT "${lib_target}" MATCHES "^(Qt|${QT_CMAKE_EXPORT_NAMESPACE})::.+")
+ # If both, Qt::Foo and Foo targets exist, prefer the target name with versioned
# namespace. Which one is preferred doesn't really matter. This code exists to
# avoid ending up with both, Qt::Foo and Foo in our dependencies.
- set(namespaceless_lib_target "${CMAKE_MATCH_1}")
- if(TARGET namespaceless_lib_target)
- set(lib_target ${namespaceless_lib_target})
+ set(versioned_qt_target "${QT_CMAKE_EXPORT_NAMESPACE}::${lib_target}")
+ if(TARGET "${versioned_qt_target}")
+ set(lib_target ${versioned_qt_target})
endif()
endif()
get_target_property(lib_target_type ${lib_target} TYPE)
@@ -255,8 +255,8 @@ function(__qt_internal_walk_libs
__qt_internal_promote_target_to_global(${lib_target_unaliased})
endif()
endif()
- elseif("${lib_target}" MATCHES "^Qt::(.*)")
- message(FATAL_ERROR "The ${CMAKE_MATCH_1} target is mentioned as a dependency for \
+ elseif("${lib_target}" MATCHES "^(Qt|${QT_CMAKE_EXPORT_NAMESPACE})::(.*)")
+ message(FATAL_ERROR "The ${CMAKE_MATCH_2} target is mentioned as a dependency for \
${target}, but not declared.")
else()
if(NOT operation MATCHES "^(collect|direct)_targets$")
diff --git a/cmake/QtPublicWasmToolchainHelpers.cmake b/cmake/QtPublicWasmToolchainHelpers.cmake
index 798258db94..a8994520e2 100644
--- a/cmake/QtPublicWasmToolchainHelpers.cmake
+++ b/cmake/QtPublicWasmToolchainHelpers.cmake
@@ -30,7 +30,7 @@ function(__qt_internal_query_emsdk_version emroot_path is_fatal out_var)
set(EXECUTE_COMMANDPATH "$ENV{EMSDK}/${emroot_path}/emcc")
endif()
- file(TO_NATIVE_PATH "${EXECUTE_COMMANDPATH}" EXECUTE_COMMAND)
+ file(TO_CMAKE_PATH "${EXECUTE_COMMANDPATH}" EXECUTE_COMMAND)
execute_process(COMMAND ${EXECUTE_COMMAND} --version
OUTPUT_VARIABLE emOutput
OUTPUT_STRIP_TRAILING_WHITESPACE
@@ -53,7 +53,7 @@ endfunction()
function(__qt_internal_get_emcc_recommended_version out_var)
# This version of Qt needs this version of emscripten.
- set(QT_EMCC_RECOMMENDED_VERSION "3.1.25")
+ set(QT_EMCC_RECOMMENDED_VERSION "3.1.50")
set(${out_var} "${QT_EMCC_RECOMMENDED_VERSION}" PARENT_SCOPE)
endfunction()
@@ -81,12 +81,14 @@ function(__qt_internal_get_qt_build_emsdk_version out_var)
endif()
if(EXISTS "${WASM_BUILD_DIR}/src/corelib/global/qconfig.h")
file(READ "${WASM_BUILD_DIR}/src/corelib/global/qconfig.h" ver)
- else()
+ elseif(EXISTS "${WASM_BUILD_DIR}/include/QtCore/qconfig.h")
file(READ "${WASM_BUILD_DIR}/include/QtCore/qconfig.h" ver)
endif()
- string(REGEX MATCH "#define QT_EMCC_VERSION.\"[0-9]+\\.[0-9]+\\.[0-9]+\"" emOutput ${ver})
- string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" build_emcc_version "${emOutput}")
- set(${out_var} "${build_emcc_version}" PARENT_SCOPE)
+ if (ver)
+ string(REGEX MATCH "#define QT_EMCC_VERSION.\"[0-9]+\\.[0-9]+\\.[0-9]+\"" emOutput ${ver})
+ string(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" build_emcc_version "${emOutput}")
+ set(${out_var} "${build_emcc_version}" PARENT_SCOPE)
+ endif()
endfunction()
function(_qt_test_emscripten_version)
@@ -95,7 +97,7 @@ function(_qt_test_emscripten_version)
__qt_internal_query_emsdk_version("${emroot_path}" TRUE current_emsdk_ver)
__qt_internal_get_qt_build_emsdk_version(qt_build_emcc_version)
- if(NOT "${qt_build_emcc_version}" STREQUAL "${current_emsdk_ver}")
+ if(NOT "${qt_build_emcc_version}" STREQUAL "" AND NOT "${qt_build_emcc_version}" STREQUAL "${current_emsdk_ver}")
message("Qt Wasm built with Emscripten version: ${qt_build_emcc_version}")
message("You are using Emscripten version: ${current_emsdk_ver}")
message("The recommended version of Emscripten for this Qt is: ${_recommended_emver}")
diff --git a/cmake/QtQmakeHelpers.cmake b/cmake/QtQmakeHelpers.cmake
index 8154661953..c618fa0510 100644
--- a/cmake/QtQmakeHelpers.cmake
+++ b/cmake/QtQmakeHelpers.cmake
@@ -80,7 +80,7 @@ endfunction()
# up the host qmake's properties for cross-compiling with this Qt
# build.
function(qt_generate_qmake_and_qtpaths_wrapper_for_target)
- if(NOT CMAKE_CROSSCOMPILING)
+ if(NOT CMAKE_CROSSCOMPILING OR QT_NO_GENERATE_QMAKE_WRAPPER_FOR_TARGET)
return()
endif()
@@ -211,6 +211,8 @@ function(qt_get_qmake_module_name result module)
string(REGEX REPLACE "^Qt6" "" module "${module}")
string(REGEX REPLACE "Private$" "_private" module "${module}")
string(REGEX REPLACE "Qpa$" "_qpa_lib_private" module "${module}")
+ string(REGEX REPLACE "Rhi$" "_rhi_lib_private" module "${module}")
+ string(REGEX REPLACE "Ssg$" "_ssg_lib_private" module "${module}")
string(TOLOWER "${module}" module)
set(${result} ${module} PARENT_SCOPE)
endfunction()
diff --git a/cmake/QtRpathHelpers.cmake b/cmake/QtRpathHelpers.cmake
index 2150b95e73..da6c8715a8 100644
--- a/cmake/QtRpathHelpers.cmake
+++ b/cmake/QtRpathHelpers.cmake
@@ -6,7 +6,7 @@
function(qt_internal_get_relative_rpath_base_token out_var)
if(APPLE)
set(rpath_rel_base "@loader_path")
- elseif(LINUX OR SOLARIS OR FREEBSD OR HURD)
+ elseif(LINUX OR SOLARIS OR FREEBSD OR HURD OR OPENBSD)
set(rpath_rel_base "$ORIGIN")
else()
set(rpath_rel_base "NO_KNOWN_RPATH_REL_BASE")
@@ -192,6 +192,51 @@ function(qt_apply_rpaths)
endif()
endfunction()
+macro(qt_internal_set_default_rpath_settings)
+ # the default RPATH to be used when installing, but only if it's not a system directory
+ list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES
+ "${CMAKE_INSTALL_PREFIX}/${INSTALL_LIBDIR}" isSystemDir)
+ if("${isSystemDir}" STREQUAL "-1")
+ set(_default_install_rpath "${CMAKE_INSTALL_PREFIX}/${INSTALL_LIBDIR}")
+ endif("${isSystemDir}" STREQUAL "-1")
+
+ # The default rpath settings for installed targets is empty.
+ # The rpaths will instead be computed for each target separately using qt_apply_rpaths().
+ # Additional rpaths can be passed via QT_EXTRA_RPATHS.
+ # By default this will include $ORIGIN / @loader_path, so the installation is relocatable.
+ # Bottom line: No need to pass anything to CMAKE_INSTALL_RPATH.
+ set(CMAKE_INSTALL_RPATH "" CACHE STRING "RPATH for installed binaries")
+
+ # By default, don't embed auto-determined RPATHs pointing to directories
+ # outside of the build tree, into the installed binaries.
+ # This ended up adding rpaths like ${CMAKE_INSTALL_PREFIX}/lib (or /Users/qt/work/install/lib
+ # into the official libraries created by the CI) into the non-qtbase libraries, plugins, etc.
+ #
+ # It should not be necessary, given that qt_apply_rpaths() already adds the necessary rpaths,
+ # either relocatable ones or absolute ones, depending on what the platform supports.
+ if(NOT QT_NO_DISABLE_CMAKE_INSTALL_RPATH_USE_LINK_PATH)
+ set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE)
+ endif()
+
+ # If Qt is built without rpath support, we should not add "user-project default rpaths" to
+ # qt qml plugins. Do this by setting QT_NO_QML_PLUGIN_RPATH to TRUE, which is
+ # then read by qt6_add_qml_plugin.
+ # We do this as part of the internal API, because we still want to allow user project qml
+ # plugins to have sensible default rpaths, even if Qt qml plugins were built without support
+ # for rpaths.
+ #
+ # Note that feature evaluation is not done yet in qtbase at this point, so we check both
+ # feature variable variants. In practice it doesn't really matter, because the variable is only
+ # read during qtdeclarative configuration time when the feature is already evaluated.
+ #
+ # We also make sure not to set it as a cache var just in case somebody wants to override it
+ # per directory scope.
+ if(NOT DEFINED QT_NO_QML_PLUGIN_RPATH
+ AND (QT_DISABLE_RPATH OR (NOT FEATURE_rpath) OR (NOT QT_FEATURE_rpath)))
+ set(QT_NO_QML_PLUGIN_RPATH "TRUE")
+ endif()
+endmacro()
+
# Overrides the CMAKE_STAGING_PREFIX in a subdirectory scope, to stop CMake from rewriting build
# rpaths to point into the original staging prefix, and thus breaking running executables from
# the build directory.
diff --git a/cmake/QtSanitizerHelpers.cmake b/cmake/QtSanitizerHelpers.cmake
index 775706e721..2a933b2222 100644
--- a/cmake/QtSanitizerHelpers.cmake
+++ b/cmake/QtSanitizerHelpers.cmake
@@ -26,3 +26,35 @@ function(qt_internal_set_up_sanitizer_options)
set(ECM_ENABLE_SANITIZERS "${enabled_sanitizer_features}" PARENT_SCOPE)
endif()
endfunction()
+
+# This function clears the previously set sanitizer flags from CMAKE_<C|CXX>_FLAGS
+function(qt_internal_skip_sanitizer)
+ if(CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR
+ CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR
+ CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
+ foreach(sanitizer ${ECM_ENABLE_SANITIZERS})
+ string(TOLOWER "${sanitizer}" sanitizer)
+ enable_sanitizer_flags("${sanitizer}")
+ qt_internal_remove_compiler_flags(${XSAN_COMPILE_FLAGS})
+ endforeach()
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" PARENT_SCOPE)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" PARENT_SCOPE)
+ endif()
+endfunction()
+
+# This function disables the sanitizer library linking to all targets created in a subdirectory
+# where the function is called. Note that the function should be called after all involved targets
+# are created, to make sure they are collected by the function.
+function(qt_internal_skip_linking_sanitizer)
+ _qt_internal_collect_buildsystem_targets(all_targets "${CMAKE_CURRENT_SOURCE_DIR}"
+ INCLUDE
+ STATIC_LIBRARY
+ MODULE_LIBRARY
+ SHARED_LIBRARY
+ OBJECT_LIBRARY
+ EXECUTABLE
+ )
+ foreach(t IN LISTS all_targets)
+ set_property(TARGET ${t} PROPERTY SKIP_SANITIZER TRUE)
+ endforeach()
+endfunction()
diff --git a/cmake/QtSeparateDebugInfo.Info.plist.in b/cmake/QtSeparateDebugInfo.Info.plist.in
index d3e8dfbe7f..27489e29bb 100644
--- a/cmake/QtSeparateDebugInfo.Info.plist.in
+++ b/cmake/QtSeparateDebugInfo.Info.plist.in
@@ -1,3 +1,8 @@
+<!--
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: BSD-3-Clause
+-->
+
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">
<plist version=\"1.0\">
diff --git a/cmake/QtSeparateDebugInfo.cmake b/cmake/QtSeparateDebugInfo.cmake
index ff225ad5de..61f62207fa 100644
--- a/cmake/QtSeparateDebugInfo.cmake
+++ b/cmake/QtSeparateDebugInfo.cmake
@@ -1,8 +1,6 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-include(CMakeFindBinUtils)
-
if(CMAKE_VERSION VERSION_LESS 3.17.0)
set(CMAKE_CURRENT_FUNCTION_LIST_DIR ${CMAKE_CURRENT_LIST_DIR})
endif()
@@ -201,7 +199,11 @@ endfunction()
# Enable separate debug information for the given target
function(qt_enable_separate_debug_info target installDestination)
set(flags QT_EXECUTABLE)
- set(options)
+ if(APPLE)
+ set(options DSYM_OUTPUT_DIR)
+ else()
+ set(options)
+ endif()
set(multiopts ADDITIONAL_INSTALL_ARGS)
cmake_parse_arguments(arg "${flags}" "${options}" "${multiopts}" ${ARGN})
@@ -248,12 +250,20 @@ function(qt_enable_separate_debug_info target installDestination)
get_target_property(is_framework ${target} FRAMEWORK)
if(is_framework)
qt_internal_get_framework_info(fw ${target})
- set(debug_info_bundle_dir "$<TARGET_BUNDLE_DIR:${target}>.${debug_info_suffix}")
set(BUNDLE_ID ${fw_name})
else()
- set(debug_info_bundle_dir "$<TARGET_FILE:${target}>.${debug_info_suffix}")
set(BUNDLE_ID ${target})
endif()
+
+ if (NOT "x${arg_DSYM_OUTPUT_DIR}" STREQUAL "x")
+ set(debug_info_bundle_dir "${arg_DSYM_OUTPUT_DIR}/${target}")
+ elseif(is_framework)
+ set(debug_info_bundle_dir "$<TARGET_BUNDLE_DIR:${target}>")
+ else()
+ set(debug_info_bundle_dir "$<TARGET_FILE:${target}>")
+ endif()
+ set(debug_info_bundle_dir "${debug_info_bundle_dir}.${debug_info_suffix}")
+
set(debug_info_contents_dir "${debug_info_bundle_dir}/Contents")
set(debug_info_target_dir "${debug_info_contents_dir}/Resources/DWARF")
configure_file(
diff --git a/cmake/QtSetup.cmake b/cmake/QtSetup.cmake
index 262b60d171..a420495756 100644
--- a/cmake/QtSetup.cmake
+++ b/cmake/QtSetup.cmake
@@ -1,382 +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_IS_BUILDING_QT variable so we can verify whether we are building
-# Qt from source
-set(QT_BUILDING_QT TRUE CACHE
- TYPE STRING "When this is present and set to true, it signals that we are building Qt from source.")
-
-# Pre-calculate the developer_build feature if it's set by the user via INPUT_developer_build
-if(NOT FEATURE_developer_build AND INPUT_developer_build
- AND NOT "${INPUT_developer_build}" STREQUAL "undefined")
- set(FEATURE_developer_build ON)
-endif()
-
-# 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.
-if(NOT FEATURE_no_prefix AND INPUT_no_prefix
- AND NOT "${INPUT_no_prefix}" STREQUAL "undefined")
- set(FEATURE_no_prefix ON)
-endif()
-
-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)
-
-if(NOT 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(QT_GENERATOR_IS_MULTI_CONFIG AND CMAKE_CONFIGURATION_TYPES)
- set(__qt_setup_release_configs Release RelWithDebInfo MinSizeRel)
- set(__qt_setup_found_first_release_config FALSE)
- foreach(__qt_setup_config_type IN LISTS CMAKE_CONFIGURATION_TYPES)
- # Skip assigning postfix for the first release-like config.
- if(NOT __qt_setup_found_first_release_config
- AND __qt_setup_config_type IN_LIST __qt_setup_release_configs)
- set(__qt_setup_found_first_release_config TRUE)
- continue()
- endif()
-
- string(TOLOWER "${__qt_setup_config_type}" __qt_setup_config_type_lower)
- string(TOUPPER "${__qt_setup_config_type}" __qt_setup_config_type_upper)
- set(CMAKE_${__qt_setup_config_type_upper}_POSTFIX "_${__qt_setup_config_type_lower}")
- if(APPLE)
- set(CMAKE_FRAMEWORK_MULTI_CONFIG_POSTFIX_${__qt_setup_config_type_upper}
- "_${__qt_setup_config_type_lower}")
- endif()
- endforeach()
-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(CMAKE_DEBUG_POSTFIX "d")
- endif()
- else()
- set(CMAKE_DEBUG_POSTFIX "d")
- endif()
-elseif(APPLE)
- set(CMAKE_DEBUG_POSTFIX "_debug")
- set(CMAKE_FRAMEWORK_MULTI_CONFIG_POSTFIX_DEBUG "_debug")
-endif()
-
-## Position independent code:
-set(CMAKE_POSITION_INDEPENDENT_CODE ON)
-
-# Does the linker support position independent code?
-include(CheckPIESupported)
-check_pie_supported()
-
-# Do not relink dependent libraries when no header has changed:
-set(CMAKE_LINK_DEPENDS_NO_SHARED ON)
-
-# 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)
-
-# 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()
-
-# We need to clean up QT_FEATURE_*, but only once per configuration cycle
-get_property(qt_feature_clean GLOBAL PROPERTY _qt_feature_clean)
-if(NOT qt_feature_clean)
- message(STATUS "Check for feature set changes")
- set_property(GLOBAL PROPERTY _qt_feature_clean TRUE)
- foreach(feature ${QT_KNOWN_FEATURES})
- if(DEFINED "FEATURE_${feature}" AND
- NOT "${QT_FEATURE_${feature}}" STREQUAL "${FEATURE_${feature}}")
- message(" '${feature}' is changed from ${QT_FEATURE_${feature}} \
-to ${FEATURE_${feature}}")
- set(dirty_build TRUE)
- endif()
- unset("QT_FEATURE_${feature}" CACHE)
- endforeach()
-
- set(QT_KNOWN_FEATURES "" CACHE INTERNAL "" FORCE)
-
- if(dirty_build)
- set_property(GLOBAL PROPERTY _qt_dirty_build TRUE)
- message(WARNING "Re-configuring in existing build folder. \
-Some features will be re-evaluated automatically.")
- endif()
-endif()
-
-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()
diff --git a/cmake/QtStandaloneTestsConfig.cmake.in b/cmake/QtStandaloneTestsConfig.cmake.in
index afa9d2ee79..39200167a5 100644
--- a/cmake/QtStandaloneTestsConfig.cmake.in
+++ b/cmake/QtStandaloneTestsConfig.cmake.in
@@ -1,5 +1,8 @@
+# Copyright (C) 2024 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
# TODO: Ideally this should look for each Qt module separately, with each module's specific version,
# bypassing the Qt6 Config file, aka find_package(Qt6SpecificFoo) repated x times. But it's not
# critical.
find_package(@INSTALL_CMAKE_NAMESPACE@ @main_qt_package_version@
- REQUIRED COMPONENTS @QT_REPO_KNOWN_MODULES_STRING@)
+ COMPONENTS @QT_REPO_KNOWN_MODULES_STRING@)
diff --git a/cmake/QtSyncQtHelpers.cmake b/cmake/QtSyncQtHelpers.cmake
index cbab85b19a..0188b87c6a 100644
--- a/cmake/QtSyncQtHelpers.cmake
+++ b/cmake/QtSyncQtHelpers.cmake
@@ -61,13 +61,6 @@ function(qt_internal_target_sync_headers target module_headers module_headers_ge
set(is_framework FALSE)
if(NOT is_interface_lib)
get_target_property(is_framework ${target} FRAMEWORK)
- if(is_framework)
- qt_internal_get_framework_info(fw ${target})
- get_target_property(fw_output_base_dir ${target} LIBRARY_OUTPUT_DIRECTORY)
- set(framework_args "-framework"
- "-frameworkIncludeDir" "${fw_output_base_dir}/${fw_versioned_header_dir}"
- )
- endif()
endif()
qt_internal_get_qt_all_known_modules(known_modules)
@@ -79,6 +72,8 @@ function(qt_internal_target_sync_headers target module_headers module_headers_ge
endif()
get_target_property(qpa_filter_regex ${target} _qt_module_qpa_headers_filter_regex)
+ get_target_property(rhi_filter_regex ${target} _qt_module_rhi_headers_filter_regex)
+ get_target_property(ssg_filter_regex ${target} _qt_module_ssg_headers_filter_regex)
get_target_property(private_filter_regex ${target} _qt_module_private_headers_filter_regex)
# We need to use the real paths since otherwise it may lead to the invalid work of the
@@ -96,6 +91,18 @@ function(qt_internal_target_sync_headers target module_headers module_headers_ge
)
endif()
+ if(rhi_filter_regex)
+ set(rhi_filter_argument
+ -rhiHeadersFilter "${rhi_filter_regex}"
+ )
+ endif()
+
+ if(ssg_filter_regex)
+ set(ssg_filter_argument
+ -ssgHeadersFilter "${ssg_filter_regex}"
+ )
+ endif()
+
set(common_syncqt_arguments
-module "${module}"
-sourceDir "${source_dir_real}"
@@ -104,7 +111,12 @@ function(qt_internal_target_sync_headers target module_headers module_headers_ge
-includeDir "${module_build_interface_include_dir}"
-privateIncludeDir "${module_build_interface_private_include_dir}"
-qpaIncludeDir "${module_build_interface_qpa_include_dir}"
+ -rhiIncludeDir "${module_build_interface_rhi_include_dir}"
+ -ssgIncludeDir "${module_build_interface_ssg_include_dir}"
+ -generatedHeaders ${module_headers_generated}
${qpa_filter_argument}
+ ${rhi_filter_argument}
+ ${ssg_filter_argument}
${public_namespaces_filter}
${non_qt_module_argument}
${internal_module_argument}
@@ -138,18 +150,30 @@ function(qt_internal_target_sync_headers target module_headers module_headers_ge
set(syncqt_args "${common_syncqt_arguments}")
list(APPEND syncqt_args
- ${common_syncqt_arguments}
-headers ${module_headers}
- -generatedHeaders ${module_headers_generated}
-stagingDir "${syncqt_staging_dir}"
-knownModules ${known_modules}
- ${framework_args}
${version_script_args}
)
list(JOIN syncqt_args "\n" syncqt_args_string)
set(syncqt_args_rsp "${binary_dir_real}/${target}_syncqt_args")
qt_configure_file(OUTPUT "${syncqt_args_rsp}" CONTENT "${syncqt_args_string}")
+ get_target_property(external_headers_dir ${target} _qt_external_headers_dir)
+ if(external_headers_dir)
+ if(NOT IS_ABSOLUTE "${external_headers_dir}")
+ get_filename_component(external_headers_dir "${external_headers_dir}" ABSOLUTE)
+ endif()
+ if(EXISTS "${external_headers_dir}")
+ set(external_headers_dir_copy_cmd
+ COMMAND
+ ${CMAKE_COMMAND}
+ -E copy_directory
+ "${external_headers_dir}"
+ "${module_build_interface_include_dir}"
+ )
+ endif()
+ endif()
add_custom_command(
OUTPUT
${syncqt_outputs}
@@ -157,22 +181,36 @@ function(qt_internal_target_sync_headers target module_headers module_headers_ge
${QT_CMAKE_EXPORT_NAMESPACE}::syncqt
"@${syncqt_args_rsp}"
${build_time_syncqt_arguments}
+ ${external_headers_dir_copy_cmd}
COMMAND
${CMAKE_COMMAND} -E touch "${syncqt_timestamp}"
DEPENDS
${syncqt_args_rsp}
${module_headers}
${QT_CMAKE_EXPORT_NAMESPACE}::syncqt
+ "$<GENEX_EVAL:$<TARGET_PROPERTY:${target},_qt_internal_sync_headers_deps>>"
COMMENT
"Running syncqt.cpp for module: ${module}"
VERBATIM
)
+
+ set(add_sync_headers_to_all "")
+ if(is_interface_lib)
+ set(add_sync_headers_to_all ALL)
+ endif()
+
add_custom_target(${target}_sync_headers
+ ${add_sync_headers_to_all}
DEPENDS
${syncqt_outputs}
)
add_dependencies(sync_headers ${target}_sync_headers)
+ set_target_properties(${target}
+ PROPERTIES _qt_internal_sync_headers_target ${target}_sync_headers)
+ if(is_3rd_party_library)
+ add_dependencies(thirdparty_sync_headers ${target}_sync_headers)
+ endif()
# This target is required when building docs, to make all header files and their aliases
# available for qdoc.
# ${target}_sync_headers is added as dependency to make sure that
@@ -185,6 +223,7 @@ function(qt_internal_target_sync_headers target module_headers module_headers_ge
COMMAND
${QT_CMAKE_EXPORT_NAMESPACE}::syncqt
"@${syncqt_all_args_rsp}"
+ ${external_headers_dir_copy_cmd}
DEPENDS
${module_headers}
${syncqt_all_args_rsp}
@@ -198,7 +237,7 @@ function(qt_internal_target_sync_headers target module_headers module_headers_ge
endif()
add_dependencies(sync_all_public_headers ${target}_sync_all_public_headers)
- if(NOT is_3rd_party_library AND NOT is_framework)
+ if(NOT is_3rd_party_library AND NOT is_framework AND module_headers)
# Install all the CaMeL style aliases of header files from the staging directory in one rule
qt_install(DIRECTORY "${syncqt_staging_dir}/"
DESTINATION "${module_install_interface_include_dir}"
@@ -220,7 +259,7 @@ function(qt_internal_target_sync_headers target module_headers module_headers_ge
# Run sync Qt first time at configure step to make all header files available for the code model
# of IDEs.
get_property(synced_modules GLOBAL PROPERTY _qt_synced_modules)
- if(NOT "${module}" IN_LIST synced_modules)
+ if(NOT "${module}" IN_LIST synced_modules AND QT_SYNC_HEADERS_AT_CONFIGURE_TIME)
message(STATUS "Running syncqt.cpp for module: ${module}")
get_target_property(syncqt_location ${QT_CMAKE_EXPORT_NAMESPACE}::syncqt LOCATION)
execute_process(
@@ -232,6 +271,14 @@ function(qt_internal_target_sync_headers target module_headers module_headers_ge
ERROR_VARIABLE syncqt_output
)
if(NOT syncqt_result EQUAL 0)
+ if(syncqt_output STREQUAL "")
+ string(JOIN "" syncqt_output "The syncqt process exited with code ${syncqt_result}"
+ " and without any useful output. This can happen if syncqt crashes due to the"
+ " incompatibilities with the standard C++ library located by either PATH or"
+ " LD_LIBRARY_PATH environment variables. Please make sure that PATH or"
+ " LD_LIBRARY_PATH don't point to the standard libraries different from the one you"
+ " use for building Qt.")
+ endif()
message(FATAL_ERROR
"syncqt.cpp failed for module ${module}:\n${syncqt_output}")
endif()
diff --git a/cmake/QtTargetHelpers.cmake b/cmake/QtTargetHelpers.cmake
index c67b862779..d361a8096d 100644
--- a/cmake/QtTargetHelpers.cmake
+++ b/cmake/QtTargetHelpers.cmake
@@ -14,8 +14,12 @@
# module, these files will raise a warning at configure time if the condition is not met.
# COMPILE_FLAGS
# Custom compilation flags.
+# EXTRA_LINKER_SCRIPT_CONTENT
+# Extra content that should be appended to a target linker script. Applicable for ld only.
+# EXTRA_LINKER_SCRIPT_EXPORTS
+# Extra content that should be added to export section of the linker script.
# NO_PCH_SOURCES
-# Skip the specified source files by PRECOMPILE_HEADERS feature.
+# Exclude the specified source files from PRECOMPILE_HEADERS and UNITY_BUILD builds.
function(qt_internal_extend_target target)
if(NOT TARGET "${target}")
message(FATAL_ERROR "${target} is not a target.")
@@ -40,6 +44,7 @@ function(qt_internal_extend_target target)
)
set(single_args
PRECOMPILED_HEADER
+ EXTRA_LINKER_SCRIPT_CONTENT
)
set(multi_args
${__default_public_args}
@@ -48,7 +53,7 @@ function(qt_internal_extend_target target)
CONDITION
CONDITION_INDEPENDENT_SOURCES
COMPILE_FLAGS
- NO_PCH_SOURCES
+ EXTRA_LINKER_SCRIPT_EXPORTS
)
cmake_parse_arguments(PARSE_ARGV 1 arg
@@ -94,10 +99,13 @@ function(qt_internal_extend_target target)
get_target_property(target_type ${target} TYPE)
set(is_library FALSE)
set(is_interface_lib FALSE)
+ set(is_executable FALSE)
if(${target_type} STREQUAL "STATIC_LIBRARY" OR ${target_type} STREQUAL "SHARED_LIBRARY")
set(is_library TRUE)
elseif(target_type STREQUAL "INTERFACE_LIBRARY")
set(is_interface_lib TRUE)
+ elseif(target_type STREQUAL "EXECUTABLE")
+ set(is_executable TRUE)
endif()
foreach(lib ${arg_PUBLIC_LIBRARIES} ${arg_LIBRARIES})
@@ -111,8 +119,27 @@ function(qt_internal_extend_target target)
if(NOT base_lib STREQUAL lib)
qt_create_nolink_target("${base_lib}" ${target})
endif()
+
+ # Collect _sync_headers targets from libraries that the target depends on. This is
+ # heuristic way of building the dependency tree between the _sync_headers targets of
+ # different Qt modules.
+ if(TARGET "${lib}")
+ get_target_property(is_imported ${lib} IMPORTED)
+ if(NOT is_imported)
+ get_target_property(is_private ${lib} _qt_is_private_module)
+ if(is_private)
+ get_target_property(lib ${lib} _qt_public_module_target_name)
+ endif()
+ set(out_genex "$<TARGET_PROPERTY:${lib},_qt_internal_sync_headers_target>")
+ set_property(TARGET ${target}
+ APPEND PROPERTY _qt_internal_sync_headers_deps "${out_genex}")
+ endif()
+ endif()
endforeach()
+ list(TRANSFORM arg_PUBLIC_LIBRARIES REPLACE "^Qt::" "${QT_CMAKE_EXPORT_NAMESPACE}::")
+ list(TRANSFORM arg_LIBRARIES REPLACE "^Qt::" "${QT_CMAKE_EXPORT_NAMESPACE}::")
+
# Set-up the target
# CMake versions less than 3.19 don't support adding the source files to the PRIVATE scope
@@ -241,6 +268,238 @@ function(qt_internal_extend_target target)
${sources_property} "${arg_CONDITION_INDEPENDENT_SOURCES}")
endif()
+ if(arg_EXTRA_LINKER_SCRIPT_CONTENT)
+ set_target_properties(${target} PROPERTIES
+ _qt_extra_linker_script_content "${arg_EXTRA_LINKER_SCRIPT_CONTENT}")
+ endif()
+ if(arg_EXTRA_LINKER_SCRIPT_EXPORTS)
+ set_target_properties(${target} PROPERTIES
+ _qt_extra_linker_script_exports "${arg_EXTRA_LINKER_SCRIPT_EXPORTS}")
+ endif()
+
+ if(is_executable)
+ # If linking against Gui, make sure to also build the default QPA plugin.
+ # This makes the experience of an initial Qt configuration to build and run one single
+ # test / executable nicer.
+ set(linked_libs ${arg_PUBLIC_LIBRARIES} ${arg_LIBRARIES})
+ if(linked_libs MATCHES "(^|;)(${QT_CMAKE_EXPORT_NAMESPACE}::|Qt::)?Gui($|;)" AND
+ TARGET qpa_default_plugins)
+ add_dependencies("${target}" qpa_default_plugins)
+ endif()
+
+ # For executables collect static plugins that these targets depend on.
+ qt_internal_import_plugins(${target} ${linked_libs})
+ endif()
+endfunction()
+
+# Given CMAKE_CONFIG and ALL_CMAKE_CONFIGS, determines if a directory suffix needs to be appended
+# to each destination, and sets the computed install target destination arguments in OUT_VAR.
+# Defaults used for each of the destination types, and can be configured per destination type.
+function(qt_get_install_target_default_args)
+ cmake_parse_arguments(PARSE_ARGV 0 arg
+ ""
+ "OUT_VAR;CMAKE_CONFIG;RUNTIME;LIBRARY;ARCHIVE;INCLUDES;BUNDLE"
+ "ALL_CMAKE_CONFIGS")
+ _qt_internal_validate_all_args_are_parsed(arg)
+
+ if(NOT arg_CMAKE_CONFIG)
+ message(FATAL_ERROR "No value given for CMAKE_CONFIG.")
+ endif()
+ if(NOT arg_ALL_CMAKE_CONFIGS)
+ message(FATAL_ERROR "No value given for ALL_CMAKE_CONFIGS.")
+ endif()
+ list(LENGTH arg_ALL_CMAKE_CONFIGS all_configs_count)
+ list(GET arg_ALL_CMAKE_CONFIGS 0 first_config)
+
+ set(suffix "")
+ if(all_configs_count GREATER 1 AND NOT arg_CMAKE_CONFIG STREQUAL first_config)
+ set(suffix "/${arg_CMAKE_CONFIG}")
+ endif()
+
+ set(runtime "${INSTALL_BINDIR}")
+ if(arg_RUNTIME)
+ set(runtime "${arg_RUNTIME}")
+ endif()
+
+ set(library "${INSTALL_LIBDIR}")
+ if(arg_LIBRARY)
+ set(library "${arg_LIBRARY}")
+ endif()
+
+ set(archive "${INSTALL_LIBDIR}")
+ if(arg_ARCHIVE)
+ set(archive "${arg_ARCHIVE}")
+ endif()
+
+ set(includes "${INSTALL_INCLUDEDIR}")
+ if(arg_INCLUDES)
+ set(includes "${arg_INCLUDES}")
+ endif()
+
+ set(bundle "${INSTALL_BINDIR}")
+ if(arg_BUNDLE)
+ set(bundle "${arg_BUNDLE}")
+ endif()
+
+ set(args
+ RUNTIME DESTINATION "${runtime}${suffix}"
+ LIBRARY DESTINATION "${library}${suffix}"
+ ARCHIVE DESTINATION "${archive}${suffix}" COMPONENT Devel
+ BUNDLE DESTINATION "${bundle}${suffix}"
+ INCLUDES DESTINATION "${includes}${suffix}")
+ set(${arg_OUT_VAR} "${args}" PARENT_SCOPE)
+endfunction()
+
+macro(qt_internal_setup_default_target_function_options)
+ set(__default_private_args
+ SOURCES
+ LIBRARIES
+ INCLUDE_DIRECTORIES
+ SYSTEM_INCLUDE_DIRECTORIES
+ DEFINES
+ DBUS_ADAPTOR_BASENAME
+ DBUS_ADAPTOR_FLAGS
+ DBUS_ADAPTOR_SOURCES
+ DBUS_INTERFACE_BASENAME
+ DBUS_INTERFACE_FLAGS
+ DBUS_INTERFACE_SOURCES
+ FEATURE_DEPENDENCIES
+ COMPILE_OPTIONS
+ LINK_OPTIONS
+ MOC_OPTIONS
+ DISABLE_AUTOGEN_TOOLS
+ ENABLE_AUTOGEN_TOOLS
+ PLUGIN_TYPES
+ NO_PCH_SOURCES
+ NO_UNITY_BUILD_SOURCES
+ )
+ set(__default_public_args
+ PUBLIC_LIBRARIES
+ PUBLIC_INCLUDE_DIRECTORIES
+ PUBLIC_DEFINES
+ PUBLIC_COMPILE_OPTIONS
+ PUBLIC_LINK_OPTIONS
+ )
+ set(__default_private_module_args
+ PRIVATE_MODULE_INTERFACE
+ )
+ set(__default_target_info_args
+ TARGET_VERSION
+ TARGET_PRODUCT
+ TARGET_DESCRIPTION
+ TARGET_COMPANY
+ TARGET_COPYRIGHT
+ )
+
+ # Collection of arguments so they can be shared across qt_internal_add_executable
+ # and qt_internal_add_test_helper.
+ set(__qt_internal_add_executable_optional_args
+ GUI
+ NO_INSTALL
+ EXCEPTIONS
+ DELAY_RC
+ DELAY_TARGET_INFO
+ QT_APP
+ NO_UNITY_BUILD
+ )
+ set(__qt_internal_add_executable_single_args
+ CORE_LIBRARY
+ OUTPUT_DIRECTORY
+ INSTALL_DIRECTORY
+ VERSION
+ ${__default_target_info_args}
+ )
+ set(__qt_internal_add_executable_multi_args
+ ${__default_private_args}
+ ${__default_public_args}
+ )
+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 '_<config_type_lower>' 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}}")
+ 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)
@@ -313,19 +572,19 @@ endfunction()
# On Windows, these properties are used to generate the version information resource.
function(qt_set_target_info_properties target)
cmake_parse_arguments(arg "" "${__default_target_info_args}" "" ${ARGN})
- if("${arg_TARGET_VERSION}" STREQUAL "")
+ if(NOT arg_TARGET_VERSION)
set(arg_TARGET_VERSION "${PROJECT_VERSION}.0")
endif()
- if("${arg_TARGET_PRODUCT}" STREQUAL "")
+ if(NOT arg_TARGET_PRODUCT)
set(arg_TARGET_PRODUCT "Qt6")
endif()
- if("${arg_TARGET_DESCRIPTION}" STREQUAL "")
+ if(NOT arg_TARGET_DESCRIPTION)
set(arg_TARGET_DESCRIPTION "C++ Application Development Framework")
endif()
- if("${arg_TARGET_COMPANY}" STREQUAL "")
+ if(NOT arg_TARGET_COMPANY)
set(arg_TARGET_COMPANY "The Qt Company Ltd.")
endif()
- if("${arg_TARGET_COPYRIGHT}" STREQUAL "")
+ if(NOT arg_TARGET_COPYRIGHT)
set(arg_TARGET_COPYRIGHT "${QT_COPYRIGHT}")
endif()
set_target_properties(${target} PROPERTIES
@@ -573,9 +832,8 @@ endif()
endif()
# INTERFACE libraries don't have IMPORTED_LOCATION-like properties.
- # OBJECT libraries have properties like IMPORTED_OBJECTS instead.
# Skip the rest of the processing for those.
- if(target_type STREQUAL "INTERFACE_LIBRARY" OR target_type STREQUAL "OBJECT_LIBRARY")
+ if(target_type STREQUAL "INTERFACE_LIBRARY")
continue()
endif()
@@ -586,19 +844,46 @@ endif()
# For Multi-config developer builds we should simply reuse IMPORTED_LOCATION of the
# target.
if(NOT QT_WILL_INSTALL AND QT_FEATURE_debug_and_release)
+ set(configure_time_target_build_location "")
get_target_property(configure_time_target_install_location ${target}
IMPORTED_LOCATION)
else()
+ if(IS_ABSOLUTE "${arg_CONFIG_INSTALL_DIR}")
+ file(RELATIVE_PATH reverse_relative_prefix_path
+ "${arg_CONFIG_INSTALL_DIR}" "${CMAKE_INSTALL_PREFIX}")
+ else()
+ file(RELATIVE_PATH reverse_relative_prefix_path
+ "${CMAKE_INSTALL_PREFIX}/${arg_CONFIG_INSTALL_DIR}"
+ "${CMAKE_INSTALL_PREFIX}")
+ endif()
+
+ get_target_property(configure_time_target_build_location ${target}
+ _qt_internal_configure_time_target_build_location)
+ string(TOUPPER "${QT_CMAKE_EXPORT_NAMESPACE}_INSTALL_PREFIX" install_prefix_var)
+ string(JOIN "" configure_time_target_build_location
+ "$\{CMAKE_CURRENT_LIST_DIR}/"
+ "${reverse_relative_prefix_path}"
+ "${configure_time_target_build_location}")
+
get_target_property(configure_time_target_install_location ${target}
_qt_internal_configure_time_target_install_location)
- set(configure_time_target_install_location
- "$\{PACKAGE_PREFIX_DIR}/${configure_time_target_install_location}")
+
+ string(JOIN "" configure_time_target_install_location
+ "$\{CMAKE_CURRENT_LIST_DIR}/"
+ "${reverse_relative_prefix_path}"
+ "${configure_time_target_install_location}")
endif()
if(configure_time_target_install_location)
string(APPEND content "
# Import configure-time executable ${full_target}
if(NOT TARGET ${full_target})
- set(_qt_imported_location \"${configure_time_target_install_location}\")
+ set(_qt_imported_build_location \"${configure_time_target_build_location}\")
+ set(_qt_imported_install_location \"${configure_time_target_install_location}\")
+ set(_qt_imported_location \"\${_qt_imported_install_location}\")
+ if(NOT EXISTS \"$\{_qt_imported_location}\"
+ AND NOT \"$\{_qt_imported_build_location}\" STREQUAL \"\")
+ set(_qt_imported_location \"\${_qt_imported_build_location}\")
+ endif()
if(NOT EXISTS \"$\{_qt_imported_location}\")
message(FATAL_ERROR \"Unable to add configure time executable ${full_target}\"
\" $\{_qt_imported_location} doesn't exists\")
@@ -609,6 +894,8 @@ if(NOT TARGET ${full_target})
\"$\{_qt_imported_location}\")
set_property(TARGET ${full_target} PROPERTY IMPORTED_GLOBAL TRUE)
unset(_qt_imported_location)
+ unset(_qt_imported_build_location)
+ unset(_qt_imported_install_location)
endif()
\n")
endif()
@@ -618,7 +905,7 @@ endif()
# the target. It is not built by default.
if(NOT QT_WILL_INSTALL AND QT_FEATURE_debug_and_release)
get_target_property(excluded_genex ${target} EXCLUDE_FROM_ALL)
- if(NOT excluded_genex STREQUAL "")
+ if(excluded_genex)
string(APPEND content "
# ${full_target} is not built by default in the Debug configuration. Check existence.
get_target_property(_qt_imported_location ${full_target} IMPORTED_LOCATION_DEBUG)
@@ -633,6 +920,9 @@ endif()\n")
set(write_implib FALSE)
set(write_soname FALSE)
+ set(write_objects FALSE)
+ set(write_location TRUE)
+
if(target_type STREQUAL "SHARED_LIBRARY")
if(WIN32)
set(write_implib TRUE)
@@ -641,24 +931,41 @@ endif()\n")
else()
set(write_soname TRUE)
endif()
+ elseif(target_type STREQUAL "OBJECT_LIBRARY")
+ set(write_objects TRUE)
+ set(write_location FALSE)
endif()
if(NOT "${uc_release_cfg}" STREQUAL "")
- string(APPEND content "get_target_property(_qt_imported_location ${full_target} IMPORTED_LOCATION_${uc_release_cfg})\n")
+ if(write_location)
+ string(APPEND content "get_target_property(_qt_imported_location ${full_target} IMPORTED_LOCATION_${uc_release_cfg})\n")
+ endif()
if(write_implib)
string(APPEND content "get_target_property(_qt_imported_implib ${full_target} IMPORTED_IMPLIB_${uc_release_cfg})\n")
endif()
if(write_soname)
string(APPEND content "get_target_property(_qt_imported_soname ${full_target} IMPORTED_SONAME_${uc_release_cfg})\n")
endif()
+ if(write_objects)
+ string(APPEND content "get_target_property(_qt_imported_objects ${full_target} IMPORTED_OBJECTS_${uc_release_cfg})\n")
+ # We generate CLR props as well, because that's what CMake generates for object
+ # libraries with CMake 3.27. They are usually empty strings though, aka "".
+ string(APPEND content "get_target_property(_qt_imported_clr ${full_target} IMPORTED_COMMON_LANGUAGE_RUNTIME_${uc_release_cfg})\n")
+ endif()
+ endif()
+ if(write_location)
+ string(APPEND content "get_target_property(_qt_imported_location_default ${full_target} IMPORTED_LOCATION_$\{QT_DEFAULT_IMPORT_CONFIGURATION})\n")
endif()
- string(APPEND content "get_target_property(_qt_imported_location_default ${full_target} IMPORTED_LOCATION_$\{QT_DEFAULT_IMPORT_CONFIGURATION})\n")
if(write_implib)
string(APPEND content "get_target_property(_qt_imported_implib_default ${full_target} IMPORTED_IMPLIB_$\{QT_DEFAULT_IMPORT_CONFIGURATION})\n")
endif()
if(write_soname)
string(APPEND content "get_target_property(_qt_imported_soname_default ${full_target} IMPORTED_SONAME_$\{QT_DEFAULT_IMPORT_CONFIGURATION})\n")
endif()
+ if(write_objects)
+ string(APPEND content "get_target_property(_qt_imported_objects_default ${full_target} IMPORTED_OBJECTS_$\{QT_DEFAULT_IMPORT_CONFIGURATION})\n")
+ string(APPEND content "get_target_property(_qt_imported_clr_default ${full_target} IMPORTED_COMMON_LANGUAGE_RUNTIME_$\{QT_DEFAULT_IMPORT_CONFIGURATION})\n")
+ endif()
foreach(config ${configurations_to_export} "")
string(TOUPPER "${config}" ucconfig)
if("${config}" STREQUAL "")
@@ -673,10 +980,12 @@ endif()\n")
set_property(TARGET ${full_target} APPEND PROPERTY IMPORTED_CONFIGURATIONS ${ucconfig})
")
endif()
- string(APPEND content "
+ if(write_location)
+ string(APPEND content "
if(_qt_imported_location${var_suffix})
set_property(TARGET ${full_target} PROPERTY IMPORTED_LOCATION${property_suffix} \"$\{_qt_imported_location${var_suffix}}\")
endif()")
+ endif()
if(write_implib)
string(APPEND content "
if(_qt_imported_implib${var_suffix})
@@ -689,6 +998,16 @@ if(_qt_imported_soname${var_suffix})
set_property(TARGET ${full_target} PROPERTY IMPORTED_SONAME${property_suffix} \"$\{_qt_imported_soname${var_suffix}}\")
endif()")
endif()
+ if(write_objects)
+ string(APPEND content "
+if(_qt_imported_objects${var_suffix})
+ set_property(TARGET ${full_target} PROPERTY IMPORTED_OBJECTS${property_suffix} \"$\{_qt_imported_objects${var_suffix}}\")
+endif()")
+ string(APPEND content "
+if(_qt_imported_clr${var_suffix})
+ set_property(TARGET ${full_target} PROPERTY IMPORTED_COMMON_LANGUAGE_RUNTIME${property_suffix} \"$\{_qt_imported_clr${var_suffix}}\")
+endif()")
+ endif()
string(APPEND content "\n")
endforeach()
endforeach()
@@ -699,6 +1018,10 @@ unset(_qt_imported_location)
unset(_qt_imported_location_default)
unset(_qt_imported_soname)
unset(_qt_imported_soname_default)
+unset(_qt_imported_objects)
+unset(_qt_imported_objects_default)
+unset(_qt_imported_clr)
+unset(_qt_imported_clr_default)
unset(_qt_imported_configs)")
endif()
@@ -712,25 +1035,51 @@ unset(_qt_imported_configs)")
endfunction()
function(qt_internal_export_modern_cmake_config_targets_file)
- cmake_parse_arguments(__arg "" "EXPORT_NAME_PREFIX;CONFIG_INSTALL_DIR" "TARGETS" ${ARGN})
+ cmake_parse_arguments(arg
+ ""
+ "EXPORT_NAME_PREFIX;CONFIG_BUILD_DIR;CONFIG_INSTALL_DIR"
+ "TARGETS"
+ ${ARGN}
+ )
- set(export_name "${__arg_EXPORT_NAME_PREFIX}VersionlessTargets")
- foreach(target ${__arg_TARGETS})
- if (TARGET "${target}Versionless")
- continue()
- endif()
+ if("${arg_TARGETS}" STREQUAL "")
+ message(FATAL_ERROR "Target list is empty")
+ endif()
- add_library("${target}Versionless" INTERFACE)
- target_link_libraries("${target}Versionless" INTERFACE "${target}")
- set_target_properties("${target}Versionless" PROPERTIES
- EXPORT_NAME "${target}"
- _qt_is_versionless_target "TRUE")
- set_property(TARGET "${target}Versionless"
- APPEND PROPERTY EXPORT_PROPERTIES _qt_is_versionless_target)
+ if("${arg_CONFIG_BUILD_DIR}" STREQUAL "")
+ message(FATAL_ERROR "CONFIG_BUILD_DIR is not specified")
+ endif()
- qt_install(TARGETS "${target}Versionless" EXPORT ${export_name})
- endforeach()
- qt_install(EXPORT ${export_name} NAMESPACE Qt:: DESTINATION "${__arg_CONFIG_INSTALL_DIR}")
+ if("${arg_CONFIG_INSTALL_DIR}" STREQUAL "")
+ message(FATAL_ERROR "CONFIG_INSTALL_DIR is not specified")
+ endif()
+
+ if("${arg_EXPORT_NAME_PREFIX}" STREQUAL "")
+ message(FATAL_ERROR "EXPORT_NAME_PREFIX is not specified")
+ endif()
+
+ set(versionless_targets ${arg_TARGETS})
+
+ # CMake versions < 3.18 compatibility code. Creates the mimics of the versioned libraries.
+ set(versionless_targets_export "${arg_CONFIG_BUILD_DIR}/${arg_EXPORT_NAME_PREFIX}VersionlessTargets.cmake")
+ configure_file("${QT_CMAKE_DIR}/QtVersionlessTargets.cmake.in"
+ "${versionless_targets_export}"
+ @ONLY
+ )
+
+ # CMake versions >= 3.18 code. Create the versionless ALIAS targets.
+ set(alias_export "${arg_CONFIG_BUILD_DIR}/${arg_EXPORT_NAME_PREFIX}VersionlessAliasTargets.cmake")
+ configure_file("${QT_CMAKE_DIR}/QtVersionlessAliasTargets.cmake.in"
+ "${alias_export}"
+ @ONLY
+ )
+
+ qt_install(FILES
+ "${alias_export}"
+ "${versionless_targets_export}"
+ DESTINATION "${arg_CONFIG_INSTALL_DIR}"
+ COMPONENT Devel
+ )
endfunction()
function(qt_internal_create_tracepoints name tracepoints_file)
@@ -1005,6 +1354,15 @@ endfunction()
# Needed to allow selectively applying certain flags via PlatformXInternal targets.
function(qt_internal_mark_as_internal_library target)
set_target_properties(${target} PROPERTIES _qt_is_internal_library TRUE)
+ qt_internal_mark_as_internal_target(${target})
+endfunction()
+
+# Marks a target with a property that it was built using the internal Qt API (qt_internal_*) as
+# opposed to it being a user project library or executable(qt_add_*, etc).
+#
+# Needed to allow selectively applying certain flags via PlatformXInternal targets.
+function(qt_internal_mark_as_internal_target target)
+ set_target_properties(${target} PROPERTIES _qt_is_internal_target TRUE)
endfunction()
# Marks a target with a property to skip it adding it as a dependency when building examples as
@@ -1300,3 +1658,32 @@ function(qt_internal_export_genex_properties)
COMPONENT Devel
)
endfunction()
+
+# The macro promotes the Qt platform targets and their dependencies to global. The macro shouldn't
+# be called explicitly in regular cases. It's called right after the first find_package(Qt ...)
+# call in the qt_internal_project_setup macro.
+# This allows using the qt_find_package(Wrap<3rdparty> PROVIDED_TARGETS ...) function,
+# without the risk of having duplicated global promotion of Qt internals. This is especially
+# sensitive for the bundled 3rdparty libraries.
+macro(qt_internal_promote_platform_targets_to_global)
+ if(TARGET Qt6::Platform)
+ get_target_property(is_imported Qt6::Platform IMPORTED)
+ if(is_imported)
+ set(known_platform_targets
+ Platform
+ PlatformCommonInternal
+ PlatformModuleInternal
+ PlatformPluginInternal
+ PlatformAppInternal
+ PlatformToolInternal
+ )
+ set(versionless_platform_targets ${known_platform_targets})
+
+ list(TRANSFORM known_platform_targets PREPEND Qt6::)
+ list(TRANSFORM versionless_platform_targets PREPEND Qt::)
+ qt_find_package(Qt6 PROVIDED_TARGETS
+ ${known_platform_targets}
+ ${versionless_platform_targets})
+ endif()
+ endif()
+endmacro()
diff --git a/cmake/QtTestHelpers.cmake b/cmake/QtTestHelpers.cmake
index 967d8ff99b..62ee91296f 100644
--- a/cmake/QtTestHelpers.cmake
+++ b/cmake/QtTestHelpers.cmake
@@ -31,11 +31,13 @@ function(qt_internal_add_benchmark target)
)
if(NOT arg_OUTPUT_DIRECTORY)
- set(arg_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
+ if(CMAKE_RUNTIME_OUTPUT_DIRECTORY)
+ set(arg_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
+ else()
+ set(arg_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
+ endif()
endif()
- qt_internal_library_deprecation_level(deprecation_define)
-
qt_internal_add_executable(${target}
NO_INSTALL # we don't install benchmarks
NO_UNITY_BUILD # excluded by default
@@ -214,6 +216,7 @@ function(qt_internal_get_test_arg_definitions optional_args single_value_args mu
MANUAL
NO_BATCH
NO_INSTALL
+ BUNDLE_ANDROID_OPENSSL_LIBS
PARENT_SCOPE
)
set(${single_value_args}
@@ -246,7 +249,6 @@ function(qt_internal_add_test_to_batch batch_name name)
# Lazy-init the test batch
if(NOT TARGET ${target})
- qt_internal_library_deprecation_level(deprecation_define)
qt_internal_add_executable(${target}
${exceptions_text}
${gui_text}
@@ -314,6 +316,34 @@ function(qt_internal_add_test_to_batch batch_name name)
list(PREPEND batched_test_list ${name})
set_property(GLOBAL PROPERTY _qt_batched_test_list_property ${batched_test_list})
+ # Test batching produces single executable which can result in one source file being added
+ # multiple times (with different definitions) to one translation unit. This is not supported by
+ # CMake so instead we try to detect such situation and rename file every time it's added
+ # to the build more than once. This avoids filenames collisions in one translation unit.
+ get_property(batched_test_sources_list GLOBAL PROPERTY _qt_batched_test_sources_list_property)
+ if(NOT batched_test_sources_list)
+ set_property(GLOBAL PROPERTY _qt_batched_test_sources_list_property "")
+ set(batched_test_sources_list "")
+ endif()
+ foreach(source ${arg_SOURCES})
+ set(source_path ${source})
+ if(${source} IN_LIST batched_test_sources_list)
+ set(new_filename ${name}.cpp)
+ configure_file(${source} ${new_filename})
+ set(source_path ${CMAKE_CURRENT_BINARY_DIR}/${new_filename})
+ set(skip_automoc ON)
+ list(APPEND arg_SOURCES ${source_path})
+ else()
+ set(skip_automoc OFF)
+ list(APPEND batched_test_sources_list ${source})
+ endif()
+ set_source_files_properties(${source_path}
+ TARGET_DIRECTORY ${target} PROPERTIES
+ SKIP_AUTOMOC ${skip_automoc}
+ COMPILE_DEFINITIONS "BATCHED_TEST_NAME=\"${name}\";${arg_DEFINES}")
+ endforeach()
+ set_property(GLOBAL PROPERTY _qt_batched_test_sources_list_property ${batched_test_sources_list})
+
# Merge the current test with the rest of the batch
qt_internal_extend_target(${target}
INCLUDE_DIRECTORIES ${arg_INCLUDE_DIRECTORIES}
@@ -329,15 +359,6 @@ function(qt_internal_add_test_to_batch batch_name name)
NO_UNITY_BUILD # Tests should not be built using UNITY_BUILD
)
- foreach(source ${arg_SOURCES})
- # We define the test name which is later used to launch this test using
- # commandline parameters. Target directory is that of the target test_batch,
- # otherwise the batch won't honor our choices of compile definitions.
- set_source_files_properties(${source}
- TARGET_DIRECTORY ${target}
- PROPERTIES COMPILE_DEFINITIONS
- "BATCHED_TEST_NAME=\"${name}\";${arg_DEFINES}" )
- endforeach()
set(${batch_name} ${target} PARENT_SCOPE)
# Add a dummy target so that new tests don't have problems with a nonexistent
@@ -457,8 +478,12 @@ function(qt_internal_add_test name)
endif()
endif()
- if (NOT arg_OUTPUT_DIRECTORY)
- set(arg_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
+ if(NOT arg_OUTPUT_DIRECTORY)
+ if(CMAKE_RUNTIME_OUTPUT_DIRECTORY)
+ set(arg_OUTPUT_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
+ else()
+ set(arg_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
+ endif()
endif()
set(private_includes
@@ -485,7 +510,6 @@ function(qt_internal_add_test name)
list(APPEND private_includes ${arg_INCLUDE_DIRECTORIES})
qt_internal_prepare_test_target_flags(version_arg exceptions_text gui_text ${ARGN})
- qt_internal_library_deprecation_level(deprecation_define)
qt_internal_add_executable("${name}"
${exceptions_text}
@@ -538,12 +562,14 @@ function(qt_internal_add_test name)
LIBRARIES ${QT_CMAKE_EXPORT_NAMESPACE}::QuickTest
)
- qt_internal_extend_target("${name}" CONDITION arg_QMLTEST AND NOT ANDROID
+ qt_internal_extend_target("${name}"
+ CONDITION arg_QMLTEST AND NOT ANDROID AND NOT QT_FORCE_BUILTIN_TESTDATA
DEFINES
QUICK_TEST_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}"
)
- qt_internal_extend_target("${name}" CONDITION arg_QMLTEST AND ANDROID
+ qt_internal_extend_target("${name}"
+ CONDITION arg_QMLTEST AND (ANDROID OR QT_FORCE_BUILTIN_TESTDATA)
DEFINES
QUICK_TEST_SOURCE_DIR=":/"
)
@@ -554,6 +580,11 @@ function(qt_internal_add_test name)
)
set_target_properties(${name} PROPERTIES _qt_is_test_executable TRUE)
set_target_properties(${name} PROPERTIES _qt_is_manual_test ${arg_MANUAL})
+
+ set(blacklist_file "${CMAKE_CURRENT_SOURCE_DIR}/BLACKLIST")
+ if(EXISTS ${blacklist_file})
+ _qt_internal_expose_source_file_to_ide("${name}" ${blacklist_file})
+ endif()
endif()
foreach(path IN LISTS arg_QML_IMPORTPATH)
@@ -579,7 +610,43 @@ function(qt_internal_add_test name)
endif()
if (ANDROID)
- qt_internal_android_test_arguments("${name}" test_executable extra_test_args)
+ # Pass 95% of the timeout to allow the test runner time to do any cleanup
+ # before being killed.
+ set(percentage "95")
+ qt_internal_get_android_test_timeout("${arg_TIMEOUT}" "${percentage}" android_timeout)
+
+ if(arg_BUNDLE_ANDROID_OPENSSL_LIBS)
+ if(EXISTS "${OPENSSL_ROOT_DIR}/${CMAKE_ANDROID_ARCH_ABI}/libcrypto_3.so")
+ message(STATUS "Looking for OpenSSL in ${OPENSSL_ROOT_DIR}")
+ set_property(TARGET ${name} APPEND PROPERTY QT_ANDROID_EXTRA_LIBS
+ "${OPENSSL_ROOT_DIR}/${CMAKE_ANDROID_ARCH_ABI}/libcrypto_3.so"
+ "${OPENSSL_ROOT_DIR}/${CMAKE_ANDROID_ARCH_ABI}/libssl_3.so")
+ elseif(QT_USE_VCPKG AND DEFINED ENV{VCPKG_ROOT})
+ message(STATUS "Looking for OpenSSL in $ENV{VCPKG_ROOT}")
+ if (CMAKE_ANDROID_ARCH_ABI MATCHES "arm64-v8a")
+ set(coin_vcpkg_target_triplet "arm64-android-dynamic")
+ elseif(CMAKE_ANDROID_ARCH_ABI MATCHES "armeabi-v7a")
+ set(coin_vcpkg_target_triplet "arm-neon-android-dynamic")
+ elseif(CMAKE_ANDROID_ARCH_ABI MATCHES "x86_64")
+ set(coin_vcpkg_target_triplet "x64-android-dynamic")
+ elseif(CMAKE_ANDROID_ARCH_ABI MATCHES "x86")
+ set(coin_vcpkg_target_triplet "x86-android-dynamic")
+ endif()
+ if(EXISTS "$ENV{VCPKG_ROOT}/installed/${coin_vcpkg_target_triplet}/lib/libcrypto.so")
+ message(STATUS "Found OpenSSL in $ENV{VCPKG_ROOT}/installed/${coin_vcpkg_target_triplet}/lib")
+ set_property(TARGET ${name} APPEND PROPERTY QT_ANDROID_EXTRA_LIBS
+ "$ENV{VCPKG_ROOT}/installed/${coin_vcpkg_target_triplet}/lib/libcrypto.so"
+ "$ENV{VCPKG_ROOT}/installed/${coin_vcpkg_target_triplet}/lib/libssl.so")
+ endif()
+ else()
+ message(STATUS "The argument BUNDLE_ANDROID_OPENSSL_LIBS is set "
+ "but OPENSSL_ROOT_DIR parameter is not set. "
+ "Test should bundle OpenSSL libraries but they are not found. "
+ "This is fine if OpenSSL was built statically.")
+ endif()
+ endif()
+ qt_internal_android_test_arguments(
+ "${name}" "${android_timeout}" test_executable extra_test_args)
set(test_working_dir "${CMAKE_CURRENT_BINARY_DIR}")
elseif(QNX)
set(test_working_dir "")
@@ -602,14 +669,21 @@ function(qt_internal_add_test name)
list(APPEND extra_test_args "--browser_args=\"--password-store=basic\"")
list(APPEND extra_test_args "--kill_exit")
- # We always want to enable asyncify for tests, as some of them use exec
+ # Tests may require asyncify if they use exec(). Enable asyncify for
+ # batched tests since this is the configuration used on the CI system.
# Optimize for size (-Os), since asyncify tends to make the resulting
# binary very large
- target_link_options("${name}" PRIVATE "SHELL:-s ASYNCIFY" "-Os")
+ if(batch_current_test)
+ target_link_options("${name}" PRIVATE "SHELL:-s ASYNCIFY" "-Os")
+ endif()
# This tells cmake to run the tests with this script, since wasm files can't be
# executed directly
- set_property(TARGET "${name}" PROPERTY CROSSCOMPILING_EMULATOR "emrun")
+ if (CMAKE_HOST_WIN32)
+ set_property(TARGET "${name}" PROPERTY CROSSCOMPILING_EMULATOR "emrun.bat")
+ else()
+ set_property(TARGET "${name}" PROPERTY CROSSCOMPILING_EMULATOR "emrun")
+ endif()
else()
if(arg_QMLTEST AND NOT arg_SOURCES)
set(test_working_dir "${CMAKE_CURRENT_SOURCE_DIR}")
@@ -670,6 +744,14 @@ function(qt_internal_add_test name)
set_tests_properties(${testname} PROPERTIES TIMEOUT ${arg_TIMEOUT})
endif()
+ if(ANDROID AND NOT CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
+ # Set timeout signal and some time for androidtestrunner to do cleanup
+ set_tests_properties(${testname} PROPERTIES
+ TIMEOUT_SIGNAL_NAME "SIGINT"
+ TIMEOUT_SIGNAL_GRACE_PERIOD 10.0
+ )
+ endif()
+
# Add a ${target}/check makefile target, to more easily test one test.
set(test_config_options "")
@@ -690,7 +772,7 @@ function(qt_internal_add_test name)
endif()
endif()
- if(ANDROID OR IOS OR WASM OR INTEGRITY OR arg_BUILTIN_TESTDATA)
+ if(ANDROID OR IOS OR WASM OR INTEGRITY OR arg_BUILTIN_TESTDATA OR QT_FORCE_BUILTIN_TESTDATA)
set(builtin_testdata TRUE)
endif()
@@ -744,15 +826,27 @@ function(qt_internal_add_test name)
endif()
endif()
else()
- # Install test data
- file(RELATIVE_PATH relative_path_to_test_project
- "${QT_TOP_LEVEL_SOURCE_DIR}"
- "${CMAKE_CURRENT_SOURCE_DIR}")
- qt_path_join(testdata_install_dir ${QT_INSTALL_DIR}
- "${relative_path_to_test_project}")
- if (testdata_install_dir)
+ # Install test data, when tests are built in-tree or as standalone tests, but not as a
+ # single standalone test, which is checked by the existence of the QT_TOP_LEVEL_SOURCE_DIR
+ # variable.
+ # TODO: Shouldn't we also handle the single standalone test case?
+ # TODO: Does installing even makes sense, given where QFINDTESTDATA looks for installed
+ # test data, and where we end up installing it? See QTBUG-117098.
+ if(QT_TOP_LEVEL_SOURCE_DIR)
foreach(testdata IN LISTS arg_TESTDATA)
set(testdata "${CMAKE_CURRENT_SOURCE_DIR}/${testdata}")
+
+ # Get the relative source dir for each test data entry, because it might contain a
+ # subdirectory.
+ file(RELATIVE_PATH relative_path_to_test_project
+ "${QT_TOP_LEVEL_SOURCE_DIR}"
+ "${testdata}")
+ get_filename_component(relative_path_to_test_project
+ "${relative_path_to_test_project}" DIRECTORY)
+
+ qt_path_join(testdata_install_dir ${QT_INSTALL_DIR}
+ "${relative_path_to_test_project}")
+
if (IS_DIRECTORY "${testdata}")
qt_install(
DIRECTORY "${testdata}"
@@ -769,6 +863,35 @@ function(qt_internal_add_test name)
qt_internal_add_test_finalizers("${name}")
endfunction()
+# Given an optional test timeout value (specified via qt_internal_add_test's TIMEOUT option)
+# returns a percentage of the final timeout to be passed to the androidtestrunner executable.
+#
+# When the optional timeout is empty, default to cmake's defaults for getting the timeout.
+function(qt_internal_get_android_test_timeout input_timeout percentage output_timeout_var)
+ set(actual_timeout "${input_timeout}")
+ if(NOT actual_timeout)
+ # we have coin ci timeout set use that to avoid having the emulator killed
+ # so we can at least get some logs from the android test runner.
+ set(coin_timeout $ENV{COIN_COMMAND_OUTPUT_TIMEOUT})
+ if(coin_timeout)
+ set(actual_timeout "${coin_timeout}")
+ elseif(DART_TESTING_TIMEOUT)
+ # Related: https://gitlab.kitware.com/cmake/cmake/-/issues/20450
+ set(actual_timeout "${DART_TESTING_TIMEOUT}")
+ elseif(CTEST_TEST_TIMEOUT)
+ set(actual_timeout "${CTEST_TEST_TIMEOUT}")
+ else()
+ # Default DART_TESTING_TIMEOUT is 25 minutes, specified in seconds
+ # https://github.com/Kitware/CMake/blob/master/Modules/CTest.cmake#L167C16-L167C16
+ set(actual_timeout "1500")
+ endif()
+ endif()
+
+ math(EXPR calculated_timeout "${actual_timeout} * ${percentage} / 100")
+
+ set(${output_timeout_var} "${calculated_timeout}" PARENT_SCOPE)
+endfunction()
+
# This function adds test with specified NAME and wraps given test COMMAND with standalone cmake
# script.
#
diff --git a/cmake/QtToolHelpers.cmake b/cmake/QtToolHelpers.cmake
index c63828ef8c..0aef6a43a3 100644
--- a/cmake/QtToolHelpers.cmake
+++ b/cmake/QtToolHelpers.cmake
@@ -15,6 +15,13 @@
# INSTALL_VERSIONED_LINK
# Prefix build only. On installation, create a versioned hard-link of the installed file.
# E.g. create a link of "bin/qmake6" to "bin/qmake".
+# TRY_RUN
+# On Windows, it creates a helper batch script that tests whether the tool can be executed
+# successfully or not. If not, build halts and an error will be show, with tips on what
+# might be cause, and how to fix it. TRY_RUN is disabled when cross-compiling.
+# TRY_RUN_FLAGS
+# Command line flags that are going to be passed to the tool for testing its correctness.
+# If no flags were given, we default to `-v`.
#
# One-value Arguments:
# EXTRA_CMAKE_FILES
@@ -42,11 +49,13 @@ function(qt_internal_add_tool target_name)
USER_FACING
INSTALL_VERSIONED_LINK
EXCEPTIONS
- NO_UNITY_BUILD)
+ NO_UNITY_BUILD
+ TRY_RUN)
set(one_value_keywords
TOOLS_TARGET
INSTALL_DIR
CORE_LIBRARY
+ TRY_RUN_FLAGS
${__default_target_info_args})
set(multi_value_keywords
EXTRA_CMAKE_FILES
@@ -91,29 +100,23 @@ function(qt_internal_add_tool target_name)
"removed in a future Qt version. Use the LIBRARIES option instead.")
endif()
- qt_internal_library_deprecation_level(deprecation_define)
-
if(arg_NO_UNITY_BUILD)
set(arg_NO_UNITY_BUILD "NO_UNITY_BUILD")
else()
set(arg_NO_UNITY_BUILD "")
endif()
- if(arg_NO_UNITY_BUILD_SOURCES)
- set(arg_NO_UNITY_BUILD_SOURCES "NO_UNITY_BUILD_SOURCES ${arg_NO_UNITY_BUILD_SOURCES}")
- else()
- set(arg_NO_UNITY_BUILD_SOURCES "")
- endif()
-
qt_internal_add_executable("${target_name}"
OUTPUT_DIRECTORY "${output_dir}"
${exceptions}
NO_INSTALL
+ ${arg_NO_UNITY_BUILD}
SOURCES ${arg_SOURCES}
+ NO_PCH_SOURCES ${arg_NO_PCH_SOURCES}
+ NO_UNITY_BUILD_SOURCES ${arg_NO_UNITY_BUILD_SOURCES}
INCLUDE_DIRECTORIES
${arg_INCLUDE_DIRECTORIES}
DEFINES
- QT_USE_QSTRINGBUILDER
${arg_DEFINES}
${deprecation_define}
${corelib}
@@ -125,13 +128,13 @@ function(qt_internal_add_tool target_name)
LINK_OPTIONS ${arg_LINK_OPTIONS}
MOC_OPTIONS ${arg_MOC_OPTIONS}
DISABLE_AUTOGEN_TOOLS ${disable_autogen_tools}
- TARGET_VERSION "${arg_TARGET_VERSION}"
- TARGET_PRODUCT "${arg_TARGET_PRODUCT}"
- TARGET_DESCRIPTION "${arg_TARGET_DESCRIPTION}"
- TARGET_COMPANY "${arg_TARGET_COMPANY}"
- TARGET_COPYRIGHT "${arg_TARGET_COPYRIGHT}"
- ${arg_NO_UNITY_BUILD_SOURCES}
- ${arg_NO_UNITY_BUILD}
+ TARGET_VERSION ${arg_TARGET_VERSION}
+ TARGET_PRODUCT ${arg_TARGET_PRODUCT}
+ TARGET_DESCRIPTION ${arg_TARGET_DESCRIPTION}
+ TARGET_COMPANY ${arg_TARGET_COMPANY}
+ TARGET_COPYRIGHT ${arg_TARGET_COPYRIGHT}
+ # If you are putting anything after these, make sure that
+ # qt_set_target_info_properties knows how to process them
)
qt_internal_add_target_aliases("${target_name}")
_qt_internal_apply_strict_cpp("${target_name}")
@@ -201,7 +204,7 @@ function(qt_internal_add_tool target_name)
OUT_VAR install_targets_default_args
RUNTIME "${install_dir}"
CMAKE_CONFIG "${cmake_config}"
- ALL_CMAKE_CONFIGS "${cmake_configs}")
+ ALL_CMAKE_CONFIGS ${cmake_configs})
# Make installation optional for targets that are not built by default in this config
if(QT_FEATURE_debug_and_release
@@ -228,10 +231,62 @@ function(qt_internal_add_tool target_name)
qt_internal_apply_staging_prefix_build_rpath_workaround()
endif()
+ if(arg_TRY_RUN AND WIN32 AND NOT CMAKE_CROSSCOMPILING)
+ if(NOT arg_TRY_RUN_FLAGS)
+ set(arg_TRY_RUN_FLAGS "-v")
+ endif()
+ _qt_internal_add_try_run_post_build("${target_name}" "${arg_TRY_RUN_FLAGS}")
+ endif()
+
qt_enable_separate_debug_info(${target_name} "${install_dir}" QT_EXECUTABLE)
qt_internal_install_pdb_files(${target_name} "${install_dir}")
endfunction()
+function(_qt_internal_add_try_run_post_build target try_run_flags)
+ qt_internal_get_upper_case_main_cmake_configuration(main_cmake_configuration)
+ get_target_property(target_out_dir ${target}
+ RUNTIME_OUTPUT_DIRECTORY_${main_cmake_configuration})
+ get_target_property(target_bin_dir ${target}
+ BINARY_DIR)
+
+ set(try_run_scripts_path "${target_bin_dir}/${target}_try_run.bat")
+ # The only reason -h is passed is because some of the tools, e.g., moc
+ # wait for an input without any arguments.
+
+ qt_configure_file(OUTPUT "${try_run_scripts_path}"
+ CONTENT "@echo off
+
+${target_out_dir}/${target}.exe ${try_run_flags} > nul 2>&1
+
+if \"%errorlevel%\" == \"-1073741515\" (
+echo
+echo '${target}' is built successfully, but some of the libraries
+echo necessary for running it are missing. If you are building Qt with
+echo 3rdparty libraries, make sure that you add their directory to the
+echo PATH environment variable.
+echo
+exit /b %errorlevel%
+)
+echo. > ${target_bin_dir}/${target}_try_run_passed"
+ )
+
+ add_custom_command(
+ OUTPUT
+ ${target_bin_dir}/${target}_try_run_passed
+ DEPENDS
+ ${target}
+ COMMAND
+ ${CMAKE_COMMAND} -E env QT_COMMAND_LINE_PARSER_NO_GUI_MESSAGE_BOXES=1
+ ${try_run_scripts_path}
+ COMMENT
+ "Testing ${target} by trying to run it."
+ VERBATIM
+ )
+
+ add_custom_target(${target}_try_run ALL
+ DEPENDS ${target_bin_dir}/${target}_try_run_passed)
+endfunction()
+
function(qt_export_tools module_name)
# Bail out when not building tools.
if(NOT QT_WILL_BUILD_TOOLS)
@@ -291,7 +346,7 @@ function(qt_export_tools module_name)
string(REGEX REPLACE "_native$" "" tool_name ${tool_name})
endif()
set(extra_cmake_statements "${extra_cmake_statements}
-if (NOT QT_NO_CREATE_TARGETS)
+if(NOT QT_NO_CREATE_TARGETS AND ${INSTALL_CMAKE_NAMESPACE}${target}_FOUND)
__qt_internal_promote_target_to_global(${INSTALL_CMAKE_NAMESPACE}::${tool_name})
endif()
")
@@ -440,25 +495,34 @@ endfunction()
# Sets QT_WILL_BUILD_TOOLS if tools will be built and QT_WILL_RENAME_TOOL_TARGETS
# if those tools have replaced naming.
function(qt_check_if_tools_will_be_built)
- # By default, we build our own tools unless we're cross-building.
+ # By default, we build our own tools unless we're cross-building or QT_HOST_PATH is set.
set(need_target_rename FALSE)
+ set(require_find_tools FALSE)
if(CMAKE_CROSSCOMPILING)
set(will_build_tools FALSE)
if(QT_FORCE_BUILD_TOOLS)
set(will_build_tools TRUE)
set(need_target_rename TRUE)
endif()
+ set(require_find_tools TRUE)
else()
- set(will_build_tools TRUE)
+ if(QT_HOST_PATH)
+ set(will_build_tools FALSE)
+ else()
+ set(will_build_tools TRUE)
+ endif()
if(QT_FORCE_FIND_TOOLS)
set(will_build_tools FALSE)
- if(QT_FORCE_BUILD_TOOLS)
- set(will_build_tools TRUE)
- set(need_target_rename TRUE)
- endif()
+ set(require_find_tools TRUE)
+ endif()
+ if(QT_FORCE_BUILD_TOOLS)
+ set(will_build_tools TRUE)
+ set(need_target_rename TRUE)
endif()
endif()
+ set_property(GLOBAL PROPERTY qt_require_find_tools "${require_find_tools}")
+
set(QT_WILL_BUILD_TOOLS ${will_build_tools} CACHE INTERNAL "Are tools going to be built" FORCE)
set(QT_WILL_RENAME_TOOL_TARGETS ${need_target_rename} CACHE INTERNAL
"Do tool targets need to be renamed" FORCE)
@@ -497,6 +561,15 @@ function(qt_internal_find_tool out_var target_name tools_target)
" (QT_WILL_BUILD_TOOLS is ${QT_WILL_BUILD_TOOLS}).")
endif()
+ if(NOT CMAKE_CROSSCOMPILING)
+ if(QT_INTERNAL_FORCE_FIND_HOST_TOOLS_MODULE_LIST AND
+ NOT "${tools_target}" IN_LIST QT_INTERNAL_FORCE_FIND_HOST_TOOLS_MODULE_LIST)
+ message(STATUS "Tool '${full_name}' will be built from source.")
+ set(${out_var} "TRUE" PARENT_SCOPE)
+ return()
+ endif()
+ endif()
+
if(QT_WILL_RENAME_TOOL_TARGETS AND (name STREQUAL target_name))
message(FATAL_ERROR
"qt_internal_add_tool must be passed a target obtained from qt_get_tool_target_name.")
@@ -610,7 +683,8 @@ function(qt_internal_find_tool out_var target_name tools_target)
endif()
endif()
- if(NOT QT_WILL_BUILD_TOOLS)
+ get_property(require_find_tools GLOBAL PROPERTY qt_require_find_tools)
+ if(require_find_tools AND NOT TARGET ${full_name})
if(${${tools_package_name}_FOUND})
set(pkg_found_msg "")
string(APPEND pkg_found_msg
@@ -627,7 +701,9 @@ function(qt_internal_find_tool out_var target_name tools_target)
message(FATAL_ERROR
"Failed to find the host tool \"${full_name}\". It is part of "
${pkg_found_msg})
- else()
+ endif()
+
+ if(QT_WILL_BUILD_TOOLS)
message(STATUS "Tool '${full_name}' will be built from source.")
endif()
set(${out_var} "TRUE" PARENT_SCOPE)
diff --git a/cmake/QtToolchainHelpers.cmake b/cmake/QtToolchainHelpers.cmake
index 13b7acc0fc..26b44bb10c 100644
--- a/cmake/QtToolchainHelpers.cmake
+++ b/cmake/QtToolchainHelpers.cmake
@@ -31,6 +31,14 @@ set(__qt_chainload_toolchain_file \"\${__qt_initially_configured_toolchain_file}
list(APPEND init_platform "set(CMAKE_SYSTEM_PROCESSOR arm64 CACHE STRING \"\")")
endif()
+ if(QT_QMAKE_TARGET_MKSPEC)
+ list(APPEND init_platform
+ "if(NOT QT_QMAKE_TARGET_MKSPEC)"
+ " set(QT_QMAKE_TARGET_MKSPEC ${QT_QMAKE_TARGET_MKSPEC} CACHE STRING \"\")"
+ "endif()"
+ )
+ endif()
+
if("${QT_QMAKE_TARGET_MKSPEC}" STREQUAL "linux-g++-32" AND NOT QT_NO_AUTO_DETECT_LINUX_X86)
set(__qt_toolchain_common_flags_init "-m32")
@@ -121,39 +129,41 @@ set(__qt_chainload_toolchain_file \"\${__qt_initially_configured_toolchain_file}
endif()
if(__qt_embed_toolchain_compilers)
list(APPEND init_platform "
- set(__qt_initial_c_compiler \"${CMAKE_C_COMPILER}\")
- set(__qt_initial_cxx_compiler \"${CMAKE_CXX_COMPILER}\")
- if(NOT DEFINED CMAKE_C_COMPILER AND EXISTS \"\${__qt_initial_c_compiler}\")
- set(CMAKE_C_COMPILER \"\${__qt_initial_c_compiler}\" CACHE STRING \"\")
- endif()
- if(NOT DEFINED CMAKE_CXX_COMPILER AND EXISTS \"\${__qt_initial_cxx_compiler}\")
- set(CMAKE_CXX_COMPILER \"\${__qt_initial_cxx_compiler}\" CACHE STRING \"\")
- endif()")
+set(__qt_initial_c_compiler \"${CMAKE_C_COMPILER}\")
+set(__qt_initial_cxx_compiler \"${CMAKE_CXX_COMPILER}\")
+if(QT_USE_ORIGINAL_COMPILER AND NOT DEFINED CMAKE_C_COMPILER
+ AND EXISTS \"\${__qt_initial_c_compiler}\")
+ set(CMAKE_C_COMPILER \"\${__qt_initial_c_compiler}\" CACHE STRING \"\")
+endif()
+if(QT_USE_ORIGINAL_COMPILER AND NOT DEFINED CMAKE_CXX_COMPILER
+ AND EXISTS \"\${__qt_initial_cxx_compiler}\")
+ set(CMAKE_CXX_COMPILER \"\${__qt_initial_cxx_compiler}\" CACHE STRING \"\")
+endif()")
endif()
unset(init_additional_used_variables)
if(APPLE)
- # For an iOS simulator_and_device build, we should not explicitly set the sysroot, but let
- # CMake do it's universal build magic to use one sysroot / sdk per-arch.
- # For a single arch / sysroot iOS build, try to use the initially configured sysroot
- # path if it exists, otherwise just set the name of the sdk to be used.
- # The latter "name" part is important for user projects so that running 'xcodebuild' from
- # the command line chooses the correct sdk.
+ # For an iOS simulator_and_device build, we should not explicitly set the sysroot,
+ # but let CMake do it's universal build magic to use one sysroot / sdk per-arch.
+ # For a single arch / sysroot build, try to use the initially configured sysroot
+ # by name.
+ #
# Also allow to opt out just in case.
#
# TODO: Figure out if the same should apply to universal macOS builds.
+ # We want to preserve the sysroot as an SDK name, instead of the path
+ # that CMake transforms it into in Darwin-initialize.cmake, so we pick
+ # it out from the cache, where it hasn't been touched by CMake.
+ set(cmake_sysroot_name "$CACHE{CMAKE_OSX_SYSROOT}")
+
list(LENGTH CMAKE_OSX_ARCHITECTURES _qt_osx_architectures_count)
- if(CMAKE_OSX_SYSROOT AND NOT _qt_osx_architectures_count GREATER 1 AND UIKIT)
+ if(cmake_sysroot_name AND NOT _qt_osx_architectures_count GREATER 1 AND UIKIT)
list(APPEND init_platform "
- set(__qt_uikit_sdk \"${QT_UIKIT_SDK}\")
- set(__qt_initial_cmake_osx_sysroot \"${CMAKE_OSX_SYSROOT}\")
- if(NOT DEFINED CMAKE_OSX_SYSROOT AND EXISTS \"\${__qt_initial_cmake_osx_sysroot}\")
- set(CMAKE_OSX_SYSROOT \"\${__qt_initial_cmake_osx_sysroot}\" CACHE PATH \"\")
- elseif(NOT DEFINED CMAKE_OSX_SYSROOT AND NOT QT_NO_SET_OSX_SYSROOT)
- set(CMAKE_OSX_SYSROOT \"\${__qt_uikit_sdk}\" CACHE PATH \"\")
- endif()")
+if(NOT DEFINED CMAKE_OSX_SYSROOT)
+ set(CMAKE_OSX_SYSROOT \"${cmake_sysroot_name}\" CACHE STRING \"\")
+endif()")
endif()
if(CMAKE_OSX_DEPLOYMENT_TARGET)
@@ -208,7 +218,7 @@ set(__qt_chainload_toolchain_file \"\${__qt_initially_configured_toolchain_file}
qt_internal_get_first_osx_arch(osx_first_arch)
list(APPEND init_platform
"if((NOT CMAKE_GENERATOR STREQUAL \"Xcode\" AND NOT __qt_toolchain_building_qt_repo)
- OR (CMAKE_GENERATOR STREQUAL \"Xcode\" AND __qt_uikit_sdk AND NOT QT_NO_SET_OSX_ARCHITECTURES))")
+ OR (CMAKE_GENERATOR STREQUAL \"Xcode\" AND __qt_apple_sdk AND NOT QT_NO_SET_OSX_ARCHITECTURES))")
list(APPEND init_platform
" set(CMAKE_OSX_ARCHITECTURES \"${osx_first_arch}\" CACHE STRING \"\")")
list(APPEND init_platform "endif()")
@@ -222,15 +232,11 @@ set(__qt_chainload_toolchain_file \"\${__qt_initially_configured_toolchain_file}
elseif(ANDROID)
list(APPEND init_platform
"# Detect Android SDK/NDK from environment before loading the Android platform toolchain file."
-"if(NOT DEFINED ANDROID_SDK_ROOT)"
-" if(NOT \"\$ENV{ANDROID_SDK_ROOT}\" STREQUAL \"\")"
-" set(ANDROID_SDK_ROOT \"\$ENV{ANDROID_SDK_ROOT}\" CACHE STRING \"Path to the Android SDK\")"
-" endif()"
+"if(\"$\{ANDROID_SDK_ROOT}\" STREQUAL \"\" AND NOT \"\$ENV{ANDROID_SDK_ROOT}\" STREQUAL \"\")"
+" set(ANDROID_SDK_ROOT \"\$ENV{ANDROID_SDK_ROOT}\" CACHE STRING \"Path to the Android SDK\")"
"endif()"
-"if(NOT DEFINED ANDROID_NDK_ROOT)"
-" if(NOT \"\$ENV{ANDROID_NDK_ROOT}\" STREQUAL \"\")"
-" set(ANDROID_NDK_ROOT \"\$ENV{ANDROID_NDK_ROOT}\" CACHE STRING \"Path to the Android NDK\")"
-" endif()"
+"if(\"$\{ANDROID_NDK_ROOT}\" STREQUAL \"\" AND NOT \"\$ENV{ANDROID_NDK_ROOT}\" STREQUAL \"\")"
+" set(ANDROID_NDK_ROOT \"\$ENV{ANDROID_NDK_ROOT}\" CACHE STRING \"Path to the Android NDK\")"
"endif()"
)
diff --git a/cmake/QtUnityBuildHelpers.cmake b/cmake/QtUnityBuildHelpers.cmake
index b66c6765ba..e804396f59 100644
--- a/cmake/QtUnityBuildHelpers.cmake
+++ b/cmake/QtUnityBuildHelpers.cmake
@@ -11,7 +11,14 @@ function(_qt_internal_validate_no_unity_build prefix)
endfunction()
function(qt_update_ignore_unity_build_sources target sources)
- if (sources)
- set_source_files_properties(${sources} PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON)
+ if(sources)
+ # We need to add the TARGET_DIRECTORY scope for targets that have qt_internal_extend_target
+ # calls in different subdirectories, like in qtgraphs.
+ set(scope_args)
+ if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.18")
+ set(scope_args TARGET_DIRECTORY ${target})
+ endif()
+ set_source_files_properties(${sources} ${scope_args}
+ PROPERTIES SKIP_UNITY_BUILD_INCLUSION ON)
endif()
endfunction()
diff --git a/cmake/QtVersionlessAliasTargets.cmake.in b/cmake/QtVersionlessAliasTargets.cmake.in
new file mode 100644
index 0000000000..fcf182941c
--- /dev/null
+++ b/cmake/QtVersionlessAliasTargets.cmake.in
@@ -0,0 +1,7 @@
+# Protect against multiple inclusion, which would fail when already imported targets are
+# added once more.
+_qt_internal_check_multiple_inclusion(_targets_not_defined "@versionless_targets@")
+
+_qt_internal_create_versionless_alias_targets("${_targets_not_defined}" @INSTALL_CMAKE_NAMESPACE@)
+
+unset(_targets_not_defined)
diff --git a/cmake/QtVersionlessTargets.cmake.in b/cmake/QtVersionlessTargets.cmake.in
new file mode 100644
index 0000000000..c809915e65
--- /dev/null
+++ b/cmake/QtVersionlessTargets.cmake.in
@@ -0,0 +1,7 @@
+# Protect against multiple inclusion, which would fail when already imported targets are
+# added once more.
+_qt_internal_check_multiple_inclusion(_targets_not_defined "@versionless_targets@")
+
+_qt_internal_create_versionless_targets("${_targets_not_defined}" @INSTALL_CMAKE_NAMESPACE@)
+
+unset(_targets_not_defined)
diff --git a/cmake/QtWasmHelpers.cmake b/cmake/QtWasmHelpers.cmake
index 29478b33a4..41ef5cb0ba 100644
--- a/cmake/QtWasmHelpers.cmake
+++ b/cmake/QtWasmHelpers.cmake
@@ -18,14 +18,9 @@ function (qt_internal_setup_wasm_target_properties wasmTarget)
target_compile_options("${wasmTarget}" INTERFACE "SHELL:-s MEMORY64=1" )
target_link_options("${wasmTarget}" INTERFACE "SHELL:-s MEMORY64=1" -mwasm64)
endif()
- # Enable MODULARIZE and set EXPORT_NAME, which makes it possible to
- # create application instances using a global constructor function,
- # e.g. let app_instance = await createQtAppInstance().
- # (as opposed to MODULARIZE=0, where Emscripten creates a global app
- # instance object at Javascript eval time)
- target_link_options("${wasmTarget}" INTERFACE
- "SHELL:-s MODULARIZE=1"
- "SHELL:-s EXPORT_NAME=createQtAppInstance")
+ # Enable MODULARIZE so that we are able to set EXPORT_NAME later and instantiate on demand (with
+ # MODULARIZE=0, emscripten creates a global app instance object at Javascript eval time)
+ target_link_options("${wasmTarget}" INTERFACE "SHELL:-s MODULARIZE=1")
#simd
if (QT_FEATURE_wasm_simd128)
@@ -39,8 +34,6 @@ function (qt_internal_setup_wasm_target_properties wasmTarget)
if (QT_FEATURE_wasm_exceptions)
target_compile_options("${wasmTarget}" INTERFACE -fwasm-exceptions)
target_link_options("${wasmTarget}" INTERFACE -fwasm-exceptions)
- else()
- target_link_options("${wasmTarget}" INTERFACE "SHELL:-s DISABLE_EXCEPTION_CATCHING=1")
endif()
if (QT_FEATURE_thread)
@@ -105,6 +98,12 @@ function (qt_internal_setup_wasm_target_properties wasmTarget)
"${enable_main_module_if_needed}"
)
+ # Add Qt libdir to linker library paths
+ set(qt_lib_location
+ "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}/${INSTALL_LIBDIR}")
+ target_link_options("${wasmTarget}" INTERFACE
+ "$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:SHELL:" -L${qt_lib_location}/>)
+
target_compile_options("${wasmTarget}" INTERFACE "${set_shared_module_type_if_needed}")
target_link_options("${wasmTarget}" INTERFACE "${set_shared_module_type_if_needed}")
@@ -120,6 +119,7 @@ function (qt_internal_setup_wasm_target_properties wasmTarget)
endfunction()
function(qt_internal_wasm_add_finalizers target)
+ qt_add_list_file_finalizer(_qt_internal_set_wasm_export_name ${target})
qt_add_list_file_finalizer(_qt_internal_add_wasm_extra_exported_methods ${target})
qt_add_list_file_finalizer(_qt_internal_wasm_add_target_helpers ${target})
endfunction()
diff --git a/cmake/QtWrapperScriptHelpers.cmake b/cmake/QtWrapperScriptHelpers.cmake
index e87d0ad2e5..8eb4416e6d 100644
--- a/cmake/QtWrapperScriptHelpers.cmake
+++ b/cmake/QtWrapperScriptHelpers.cmake
@@ -19,13 +19,18 @@ function(qt_internal_create_wrapper_scripts)
set(generate_non_unix TRUE)
endif()
+ set(extra_qt_cmake_code "")
if(generate_unix)
- if(IOS)
- set(infix ".ios")
- else()
- set(infix "")
+
+ if(UIKIT)
+ set(extra_qt_cmake_code [=[
+# Specify Xcode as the default generator by assigning it to the CMAKE_GENERATOR env var.
+# An explicit -G or -D CMAKE_GENERATOR given on the command line will still take precedence.
+export CMAKE_GENERATOR=Xcode
+]=])
endif()
- configure_file("${CMAKE_CURRENT_SOURCE_DIR}/bin/qt-cmake${infix}.in"
+
+ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/bin/qt-cmake.in"
"${QT_BUILD_DIR}/${INSTALL_BINDIR}/qt-cmake" @ONLY
NEWLINE_STYLE LF)
qt_install(PROGRAMS "${QT_BUILD_DIR}/${INSTALL_BINDIR}/qt-cmake"
@@ -53,15 +58,20 @@ function(qt_internal_create_wrapper_scripts)
qt_install(PROGRAMS "${QT_BUILD_DIR}/${INSTALL_BINDIR}/qt-cmake-create.bat"
DESTINATION "${INSTALL_BINDIR}")
endif()
- # Provide a private convenience wrapper with options which should not be propagated via the
+
+ # Reset the contents for the next script.
+ set(extra_qt_cmake_code "")
+
+ # Provide a private convenience wrapper with options that should not be propagated via the
# public qt-cmake wrapper e.g. CMAKE_GENERATOR.
# These options can not be set in a toolchain file, but only on the command line.
# These options should not be in the public wrapper, because a consumer of Qt might want to
# build their CMake app with the Unix Makefiles generator, while Qt should be built with the
- # Ninja generator.
- # The private wrapper is more conveient for building Qt itself, because a developer doesn't need
- # to specify the same options for each qt module built.
- set(__qt_cmake_extra "-G\"${CMAKE_GENERATOR}\"")
+ # Ninja generator. In a similar vein, we do want to use the same compiler for all Qt modules,
+ # but not for user applications.
+ # The private wrapper is more convenient for building Qt itself, because a developer doesn't
+ # need to specify the same options for each qt module built.
+ set(__qt_cmake_extra "-G\"${CMAKE_GENERATOR}\" -DQT_USE_ORIGINAL_COMPILER=ON")
if(generate_unix)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/bin/qt-cmake.in"
"${QT_BUILD_DIR}/${INSTALL_LIBEXECDIR}/qt-cmake-private" @ONLY
@@ -202,16 +212,33 @@ function(qt_internal_create_wrapper_scripts)
elseif(CMAKE_BUILD_TYPE)
set(__qt_configured_configs "${CMAKE_BUILD_TYPE}")
endif()
+
+ if(
+ # Skip stripping pure debug builds so it's easier to debug issues in CI VMs.
+ (NOT QT_FEATURE_debug_and_release
+ AND QT_FEATURE_debug
+ AND NOT QT_FEATURE_separate_debug_info)
+
+ # Skip stripping on MSVC because ${CMAKE_STRIP} might contain a MinGW strip binary
+ # and the breaks the linker version flag embedded in the binary and causes Qt Creator
+ # to mis-identify the Kit ABI.
+ OR MSVC
+ )
+ set(__qt_skip_strip_installed_artifacts TRUE)
+ else()
+ set(__qt_skip_strip_installed_artifacts FALSE)
+ endif()
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/bin/${__qt_cmake_install_script_name}.in"
"${QT_BUILD_DIR}/${INSTALL_LIBEXECDIR}/${__qt_cmake_install_script_name}" @ONLY)
qt_install(FILES "${QT_BUILD_DIR}/${INSTALL_LIBEXECDIR}/${__qt_cmake_install_script_name}"
DESTINATION "${INSTALL_LIBEXECDIR}")
- qt_internal_create_qt_configure_tests_wrapper_script()
- qt_internal_install_android_helper_scripts()
+ qt_internal_create_qt_configure_part_wrapper_script("STANDALONE_TESTS")
+ qt_internal_create_qt_configure_part_wrapper_script("STANDALONE_EXAMPLES")
+ qt_internal_create_qt_configure_redo_script()
endfunction()
-function(qt_internal_create_qt_configure_tests_wrapper_script)
+function(qt_internal_create_qt_configure_part_wrapper_script component)
if(QT_GENERATE_WRAPPER_SCRIPTS_FOR_ALL_HOSTS)
set(generate_unix TRUE)
set(generate_non_unix TRUE)
@@ -221,17 +248,27 @@ function(qt_internal_create_qt_configure_tests_wrapper_script)
set(generate_non_unix TRUE)
endif()
- # Create a private wrapper script to configure and build all standalone tests.
+ # Create a private wrapper script to configure and build all standalone tests / examples.
#
# The script uses qt-cmake instead of qt-cmake-private on purpose. That's to ensure we build
# only one configuration of tests (e.g RelWithDebInfo only) when Qt is configured with more
# than one configuration (RelWithDebInfo;Debug).
# Meant to be used by our CI instructions.
#
- # The script takes a path to the repo for which the standalone tests will be configured.
- set(script_name "qt-internal-configure-tests")
+ # The script takes a path to the repo for which the standalone tests / examples will be
+ # configured.
- set(script_passed_args "-DQT_BUILD_STANDALONE_TESTS=ON")
+ if(component STREQUAL "STANDALONE_TESTS")
+ set(script_name "qt-internal-configure-tests")
+ set(script_passed_args "-DQT_BUILD_STANDALONE_TESTS=ON -DQT_BUILD_EXAMPLES=OFF")
+ elseif(component STREQUAL "STANDALONE_EXAMPLES")
+ set(script_name "qt-internal-configure-examples")
+ set(script_passed_args "-DQT_BUILD_STANDALONE_EXAMPLES=ON -DQT_BUILD_TESTS=OFF")
+ else()
+ message(FATAL_ERROR "Invalid component type: ${component}")
+ endif()
+
+ string(APPEND script_passed_args " -DQT_USE_ORIGINAL_COMPILER=ON")
file(RELATIVE_PATH relative_path_from_libexec_dir_to_bin_dir
${__qt_libexec_dir_absolute}
@@ -257,8 +294,40 @@ function(qt_internal_create_qt_configure_tests_wrapper_script)
endif()
endfunction()
-function(qt_internal_install_android_helper_scripts)
- qt_path_join(destination "${QT_INSTALL_DIR}" "${INSTALL_LIBEXECDIR}")
- qt_copy_or_install(PROGRAMS "${CMAKE_CURRENT_SOURCE_DIR}/util/android/android_emulator_launcher.sh"
- DESTINATION "${destination}")
+# Create a shell wrapper script to reconfigure Qt with the original configure arguments and
+# any additional ones passed.
+#
+# Removes CMakeCache.txt and friends, either manually, or using CMake's --fresh.
+#
+# The script is created in the root of the build dir and is called config.redo
+# It has the same contents as the 'config.status' script we created in qt 5.
+function(qt_internal_create_qt_configure_redo_script)
+ set(input_script_name "qt-internal-config.redo")
+ set(input_script_path "${CMAKE_CURRENT_SOURCE_DIR}/libexec/${input_script_name}")
+
+ # We don't use QT_BUILD_DIR because we want the file in the root of the build dir in a top-level
+ # build.
+ set(output_script_name "config.redo")
+ set(output_path "${CMAKE_BINARY_DIR}/${output_script_name}")
+
+ if(QT_SUPERBUILD)
+ set(configure_script_path "${Qt_SOURCE_DIR}")
+ else()
+ set(configure_script_path "${QtBase_SOURCE_DIR}")
+ endif()
+ string(APPEND configure_script_path "/configure")
+
+ # Used in the file contents.
+ file(TO_NATIVE_PATH "${configure_script_path}" configure_path)
+
+ if(CMAKE_HOST_UNIX)
+ string(APPEND input_script_path ".in")
+ set(newline_style "LF")
+ else()
+ string(APPEND input_script_path ".bat.in")
+ string(APPEND output_path ".bat")
+ set(newline_style "CRLF")
+ endif()
+
+ configure_file("${input_script_path}" "${output_path}" @ONLY NEWLINE_STYLE ${newline_style})
endfunction()
diff --git a/cmake/QtWriteArgsFile.cmake b/cmake/QtWriteArgsFile.cmake
index acc771ec3b..77a9eb2463 100644
--- a/cmake/QtWriteArgsFile.cmake
+++ b/cmake/QtWriteArgsFile.cmake
@@ -19,8 +19,15 @@ cmake_minimum_required(VERSION 3.16)
# Read arguments from IN_FILE and separate them.
file(READ "${IN_FILE}" raw_args)
+# To catch cases where the path ends with an `\`, e.g., `-prefix "C:\Path\"`
+string(REPLACE "\\\"" "\"" raw_args "${raw_args}")
+string(REPLACE ";" "[[;]]" raw_args "${raw_args}")
+
separate_arguments(args NATIVE_COMMAND "${raw_args}")
+string(REPLACE "\;" ";" args "${args}")
+string(REPLACE "[[;]]" "\;" args "${args}")
+
if(DEFINED REDO_FILE)
file(READ "${REDO_FILE}" raw_redo_args)
separate_arguments(redo_args NATIVE_COMMAND "${raw_redo_args}")
@@ -65,7 +72,6 @@ if(DEFINED REDO_FILE)
else()
list(APPEND args "${redo_args}")
endif()
-
endif()
# Skip arguments if requested
diff --git a/cmake/README.md b/cmake/README.md
index ac9d1012cf..0d8179a32c 100644
--- a/cmake/README.md
+++ b/cmake/README.md
@@ -4,6 +4,11 @@ This document gives an overview of the Qt 6 build system. For a hands-on guide o
to build Qt 6, see https://doc.qt.io/qt-6/build-sources.html and
https://wiki.qt.io/Building_Qt_6_from_Git
+# Contributing
+
+See qtbase/cmake/CODESTYLE.md for the code style you should follow when contributing
+to Qt's cmake files.
+
# CMake Versions
* You need CMake 3.16.0 or later for most platforms (due to new AUTOMOC json feature).
@@ -185,7 +190,7 @@ If you don't supply the configuration argument ``-DANDROID_ABI=...``, it will de
* x86: ``-DANDROID_ABI=x86``
* x86_64: ``-DANDROID_ABI=x86_64``
-By default we set the android API level to 23. Should you need to change this supply the following
+By default we set the android API level to 28. Should you need to change this supply the following
configuration argument to the above CMake call: ``-DANDROID_PLATFORM=android-${API_LEVEL}``.
### Cross compiling for iOS
@@ -195,13 +200,13 @@ In order to cross-compile Qt to iOS, you need a host macOS build.
When running cmake in qtbase, pass
``-DCMAKE_SYSTEM_NAME=iOS -DQT_HOST_PATH=/path/to/your/host/build -DCMAKE_INSTALL_PREFIX=$INSTALL_PATH``
-If you don't supply the configuration argument ``-DQT_UIKIT_SDK=...``, CMake will build a
+If you don't supply the configuration argument ``-DQT_APPLE_SDK=...``, CMake will build a
multi-arch simulator_and_device iOS build.
To target another SDK / device type, use one of the following values:
- * iphonesimulator: ``-DQT_UIKIT_SDK=iphonesimulator``
- * iphoneos: ``-DQT_UIKIT_SDK=iphoneos``
+ * iphonesimulator: ``-DQT_APPLE_SDK=iphonesimulator``
+ * iphoneos: ``-DQT_APPLE_SDK=iphoneos``
-Depending on what value you pass to ``-DQT_UIKIT_SDK=`` a list of target architectures is chosen
+Depending on what value you pass to ``-DQT_APPLE_SDK=`` a list of target architectures is chosen
by default:
* iphonesimulator: ``x86_64``
* iphoneos: ``arm64``
diff --git a/cmake/configure-cmake-mapping.md b/cmake/configure-cmake-mapping.md
index af7e741dd0..6a184f6119 100644
--- a/cmake/configure-cmake-mapping.md
+++ b/cmake/configure-cmake-mapping.md
@@ -8,6 +8,7 @@ The following table describes the mapping of configure options to CMake argument
| -extprefix /opt/qt6 | -DCMAKE_STAGING_PREFIX=/opt/qt6 | |
| -bindir <dir> | -DINSTALL_BINDIR=<dir> | similar for -headerdir -libdir and so on |
| -hostdatadir <dir> | -DINSTALL_MKSPECSDIR=<dir> | |
+| -qt-host-path <dir> | -DQT_HOST_PATH=<dir> | |
| -help | n/a | Handled by configure[.bat]. |
| -verbose | --log-level=STATUS | Sets the CMake log level to STATUS. The default one is NOTICE. |
| -continue | | |
@@ -17,7 +18,6 @@ The following table describes the mapping of configure options to CMake argument
| -no-feature-foo | -DFEATURE_foo=OFF | |
| -list-features | | At the moment: configure with cmake once, |
| | | then use ccmake or cmake-gui to inspect the features. |
-| -list-libraries | | |
| -opensource | n/a | |
| -commercial | n/a | |
| -confirm-license | n/a | |
@@ -45,10 +45,11 @@ The following table describes the mapping of configure options to CMake argument
| -device-option <key=value> | -DQT_QMAKE_DEVICE_OPTIONS=key1=value1;key2=value2 | Only used for generation qmake-compatibility files. |
| | | The device options are written into mkspecs/qdevice.pri. |
| -appstore-compliant | -DFEATURE_appstore_compliant=ON | |
+| -qtinlinenamespace | -DQT_INLINE_NAMESPACE=ON | Make the namespace specified by -qtnamespace an inline one. |
| -qtnamespace <name> | -DQT_NAMESPACE=<name> | |
| -qtlibinfix <infix> | -DQT_LIBINFIX=<infix> | |
-| -testcocoon | | |
-| -gcov | | |
+| -coverage <tool> | -DINPUT_coverage=<tool> | Enables code coverage using the specified tool. |
+| -gcov | -DINPUT_coverage=gcov | Enables code coverage using the gcov tool. |
| -trace [backend] | -DINPUT_trace=yes or -DINPUT_trace=<backend> | |
| | or -DFEATURE_<backend> | |
| -sanitize address -sanitize undefined | -DFEATURE_sanitize_address=ON | Directly setting -DECM_ENABLE_SANITIZERS=foo is not supported |
@@ -76,32 +77,27 @@ The following table describes the mapping of configure options to CMake argument
| -ccache | -DQT_USE_CCACHE=ON | |
| -unity-build | -DQT_UNITY_BUILD=ON | |
| -unity-build-batch-size <int> | -DQT_UNITY_BUILD_BATCH_SIZE=<int> | |
-| -make-tool <tool> | n/a | |
-| -mp | n/a | |
| -warnings-are-errors | -DWARNINGS_ARE_ERRORS=ON | |
-| -silent | n/a | |
-| -sysroot <dir> | -DCMAKE_SYSROOT=<dir> | Should be provided by a toolchain file that's |
-| | | passed via -DCMAKE_TOOLCHAIN_FILE=<filename> |
-| -no-gcc-sysroot | n/a | The corresponding CMake variables are CMAKE_SYSROOT_LINK |
-| | | and CMAKE_SYSROOT_COMPILE. |
-| | | They are usually set in a toolchain file. |
| -no-pkg-config | -DFEATURE_pkg_config=OFF | |
+| -vcpkg | -DQT_USE_VCPKG=ON | |
| -D <string> | -DQT_EXTRA_DEFINES=<string1>;<string2> | |
| -I <string> | -DQT_EXTRA_INCLUDEPATHS=<string1>;<string2> | |
| -L <string> | -DQT_EXTRA_LIBDIRS=<string1>;<string2> | |
| -F <string> | -DQT_EXTRA_FRAMEWORKPATHS=<string1>;<string2> | |
-| -sdk <sdk> | -DQT_UIKIT_SDK=<value> | Should be provided a value like 'iphoneos' or 'iphonesimulator' |
+| -sdk <sdk> | -DQT_APPLE_SDK=<value> | Should be provided a value like 'iphoneos' or 'iphonesimulator' |
| | | If no value is provided, a simulator_and_device build is |
| | | assumed. |
| -android-sdk <path> | -DANDROID_SDK_ROOT=<path> | |
| -android-ndk <path> | -DCMAKE_TOOLCHAIN_FILE=<toolchain file in NDK> | |
-| -android-ndk-platform android-23 | -DANDROID_PLATFORM=android-23 | |
+| -android-ndk-platform android-28 | -DANDROID_PLATFORM=android-28 | |
| -android-abis <abi_1>,...,<abi_n> | -DANDROID_ABI=<abi_1> | only one ABI can be specified |
| -android-style-assets | -DFEATURE_android_style_assets=ON | |
| -android-javac-source | -DQT_ANDROID_JAVAC_SOURCE=7 | Set the javac build source version. |
| -android-javac-target | -DQT_ANDROID_JAVAC_TARGET=7 | Set the javac build target version. |
| -skip <repo>,...,<repo_n> | -DBUILD_<repo>=OFF | |
-| -submodules <repo>,...,<repo_n> | -DQT_BUILD_SUBMODULES=<repo>;...;<repo> | |
+| -skip-tests <repo>,...,<repo_n> | -DQT_BUILD_TESTS_PROJECT_<repo>=OFF | |
+| -skip-examples <repo>,...,<repo_n> | -DQT_BUILD_EXAMPLES_PROJECT_<repo>=OFF | |
+| -submodules <repo>,...,<repo_n> | -DQT_BUILD_SUBMODULES=<repo>;...;<repo> | |
| -make <part> | -DQT_BUILD_TESTS=ON | A way to turn on tools explicitly is missing. If tests/examples |
| | -DQT_BUILD_EXAMPLES=ON | are enabled, you can disable their building as part of the |
| | | 'all' target by also passing -DQT_BUILD_TESTS_BY_DEFAULT=OFF or |
@@ -111,6 +107,7 @@ The following table describes the mapping of configure options to CMake argument
| | | build them separately, after configuration. |
| -nomake <part> | -DQT_BUILD_TESTS=OFF | A way to turn off tools explicitly is missing. |
| | -DQT_BUILD_EXAMPLES=OFF | |
+| -install-examples-sources | -DQT_INSTALL_EXAMPLES_SOURCES=ON | |
| -no-gui | -DFEATURE_gui=OFF | |
| -no-widgets | -DFEATURE_widgets=OFF | |
| -no-dbus | -DFEATURE_dbus=OFF | |
@@ -121,7 +118,6 @@ The following table describes the mapping of configure options to CMake argument
| -doubleconversion | -DFEATURE_doubleconversion=ON | |
| | -DFEATURE_system_doubleconversion=ON/OFF | |
| -glib | -DFEATURE_glib=ON | |
-| -eventfd | -DFEATURE_eventfd=ON | |
| -inotify | -DFEATURE_inotify=ON | |
| -icu | -DFEATURE_icu=ON | |
| -pcre | -DFEATURE_pcre2=ON | |
@@ -149,7 +145,8 @@ The following table describes the mapping of configure options to CMake argument
| -opengl <api> | -DINPUT_opengl=<api> | |
| -opengles3 | -DFEATURE_opengles3=ON | |
| -egl | -DFEATURE_egl=ON | |
-| -qpa <name> | -DQT_QPA_DEFAULT_PLATFORM=<name> | |
+| -qpa <name>;...;<name_n> | -DQT_QPA_PLATFORMS=<name>;...;<name_n> | |
+| -default-qpa <name> | -DQT_QPA_DEFAULT_PLATFORM=<name> | |
| -xcb-xlib | -DFEATURE_xcb_xlib=ON | |
| -direct2d | -DFEATURE_direct2d=ON | |
| -directfb | -DFEATURE_directfb=ON | |
@@ -168,8 +165,8 @@ The following table describes the mapping of configure options to CMake argument
| -xkbcommon | -DFEATURE_xkbcommon=ON | |
| -gif | -DFEATURE_gif=ON | |
| -ico | -DFEATURE_ico=ON | |
-| -libpng | -DFEATURE_libpng=ON | |
-| -libjpeg | -DFEATURE_libjpeg=ON | |
+| -libpng | -DFEATURE_png=ON | |
+| -libjpeg | -DFEATURE_jpeg=ON | |
| -sql-<driver> | -DFEATURE_sql_<driver>=ON | |
| -sqlite [qt/system] | -DFEATURE_system_sqlite=OFF/ON | |
| -disable-deprecated-up-to <hex_version> | -DQT_DISABLE_DEPRECATED_UP_TO=<hex_version> | |
diff --git a/cmake/ios/LaunchScreen.storyboard b/cmake/ios/LaunchScreen.storyboard
index cfe5d26eba..83df24b618 100644
--- a/cmake/ios/LaunchScreen.storyboard
+++ b/cmake/ios/LaunchScreen.storyboard
@@ -14,29 +14,7 @@
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
- <subviews>
- <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="obG-Y5-kRd">
- <rect key="frame" x="0.0" y="626.5" width="375" height="20.5"/>
- <fontDescription key="fontDescription" type="system" pointSize="17"/>
- <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
- <nil key="highlightedColor"/>
- </label>
- <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="@QT_IOS_LAUNCH_SCREEN_TEXT@" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="GJd-Yh-RWb">
- <rect key="frame" x="0.0" y="202" width="375" height="43"/>
- <fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
- <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
- <nil key="highlightedColor"/>
- </label>
- </subviews>
- <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
- <constraints>
- <constraint firstItem="Bcu-3y-fUS" firstAttribute="centerX" secondItem="obG-Y5-kRd" secondAttribute="centerX" id="5cz-MP-9tL"/>
- <constraint firstItem="Bcu-3y-fUS" firstAttribute="centerX" secondItem="GJd-Yh-RWb" secondAttribute="centerX" id="Q3B-4B-g5h"/>
- <constraint firstItem="obG-Y5-kRd" firstAttribute="leading" secondItem="Bcu-3y-fUS" secondAttribute="leading" constant="20" symbolic="YES" id="SfN-ll-jLj"/>
- <constraint firstAttribute="bottom" secondItem="obG-Y5-kRd" secondAttribute="bottom" constant="20" id="Y44-ml-fuU"/>
- <constraint firstItem="GJd-Yh-RWb" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="bottom" multiplier="1/3" constant="1" id="moa-c2-u7t"/>
- <constraint firstItem="GJd-Yh-RWb" firstAttribute="leading" secondItem="Bcu-3y-fUS" secondAttribute="leading" constant="20" symbolic="YES" id="x7j-FC-K8j"/>
- </constraints>
+ <color key="backgroundColor" systemColor="systemBackgroundColor"/>
<viewLayoutGuide key="safeArea" id="Bcu-3y-fUS"/>
</view>
</viewController>
@@ -45,4 +23,9 @@
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
+ <resources>
+ <systemColor name="systemBackgroundColor">
+ <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+ </systemColor>
+ </resources>
</document>
diff --git a/cmake/ios/PrivacyInfo.xcprivacy b/cmake/ios/PrivacyInfo.xcprivacy
new file mode 100644
index 0000000000..d75908da05
--- /dev/null
+++ b/cmake/ios/PrivacyInfo.xcprivacy
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>NSPrivacyTracking</key>
+ <false/>
+ <key>NSPrivacyCollectedDataTypes</key>
+ <array/>
+ <key>NSPrivacyTrackingDomains</key>
+ <array/>
+ <key>NSPrivacyAccessedAPITypes</key>
+ <array/>
+</dict>
+</plist>
diff --git a/cmake/macos/MacOSXBundleInfo.plist.in b/cmake/macos/Info.plist.app.in
index c791521655..c791521655 100644
--- a/cmake/macos/MacOSXBundleInfo.plist.in
+++ b/cmake/macos/Info.plist.app.in
diff --git a/cmake/macos/PrivacyInfo.xcprivacy b/cmake/macos/PrivacyInfo.xcprivacy
new file mode 100644
index 0000000000..96aff954ea
--- /dev/null
+++ b/cmake/macos/PrivacyInfo.xcprivacy
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>NSPrivacyTracking</key>
+ <false/>
+ <key>NSPrivacyCollectedDataTypes</key>
+ <array/>
+ <key>NSPrivacyTrackingDomains</key>
+ <array/>
+</dict>
+</plist>
diff --git a/cmake/modulecppexports.h.in b/cmake/modulecppexports.h.in
index a7a349084e..4d41a3a2a2 100644
--- a/cmake/modulecppexports.h.in
+++ b/cmake/modulecppexports.h.in
@@ -1,11 +1,13 @@
// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
-#include <QtCore/qglobal.h>
-
#ifndef @header_base_name_upper@_H
#define @header_base_name_upper@_H
+#include <QtCore/qcompilerdetection.h>
+#include <QtCore/qtconfigmacros.h> // Q_@module_define_infix@_EXPORT
+#include <QtCore/qtdeprecationmarkers.h> // QT_IF_DEPRECATED_SINCE
+
#if defined(QT_SHARED) || !defined(QT_STATIC)
# if defined(QT_BUILD_@module_define_infix@_LIB)
# define Q_@module_define_infix@_EXPORT Q_DECL_EXPORT
@@ -17,22 +19,22 @@
#endif
#if !defined(QT_BUILD_@module_define_infix@_LIB) && !defined(QT_STATIC)
-/* outside library → inline decl + defi */
+/* outside library -> inline decl + defi */
/* static builds treat everything as part of the library, so they never inline */
# define QT_@module_define_infix@_INLINE_SINCE(major, minor) inline
# define QT_@module_define_infix@_INLINE_IMPL_SINCE(major, minor) 1
#elif defined(QT_@module_define_infix@_BUILD_REMOVED_API)
/* inside library, inside removed_api.cpp:
- * keep deprecated API → non-inline decl;
- * remove deprecated API → inline decl;
+ * keep deprecated API -> non-inline decl;
+ * remove deprecated API -> inline decl;
* definition is always available */
# define QT_@module_define_infix@_INLINE_SINCE(major, minor) \
QT_IF_DEPRECATED_SINCE(major, minor, inline, /* not inline */)
# define QT_@module_define_infix@_INLINE_IMPL_SINCE(major, minor) 1
#else
/* inside library, outside removed_api.cpp:
- * keep deprecated API → non-inline decl, no defi;
- * remove deprecated API → inline decl, defi */
+ * keep deprecated API -> non-inline decl, no defi;
+ * remove deprecated API -> inline decl, defi */
# define QT_@module_define_infix@_INLINE_SINCE(major, minor) \
QT_IF_DEPRECATED_SINCE(major, minor, inline, /* not inline */)
# define QT_@module_define_infix@_INLINE_IMPL_SINCE(major, minor) \
diff --git a/cmake/modulecppexports_p.h.in b/cmake/modulecppexports_p.h.in
deleted file mode 100644
index 5f873e3c70..0000000000
--- a/cmake/modulecppexports_p.h.in
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright (C) 2021 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
-
-#ifndef @header_base_name_upper@_P_H
-#define @header_base_name_upper@_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <@module_include_name@/@header_base_name@.h>
-
-#define Q_@module_define_infix@_PRIVATE_EXPORT Q_@module_define_infix@_EXPORT
-
-#endif // @header_base_name_upper@_P_H
diff --git a/cmake/qbatchedtestrunner.in.cpp b/cmake/qbatchedtestrunner.in.cpp
index fb49cbbb98..cc49b77e0a 100644
--- a/cmake/qbatchedtestrunner.in.cpp
+++ b/cmake/qbatchedtestrunner.in.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2022 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QList>
#include <QString>
diff --git a/cmake/tests/main.cpp b/cmake/tests/main.cpp
index a9b8738990..2cd8b7a103 100644
--- a/cmake/tests/main.cpp
+++ b/cmake/tests/main.cpp
@@ -1 +1,3 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: BSD-3-Clause
int main(int argc, char** argv) { return 0; }
diff --git a/cmake/visionos/Info.plist.app.in b/cmake/visionos/Info.plist.app.in
new file mode 100644
index 0000000000..984b7aa10b
--- /dev/null
+++ b/cmake/visionos/Info.plist.app.in
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+
+ <key>CFBundleName</key>
+ <string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
+
+ <key>CFBundleDisplayName</key>
+ <string>${QT_INTERNAL_DOLLAR_VAR}{PRODUCT_NAME}</string>
+
+ <key>CFBundleIdentifier</key>
+ <string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
+
+ <key>CFBundleExecutable</key>
+ <string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
+
+ <key>CFBundleVersion</key>
+ <string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
+
+ <key>CFBundleShortVersionString</key>
+ <string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
+
+ <key>CFBundleIconFile</key>
+ <string>${MACOSX_BUNDLE_ICON_FILE}</string>
+
+ <key>CFBundleDevelopmentRegion</key>
+ <string>$(DEVELOPMENT_LANGUAGE)</string>
+ <key>CFBundleAllowMixedLocalizations</key>
+ <true/>
+
+ <key>CFBundleSupportedPlatforms</key>
+ <array>
+ <string>XROS</string>
+ </array>
+
+ <key>UIApplicationSceneManifest</key>
+ <dict>
+ <key>UIApplicationSupportsMultipleScenes</key>
+ <true/>
+ <key>UISceneConfigurations</key>
+ <dict/>
+ </dict>
+</dict>
+</plist>
diff --git a/cmake/visionos/PrivacyInfo.xcprivacy b/cmake/visionos/PrivacyInfo.xcprivacy
new file mode 100644
index 0000000000..d75908da05
--- /dev/null
+++ b/cmake/visionos/PrivacyInfo.xcprivacy
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>NSPrivacyTracking</key>
+ <false/>
+ <key>NSPrivacyCollectedDataTypes</key>
+ <array/>
+ <key>NSPrivacyTrackingDomains</key>
+ <array/>
+ <key>NSPrivacyAccessedAPITypes</key>
+ <array/>
+</dict>
+</plist>