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/FindWaylandScanner.cmake3
-rw-r--r--cmake/3rdparty/extra-cmake-modules/find-modules/FindXCB.cmake14
-rw-r--r--cmake/3rdparty/extra-cmake-modules/modules/ECMEnableSanitizers.cmake10
-rw-r--r--cmake/3rdparty/extra-cmake-modules/modules/ECMFindModuleHelpers.cmake2
-rw-r--r--cmake/3rdparty/extra-cmake-modules/qt_attribution.json2
-rw-r--r--cmake/3rdparty/kwin/qt_attribution.json2
-rw-r--r--cmake/CODESTYLE.md197
-rw-r--r--cmake/FindATSPI2.cmake4
-rw-r--r--cmake/FindDB2.cmake2
-rw-r--r--cmake/FindDirectFB.cmake4
-rw-r--r--cmake/FindGLESv2.cmake2
-rw-r--r--cmake/FindGSSAPI.cmake27
-rw-r--r--cmake/FindGTK3.cmake4
-rw-r--r--cmake/FindInterbase.cmake3
-rw-r--r--cmake/FindLibb2.cmake4
-rw-r--r--cmake/FindLibproxy.cmake4
-rw-r--r--cmake/FindLibsystemd.cmake4
-rw-r--r--cmake/FindLibudev.cmake4
-rw-r--r--cmake/FindMimer.cmake98
-rw-r--r--cmake/FindMtdev.cmake4
-rw-r--r--cmake/FindMySQL.cmake56
-rw-r--r--cmake/FindOracle.cmake2
-rw-r--r--cmake/FindPPS.cmake10
-rw-r--r--cmake/FindPostgreSQL.cmake5
-rw-r--r--cmake/FindRenderDoc.cmake20
-rw-r--r--cmake/FindSlog2.cmake2
-rw-r--r--cmake/FindTslib.cmake4
-rw-r--r--cmake/FindWrapAtomic.cmake2
-rw-r--r--cmake/FindWrapBacktrace.cmake2
-rw-r--r--cmake/FindWrapBrotli.cmake8
-rw-r--r--cmake/FindWrapDBus1.cmake2
-rw-r--r--cmake/FindWrapFreetype.cmake2
-rw-r--r--cmake/FindWrapHarfbuzz.cmake2
-rw-r--r--cmake/FindWrapJpeg.cmake2
-rw-r--r--cmake/FindWrapOpenGL.cmake20
-rw-r--r--cmake/FindWrapOpenSSL.cmake2
-rw-r--r--cmake/FindWrapOpenSSLHeaders.cmake2
-rw-r--r--cmake/FindWrapPCRE2.cmake2
-rw-r--r--cmake/FindWrapPNG.cmake2
-rw-r--r--cmake/FindWrapResolv.cmake53
-rw-r--r--cmake/FindWrapRt.cmake26
-rw-r--r--cmake/FindWrapSystemDoubleConversion.cmake2
-rw-r--r--cmake/FindWrapSystemFreetype.cmake2
-rw-r--r--cmake/FindWrapSystemHarfbuzz.cmake4
-rw-r--r--cmake/FindWrapSystemJpeg.cmake2
-rw-r--r--cmake/FindWrapSystemMd4c.cmake44
-rw-r--r--cmake/FindWrapSystemPCRE2.cmake10
-rw-r--r--cmake/FindWrapSystemPNG.cmake2
-rw-r--r--cmake/FindWrapSystemZLIB.cmake2
-rw-r--r--cmake/FindWrapVulkan.cmake2
-rw-r--r--cmake/FindWrapVulkanHeaders.cmake22
-rw-r--r--cmake/FindWrapZLIB.cmake2
-rw-r--r--cmake/FindWrapZSTD.cmake10
-rw-r--r--cmake/FindXKB_COMMON_X11.cmake4
-rw-r--r--cmake/FindXRender.cmake4
-rw-r--r--cmake/ModuleDescription.json.in10
-rw-r--r--cmake/Qt3rdPartyLibraryConfig.cmake.in9
-rw-r--r--cmake/Qt3rdPartyLibraryHelpers.cmake36
-rw-r--r--cmake/QtAndroidHelpers.cmake200
-rw-r--r--cmake/QtAppHelpers.cmake37
-rw-r--r--cmake/QtAutoDetect.cmake542
-rw-r--r--cmake/QtAutoDetectHelpers.cmake487
-rw-r--r--cmake/QtAutogenHelpers.cmake53
-rw-r--r--cmake/QtBaseCMakeTesting.cmake2
-rw-r--r--cmake/QtBaseConfigureTests.cmake76
-rw-r--r--cmake/QtBaseGlobalTargets.cmake223
-rw-r--r--cmake/QtBaseHelpers.cmake222
-rw-r--r--cmake/QtBaseTopLevelHelpers.cmake96
-rw-r--r--cmake/QtBuild.cmake576
-rw-r--r--cmake/QtBuildHelpers.cmake458
-rw-r--r--cmake/QtBuildInformation.cmake105
-rw-r--r--cmake/QtBuildInternals/QtBuildInternalsConfig.cmake1317
-rw-r--r--cmake/QtBuildInternals/QtStandaloneTestTemplateProject/CMakeLists.txt28
-rw-r--r--cmake/QtBuildInternals/QtStandaloneTestTemplateProject/Main.cmake12
-rw-r--r--cmake/QtBuildInternalsExtra.cmake.in53
-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.cmake55
-rw-r--r--cmake/QtCMakePackageVersionFile.cmake.in5
-rw-r--r--cmake/QtCMakeVersionHelpers.cmake21
-rw-r--r--cmake/QtCompilerFlags.cmake17
-rw-r--r--cmake/QtCompilerOptimization.cmake80
-rw-r--r--cmake/QtConfig.cmake.in113
-rw-r--r--cmake/QtConfigDependencies.cmake.in3
-rw-r--r--cmake/QtConfigExtras.cmake.in5
-rw-r--r--cmake/QtConfigureTimeExecutableCMakeLists.txt.in26
-rw-r--r--cmake/QtCopyFileIfDifferent.cmake2
-rw-r--r--cmake/QtDbusHelpers.cmake10
-rw-r--r--cmake/QtDeferredDependenciesHelpers.cmake2
-rw-r--r--cmake/QtDocsHelpers.cmake45
-rw-r--r--cmake/QtExecutableHelpers.cmake271
-rw-r--r--cmake/QtFeature.cmake327
-rw-r--r--cmake/QtFeatureCommon.cmake2
-rw-r--r--cmake/QtFindPackageHelpers.cmake91
-rw-r--r--cmake/QtFindWrapConfigExtra.cmake.in3
-rw-r--r--cmake/QtFindWrapHelper.cmake2
-rw-r--r--cmake/QtFinishPkgConfigFile.cmake2
-rw-r--r--cmake/QtFinishPrlFile.cmake2
-rw-r--r--cmake/QtFlagHandlingHelpers.cmake326
-rw-r--r--cmake/QtFrameworkHelpers.cmake109
-rw-r--r--cmake/QtGenerateExtPri.cmake2
-rw-r--r--cmake/QtGenerateLibHelpers.cmake2
-rw-r--r--cmake/QtGenerateLibPri.cmake2
-rw-r--r--cmake/QtGlobalStateHelpers.cmake2
-rw-r--r--cmake/QtHeadersClean.cmake234
-rw-r--r--cmake/QtHostInfoConfig.cmake.in3
-rw-r--r--cmake/QtInitProject.cmake214
-rw-r--r--cmake/QtInstallHelpers.cmake121
-rw-r--r--cmake/QtInstallPaths.cmake.in16
-rw-r--r--cmake/QtInternalTargets.cmake134
-rw-r--r--cmake/QtJavaHelpers.cmake13
-rw-r--r--cmake/QtLalrHelpers.cmake11
-rw-r--r--cmake/QtMkspecHelpers.cmake146
-rw-r--r--cmake/QtModuleConfig.cmake.in38
-rw-r--r--cmake/QtModuleDependencies.cmake.in5
-rw-r--r--cmake/QtModuleHeadersCheck.cmake34
-rw-r--r--cmake/QtModuleHelpers.cmake713
-rw-r--r--cmake/QtModuleToolsConfig.cmake.in19
-rw-r--r--cmake/QtModuleToolsDependencies.cmake.in3
-rw-r--r--cmake/QtModuleToolsVersionlessTargets.cmake.in3
-rw-r--r--cmake/QtNoLinkTargetHelpers.cmake2
-rw-r--r--cmake/QtPkgConfigHelpers.cmake16
-rw-r--r--cmake/QtPlatformAndroid.cmake17
-rw-r--r--cmake/QtPlatformSupport.cmake7
-rw-r--r--cmake/QtPlatformTargetHelpers.cmake11
-rw-r--r--cmake/QtPluginConfig.cmake.in5
-rw-r--r--cmake/QtPluginDependencies.cmake.in3
-rw-r--r--cmake/QtPluginHelpers.cmake134
-rw-r--r--cmake/QtPlugins.cmake.in8
-rw-r--r--cmake/QtPostProcess.cmake4
-rw-r--r--cmake/QtPostProcessHelpers.cmake102
-rw-r--r--cmake/QtPrecompiledHeadersHelpers.cmake6
-rw-r--r--cmake/QtPriHelpers.cmake58
-rw-r--r--cmake/QtPrlHelpers.cmake3
-rw-r--r--cmake/QtProcessConfigureArgs.cmake202
-rw-r--r--cmake/QtProperties.cmake2
-rw-r--r--cmake/QtPublicAppleHelpers.cmake954
-rw-r--r--cmake/QtPublicCMakeHelpers.cmake481
-rw-r--r--cmake/QtPublicCMakeVersionHelpers.cmake2
-rw-r--r--cmake/QtPublicDependencyHelpers.cmake6
-rw-r--r--cmake/QtPublicExternalProjectHelpers.cmake86
-rw-r--r--cmake/QtPublicFinalizerHelpers.cmake2
-rw-r--r--cmake/QtPublicFindPackageHelpers.cmake2
-rw-r--r--cmake/QtPublicPluginHelpers.cmake93
-rw-r--r--cmake/QtPublicTargetHelpers.cmake28
-rw-r--r--cmake/QtPublicTestHelpers.cmake10
-rw-r--r--cmake/QtPublicToolHelpers.cmake72
-rw-r--r--cmake/QtPublicWalkLibsHelpers.cmake27
-rw-r--r--cmake/QtPublicWasmToolchainHelpers.cmake40
-rw-r--r--cmake/QtQmakeHelpers.cmake42
-rw-r--r--cmake/QtResourceHelpers.cmake20
-rw-r--r--cmake/QtRpathHelpers.cmake56
-rw-r--r--cmake/QtSanitizerHelpers.cmake34
-rw-r--r--cmake/QtScopeFinalizerHelpers.cmake2
-rw-r--r--cmake/QtSeparateDebugInfo.Info.plist.in5
-rw-r--r--cmake/QtSeparateDebugInfo.cmake22
-rw-r--r--cmake/QtSetup.cmake328
-rw-r--r--cmake/QtSimdHelpers.cmake14
-rw-r--r--cmake/QtSingleRepoTargetSetBuildHelpers.cmake2
-rw-r--r--cmake/QtStandaloneTestsConfig.cmake.in5
-rw-r--r--cmake/QtSyncQtHelpers.cmake470
-rw-r--r--cmake/QtTargetHelpers.cmake845
-rw-r--r--cmake/QtTestHelpers.cmake730
-rw-r--r--cmake/QtToolHelpers.cmake488
-rw-r--r--cmake/QtToolchainHelpers.cmake70
-rw-r--r--cmake/QtUnityBuildHelpers.cmake24
-rw-r--r--cmake/QtVersionlessAliasTargets.cmake.in7
-rw-r--r--cmake/QtVersionlessTargets.cmake.in7
-rw-r--r--cmake/QtWasmHelpers.cmake74
-rw-r--r--cmake/QtWrapperScriptHelpers.cmake199
-rw-r--r--cmake/QtWriteArgsFile.cmake61
-rw-r--r--cmake/README.md30
-rw-r--r--cmake/configure-cmake-mapping.md33
-rw-r--r--cmake/ios/Info.plist.app.in71
-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)4
-rw-r--r--cmake/macos/PrivacyInfo.xcprivacy12
-rw-r--r--cmake/modulecppexports.h.in17
-rw-r--r--cmake/modulecppexports_p.h.in22
-rw-r--r--cmake/platforms/FindIntegrityPlatformGraphics.cmake2
-rw-r--r--cmake/platforms/Platform/Integrity.cmake2
-rw-r--r--cmake/qbatchedtestrunner.in.cpp18
-rw-r--r--cmake/tests/CMakeLists.txt2
-rw-r--r--cmake/tests/features/CMakeLists.txt2
-rw-r--r--cmake/tests/features/configure.cmake2
-rw-r--r--cmake/tests/features/src/CMakeLists.txt2
-rw-r--r--cmake/tests/qt_make_output_file/CMakeLists.txt2
-rw-r--r--cmake/tests/test.cmake2
-rw-r--r--cmake/visionos/Info.plist.app.in42
-rw-r--r--cmake/visionos/PrivacyInfo.xcprivacy14
194 files changed, 12149 insertions, 4933 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/FindWaylandScanner.cmake b/cmake/3rdparty/extra-cmake-modules/find-modules/FindWaylandScanner.cmake
index 13291afcda..60adaf4184 100644
--- a/cmake/3rdparty/extra-cmake-modules/find-modules/FindWaylandScanner.cmake
+++ b/cmake/3rdparty/extra-cmake-modules/find-modules/FindWaylandScanner.cmake
@@ -107,9 +107,6 @@ set_package_properties(WaylandScanner PROPERTIES
DESCRIPTION "Executable that converts XML protocol files to C code"
)
-
-include(CMakeParseArguments)
-
function(ecm_add_wayland_client_protocol out_var)
# Parse arguments
set(oneValueArgs PROTOCOL BASENAME)
diff --git a/cmake/3rdparty/extra-cmake-modules/find-modules/FindXCB.cmake b/cmake/3rdparty/extra-cmake-modules/find-modules/FindXCB.cmake
index d530d2d7f4..26b9bf8963 100644
--- a/cmake/3rdparty/extra-cmake-modules/find-modules/FindXCB.cmake
+++ b/cmake/3rdparty/extra-cmake-modules/find-modules/FindXCB.cmake
@@ -129,10 +129,6 @@ set(XCB_known_components
XVMC
)
-# XINPUT is unstable; do not include it by default
-set(XCB_default_components ${XCB_known_components})
-list(REMOVE_ITEM XCB_default_components "XINPUT")
-
# default component info: xcb components have fairly predictable
# header files, library names and pkg-config names
foreach(_comp ${XCB_known_components})
@@ -141,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)
@@ -175,11 +174,6 @@ ecm_find_package_parse_components(XCB
DEFAULT_COMPONENTS ${XCB_default_components}
)
-list(FIND XCB_components "XINPUT" _XCB_XINPUT_index)
-if (NOT _XCB_XINPUT_index EQUAL -1)
- message(AUTHOR_WARNING "XINPUT from XCB was requested: this is EXPERIMENTAL and is likely to unavailable on many systems!")
-endif()
-
ecm_find_package_handle_library_components(XCB
COMPONENTS ${XCB_components}
)
@@ -196,6 +190,6 @@ find_package_handle_standard_args(XCB
include(FeatureSummary)
set_package_properties(XCB PROPERTIES
- URL "http://xcb.freedesktop.org"
+ URL "https://xcb.freedesktop.org/"
DESCRIPTION "X protocol C-language Binding"
)
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/3rdparty/extra-cmake-modules/modules/ECMFindModuleHelpers.cmake b/cmake/3rdparty/extra-cmake-modules/modules/ECMFindModuleHelpers.cmake
index 841453998a..a5dabb1074 100644
--- a/cmake/3rdparty/extra-cmake-modules/modules/ECMFindModuleHelpers.cmake
+++ b/cmake/3rdparty/extra-cmake-modules/modules/ECMFindModuleHelpers.cmake
@@ -123,8 +123,6 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-include(CMakeParseArguments)
-
macro(ecm_find_package_version_check module_name)
if(CMAKE_VERSION VERSION_LESS 2.8.12)
message(FATAL_ERROR "CMake 2.8.12 is required by Find${module_name}.cmake")
diff --git a/cmake/3rdparty/extra-cmake-modules/qt_attribution.json b/cmake/3rdparty/extra-cmake-modules/qt_attribution.json
index 941fb9ea11..1839af3690 100644
--- a/cmake/3rdparty/extra-cmake-modules/qt_attribution.json
+++ b/cmake/3rdparty/extra-cmake-modules/qt_attribution.json
@@ -9,7 +9,7 @@
"Version": "5.84.0",
"License": "BSD-3-Clause",
- "LicenseId": "BSD 3-Clause License",
+ "LicenseId": "BSD-3-Clause",
"LicenseFile": "COPYING-CMAKE-SCRIPTS",
"Copyright": "Copyright © 2011-2018 The KDE community"
}
diff --git a/cmake/3rdparty/kwin/qt_attribution.json b/cmake/3rdparty/kwin/qt_attribution.json
index 5c22641132..fef6bbe4c3 100644
--- a/cmake/3rdparty/kwin/qt_attribution.json
+++ b/cmake/3rdparty/kwin/qt_attribution.json
@@ -9,7 +9,7 @@
"Version": "5.13.4",
"License": "BSD-3-Clause",
- "LicenseId": "BSD 3-Clause License",
+ "LicenseId": "BSD-3-Clause",
"LicenseFile": "COPYING-CMAKE-SCRIPTS",
"Copyright": "Copyright 2014 Alex Merry <alex.merry@kde.org>
Copyright 2014 Martin Gräßlin <mgraesslin@kde.org>,
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/FindATSPI2.cmake b/cmake/FindATSPI2.cmake
index edc6277693..80176db579 100644
--- a/cmake/FindATSPI2.cmake
+++ b/cmake/FindATSPI2.cmake
@@ -1,9 +1,9 @@
# 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: BSD-3-Clause
find_package(PkgConfig QUIET)
-pkg_check_modules(ATSPI2 atspi-2 IMPORTED_TARGET)
+pkg_check_modules(ATSPI2 IMPORTED_TARGET "atspi-2")
if (NOT TARGET PkgConfig::ATSPI2)
set(ATSPI2_FOUND 0)
diff --git a/cmake/FindDB2.cmake b/cmake/FindDB2.cmake
index f67f8479db..31f7bbcae9 100644
--- a/cmake/FindDB2.cmake
+++ b/cmake/FindDB2.cmake
@@ -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: BSD-3-Clause
#.rst:
# FindDB2
diff --git a/cmake/FindDirectFB.cmake b/cmake/FindDirectFB.cmake
index ea2c53aa25..8c5711f178 100644
--- a/cmake/FindDirectFB.cmake
+++ b/cmake/FindDirectFB.cmake
@@ -1,9 +1,9 @@
# 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: BSD-3-Clause
find_package(PkgConfig QUIET)
-pkg_check_modules(DirectFB directfb IMPORTED_TARGET)
+pkg_check_modules(DirectFB IMPORTED_TARGET "directfb")
if (NOT TARGET PkgConfig::DirectFB)
set(DirectFB_FOUND 0)
diff --git a/cmake/FindGLESv2.cmake b/cmake/FindGLESv2.cmake
index 9a9d079180..4730418209 100644
--- a/cmake/FindGLESv2.cmake
+++ b/cmake/FindGLESv2.cmake
@@ -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: BSD-3-Clause
include(CheckCXXSourceCompiles)
diff --git a/cmake/FindGSSAPI.cmake b/cmake/FindGSSAPI.cmake
index 8b7cf7d2ee..44594941e3 100644
--- a/cmake/FindGSSAPI.cmake
+++ b/cmake/FindGSSAPI.cmake
@@ -1,10 +1,10 @@
# 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: BSD-3-Clause
find_package(PkgConfig QUIET)
-pkg_check_modules(PC_GSSAPI QUIET krb5-gssapi)
+pkg_check_modules(PC_GSSAPI QUIET "krb5-gssapi")
if (NOT PC_GSSAPI_FOUND)
- pkg_check_modules(PC_GSSAPI QUIET mit-krb5-gssapi)
+ pkg_check_modules(PC_GSSAPI QUIET "mit-krb5-gssapi")
endif()
find_path(GSSAPI_INCLUDE_DIRS
@@ -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/FindGTK3.cmake b/cmake/FindGTK3.cmake
index e7ac17d258..221d5a34d1 100644
--- a/cmake/FindGTK3.cmake
+++ b/cmake/FindGTK3.cmake
@@ -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: BSD-3-Clause
find_package(PkgConfig QUIET)
@@ -7,7 +7,7 @@ set(__gtk3_required_version "${${CMAKE_FIND_PACKAGE_NAME}_FIND_VERSION}")
if(__gtk3_required_version)
set(__gtk3_required_version " >= ${__gtk3_required_version}")
endif()
-pkg_check_modules(GTK3 "gtk+-3.0${__gtk3_required_version}" IMPORTED_TARGET)
+pkg_check_modules(GTK3 IMPORTED_TARGET "gtk+-3.0${__gtk3_required_version}")
if (NOT TARGET PkgConfig::GTK3)
set(GTK3_FOUND 0)
diff --git a/cmake/FindInterbase.cmake b/cmake/FindInterbase.cmake
index 2cef1754c8..95b735e56a 100644
--- a/cmake/FindInterbase.cmake
+++ b/cmake/FindInterbase.cmake
@@ -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: BSD-3-Clause
#.rst:
# FindInterbase
@@ -24,6 +24,7 @@
find_path(Interbase_INCLUDE_DIR
NAMES ibase.h
HINTS ${Interbase_INCLUDEDIR}
+ PATH_SUFFIXES firebird
)
find_library(Interbase_LIBRARY
diff --git a/cmake/FindLibb2.cmake b/cmake/FindLibb2.cmake
index b8704d0da4..bf51c37aed 100644
--- a/cmake/FindLibb2.cmake
+++ b/cmake/FindLibb2.cmake
@@ -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: BSD-3-Clause
# Blake2 contains a reference implementation, libb2 is a more efficient
# implementation of a subset of Blake2 functions and should be preferred.
@@ -13,7 +13,7 @@ endif()
find_package(PkgConfig QUIET)
if(PkgConfig_FOUND)
- pkg_check_modules(Libb2 libb2 IMPORTED_TARGET)
+ pkg_check_modules(Libb2 IMPORTED_TARGET "libb2")
if (TARGET PkgConfig::Libb2)
add_library(Libb2::Libb2 INTERFACE IMPORTED)
diff --git a/cmake/FindLibproxy.cmake b/cmake/FindLibproxy.cmake
index d4edc9a192..4ee3943220 100644
--- a/cmake/FindLibproxy.cmake
+++ b/cmake/FindLibproxy.cmake
@@ -1,9 +1,9 @@
# 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: BSD-3-Clause
find_package(PkgConfig QUIET)
-pkg_check_modules(Libproxy libproxy-1.0 IMPORTED_TARGET)
+pkg_check_modules(Libproxy IMPORTED_TARGET "libproxy-1.0")
if (NOT TARGET PkgConfig::Libproxy)
set(Libproxy_FOUND 0)
diff --git a/cmake/FindLibsystemd.cmake b/cmake/FindLibsystemd.cmake
index 1a77c53f22..372a718027 100644
--- a/cmake/FindLibsystemd.cmake
+++ b/cmake/FindLibsystemd.cmake
@@ -1,9 +1,9 @@
# 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: BSD-3-Clause
find_package(PkgConfig QUIET)
-pkg_check_modules(Libsystemd libsystemd IMPORTED_TARGET)
+pkg_check_modules(Libsystemd IMPORTED_TARGET "libsystemd")
if (NOT TARGET PkgConfig::Libsystemd)
set(Libsystemd_FOUND 0)
diff --git a/cmake/FindLibudev.cmake b/cmake/FindLibudev.cmake
index df2827c921..57e34659d1 100644
--- a/cmake/FindLibudev.cmake
+++ b/cmake/FindLibudev.cmake
@@ -1,9 +1,9 @@
# 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: BSD-3-Clause
find_package(PkgConfig QUIET)
-pkg_check_modules(Libudev libudev IMPORTED_TARGET)
+pkg_check_modules(Libudev IMPORTED_TARGET "libudev")
if (NOT TARGET PkgConfig::Libudev)
set(Libudev_FOUND 0)
diff --git a/cmake/FindMimer.cmake b/cmake/FindMimer.cmake
new file mode 100644
index 0000000000..5cbc6e6907
--- /dev/null
+++ b/cmake/FindMimer.cmake
@@ -0,0 +1,98 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# Copyright (C) 2022 Mimer Information Technology
+# SPDX-License-Identifier: BSD-3-Clause
+
+# 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()
+
+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 ${MimerSQL_include_dir_hints})
+
+if(WIN32)
+ if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86|X86)$")
+ set(MIMER_LIBS_NAMES mimapi32)
+ elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(amd64|AMD64)$")
+ set(MIMER_LIBS_NAMES mimapi64)
+ endif()
+else()
+ set(MIMER_LIBS_NAMES mimerapi)
+endif()
+
+find_library(Mimer_LIBRARIES
+ NAMES ${MIMER_LIBS_NAMES}
+ HINTS ${MimerSQL_library_hints})
+
+include(FindPackageHandleStandardArgs)
+
+find_package_handle_standard_args(Mimer
+ REQUIRED_VARS Mimer_LIBRARIES Mimer_INCLUDE_DIR)
+
+
+
+# Now try to get the include and library path.
+if(Mimer_FOUND)
+ set(Mimer_INCLUDE_DIRS ${Mimer_INCLUDE_DIR})
+ set(Mimer_LIBRARY_DIRS ${Mimer_LIBRARIES})
+ if (NOT TARGET MimerSQL::MimerSQL)
+ add_library(MimerSQL::MimerSQL UNKNOWN IMPORTED)
+ set_target_properties(MimerSQL::MimerSQL PROPERTIES
+ IMPORTED_LOCATION "${Mimer_LIBRARY_DIRS}"
+ INTERFACE_INCLUDE_DIRECTORIES "${Mimer_INCLUDE_DIRS}")
+ endif ()
+endif()
+
+mark_as_advanced(Mimer_INCLUDE_DIR Mimer_LIBRARIES)
+
+include(FeatureSummary)
+set_package_properties(MimerSQL PROPERTIES
+ URL "https://www.mimer.com"
+ DESCRIPTION "Mimer client library")
diff --git a/cmake/FindMtdev.cmake b/cmake/FindMtdev.cmake
index 0a9c1ba27f..489a87f48b 100644
--- a/cmake/FindMtdev.cmake
+++ b/cmake/FindMtdev.cmake
@@ -1,9 +1,9 @@
# 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: BSD-3-Clause
find_package(PkgConfig QUIET)
-pkg_check_modules(Mtdev mtdev IMPORTED_TARGET)
+pkg_check_modules(Mtdev IMPORTED_TARGET "mtdev")
if (NOT TARGET PkgConfig::Mtdev)
set(Mtdev_FOUND 0)
diff --git a/cmake/FindMySQL.cmake b/cmake/FindMySQL.cmake
index 8b41d26a5a..d191d1ac0a 100644
--- a/cmake/FindMySQL.cmake
+++ b/cmake/FindMySQL.cmake
@@ -1,12 +1,30 @@
# 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: BSD-3-Clause
#.rst:
# FindMySQL
# ---------
#
# Try to locate the mysql client library.
-# If found, this will define the following variables:
+#
+# By default, pkg-config is used, if available.
+# If pkg-config is not available or if you want to disable it, set the ``MySQL_ROOT`` variable.
+# The following variables can be set to control the behavior of this find module.
+#
+# ``MySQL_ROOT``
+# The root directory of the mysql client library's installation.
+# ``MySQL_INCLUDE_DIR``
+# The directory containing the include files of the mysql client library.
+# If not set, the directory is detected within ``MySQL_ROOT`` using find_path.
+# ``MySQL_LIBRARY_DIR``
+# The directory containing the binaries of the mysql client library.
+# This is used to detect ``MySQL_LIBRARY`` and passed as HINT to find_library.
+# ``MySQL_LIBRARY``
+# The file path to the mysql client library.
+# ``MySQL_LIBRARY_DEBUG``
+# The file path to the mysql client library for the DEBUG configuration.
+#
+# If the mysql client library is found, this will define the following variables:
#
# ``MySQL_FOUND``
# True if the mysql library is available
@@ -21,17 +39,39 @@
# ``MySQL::MySQL``
# The mysql client library
-find_package(PkgConfig QUIET)
-pkg_check_modules(PC_MySQL QUIET mysqlclient)
+if(NOT DEFINED MySQL_ROOT)
+ find_package(PkgConfig QUIET)
+endif()
+if(PkgConfig_FOUND AND NOT DEFINED MySQL_ROOT)
+ pkg_check_modules(PC_MySQL QUIET "mysqlclient")
+ set(MySQL_include_dir_hints ${PC_MySQL_INCLUDEDIR})
+ set(MySQL_library_hints ${PC_MySQL_LIBDIR})
+ set(MySQL_library_hints_debug "")
+else()
+ set(MySQL_include_dir_hints "")
+ if(NOT DEFINED MySQL_LIBRARY_DIR)
+ set(MySQL_LIBRARY_DIR "${MySQL_ROOT}/lib")
+ endif()
+ set(MySQL_library_hints "${MySQL_LIBRARY_DIR}")
+ set(MySQL_library_hints_debug "${MySQL_LIBRARY_DIR}/debug")
+endif()
find_path(MySQL_INCLUDE_DIR
NAMES mysql.h
- HINTS ${PC_MySQL_INCLUDEDIR}
+ HINTS "${MySQL_include_dir_hints}"
PATH_SUFFIXES mysql mariadb)
find_library(MySQL_LIBRARY
+ NO_PACKAGE_ROOT_PATH
NAMES libmysql mysql mysqlclient libmariadb mariadb
- HINTS ${PC_MySQL_LIBDIR})
+ HINTS ${MySQL_library_hints})
+
+if(MySQL_library_hints_debug)
+ find_library(MySQL_LIBRARY_DEBUG
+ NO_PACKAGE_ROOT_PATH
+ NAMES libmysql mysql mysqlclient libmariadb mariadb
+ HINTS ${MySQL_library_hints_debug})
+endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(MySQL DEFAULT_MSG MySQL_LIBRARY MySQL_INCLUDE_DIR)
@@ -44,6 +84,10 @@ if(MySQL_FOUND)
set_target_properties(MySQL::MySQL PROPERTIES
IMPORTED_LOCATION "${MySQL_LIBRARIES}"
INTERFACE_INCLUDE_DIRECTORIES "${MySQL_INCLUDE_DIRS}")
+ if(MySQL_LIBRARY_DEBUG)
+ set_target_properties(MySQL::MySQL PROPERTIES
+ IMPORTED_LOCATION_DEBUG "${MySQL_LIBRARY_DEBUG}")
+ endif()
endif()
endif()
diff --git a/cmake/FindOracle.cmake b/cmake/FindOracle.cmake
index 1a19c015c1..e05bdd749e 100644
--- a/cmake/FindOracle.cmake
+++ b/cmake/FindOracle.cmake
@@ -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: BSD-3-Clause
#.rst:
# FindOracle
diff --git a/cmake/FindPPS.cmake b/cmake/FindPPS.cmake
index 334f577151..099019243c 100644
--- a/cmake/FindPPS.cmake
+++ b/cmake/FindPPS.cmake
@@ -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: BSD-3-Clause
# Find the PPS library
@@ -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 63dcebf812..a61bec9337 100644
--- a/cmake/FindPostgreSQL.cmake
+++ b/cmake/FindPostgreSQL.cmake
@@ -1,6 +1,6 @@
# Copyright (C) 2000-2022 Kitware, Inc. and Contributors.
# Copyright (C) 2022 The Qt Company Ltd.
-# SPDX-License-Identifier: (LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0) AND BSD-3-Clause
+# SPDX-License-Identifier: BSD-3-Clause
#[=======================================================================[.rst:
FindPostgreSQL
@@ -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/FindSlog2.cmake b/cmake/FindSlog2.cmake
index c24eafe260..18c10773f9 100644
--- a/cmake/FindSlog2.cmake
+++ b/cmake/FindSlog2.cmake
@@ -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: BSD-3-Clause
# Find the Slog2 library
diff --git a/cmake/FindTslib.cmake b/cmake/FindTslib.cmake
index e150023262..f5243dfa7f 100644
--- a/cmake/FindTslib.cmake
+++ b/cmake/FindTslib.cmake
@@ -1,9 +1,9 @@
# 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: BSD-3-Clause
find_package(PkgConfig QUIET)
-pkg_check_modules(Tslib tslib IMPORTED_TARGET)
+pkg_check_modules(Tslib IMPORTED_TARGET "tslib")
if (NOT TARGET PkgConfig::Tslib)
set(Tslib_FOUND 0)
diff --git a/cmake/FindWrapAtomic.cmake b/cmake/FindWrapAtomic.cmake
index b1f9db2368..04768e6490 100644
--- a/cmake/FindWrapAtomic.cmake
+++ b/cmake/FindWrapAtomic.cmake
@@ -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: 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.
diff --git a/cmake/FindWrapBacktrace.cmake b/cmake/FindWrapBacktrace.cmake
index d6048ae4fa..3cc5748dd1 100644
--- a/cmake/FindWrapBacktrace.cmake
+++ b/cmake/FindWrapBacktrace.cmake
@@ -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: BSD-3-Clause
if(TARGET WrapBacktrace::WrapBacktrace)
set(WrapBacktrace_FOUND ON)
diff --git a/cmake/FindWrapBrotli.cmake b/cmake/FindWrapBrotli.cmake
index 2f3c3f747a..e2d7b564f6 100644
--- a/cmake/FindWrapBrotli.cmake
+++ b/cmake/FindWrapBrotli.cmake
@@ -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: BSD-3-Clause
if(TARGET WrapBrotli::WrapBrotliDec)
set(WrapBrotli_FOUND ON)
@@ -22,21 +22,21 @@ if (unofficial-brotli_FOUND)
else()
find_package(PkgConfig QUIET)
if (PKG_CONFIG_FOUND)
- pkg_check_modules(libbrotlidec QUIET libbrotlidec IMPORTED_TARGET)
+ pkg_check_modules(libbrotlidec QUIET IMPORTED_TARGET "libbrotlidec")
if (libbrotlidec_FOUND)
add_library(WrapBrotli::WrapBrotliDec INTERFACE IMPORTED)
target_link_libraries(WrapBrotli::WrapBrotliDec INTERFACE PkgConfig::libbrotlidec)
set(WrapBrotli_FOUND ON)
endif()
- pkg_check_modules(libbrotlienc QUIET libbrotlienc IMPORTED_TARGET)
+ pkg_check_modules(libbrotlienc QUIET IMPORTED_TARGET "libbrotlienc")
if (libbrotlienc_FOUND)
add_library(WrapBrotli::WrapBrotliEnc INTERFACE IMPORTED)
target_link_libraries(WrapBrotli::WrapBrotliEnc INTERFACE PkgConfig::libbrotlienc)
set(WrapBrotli_FOUND ON)
endif()
- pkg_check_modules(libbrotlicommon QUIET libbrotlicommon IMPORTED_TARGET)
+ pkg_check_modules(libbrotlicommon QUIET IMPORTED_TARGET "libbrotlicommon")
if (libbrotlicommon_FOUND)
add_library(WrapBrotli::WrapBrotliCommon INTERFACE IMPORTED)
target_link_libraries(WrapBrotli::WrapBrotliCommon INTERFACE PkgConfig::libbrotlicommon)
diff --git a/cmake/FindWrapDBus1.cmake b/cmake/FindWrapDBus1.cmake
index 8b6952711e..e2a58790c4 100644
--- a/cmake/FindWrapDBus1.cmake
+++ b/cmake/FindWrapDBus1.cmake
@@ -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: BSD-3-Clause
# DBus1 is buggy and breaks PKG_CONFIG environment.
# Work around that:-/
diff --git a/cmake/FindWrapFreetype.cmake b/cmake/FindWrapFreetype.cmake
index 8584776a0a..22ae040f62 100644
--- a/cmake/FindWrapFreetype.cmake
+++ b/cmake/FindWrapFreetype.cmake
@@ -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: BSD-3-Clause
include(QtFindWrapHelper NO_POLICY_SCOPE)
diff --git a/cmake/FindWrapHarfbuzz.cmake b/cmake/FindWrapHarfbuzz.cmake
index c01b208c5c..60b0a97195 100644
--- a/cmake/FindWrapHarfbuzz.cmake
+++ b/cmake/FindWrapHarfbuzz.cmake
@@ -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: BSD-3-Clause
include(QtFindWrapHelper NO_POLICY_SCOPE)
diff --git a/cmake/FindWrapJpeg.cmake b/cmake/FindWrapJpeg.cmake
index 1bae65858c..5714c1dc34 100644
--- a/cmake/FindWrapJpeg.cmake
+++ b/cmake/FindWrapJpeg.cmake
@@ -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: BSD-3-Clause
include(QtFindWrapHelper NO_POLICY_SCOPE)
diff --git a/cmake/FindWrapOpenGL.cmake b/cmake/FindWrapOpenGL.cmake
index 538bb021a7..7295a159ca 100644
--- a/cmake/FindWrapOpenGL.cmake
+++ b/cmake/FindWrapOpenGL.cmake
@@ -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: 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.
@@ -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/FindWrapOpenSSL.cmake b/cmake/FindWrapOpenSSL.cmake
index 15ae1086e6..a4341271fe 100644
--- a/cmake/FindWrapOpenSSL.cmake
+++ b/cmake/FindWrapOpenSSL.cmake
@@ -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: 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.
diff --git a/cmake/FindWrapOpenSSLHeaders.cmake b/cmake/FindWrapOpenSSLHeaders.cmake
index dcc5eda798..510ae10854 100644
--- a/cmake/FindWrapOpenSSLHeaders.cmake
+++ b/cmake/FindWrapOpenSSLHeaders.cmake
@@ -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: 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.
diff --git a/cmake/FindWrapPCRE2.cmake b/cmake/FindWrapPCRE2.cmake
index cd9f08ecaa..024a9f084a 100644
--- a/cmake/FindWrapPCRE2.cmake
+++ b/cmake/FindWrapPCRE2.cmake
@@ -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: BSD-3-Clause
include(QtFindWrapHelper NO_POLICY_SCOPE)
diff --git a/cmake/FindWrapPNG.cmake b/cmake/FindWrapPNG.cmake
index 566427a76a..ba69628ac1 100644
--- a/cmake/FindWrapPNG.cmake
+++ b/cmake/FindWrapPNG.cmake
@@ -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: BSD-3-Clause
include(QtFindWrapHelper NO_POLICY_SCOPE)
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/FindWrapRt.cmake b/cmake/FindWrapRt.cmake
index b05ddaad8f..b394b062da 100644
--- a/cmake/FindWrapRt.cmake
+++ b/cmake/FindWrapRt.cmake
@@ -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: 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.
@@ -21,17 +21,31 @@ if(LIBRT)
endif()
check_cxx_source_compiles("
-#include <unistd.h>
#include <time.h>
+#include <unistd.h>
int main(int, char **) {
- timespec ts; clock_gettime(CLOCK_REALTIME, &ts);
-}" HAVE_GETTIME)
+ struct timespec ts;
+ clock_gettime(CLOCK_REALTIME, &ts);
+ return 0;
+}
+" HAVE_GETTIME)
-cmake_pop_check_state()
+check_cxx_source_compiles("
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+int main(int, char **) {
+ shm_open(\"test\", O_RDWR | O_CREAT | O_EXCL, 0666);
+ shm_unlink(\"test\");
+ return 0;
+}
+" HAVE_SHM_OPEN_SHM_UNLINK)
+
+cmake_pop_check_state()
-if(HAVE_GETTIME)
+if(HAVE_GETTIME OR HAVE_SHM_OPEN_SHM_UNLINK)
set(WrapRt_FOUND ON)
add_library(WrapRt::WrapRt INTERFACE IMPORTED)
if (LIBRT)
diff --git a/cmake/FindWrapSystemDoubleConversion.cmake b/cmake/FindWrapSystemDoubleConversion.cmake
index cb3a16c2c7..e0cbc946df 100644
--- a/cmake/FindWrapSystemDoubleConversion.cmake
+++ b/cmake/FindWrapSystemDoubleConversion.cmake
@@ -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: 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.
diff --git a/cmake/FindWrapSystemFreetype.cmake b/cmake/FindWrapSystemFreetype.cmake
index 1a56b8773c..d0c27a9f0f 100644
--- a/cmake/FindWrapSystemFreetype.cmake
+++ b/cmake/FindWrapSystemFreetype.cmake
@@ -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: 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.
diff --git a/cmake/FindWrapSystemHarfbuzz.cmake b/cmake/FindWrapSystemHarfbuzz.cmake
index b6461be4d3..07b3405bc0 100644
--- a/cmake/FindWrapSystemHarfbuzz.cmake
+++ b/cmake/FindWrapSystemHarfbuzz.cmake
@@ -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: 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.
@@ -32,7 +32,7 @@ endif()
if(__harfbuzz_broken_config_file OR NOT __harfbuzz_found)
find_package(PkgConfig QUIET)
- pkg_check_modules(PC_HARFBUZZ harfbuzz IMPORTED_TARGET)
+ pkg_check_modules(PC_HARFBUZZ IMPORTED_TARGET "harfbuzz")
if(PC_HARFBUZZ_FOUND)
set(__harfbuzz_target_name "PkgConfig::PC_HARFBUZZ")
set(__harfbuzz_find_include_dirs_hints
diff --git a/cmake/FindWrapSystemJpeg.cmake b/cmake/FindWrapSystemJpeg.cmake
index e9bfd3f50e..16a9e5ab23 100644
--- a/cmake/FindWrapSystemJpeg.cmake
+++ b/cmake/FindWrapSystemJpeg.cmake
@@ -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: BSD-3-Clause
if(TARGET WrapSystemJpeg::WrapSystemJpeg)
set(WrapSystemJpeg_FOUND TRUE)
diff --git a/cmake/FindWrapSystemMd4c.cmake b/cmake/FindWrapSystemMd4c.cmake
index 538a356b7b..5ac3ded975 100644
--- a/cmake/FindWrapSystemMd4c.cmake
+++ b/cmake/FindWrapSystemMd4c.cmake
@@ -1,27 +1,43 @@
# 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: BSD-3-Clause
if(TARGET WrapSystemMd4c::WrapSystemMd4c)
set(WrapSystemMd4c_FOUND TRUE)
return()
endif()
+set(WrapSystemMd4c_REQUIRED_VARS __md4c_found)
-find_package(md4c CONFIG)
+find_package(md4c ${${CMAKE_FIND_PACKAGE_NAME}_FIND_VERSION} QUIET)
-# md4c provides a md4c::md4c target but
-# older versions create a md4c target without
-# namespace. If we find the old variant create
-# a namespaced target out of the md4c target.
-if(TARGET md4c AND NOT TARGET md4c::md4c)
- add_library(md4c::md4c INTERFACE IMPORTED)
- target_link_libraries(md4c::md4c INTERFACE md4c)
+set(__md4c_target_name "md4c::md4c")
+
+if(md4c_FOUND)
+ set(__md4c_found TRUE)
+
+ # md4c provides a md4c::md4c target but
+ # older versions create a md4c target without
+ # namespace. If we find the old variant create
+ # a namespaced target out of the md4c target.
+ if(TARGET md4c AND NOT TARGET ${__md4c_target_name})
+ add_library(${__md4c_target_name} INTERFACE IMPORTED)
+ target_link_libraries(${__md4c_target_name} INTERFACE md4c)
+ endif()
+
+ if(md4c_VERSION)
+ set(WrapSystemMd4c_VERSION "${md4c_VERSION}")
+ endif()
endif()
-if(TARGET md4c::md4c)
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(WrapSystemMd4c
+ REQUIRED_VARS ${WrapSystemMd4c_REQUIRED_VARS}
+ VERSION_VAR WrapSystemMd4c_VERSION)
+
+if(WrapSystemMd4c_FOUND)
add_library(WrapSystemMd4c::WrapSystemMd4c INTERFACE IMPORTED)
- target_link_libraries(WrapSystemMd4c::WrapSystemMd4c INTERFACE md4c::md4c)
+ target_link_libraries(WrapSystemMd4c::WrapSystemMd4c
+ INTERFACE "${__md4c_target_name}")
endif()
-if(TARGET WrapSystemMd4c::WrapSystemMd4c)
- set(WrapSystemMd4c_FOUND TRUE)
-endif()
+unset(__md4c_found)
+unset(__md4c_target_name)
diff --git a/cmake/FindWrapSystemPCRE2.cmake b/cmake/FindWrapSystemPCRE2.cmake
index cdf2cbfc54..61e0d2fb5b 100644
--- a/cmake/FindWrapSystemPCRE2.cmake
+++ b/cmake/FindWrapSystemPCRE2.cmake
@@ -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: BSD-3-Clause
if(TARGET WrapSystemPCRE2::WrapSystemPCRE2)
set(WrapSystemPCRE2_FOUND TRUE)
@@ -9,11 +9,7 @@ set(WrapSystemPCRE2_REQUIRED_VARS __pcre2_found)
find_package(PCRE2 ${${CMAKE_FIND_PACKAGE_NAME}_FIND_VERSION} COMPONENTS 16BIT QUIET)
-# TODO: pcre2-16 is not the target name provided by the upstream Config file. It is PCRE2::16BIT.
-# https://github.com/PCRE2Project/pcre2/blob/2410fbe3869cab403f02b94caa9ab37ee9f5854b/cmake/pcre2-config.cmake.in#L122
-# We don't strictly need to handle that though, because the pkg-config code path below still
-# finds the correct libraries.
-set(__pcre2_target_name "PCRE2::pcre2-16")
+set(__pcre2_target_name "PCRE2::16BIT")
if(PCRE2_FOUND AND TARGET "${__pcre2_target_name}")
# Hunter case.
set(__pcre2_found TRUE)
@@ -26,7 +22,7 @@ if(NOT __pcre2_found)
list(PREPEND WrapSystemPCRE2_REQUIRED_VARS PCRE2_LIBRARIES PCRE2_INCLUDE_DIRS)
find_package(PkgConfig QUIET)
- pkg_check_modules(PC_PCRE2 QUIET libpcre2-16)
+ pkg_check_modules(PC_PCRE2 QUIET "libpcre2-16")
find_path(PCRE2_INCLUDE_DIRS
NAMES pcre2.h
diff --git a/cmake/FindWrapSystemPNG.cmake b/cmake/FindWrapSystemPNG.cmake
index c7cc0b98f0..967ccc5c02 100644
--- a/cmake/FindWrapSystemPNG.cmake
+++ b/cmake/FindWrapSystemPNG.cmake
@@ -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: 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.
diff --git a/cmake/FindWrapSystemZLIB.cmake b/cmake/FindWrapSystemZLIB.cmake
index 62c9947df1..5db43db626 100644
--- a/cmake/FindWrapSystemZLIB.cmake
+++ b/cmake/FindWrapSystemZLIB.cmake
@@ -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: 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.
diff --git a/cmake/FindWrapVulkan.cmake b/cmake/FindWrapVulkan.cmake
index 4b4de35952..843ca4c202 100644
--- a/cmake/FindWrapVulkan.cmake
+++ b/cmake/FindWrapVulkan.cmake
@@ -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: 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.
diff --git a/cmake/FindWrapVulkanHeaders.cmake b/cmake/FindWrapVulkanHeaders.cmake
index fdee976c60..92510ae000 100644
--- a/cmake/FindWrapVulkanHeaders.cmake
+++ b/cmake/FindWrapVulkanHeaders.cmake
@@ -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: 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.
@@ -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/FindWrapZLIB.cmake b/cmake/FindWrapZLIB.cmake
index e01a9aaef8..6cf60fab9f 100644
--- a/cmake/FindWrapZLIB.cmake
+++ b/cmake/FindWrapZLIB.cmake
@@ -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: BSD-3-Clause
include(QtFindWrapHelper NO_POLICY_SCOPE)
diff --git a/cmake/FindWrapZSTD.cmake b/cmake/FindWrapZSTD.cmake
index 7c82190c21..fb424236b8 100644
--- a/cmake/FindWrapZSTD.cmake
+++ b/cmake/FindWrapZSTD.cmake
@@ -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: BSD-3-Clause
#.rst:
# FindZstd
@@ -28,10 +28,10 @@ include(FindPackageHandleStandardArgs)
if(TARGET zstd::libzstd_static OR TARGET zstd::libzstd_shared)
find_package_handle_standard_args(WrapZSTD
REQUIRED_VARS zstd_VERSION VERSION_VAR zstd_VERSION)
- if(TARGET zstd::libzstd_static)
- set(zstdtargetsuffix "_static")
- else()
+ if(TARGET zstd::libzstd_shared)
set(zstdtargetsuffix "_shared")
+ else()
+ set(zstdtargetsuffix "_static")
endif()
if(NOT TARGET WrapZSTD::WrapZSTD)
add_library(WrapZSTD::WrapZSTD INTERFACE IMPORTED)
@@ -40,7 +40,7 @@ if(TARGET zstd::libzstd_static OR TARGET zstd::libzstd_shared)
endif()
else()
find_package(PkgConfig QUIET)
- pkg_check_modules(PC_ZSTD QUIET libzstd)
+ pkg_check_modules(PC_ZSTD QUIET "libzstd")
find_path(ZSTD_INCLUDE_DIRS
NAMES zstd.h
diff --git a/cmake/FindXKB_COMMON_X11.cmake b/cmake/FindXKB_COMMON_X11.cmake
index 03fdd89fa4..a00acb3cb0 100644
--- a/cmake/FindXKB_COMMON_X11.cmake
+++ b/cmake/FindXKB_COMMON_X11.cmake
@@ -1,9 +1,9 @@
# 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: BSD-3-Clause
find_package(PkgConfig QUIET)
-pkg_check_modules(XKB_COMMON_X11 "xkbcommon-x11>=0.4.1" IMPORTED_TARGET)
+pkg_check_modules(XKB_COMMON_X11 IMPORTED_TARGET "xkbcommon-x11>=0.4.1")
if (NOT TARGET PkgConfig::XKB_COMMON_X11)
set(XKB_COMMON_X11_FOUND 0)
diff --git a/cmake/FindXRender.cmake b/cmake/FindXRender.cmake
index 35467375b8..6908cc45fb 100644
--- a/cmake/FindXRender.cmake
+++ b/cmake/FindXRender.cmake
@@ -1,10 +1,10 @@
# 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: BSD-3-Clause
find_package(PkgConfig QUIET)
if(NOT TARGET PkgConfig::XRender)
- pkg_check_modules(XRender xrender IMPORTED_TARGET)
+ pkg_check_modules(XRender IMPORTED_TARGET "xrender")
if (NOT TARGET PkgConfig::XRender)
set(XRender_FOUND 0)
diff --git a/cmake/ModuleDescription.json.in b/cmake/ModuleDescription.json.in
index 6aae9a4a59..93f9a5ed25 100644
--- a/cmake/ModuleDescription.json.in
+++ b/cmake/ModuleDescription.json.in
@@ -1,11 +1,13 @@
{
- "module_name": "${target}",
- "version": "${PROJECT_VERSION}",
- "built_with": {
+ "name": "${target}",
+ "repository": "${lower_case_project_name}",
+ "version": "${PROJECT_VERSION}",${extra_module_information}
+ "built_with": {${extra_build_information}
"compiler_id": "${CMAKE_CXX_COMPILER_ID}",
"compiler_target": "${CMAKE_CXX_COMPILER_TARGET}",
"compiler_version": "${CMAKE_CXX_COMPILER_VERSION}",
"cross_compiled": ${cross_compilation},
- "target_system": "${CMAKE_SYSTEM_NAME}"
+ "target_system": "${CMAKE_SYSTEM_NAME}",
+ "architecture": "${TEST_architecture_arch}"
}
}
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 a118997bcf..924db182be 100644
--- a/cmake/Qt3rdPartyLibraryHelpers.cmake
+++ b/cmake/Qt3rdPartyLibraryHelpers.cmake
@@ -4,6 +4,7 @@ macro(qt_internal_get_add_library_option_args option_args)
STATIC
MODULE
INTERFACE
+ NO_UNITY_BUILD
)
endmacro()
@@ -14,12 +15,12 @@ endmacro()
# Everything else is just prepation for option validating.
function(qt_internal_add_common_qt_library_helper target)
qt_internal_get_add_library_option_args(option_args)
- qt_parse_all_arguments(arg "qt_internal_add_common_qt_library_helper"
+ cmake_parse_arguments(PARSE_ARGV 1 arg
"${option_args}"
""
""
- ${ARGN}
)
+ _qt_internal_validate_all_args_are_parsed(arg)
if(arg_SHARED)
set(arg_SHARED SHARED)
@@ -50,6 +51,11 @@ function(qt_internal_add_common_qt_library_helper target)
endif()
_qt_internal_add_library(${target} ${arg_STATIC} ${arg_SHARED} ${arg_MODULE} ${arg_INTERFACE})
+
+ if(arg_NO_UNITY_BUILD)
+ set_property(TARGET "${target}" PROPERTY UNITY_BUILD OFF)
+ endif()
+
qt_internal_mark_as_internal_library(${target})
endfunction()
@@ -67,12 +73,13 @@ function(qt_internal_add_cmake_library target)
${__default_public_args}
)
- qt_parse_all_arguments(arg "qt_add_cmake_library"
+ cmake_parse_arguments(PARSE_ARGV 1 arg
"${option_args}"
"${single_args}"
"${multi_args}"
- ${ARGN}
)
+ _qt_internal_validate_all_args_are_parsed(arg)
+ _qt_internal_validate_no_unity_build(arg)
qt_remove_args(library_helper_args
ARGS_TO_REMOVE
@@ -102,6 +109,8 @@ function(qt_internal_add_cmake_library target)
SOURCES ${arg_SOURCES}
INCLUDE_DIRECTORIES
${arg_INCLUDE_DIRECTORIES}
+ SYSTEM_INCLUDE_DIRECTORIES
+ ${arg_SYSTEM_INCLUDE_DIRECTORIES}
PUBLIC_INCLUDE_DIRECTORIES
${arg_PUBLIC_INCLUDE_DIRECTORIES}
PUBLIC_DEFINES
@@ -117,6 +126,7 @@ function(qt_internal_add_cmake_library target)
MOC_OPTIONS ${arg_MOC_OPTIONS}
ENABLE_AUTOGEN_TOOLS ${arg_ENABLE_AUTOGEN_TOOLS}
DISABLE_AUTOGEN_TOOLS ${arg_DISABLE_AUTOGEN_TOOLS}
+ NO_UNITY_BUILD # Disabled by default
)
endfunction()
@@ -139,12 +149,13 @@ function(qt_internal_add_3rdparty_library target)
${__default_public_args}
)
- qt_parse_all_arguments(arg "qt_internal_add_3rdparty_library"
+ cmake_parse_arguments(PARSE_ARGV 1 arg
"${library_option_args};${option_args}"
"${single_args}"
"${multi_args}"
- ${ARGN}
)
+ _qt_internal_validate_all_args_are_parsed(arg)
+ _qt_internal_validate_no_unity_build(arg)
qt_remove_args(library_helper_args
ARGS_TO_REMOVE
@@ -238,6 +249,7 @@ function(qt_internal_add_3rdparty_library target)
MOC_OPTIONS ${arg_MOC_OPTIONS}
ENABLE_AUTOGEN_TOOLS ${arg_ENABLE_AUTOGEN_TOOLS}
DISABLE_AUTOGEN_TOOLS ${arg_DISABLE_AUTOGEN_TOOLS}
+ NO_UNITY_BUILD
)
if(NOT BUILD_SHARED_LIBS OR arg_INSTALL)
@@ -298,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}"
)
@@ -308,6 +321,12 @@ function(qt_internal_add_3rdparty_library target)
qt_enable_separate_debug_info(${target} "${debug_install_dir}")
qt_internal_install_pdb_files(${target} "${INSTALL_LIBDIR}")
endif()
+
+ if(BUILD_SHARED_LIBS AND MSVC)
+ set_target_properties(${target} PROPERTIES
+ INTERPROCEDURAL_OPTIMIZATION OFF
+ )
+ endif()
endfunction()
function(qt_install_3rdparty_library_wrap_config_extra_file target)
@@ -341,12 +360,13 @@ function(qt_internal_add_3rdparty_header_module target)
set(multi_args
EXTERNAL_HEADERS
)
- qt_parse_all_arguments(arg "qt_internal_add_header_module"
+ cmake_parse_arguments(PARSE_ARGV 1 arg
"${option_args}"
"${single_args}"
"${multi_args}"
- ${ARGN}
)
+ _qt_internal_validate_all_args_are_parsed(arg)
+
qt_internal_add_module(${target}
INTERNAL_MODULE
HEADER_MODULE
diff --git a/cmake/QtAndroidHelpers.cmake b/cmake/QtAndroidHelpers.cmake
index d86fc5f96c..0743fe41a9 100644
--- a/cmake/QtAndroidHelpers.cmake
+++ b/cmake/QtAndroidHelpers.cmake
@@ -1,91 +1,92 @@
# 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: BSD-3-Clause
#
# 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)
@@ -130,8 +131,9 @@ function(qt_internal_android_dependencies_content target file_content_out)
if (init_class)
set(init_class "initClass=\"${init_class}\"")
endif()
- file(TO_NATIVE_PATH ${jar_file} jar_file_native)
- string(APPEND file_contents "<jar file=\"${jar_file_native}\" ${init_class} />\n")
+ # Use unix path to allow using files on any host platform.
+ file(TO_CMAKE_PATH ${jar_file} jar_file_unix_path)
+ string(APPEND file_contents "<jar file=\"${jar_file_unix_path}\" ${init_class} />\n")
endforeach()
endif()
@@ -142,8 +144,10 @@ function(qt_internal_android_dependencies_content target file_content_out)
if (init_class)
set(init_class "initClass=\"${init_class}\"")
endif()
- file(TO_NATIVE_PATH ${bundle_file} jar_bundle_native)
- string(APPEND file_contents "<jar bundling=\"1\" file=\"${jar_bundle_native}\" ${init_class} />\n")
+ # Use unix path to allow using files on any host platform.
+ file(TO_CMAKE_PATH ${bundle_file} jar_bundle_unix_path)
+ string(APPEND file_contents
+ "<jar bundling=\"1\" file=\"${jar_bundle_unix_path}\" ${init_class} />\n")
endforeach()
endif()
@@ -155,8 +159,9 @@ function(qt_internal_android_dependencies_content target file_content_out)
if (lib_extends)
set(lib_extends "extends=\"${lib_extends}\"")
endif()
- file(TO_NATIVE_PATH ${lib_file} lib_file_native)
- string(APPEND file_contents "<lib file=\"${lib_file_native}\" ${lib_extends} />\n")
+ # Use unix path to allow using files on any host platform.
+ file(TO_CMAKE_PATH ${lib_file} lib_file_unix_path)
+ string(APPEND file_contents "<lib file=\"${lib_file_unix_path}\" ${lib_extends} />\n")
endforeach()
endif()
@@ -166,19 +171,23 @@ function(qt_internal_android_dependencies_content target file_content_out)
string(REPLACE ".so" "_${CMAKE_ANDROID_ARCH_ABI}.so" lib ${lib})
section(${lib} ":" lib_file lib_replacement)
if (lib_replacement)
- file(TO_NATIVE_PATH ${lib_replacement} lib_replacement_native)
- set(lib_replacement "replaces=\"${lib_replacement_native}\"")
+ # Use unix path to allow using files on any host platform.
+ file(TO_CMAKE_PATH ${lib_replacement} lib_replacement_unix_path)
+ set(lib_replacement "replaces=\"${lib_replacement_unix_path}\"")
endif()
- file(TO_NATIVE_PATH ${lib_file} lib_file_native)
- string(APPEND file_contents "<lib file=\"${lib_file_native}\" ${lib_replacement} />\n")
+ # Use unix path to allow using files on any host platform.
+ file(TO_CMAKE_PATH ${lib_file} lib_file_unix_path)
+ string(APPEND file_contents
+ "<lib file=\"${lib_file_unix_path}\" ${lib_replacement} />\n")
endforeach()
endif()
# Bundled files
if(arg_BUNDLED_FILES)
foreach(bundled_file IN LISTS arg_BUNDLED_FILES)
- file(TO_NATIVE_PATH ${bundled_file} file_native)
- string(APPEND file_contents "<bundled file=\"${file_native}\" />\n")
+ # Use unix path to allow using files on any host platform.
+ file(TO_CMAKE_PATH ${bundled_file} file_unix_path)
+ string(APPEND file_contents "<bundled file=\"${file_unix_path}\" />\n")
endforeach()
endif()
@@ -244,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=\"plugins/${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 bb35aac5d1..c0ad53ab9e 100644
--- a/cmake/QtAppHelpers.cmake
+++ b/cmake/QtAppHelpers.cmake
@@ -1,15 +1,15 @@
# 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: BSD-3-Clause
# This function creates a CMake target for a Qt internal app.
# Such projects had a load(qt_app) command.
function(qt_internal_add_app target)
- qt_parse_all_arguments(arg
- "qt_internal_add_app"
- "NO_INSTALL;INSTALL_VERSIONED_LINK;EXCEPTIONS"
+ cmake_parse_arguments(PARSE_ARGV 1 arg
+ "NO_INSTALL;INSTALL_VERSIONED_LINK;EXCEPTIONS;NO_UNITY_BUILD"
"${__default_target_info_args};INSTALL_DIR"
"${__default_private_args};PUBLIC_LIBRARIES"
- ${ARGN})
+ )
+ _qt_internal_validate_all_args_are_parsed(arg)
set(exceptions "")
if(arg_EXCEPTIONS)
@@ -35,6 +35,14 @@ 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
DELAY_RC
@@ -42,12 +50,16 @@ 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
${arg_DEFINES}
+ ${deprecation_define}
LIBRARIES
${arg_LIBRARIES}
${arg_PUBLIC_LIBRARIES}
@@ -57,11 +69,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}")
@@ -80,7 +94,8 @@ function(qt_internal_add_app target)
# Install versioned link if requested.
if(NOT arg_NO_INSTALL AND arg_INSTALL_VERSIONED_LINK)
- qt_internal_install_versioned_link("${arg_INSTALL_DIR}" ${target})
+ qt_internal_install_versioned_link(WORKING_DIRECTORY "${arg_INSTALL_DIR}"
+ TARGETS ${target})
endif()
qt_add_list_file_finalizer(qt_internal_finalize_app ${target})
diff --git a/cmake/QtAutoDetect.cmake b/cmake/QtAutoDetect.cmake
index 10f91cd047..464e8e900b 100644
--- a/cmake/QtAutoDetect.cmake
+++ b/cmake/QtAutoDetect.cmake
@@ -1,541 +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: 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")
- 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)
-
- # 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_ensure_static_qt_config()
-
- __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
- OR CMAKE_SYSTEM_NAME STREQUAL watchOS
- OR CMAKE_SYSTEM_NAME STREQUAL tvOS)
- 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(CMAKE_SYSTEM_NAME STREQUAL iOS)
- 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 proviude 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()
- elseif(CMAKE_SYSTEM_NAME STREQUAL tvOS)
- if(simulator_and_device)
- set(osx_architectures "arm64;x86_64")
- elseif(QT_UIKIT_SDK STREQUAL "appletvos")
- set(osx_architectures "arm64")
- elseif(QT_UIKIT_SDK STREQUAL "appletvsimulator")
- set(osx_architectures "x86_64")
- else()
- if(NOT DEFINED QT_UIKIT_SDK)
- message(FATAL_ERROR "Please proviude a value for -DQT_UIKIT_SDK."
- " Possible values: appletvos, appletvsimulator.")
- else()
- message(FATAL_ERROR
- "Unknown SDK argument given to QT_UIKIT_SDK: ${QT_UIKIT_SDK}.")
- endif()
- endif()
- elseif(CMAKE_SYSTEM_NAME STREQUAL watchOS)
- if(simulator_and_device)
- set(osx_architectures "armv7k;i386")
- elseif(QT_UIKIT_SDK STREQUAL "watchos")
- set(osx_architectures "armv7k")
- elseif(QT_UIKIT_SDK STREQUAL "watchsimulator")
- set(osx_architectures "i386")
- else()
- if(NOT DEFINED QT_UIKIT_SDK)
- message(FATAL_ERROR "Please proviude a value for -DQT_UIKIT_SDK."
- " Possible values: watchos, watchsimulator.")
- else()
- message(FATAL_ERROR
- "Unknown SDK argument given to QT_UIKIT_SDK: ${QT_UIKIT_SDK}.")
- endif()
- 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 "")
-
- qt_internal_ensure_static_qt_config()
-
- # 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(IOS)
- set(sdk_name "iphoneos")
- elseif(TVOS)
- set(sdk_name "appletvos")
- elseif(WATCHOS)
- set(sdk_name "watchos")
- 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 "10.14")
- elseif(CMAKE_SYSTEM_NAME STREQUAL iOS)
- set(version "13.0")
- elseif(CMAKE_SYSTEM_NAME STREQUAL watchOS)
- set(version "6.0")
- elseif(CMAKE_SYSTEM_NAME STREQUAL tvOS)
- set(version "13.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.")
-
- set(device_names "iOS" "watchOS" "tvOS")
- list(LENGTH CMAKE_OSX_ARCHITECTURES arch_count)
- if(NOT CMAKE_SYSTEM_NAME IN_LIST device_names 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)
- set(device_names "iOS" "watchOS" "tvOS")
- if(APPLE AND NOT CMAKE_SYSTEM_NAME IN_LIST device_names)
- 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..ad0764b804
--- /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 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(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 0e827fbb14..029a709e90 100644
--- a/cmake/QtAutogenHelpers.cmake
+++ b/cmake/QtAutogenHelpers.cmake
@@ -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: BSD-3-Clause
# Initial autogen setup for a target to specify certain CMake properties which are common
# to all autogen tools. Also enable AUTOMOC by default.
@@ -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)
@@ -61,7 +60,8 @@ endfunction()
# This function adds or removes additional AUTOGEN tools to a target: AUTOMOC/UIC/RCC
function(qt_autogen_tools target)
- qt_parse_all_arguments(arg "qt_autogen_tools" "" "" "${__default_private_args}" ${ARGN})
+ cmake_parse_arguments(PARSE_ARGV 1 arg "" "" "${__default_private_args}")
+ _qt_internal_validate_all_args_are_parsed(arg)
if(arg_ENABLE_AUTOGEN_TOOLS)
foreach(tool ${arg_ENABLE_AUTOGEN_TOOLS})
@@ -78,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)
@@ -94,7 +103,7 @@ function(qt_manual_moc result)
"${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_BINARY_DIR}" outfile)
list(APPEND moc_files "${outfile}")
- set(moc_parameters_file "${outfile}_parameters$<$<BOOL:$<CONFIGURATION>>:_$<CONFIGURATION>>")
+ set(moc_parameters_file "${outfile}_parameters$<$<BOOL:$<CONFIG>>:_$<CONFIG>>")
set(moc_parameters ${arg_FLAGS} -o "${outfile}" "${infile}")
foreach(dir IN ITEMS ${arg_INCLUDE_DIRECTORIES})
@@ -102,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>>")
@@ -128,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/QtBaseCMakeTesting.cmake b/cmake/QtBaseCMakeTesting.cmake
index c06827a948..db64b49189 100644
--- a/cmake/QtBaseCMakeTesting.cmake
+++ b/cmake/QtBaseCMakeTesting.cmake
@@ -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: BSD-3-Clause
## Test the cmake build system:
option(BUILD_CMAKE_TESTING "Build tests for the Qt build system" OFF)
diff --git a/cmake/QtBaseConfigureTests.cmake b/cmake/QtBaseConfigureTests.cmake
index acc5bdbcb1..66a0b3b6dd 100644
--- a/cmake/QtBaseConfigureTests.cmake
+++ b/cmake/QtBaseConfigureTests.cmake
@@ -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: BSD-3-Clause
include(CheckCXXSourceCompiles)
@@ -12,10 +12,14 @@ function(qt_run_config_test_architecture)
qt_get_platform_try_compile_vars(platform_try_compile_vars)
list(APPEND flags ${platform_try_compile_vars})
- list(TRANSFORM flags PREPEND " " OUTPUT_VARIABLE flags_indented)
+ list(TRANSFORM flags PREPEND " " OUTPUT_VARIABLE flags_indented)
list(JOIN flags_indented "\n" flags_indented)
+
message(STATUS
- "Building architecture extraction project with the following CMake arguments:\n${flags_indented}")
+ "Building architecture extraction project with the following CMake arguments:")
+ list(POP_BACK CMAKE_MESSAGE_CONTEXT _context)
+ message(NOTICE ${flags_indented})
+ list(APPEND CMAKE_MESSAGE_CONTEXT ${_context})
try_compile(
_arch_result
@@ -58,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)
@@ -69,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}")
@@ -111,41 +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")
endfunction()
function(qt_internal_ensure_latest_win_nt_api)
@@ -194,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}\"")
@@ -202,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 8552137de7..1e604559ed 100644
--- a/cmake/QtBaseGlobalTargets.cmake
+++ b/cmake/QtBaseGlobalTargets.cmake
@@ -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: BSD-3-Clause
set(__GlobalConfig_path_suffix "${INSTALL_CMAKE_NAMESPACE}")
qt_path_join(__GlobalConfig_build_dir ${QT_CONFIG_BUILD_DIR} ${__GlobalConfig_path_suffix})
@@ -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,97 +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/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/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/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
+ ${__private_files}
DESTINATION "${__GlobalConfig_install_dir}"
)
@@ -319,41 +278,32 @@ 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/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()
-# TODO: Check whether this is the right place to install these
qt_copy_or_install(DIRECTORY "cmake/3rdparty" DESTINATION "${__GlobalConfig_install_dir}")
# In prefix builds we also need to copy the files into the build config directory, so that the
@@ -369,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
@@ -379,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 4c3654ba50..ee24ba188e 100644
--- a/cmake/QtBuild.cmake
+++ b/cmake/QtBuild.cmake
@@ -1,576 +1,4 @@
# 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: 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)
- qt_parse_all_arguments(arg "qt_get_install_target_default_args"
- "" "OUT_VAR;CMAKE_CONFIG;RUNTIME;LIBRARY;ARCHIVE;INCLUDES;BUNDLE"
- "ALL_CMAKE_CONFIGS" ${ARGN})
-
- 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_DATADIR}/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()
-
-# 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_wrap_tool_command
- # instead.
-endfunction()
-qt_setup_tool_path_command()
-
-function(qt_internal_generate_tool_command_wrapper)
- get_property(is_called GLOBAL PROPERTY _qt_internal_generate_tool_command_wrapper_called)
- if(NOT CMAKE_HOST_WIN32 OR is_called)
- return()
- endif()
- set(bindir "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}/${INSTALL_BINDIR}")
- file(TO_NATIVE_PATH "${bindir}" bindir)
- set(tool_command_wrapper_path "${QT_BUILD_DIR}/${INSTALL_LIBEXECDIR}/qt_setup_tool_path.bat")
- file(WRITE "${tool_command_wrapper_path}" "@echo off
-set PATH=${bindir};%PATH%
-%*")
- set(QT_TOOL_COMMAND_WRAPPER_PATH "${tool_command_wrapper_path}"
- CACHE INTERNAL "Path to the wrapper of the tool commands")
- set_property(GLOBAL PROPERTY _qt_internal_generate_tool_command_wrapper_called TRUE)
-endfunction()
-qt_internal_generate_tool_command_wrapper()
-
-# 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)
- set(QT_DEFAULT_MKSPEC wasm-emscripten)
-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_HOST_APPLE AND APPLE)
- 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
- 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
-)
-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
-)
-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(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(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 a81ec70cb3..11fa9996b1 100644
--- a/cmake/QtBuildInformation.cmake
+++ b/cmake/QtBuildInformation.cmake
@@ -1,5 +1,21 @@
# 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: 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)
@@ -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()
@@ -93,7 +107,13 @@ function(qt_print_build_instructions)
"\nTo configure and build other Qt modules, you can use the following convenience script:
${local_install_prefix}/${INSTALL_BINDIR}/${configure_module_command}")
list(APPEND msg "\nIf reconfiguration fails for some reason, try removing 'CMakeCache.txt' \
-from the build directory \n")
+from the build directory")
+ if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.24")
+ list(APPEND msg "Alternatively, you can add the --fresh flag to your CMake flags.\n")
+ else()
+ list(APPEND msg "\n")
+ endif()
+
list(JOIN msg "\n" msg)
if(NOT QT_INTERNAL_BUILD_INSTRUCTIONS_SHOWN)
@@ -101,6 +121,10 @@ from the build directory \n")
endif()
set(QT_INTERNAL_BUILD_INSTRUCTIONS_SHOWN "TRUE" CACHE STRING "" FORCE)
+
+ if(QT_SUPERBUILD)
+ qt_internal_save_previously_visited_packages()
+ endif()
endfunction()
function(qt_configure_print_summary_helper summary_reports force_show)
@@ -108,8 +132,15 @@ function(qt_configure_print_summary_helper summary_reports force_show)
# current log level.
if(force_show)
set(CMAKE_MESSAGE_LOG_LEVEL "STATUS")
+
+ # Need 2 flushes to ensure no interleaved input is printed due to a mix of message(STATUS)
+ # and message(NOTICE) calls.
+ execute_process(COMMAND ${CMAKE_COMMAND} -E echo " ")
+
+ message(STATUS "Configure summary:\n${summary_reports}")
+
+ execute_process(COMMAND ${CMAKE_COMMAND} -E echo " ")
endif()
- message(STATUS "Configure summary:\n${__qt_configure_reports}")
endfunction()
function(qt_configure_print_build_instructions_helper msg)
@@ -130,39 +161,44 @@ function(qt_configure_print_summary)
# Show Qt-specific configuration summary.
if(__qt_configure_reports)
- # We want to show the the summary file and log level messages 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)
- message("")
+ # 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(log_level_sufficient_for_printed_summary
+ AND (NOT QT_INTERNAL_SUMMARY_INSTRUCTIONS_SHOWN OR features_possibly_changed))
+ set(force_show_summary TRUE)
message(
+ "\n"
"-- Configuration summary shown below. It has also been written to"
" ${CMAKE_BINARY_DIR}/config.summary")
message(
"-- Configure with --log-level=STATUS or higher to increase "
"CMake's message verbosity. "
"The log level does not persist across reconfigurations.")
- endif()
-
- # Need 2 flushes to ensure no interleaved input is printed due to a mix of message(STATUS)
- # and message(NOTICE) calls.
- execute_process(COMMAND ${CMAKE_COMMAND} -E echo " ")
-
- # We want to show the configuration summary 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)
- set(force_show_summary TRUE)
else()
set(force_show_summary FALSE)
+ message(
+ "\n"
+ "-- Configuration summary has been written to"
+ " ${CMAKE_BINARY_DIR}/config.summary")
endif()
qt_configure_print_summary_helper(
- "Configuration summary:\n${__qt_configure_reports}"
+ "${__qt_configure_reports}"
${force_show_summary})
- execute_process(COMMAND ${CMAKE_COMMAND} -E echo " ")
-
file(APPEND "${summary_file}" "${__qt_configure_reports}")
endif()
@@ -303,9 +339,11 @@ function(qt_configure_add_summary_entry)
endfunction()
function(qt_configure_process_add_summary_entry)
- qt_parse_all_arguments(arg "qt_configure_add_summary_entry"
+ cmake_parse_arguments(PARSE_ARGV 0 arg
""
- "ARGS;TYPE;MESSAGE" "CONDITION" ${ARGN})
+ "ARGS;TYPE;MESSAGE"
+ "CONDITION")
+ _qt_internal_validate_all_args_are_parsed(arg)
if(NOT arg_TYPE)
set(arg_TYPE "feature")
@@ -462,8 +500,11 @@ function(qt_configure_add_summary_section)
endfunction()
function(qt_configure_process_add_summary_section)
- qt_parse_all_arguments(arg "qt_configure_add_summary_section"
- "" "NAME" "" ${ARGN})
+ cmake_parse_arguments(PARSE_ARGV 0 arg
+ ""
+ "NAME"
+ "")
+ _qt_internal_validate_all_args_are_parsed(arg)
qt_configure_add_report("${__qt_configure_indent}${arg_NAME}:")
if(NOT DEFINED __qt_configure_indent)
@@ -495,9 +536,11 @@ function(qt_configure_add_report_error error)
endfunction()
function(qt_configure_process_add_report_entry)
- qt_parse_all_arguments(arg "qt_configure_add_report_entry"
+ cmake_parse_arguments(PARSE_ARGV 0 arg
""
- "TYPE;MESSAGE" "CONDITION" ${ARGN})
+ "TYPE;MESSAGE"
+ "CONDITION")
+ _qt_internal_validate_all_args_are_parsed(arg)
set(possible_types NOTE WARNING ERROR FATAL_ERROR)
if(NOT "${arg_TYPE}" IN_LIST possible_types)
diff --git a/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake b/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake
index 63f9050bd2..129f1ebb77 100644
--- a/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake
+++ b/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake
@@ -1,69 +1,28 @@
# 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: BSD-3-Clause
# These values should be kept in sync with those in qtbase/.cmake.conf
-cmake_minimum_required(VERSION 3.16...3.20)
-
-###############################################
-#
-# 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 qtimageformats:
-# qtbase;qtshadertools;qtsvg;qtdeclarative;qttools
-#
-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()
+cmake_minimum_required(VERSION 3.16...3.21)
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,1249 +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" OR ${_type} STREQUAL "INTERFACE"))
- 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}")
- 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)
- 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()
-
- # 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)
-
- 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()
-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()
-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()
-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)
- 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)
- 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()
-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 always depend on all plugins so as 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_plugins ${arg_DEPENDS})
-
- if(TARGET ${qt_repo_targets_name}_src)
- list(APPEND QT_EXAMPLE_DEPENDENCIES ${qt_repo_targets_name}_src)
- 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}")
- set(QT_DISABLE_QT_ADD_PLUGIN_COMPATIBILITY TRUE)
-
- 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()
- 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 1f7425982b..766e372666 100644
--- a/cmake/QtBuildInternals/QtStandaloneTestTemplateProject/CMakeLists.txt
+++ b/cmake/QtBuildInternals/QtStandaloneTestTemplateProject/CMakeLists.txt
@@ -1,12 +1,7 @@
# 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: 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,5 +13,26 @@ 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)
+
+ if(filename STREQUAL "CMakeLists.txt")
+ set(absolute_project_path "${directory}")
+ 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 77e0148a0c..bd0984f314 100644
--- a/cmake/QtBuildInternals/QtStandaloneTestTemplateProject/Main.cmake
+++ b/cmake/QtBuildInternals/QtStandaloneTestTemplateProject/Main.cmake
@@ -1,16 +1,18 @@
# 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: 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 3297d85c52..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@)
@@ -87,6 +90,9 @@ set(QT_BUILD_MINIMAL_STATIC_TESTS @QT_BUILD_MINIMAL_STATIC_TESTS@ CACHE BOOL
set(QT_BUILD_MINIMAL_ANDROID_MULTI_ABI_TESTS @QT_BUILD_MINIMAL_ANDROID_MULTI_ABI_TESTS@ CACHE BOOL
"Build minimal subset of tests for Android multi-ABI Qt builds")
+set(QT_BUILD_TESTS_BATCHED @QT_BUILD_TESTS_BATCHED@ CACHE BOOL
+ "Should all tests be batched into a single binary.")
+
set(QT_BUILD_TESTS_BY_DEFAULT @QT_BUILD_TESTS_BY_DEFAULT@ CACHE BOOL
"Should tests be built as part of the default 'all' target.")
set(QT_BUILD_EXAMPLES_BY_DEFAULT @QT_BUILD_EXAMPLES_BY_DEFAULT@ CACHE BOOL
@@ -100,6 +106,16 @@ 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")
+
+# Propragate the value of WARNINGS_ARE_ERRORS.
+set(WARNINGS_ARE_ERRORS "@WARNINGS_ARE_ERRORS@" CACHE BOOL "Build Qt with warnings as errors")
+
# Propagate usage of versioned hard link.
set(QT_CREATE_VERSIONED_HARD_LINK "@QT_CREATE_VERSIONED_HARD_LINK@" CACHE BOOL
"Enable the use of versioned hard link")
@@ -119,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 cc183068d8..142a003cbc 100644
--- a/cmake/QtCMakeHelpers.cmake
+++ b/cmake/QtCMakeHelpers.cmake
@@ -1,22 +1,19 @@
# Copyright (C) 2022 The Qt Company Ltd.
-# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-# qt_configure_file(OUTPUT output-file <INPUT input-file | CONTENT content>)
-# input-file is relative to ${CMAKE_CURRENT_SOURCE_DIR}
-# output-file is relative to ${CMAKE_CURRENT_BINARY_DIR}
-#
-# This function is similar to file(GENERATE OUTPUT) except it writes the content
-# to the file at configure time, rather than at generate time. Once CMake 3.18 is released, it can
-# use file(CONFIGURE) in its implementation. Until then, it uses configure_file() with a generic
-# input file as source, when used with the CONTENT signature.
-function(qt_configure_file)
- qt_parse_all_arguments(arg "qt_configure_file" "" "OUTPUT;INPUT;CONTENT" "" ${ARGN})
+# SPDX-License-Identifier: BSD-3-Clause
+# The common implementation of qt_configure_file functionality.
+macro(qt_configure_file_impl)
if(NOT arg_OUTPUT)
message(FATAL_ERROR "No output file provided to qt_configure_file.")
endif()
- if(arg_CONTENT)
+ # We use this check for the cases when the specified CONTENT is empty. The value of arg_CONTENT
+ # is undefined, but we still want to create a file with empty content.
+ if(NOT "CONTENT" IN_LIST arg_KEYWORDS_MISSING_VALUES)
+ if(arg_INPUT)
+ message(WARNING "Both CONTENT and INPUT are specified. CONTENT will be used to generate"
+ " output")
+ endif()
set(template_name "QtFileConfigure.txt.in")
# When building qtbase, use the source template file.
# Otherwise use the installed file (basically wherever Qt6 package is found).
@@ -34,10 +31,29 @@ function(qt_configure_file)
endif()
configure_file("${input_file}" "${arg_OUTPUT}" @ONLY)
+endmacro()
+
+# qt_configure_file(OUTPUT output-file <INPUT input-file | CONTENT content>)
+# input-file is relative to ${CMAKE_CURRENT_SOURCE_DIR}
+# output-file is relative to ${CMAKE_CURRENT_BINARY_DIR}
+#
+# This function is similar to file(GENERATE OUTPUT) except it writes the content
+# to the file at configure time, rather than at generate time.
+#
+# TODO: Once we require 3.18+, this can use file(CONFIGURE) in its implementation,
+# or maybe its usage can be replaced by file(CONFIGURE). Until then, it uses
+# configure_file() with a generic input file as source, when used with the CONTENT
+# signature.
+function(qt_configure_file)
+ cmake_parse_arguments(PARSE_ARGV 0 arg "" "OUTPUT;INPUT;CONTENT" "")
+ qt_configure_file_impl()
endfunction()
# A version of cmake_parse_arguments that makes sure all arguments are processed and errors out
# with a message about ${type} having received unknown arguments.
+#
+# TODO: Remove when all usage of qt_parse_all_arguments were replaced by
+# cmake_parse_all_arguments(PARSEARGV) instances
macro(qt_parse_all_arguments result type flags options multiopts)
cmake_parse_arguments(${result} "${flags}" "${options}" "${multiopts}" ${ARGN})
if(DEFINED ${result}_UNPARSED_ARGUMENTS)
@@ -45,6 +61,14 @@ 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})
@@ -101,8 +125,7 @@ endfunction()
# 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 or
-# qt_parse_all_arguments
+# 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.
@@ -116,7 +139,7 @@ endfunction()
# bar(target BAR.... WWW...)
#
# function(foo target)
-# qt_parse_all_arguments(arg "" "" "BAR;ZZZ;WWW ${ARGV})
+# 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
diff --git a/cmake/QtCMakePackageVersionFile.cmake.in b/cmake/QtCMakePackageVersionFile.cmake.in
index f63a498b40..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")
@@ -8,7 +11,9 @@ if(QT_NO_PACKAGE_VERSION_CHECK)
set(__qt_disable_package_version_check TRUE)
endif()
+# Extra CMake code begin
@extra_code@
+# Extra CMake code end
if((NOT PACKAGE_VERSION_COMPATIBLE) OR PACKAGE_VERSION_UNSUITABLE)
set(__qt_package_version_incompatible TRUE)
diff --git a/cmake/QtCMakeVersionHelpers.cmake b/cmake/QtCMakeVersionHelpers.cmake
index bcbd69057b..322e58eed1 100644
--- a/cmake/QtCMakeVersionHelpers.cmake
+++ b/cmake/QtCMakeVersionHelpers.cmake
@@ -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: BSD-3-Clause
# Returns the minimum supported CMake version required to /build/ Qt as originally advertised by Qt.
function(qt_internal_get_supported_min_cmake_version_for_building_qt out_var)
@@ -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}")
@@ -198,19 +202,6 @@ function(qt_internal_warn_about_buggy_cmake_versions)
# Fixed in 3.21.2.
list(APPEND unsuitable_versions "3.21.1")
- # qt_ensure_perl fails to find perl in host PATH via find_program
- # due to Android Platform module setting CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH to OFF
- # Fixed in 3.20.6, 3.21.3. not a problem in CMake versions earlier than 3.20.0
- # https://gitlab.kitware.com/cmake/cmake/-/issues/22634
- # https://gitlab.kitware.com/cmake/cmake/-/merge_requests/5357
- # https://gitlab.kitware.com/cmake/cmake/-/merge_requests/6528
- if(ANDROID AND CMAKE_HOST_WIN32)
- list(APPEND unsuitable_versions
- "3.20.0" "3.20.1" "3.20.2" "3.20.3" "3.20.4" "3.20.5"
- "3.21.0" "3.21.1" "3.21.2"
- )
- endif()
-
foreach(unsuitable_version ${unsuitable_versions})
if(CMAKE_VERSION VERSION_EQUAL unsuitable_version)
message(WARNING
diff --git a/cmake/QtCompilerFlags.cmake b/cmake/QtCompilerFlags.cmake
index 15327374b3..f58f36b7a2 100644
--- a/cmake/QtCompilerFlags.cmake
+++ b/cmake/QtCompilerFlags.cmake
@@ -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: BSD-3-Clause
# Enable compiler warnings by default. All compilers except MSVC support -Wall -Wextra
#
@@ -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 813b16af69..ac542e9451 100644
--- a/cmake/QtCompilerOptimization.cmake
+++ b/cmake/QtCompilerOptimization.cmake
@@ -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: BSD-3-Clause
if (MSVC)
if (QT_64BIT)
@@ -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
@@ -73,7 +78,7 @@ endif()
# TODO: Missing mkspecs flags we don't handle below: win32-clang-g++, win32-clang-msvc, rtems-base
#
# gcc and clang base
-if(GCC OR CLANG AND NOT WASM)
+if(GCC OR CLANG)
set(QT_CFLAGS_OPTIMIZE "-O2")
set(QT_CFLAGS_OPTIMIZE_FULL "-O3")
set(QT_CFLAGS_OPTIMIZE_DEBUG "-Og")
@@ -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")
@@ -121,12 +131,8 @@ if (QCC)
set(QT_CFLAGS_OPTIMIZE_FULL "-O3")
endif()
+# Emscripten Clang
if(WASM)
- set(QT_CFLAGS_OPTIMIZE "-O2")
- set(QT_CFLAGS_OPTIMIZE_FULL "-O3")
- set(QT_CFLAGS_OPTIMIZE_SIZE "-Os")
- set(QT_CFLAGS_OPTIMIZE_DEBUG "-g2")
-
- set(QT_CFLAGS_SSE2 -O2 -msimd128 -msse -msse2)
-
+ set(QT_CFLAGS_OPTIMIZE_DEBUG "-O2 -g") # -Og is not supported
+ set(QT_CFLAGS_SSE2 "-O2 -msimd128 -msse -msse2")
endif()
diff --git a/cmake/QtConfig.cmake.in b/cmake/QtConfig.cmake.in
index ea92d180b5..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,13 +39,26 @@ 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.
+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
@@ -43,85 +66,15 @@ set(QT_ADDITIONAL_PACKAGES_PREFIX_PATH "" CACHE STRING
set(QT_ADDITIONAL_HOST_PACKAGES_PREFIX_PATH "" CACHE STRING
"Additional directories where find(Qt6 ...) host Qt components are searched")
-# 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".
-function(__qt_internal_collect_additional_prefix_paths out_var prefixes_var)
- if(DEFINED "${out_var}")
- return()
- endif()
-
- set(additional_packages_prefix_paths "")
-
- set(additional_packages_prefixes "")
- if(${prefixes_var})
- list(APPEND additional_packages_prefixes ${${prefixes_var}})
- endif()
- if(DEFINED ENV{${prefixes_var}}
- AND NOT "$ENV{${prefixes_var}}" STREQUAL "")
- set(prefixes_from_env "$ENV{${prefixes_var}}")
- if(NOT CMAKE_HOST_WIN32)
- string(REPLACE ":" ";" prefixes_from_env "${prefixes_from_env}")
- endif()
- list(APPEND additional_packages_prefixes ${prefixes_from_env})
- endif()
-
- foreach(additional_path IN LISTS additional_packages_prefixes)
- file(TO_CMAKE_PATH "${additional_path}" additional_path)
-
- # The prefix paths need to end with lib/cmake to ensure the packages are found when
- # cross compiling. Search for REROOT_PATH_ISSUE_MARKER in the qt.toolchain.cmake file for
- # details.
- # We must pass the values via the PATHS options because the main find_package call uses
- # 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")
- endif()
- list(APPEND additional_packages_prefix_paths "${additional_path}")
- endforeach()
-
- set("${out_var}" "${additional_packages_prefix_paths}" PARENT_SCOPE)
-endfunction()
-
__qt_internal_collect_additional_prefix_paths(_qt_additional_packages_prefix_paths
QT_ADDITIONAL_PACKAGES_PREFIX_PATH)
__qt_internal_collect_additional_prefix_paths(_qt_additional_host_packages_prefix_paths
QT_ADDITIONAL_HOST_PACKAGES_PREFIX_PATH)
-# 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)
- list(APPEND result "${path}")
- endforeach()
- set("${out_var}" "${result}" PARENT_SCOPE)
-endfunction()
-
__qt_internal_prefix_paths_to_roots(_qt_additional_host_packages_root_paths
"${_qt_additional_host_packages_prefix_paths}")
-# Public helpers available to all Qt packages.
-include("${CMAKE_CURRENT_LIST_DIR}/QtFeature.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")
-
-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.
@@ -189,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
new file mode 100644
index 0000000000..17acb37f0e
--- /dev/null
+++ b/cmake/QtConfigureTimeExecutableCMakeLists.txt.in
@@ -0,0 +1,26 @@
+# 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)
+
+set(packages "@packages@")
+set(defines @defines@)
+set(compile_options @compile_options@)
+set(link_options @link_options@)
+set(output_directory @output_directory@)
+
+foreach(package IN LISTS packages)
+ find_package(${package} REQUIRED)
+endforeach()
+
+add_executable(@configure_time_target@ @win32@ @macosx_bundle@ @sources@)
+set_target_properties(@configure_time_target@ PROPERTIES
+ INCLUDE_DIRECTORIES "@include_directories@"
+ RUNTIME_OUTPUT_DIRECTORY "${output_directory}"
+)
+
+target_compile_options(@configure_time_target@ PRIVATE ${compile_options})
+target_compile_definitions(@configure_time_target@ PRIVATE ${defines})
+target_link_options(@configure_time_target@ PRIVATE ${link_options})
diff --git a/cmake/QtCopyFileIfDifferent.cmake b/cmake/QtCopyFileIfDifferent.cmake
index 351dc6e2d0..a27221ece8 100644
--- a/cmake/QtCopyFileIfDifferent.cmake
+++ b/cmake/QtCopyFileIfDifferent.cmake
@@ -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: BSD-3-Clause
# copy_if_different works incorrect in Windows if file size if bigger than 2GB.
# See https://gitlab.kitware.com/cmake/cmake/-/issues/23052 and QTBUG-99491 for details.
diff --git a/cmake/QtDbusHelpers.cmake b/cmake/QtDbusHelpers.cmake
index 81ebfa8b3d..26e98eff27 100644
--- a/cmake/QtDbusHelpers.cmake
+++ b/cmake/QtDbusHelpers.cmake
@@ -1,9 +1,14 @@
# 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: BSD-3-Clause
# helper to set up a qdbusxml2cpp rule
function(qt_create_qdbusxml2cpp_command target infile)
- qt_parse_all_arguments(arg "qt_create_qdbusxml2cpp_command" "ADAPTOR;INTERFACE" "BASENAME" "FLAGS" ${ARGN})
+ cmake_parse_arguments(PARSE_ARGV 2 arg
+ "ADAPTOR;INTERFACE"
+ "BASENAME"
+ "FLAGS")
+ _qt_internal_validate_all_args_are_parsed(arg)
+
if((arg_ADAPTOR AND arg_INTERFACE) OR (NOT arg_ADAPTOR AND NOT arg_INTERFACE))
message(FATAL_ERROR "qt_create_dbusxml2cpp_command needs either ADAPTOR or INTERFACE.")
endif()
@@ -55,6 +60,7 @@ function(qt_create_qdbusxml2cpp_command target infile)
"${header_file}:${source_file}" "${absolute_in_file_path}"
DEPENDS "${absolute_in_file_path}" ${QT_CMAKE_EXPORT_NAMESPACE}::qdbusxml2cpp
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
+ COMMAND_EXPAND_LISTS
VERBATIM)
target_sources("${target}" PRIVATE
diff --git a/cmake/QtDeferredDependenciesHelpers.cmake b/cmake/QtDeferredDependenciesHelpers.cmake
index 2391150f90..b233865727 100644
--- a/cmake/QtDeferredDependenciesHelpers.cmake
+++ b/cmake/QtDeferredDependenciesHelpers.cmake
@@ -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: BSD-3-Clause
# Defers the connection 'dependent' -> 'dependency'
#
diff --git a/cmake/QtDocsHelpers.cmake b/cmake/QtDocsHelpers.cmake
index d08c2c2b85..8b631e88ca 100644
--- a/cmake/QtDocsHelpers.cmake
+++ b/cmake/QtDocsHelpers.cmake
@@ -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: BSD-3-Clause
# This function adds a dependency between a doc-generating target like 'generate_docs_Gui'
# and the necessary tool target like 'qdoc'.
@@ -21,14 +21,39 @@ 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
+ # If a target is not built (which can happen for tools when crosscompiling), we shouldn't try
# to generate docs.
if(NOT TARGET "${target}")
return()
@@ -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()
@@ -140,6 +166,10 @@ function(qt_internal_add_docs)
)
add_dependencies(prepare_docs_${target} qattributionsscanner_${target})
+ if(NOT TARGET sync_all_public_headers)
+ add_custom_target(sync_all_public_headers)
+ endif()
+ add_dependencies(prepare_docs_${target} sync_all_public_headers)
# generate docs target
set(generate_qdoc_args
@@ -152,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 a235c9bb36..fb96ca4db2 100644
--- a/cmake/QtExecutableHelpers.cmake
+++ b/cmake/QtExecutableHelpers.cmake
@@ -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: BSD-3-Clause
# This function creates a CMake target for a generic console or GUI binary.
# Please consider to use a more specific version target like the one created
@@ -12,11 +12,11 @@
# Qt::Core or Qt::Bootstrap libraries. Otherwise the Qt::Core library will be publicly
# linked to the executable target by default.
function(qt_internal_add_executable name)
- qt_parse_all_arguments(arg "qt_internal_add_executable"
+ cmake_parse_arguments(PARSE_ARGV 1 arg
"${__qt_internal_add_executable_optional_args}"
"${__qt_internal_add_executable_single_args}"
- "${__qt_internal_add_executable_multi_args}"
- ${ARGN})
+ "${__qt_internal_add_executable_multi_args}")
+ _qt_internal_validate_all_args_are_parsed(arg)
if ("x${arg_OUTPUT_DIRECTORY}" STREQUAL "x")
set(arg_OUTPUT_DIRECTORY "${QT_BUILD_DIR}/${INSTALL_BINDIR}")
@@ -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()
@@ -39,11 +40,6 @@ function(qt_internal_add_executable name)
PROPERTY EXCLUDE_FROM_ALL "$<NOT:$<CONFIG:${QT_MULTI_CONFIG_FIRST_CONFIG}>>")
endif()
- if(WASM)
- qt_internal_wasm_add_finalizers("${name}")
- _qt_internal_wasm_add_target_helpers("${name}")
- endif()
-
if (arg_VERSION)
if(arg_VERSION MATCHES "[0-9]+\\.[0-9]+\\.[0-9]+\\.[0-9]+")
# nothing to do
@@ -69,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)
@@ -115,8 +111,17 @@ function(qt_internal_add_executable name)
"removed in a future Qt version. Use the LIBRARIES option instead.")
endif()
+ if(arg_NO_UNITY_BUILD)
+ set(arg_NO_UNITY_BUILD "NO_UNITY_BUILD")
+ else()
+ set(arg_NO_UNITY_BUILD "")
+ 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
@@ -124,10 +129,10 @@ function(qt_internal_add_executable name)
${arg_PUBLIC_LIBRARIES}
Qt::PlatformCommonInternal
${extra_libraries}
- DBUS_ADAPTOR_SOURCES "${arg_DBUS_ADAPTOR_SOURCES}"
- DBUS_ADAPTOR_FLAGS "${arg_DBUS_ADAPTOR_FLAGS}"
- DBUS_INTERFACE_SOURCES "${arg_DBUS_INTERFACE_SOURCES}"
- DBUS_INTERFACE_FLAGS "${arg_DBUS_INTERFACE_FLAGS}"
+ DBUS_ADAPTOR_SOURCES ${arg_DBUS_ADAPTOR_SOURCES}
+ DBUS_ADAPTOR_FLAGS ${arg_DBUS_ADAPTOR_FLAGS}
+ DBUS_INTERFACE_SOURCES ${arg_DBUS_INTERFACE_SOURCES}
+ DBUS_INTERFACE_FLAGS ${arg_DBUS_INTERFACE_FLAGS}
COMPILE_OPTIONS ${arg_COMPILE_OPTIONS}
LINK_OPTIONS ${arg_LINK_OPTIONS}
MOC_OPTIONS ${arg_MOC_OPTIONS}
@@ -143,6 +148,10 @@ function(qt_internal_add_executable name)
qt_internal_set_exceptions_flags("${name}" ${arg_EXCEPTIONS})
+ if(WASM)
+ qt_internal_wasm_add_finalizers("${name}")
+ endif()
+
# Check if target needs to be excluded from all target. Also affects qt_install.
# Set by qt_exclude_tool_directories_from_default_target.
set(exclude_from_all FALSE)
@@ -296,3 +305,233 @@ Q_IMPORT_PLUGIN($<JOIN:${class_names},)\nQ_IMPORT_PLUGIN(>)
endforeach()
endfunction()
+
+# This function compiles the target at configure time the very first time and creates the custom
+# ${target}_build that re-runs compilation at build time if necessary. The resulting executable is
+# imported under the provided target name. This function should only be used to compile tiny
+# executables with system dependencies only.
+# One-value Arguments:
+# CMAKELISTS_TEMPLATE
+# The CMakeLists.txt templated that is used to configure the project
+# for an executable. By default the predefined template from the Qt installation is used.
+# INSTALL_DIRECTORY
+# installation directory of the executable. Ignored if NO_INSTALL is set.
+# OUTPUT_NAME
+# the output name of an executable
+# CONFIG
+# the name of configuration that tool needs to be build with.
+# Multi-value Arguments:
+# PACKAGES
+# list of system packages are required to successfully build the project.
+# INCLUDES
+# list of include directories are required to successfully build the project.
+# DEFINES
+# list of definitions are required to successfully build the project.
+# COMPILE_OPTIONS
+# list of compiler options are required to successfully build the project.
+# LINK_OPTIONS
+# list of linker options are required to successfully build the project.
+# SOURCES
+# list of project sources.
+# CMAKE_FLAGS
+# specify flags of the form -DVAR:TYPE=VALUE to be passed to the cmake command-line used to
+# drive the test build.
+# Options:
+# WIN32
+# reflects the corresponding add_executable argument.
+# MACOSX_BUNDLE
+# reflects the corresponding add_executable argument.
+# NO_INSTALL
+# avoids installing the tool.
+function(qt_internal_add_configure_time_executable target)
+ set(one_value_args
+ CMAKELISTS_TEMPLATE
+ INSTALL_DIRECTORY
+ OUTPUT_NAME
+ CONFIG
+ )
+ set(multi_value_args
+ PACKAGES
+ INCLUDES
+ DEFINES
+ COMPILE_OPTIONS
+ LINK_OPTIONS
+ SOURCES
+ CMAKE_FLAGS
+ )
+ set(option_args WIN32 MACOSX_BUNDLE NO_INSTALL)
+ cmake_parse_arguments(PARSE_ARGV 1 arg
+ "${option_args}" "${one_value_args}" "${multi_value_args}")
+
+ 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)
+ if(is_multi_config AND CMAKE_TRY_COMPILE_CONFIGURATION)
+ set(configuration_path "${CMAKE_TRY_COMPILE_CONFIGURATION}/")
+ set(config_build_arg "--config" "${CMAKE_TRY_COMPILE_CONFIGURATION}")
+ endif()
+
+ set(configure_time_target "${target}")
+ if(arg_OUTPUT_NAME)
+ set(configure_time_target "${arg_OUTPUT_NAME}")
+ endif()
+ set(target_binary "${configure_time_target}${CMAKE_EXECUTABLE_SUFFIX}")
+
+ set(install_dir "${INSTALL_BINDIR}")
+ 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)
+ message(FATAL_ERROR "No SOURCES given to target: ${target}")
+ endif()
+ set(sources "${arg_SOURCES}")
+
+ # Timestamp file is required because CMake ignores 'add_custom_command' if we use only the
+ # binary file as the OUTPUT.
+ 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}" --clean-first ${config_build_arg}
+ COMMAND
+ ${CMAKE_COMMAND} -E touch "${timestamp_file}"
+ DEPENDS
+ ${sources}
+ COMMENT
+ "Compiling ${target}"
+ VERBATIM
+ )
+
+ add_custom_target(${target}_build ALL
+ DEPENDS
+ "${target_binary_path}"
+ "${timestamp_file}"
+ )
+
+ set(should_build_at_configure_time TRUE)
+ 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")
+ if(${ts} GREATER ${last_ts})
+ set(last_ts ${ts})
+ endif()
+ endforeach()
+
+ file(TIMESTAMP "${target_binary_path}" ts "%s")
+ if(${ts} GREATER_EQUAL ${last_ts})
+ set(should_build_at_configure_time FALSE)
+ 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)
+ set(${template_arg_name} "")
+ if(DEFINED arg_${arg})
+ set(${template_arg_name} "${arg_${arg}}")
+ endif()
+ endforeach()
+
+ foreach(arg IN LISTS option_args)
+ string(TOLOWER "${arg}" template_arg_name)
+ set(${template_arg_name} "")
+ if(arg_${arg})
+ set(${template_arg_name} "${arg}")
+ endif()
+ endforeach()
+
+ file(MAKE_DIRECTORY "${target_binary_dir}")
+ set(template "${QT_CMAKE_DIR}/QtConfigureTimeExecutableCMakeLists.txt.in")
+ if(DEFINED arg_CMAKELISTS_TEMPLATE)
+ set(template "${arg_CMAKELISTS_TEMPLATE}")
+ 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}"
+ ${target}
+ ${cmake_flags_arg}
+ 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()
+ endif()
+
+ add_executable(${target} IMPORTED GLOBAL)
+ add_executable(${QT_CMAKE_EXPORT_NAMESPACE}::${target} ALIAS ${target})
+ set_target_properties(${target} PROPERTIES
+ _qt_internal_configure_time_target TRUE
+ _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
+ _qt_internal_configure_time_target_install_location
+ "${install_dir}/${target_binary}"
+ )
+ qt_path_join(target_install_dir ${QT_INSTALL_DIR} ${install_dir})
+ qt_install(PROGRAMS "${target_binary_path}" DESTINATION "${target_install_dir}")
+ endif()
+endfunction()
diff --git a/cmake/QtFeature.cmake b/cmake/QtFeature.cmake
index 89ae7598e5..96cb308b2c 100644
--- a/cmake/QtFeature.cmake
+++ b/cmake/QtFeature.cmake
@@ -1,13 +1,14 @@
# 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: BSD-3-Clause
-include(QtFeatureCommon)
include(CheckCXXCompilerFlag)
function(qt_feature_module_begin)
- qt_parse_all_arguments(arg "qt_feature_module_begin"
+ cmake_parse_arguments(PARSE_ARGV 0 arg
"NO_MODULE;ONLY_EVALUATE_FEATURES"
- "LIBRARY;PRIVATE_FILE;PUBLIC_FILE" "PUBLIC_DEPENDENCIES;PRIVATE_DEPENDENCIES" ${ARGN})
+ "LIBRARY;PRIVATE_FILE;PUBLIC_FILE"
+ "PUBLIC_DEPENDENCIES;PRIVATE_DEPENDENCIES")
+ _qt_internal_validate_all_args_are_parsed(arg)
if(NOT arg_ONLY_EVALUATE_FEATURES)
if ("${arg_LIBRARY}" STREQUAL "" AND (NOT ${arg_NO_MODULE}))
@@ -46,9 +47,11 @@ function(qt_feature feature)
qt_feature_normalize_name("${feature}" feature)
set_property(GLOBAL PROPERTY QT_FEATURE_ORIGINAL_NAME_${feature} "${original_name}")
- qt_parse_all_arguments(arg "qt_feature"
+ cmake_parse_arguments(PARSE_ARGV 1 arg
"PRIVATE;PUBLIC"
- "LABEL;PURPOSE;SECTION;" "AUTODETECT;CONDITION;ENABLE;DISABLE;EMIT_IF" ${ARGN})
+ "LABEL;PURPOSE;SECTION"
+ "AUTODETECT;CONDITION;ENABLE;DISABLE;EMIT_IF")
+ _qt_internal_validate_all_args_are_parsed(arg)
set(_QT_FEATURE_DEFINITION_${feature} ${ARGN} PARENT_SCOPE)
@@ -77,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})
@@ -140,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
@@ -160,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().
@@ -170,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")
@@ -235,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}}")
- set(result "${user_value}")
+ 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)
@@ -295,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.
@@ -330,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)
@@ -370,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 "")
@@ -397,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)
@@ -410,9 +444,67 @@ 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)
- qt_parse_all_arguments(arg "qt_feature_config" "NEGATE" "NAME" "" ${ARGN})
+ cmake_parse_arguments(PARSE_ARGV 2 arg
+ "NEGATE"
+ "NAME"
+ "")
+ _qt_internal_validate_all_args_are_parsed(arg)
# Store all the config related info in a unique variable key.
set(key_name "_QT_FEATURE_CONFIG_DEFINITION_${feature}_${config_var_name}")
@@ -472,7 +564,11 @@ endfunction()
function(qt_feature_definition feature name)
qt_feature_normalize_name("${feature}" feature)
- qt_parse_all_arguments(arg "qt_feature_definition" "NEGATE" "VALUE;PREREQUISITE" "" ${ARGN})
+ cmake_parse_arguments(PARSE_ARGV 2 arg
+ "NEGATE"
+ "VALUE;PREREQUISITE"
+ "")
+ _qt_internal_validate_all_args_are_parsed(arg)
# Store all the define related info in a unique variable key.
set(key_name "_QT_FEATURE_DEFINE_DEFINITION_${feature}_${name}")
@@ -528,7 +624,11 @@ function(qt_evaluate_feature_definition key)
endfunction()
function(qt_extra_definition name value)
- qt_parse_all_arguments(arg "qt_extra_definition" "PUBLIC;PRIVATE" "" "" ${ARGN})
+ cmake_parse_arguments(PARSE_ARGV 2 arg
+ "PUBLIC;PRIVATE"
+ ""
+ "")
+ _qt_internal_validate_all_args_are_parsed(arg)
if (arg_PUBLIC)
string(APPEND __QtFeature_public_extra "\n#define ${name} ${value}\n")
@@ -662,22 +762,6 @@ function(qt_feature_module_end)
)
endif()
- # Extra header injections which have to have forwarding headers created by
- # qt_install_injections.
- # Skip creating forwarding headers if qt_feature_module_begin was called with NO_MODULE, aka
- # there is no include/<module_name> so there's no place to put the forwarding headers.
- if(__QtFeature_library)
- set(injections "")
- qt_compute_injection_forwarding_header("${__QtFeature_library}"
- SOURCE "${__QtFeature_public_file}"
- OUT_VAR injections)
- qt_compute_injection_forwarding_header("${__QtFeature_library}"
- SOURCE "${__QtFeature_private_file}" PRIVATE
- OUT_VAR injections)
-
- set(${arg_OUT_VAR_PREFIX}extra_library_injections ${injections} PARENT_SCOPE)
- endif()
-
if (NOT ("${target}" STREQUAL "NO_MODULE") AND NOT arg_ONLY_EVALUATE_FEATURES)
get_target_property(targetType "${target}" TYPE)
if("${targetType}" STREQUAL "INTERFACE_LIBRARY")
@@ -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")
@@ -924,6 +1045,7 @@ function(qt_config_compile_test name)
# fail instead of cmake abort later via CMAKE_REQUIRED_LIBRARIES.
string(FIND "${library}" "::" cmake_target_namespace_separator)
if(NOT cmake_target_namespace_separator EQUAL -1)
+ message(STATUS "Performing Test ${arg_LABEL} - Failed because ${library} not found")
set(HAVE_${name} FALSE)
break()
endif()
@@ -953,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()
@@ -974,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}")
@@ -986,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()
@@ -1006,6 +1141,7 @@ function(qt_get_platform_try_compile_vars out_var)
list(APPEND flags "CMAKE_CXX_FLAGS_RELEASE")
list(APPEND flags "CMAKE_CXX_FLAGS_RELWITHDEBINFO")
list(APPEND flags "CMAKE_OBJCOPY")
+ list(APPEND flags "CMAKE_EXE_LINKER_FLAGS")
# Pass toolchain files.
if(CMAKE_TOOLCHAIN_FILE)
@@ -1022,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()
@@ -1056,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)
@@ -1223,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/QtFeatureCommon.cmake b/cmake/QtFeatureCommon.cmake
index 097baa3401..9b49d4fcac 100644
--- a/cmake/QtFeatureCommon.cmake
+++ b/cmake/QtFeatureCommon.cmake
@@ -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: BSD-3-Clause
function(qt_feature_normalize_name name out_var)
# Normalize the feature name to something CMake can deal with.
diff --git a/cmake/QtFindPackageHelpers.cmake b/cmake/QtFindPackageHelpers.cmake
index 6fae5346da..dd10bde75a 100644
--- a/cmake/QtFindPackageHelpers.cmake
+++ b/cmake/QtFindPackageHelpers.cmake
@@ -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: BSD-3-Clause
# This function recursively walks transitive link libraries of the given target
# and promotes those targets to be IMPORTED_GLOBAL if they are not.
@@ -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)
@@ -34,6 +43,20 @@ macro(qt_find_package)
# qt_find_package(PNG PROVIDED_TARGET PNG::PNG) still needs to succeed and register the provided
# targets. To enable the debugging behavior, set QT_DEBUG_QT_FIND_PACKAGE to 1.
set(_qt_find_package_skip_find_package FALSE)
+
+ # Skip looking for packages that were not found on initial configuration, because they likely
+ # won't be found again, and only waste configuration time.
+ # Speeds up reconfiguration configuration for certain platforms and repos.
+ # 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
+ 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})
@@ -141,6 +164,11 @@ macro(qt_find_package)
endif()
endif()
+ if(${ARGV0}_FOUND)
+ # Record that the package was found, so that future reconfigurations can be sped up.
+ set_property(GLOBAL APPEND PROPERTY _qt_previously_found_packages "${ARGV0}")
+ endif()
+
if(${ARGV0}_FOUND AND arg_PROVIDED_TARGETS AND NOT _qt_find_package_skip_find_package)
# If package was found, associate each target with its package name. This will be used
# later when creating Config files for Qt libraries, to generate correct find_dependency()
@@ -200,6 +228,46 @@ macro(qt_find_package)
endif()
endmacro()
+# 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_visited_packages)
+ if(DEFINED QT_INTERNAL_SAVE_PREVIOUSLY_FOUND_PACKAGES)
+ set(should_save "${QT_INTERNAL_SAVE_PREVIOUSLY_FOUND_PACKAGES}")
+ else()
+ if(FEATURE_developer_build OR QT_FEATURE_developer_build)
+ set(should_save ON)
+ else()
+ set(should_save OFF)
+ endif()
+ endif()
+
+ 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()
+
+ get_property(_qt_previously_found_packages GLOBAL PROPERTY _qt_previously_found_packages)
+ if(_qt_previously_found_packages)
+ list(REMOVE_DUPLICATES _qt_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".
function(qt_internal_map_target_to_qmake_lib target out_var)
set(${out_var} "${QT_QMAKE_LIB_OF_TARGET_${target}}" PARENT_SCOPE)
@@ -447,8 +515,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}")
@@ -464,8 +539,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 e9923b358e..a8d3da49d1 100644
--- a/cmake/QtFindWrapHelper.cmake
+++ b/cmake/QtFindWrapHelper.cmake
@@ -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: BSD-3-Clause
# Creates an imported wrapper target that links against either a Qt bundled package
# or a system package.
diff --git a/cmake/QtFinishPkgConfigFile.cmake b/cmake/QtFinishPkgConfigFile.cmake
index 1c5b424d6c..3799621400 100644
--- a/cmake/QtFinishPkgConfigFile.cmake
+++ b/cmake/QtFinishPkgConfigFile.cmake
@@ -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: BSD-3-Clause
# Finish a preliminary .pc file.
#
diff --git a/cmake/QtFinishPrlFile.cmake b/cmake/QtFinishPrlFile.cmake
index 2ade4e625f..1cf9377e6c 100644
--- a/cmake/QtFinishPrlFile.cmake
+++ b/cmake/QtFinishPrlFile.cmake
@@ -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: BSD-3-Clause
# Finish a preliminary .prl file.
#
diff --git a/cmake/QtFlagHandlingHelpers.cmake b/cmake/QtFlagHandlingHelpers.cmake
index 708496fb85..6a62b85c03 100644
--- a/cmake/QtFlagHandlingHelpers.cmake
+++ b/cmake/QtFlagHandlingHelpers.cmake
@@ -1,27 +1,79 @@
# 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: 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:
-# PRIVATE_HEADERS specifies the list of header files that are used to generate
-# Qt_<version>_PRIVATE_API section. Requires perl.
# PRIVATE_CONTENT_FILE specifies the pre-cooked content of Qt_<version>_PRIVATE_API section.
# Requires the content file available at build time.
function(qt_internal_add_linker_version_script target)
- qt_parse_all_arguments(arg "qt_internal_add_linker_version_script"
+ if(WASM)
+ return()
+ endif()
+
+ cmake_parse_arguments(PARSE_ARGV 1 arg
""
"PRIVATE_CONTENT_FILE"
"PRIVATE_HEADERS"
- ${ARGN}
)
+ _qt_internal_validate_all_args_are_parsed(arg)
if(arg_PRIVATE_CONTENT_FILE AND arg_PRIVATE_HEADERS)
message(FATAL_ERROR "Both PRIVATE_CONTENT_FILE and PRIVATE_HEADERS are specified.")
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")
@@ -31,53 +83,46 @@ 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")
file(GENERATE OUTPUT "${infile}" CONTENT "${contents}")
- if(arg_PRIVATE_HEADERS)
- qt_ensure_perl()
- set(generator_command "${HOST_PERL}"
- "${QT_MKSPECS_DIR}/features/data/unix/findclasslist.pl"
- "<" "${infile}" ">" "${outfile}"
- )
- set(generator_dependencies
- "${infile}"
- "${QT_MKSPECS_DIR}/features/data/unix/findclasslist.pl"
- )
- else()
- if(NOT arg_PRIVATE_CONTENT_FILE)
- set(arg_PRIVATE_CONTENT_FILE "")
- endif()
- set(generator_command ${CMAKE_COMMAND}
- "-DIN_FILE=${infile}"
- "-DPRIVATE_CONTENT_FILE=${arg_PRIVATE_CONTENT_FILE}"
- "-DOUT_FILE=${outfile}"
- -P "${QT_CMAKE_DIR}/QtGenerateVersionScript.cmake"
- )
- set(generator_dependencies
- "${arg_PRIVATE_CONTENT_FILE}"
- "${QT_CMAKE_DIR}/QtGenerateVersionScript.cmake"
- )
+ if(NOT arg_PRIVATE_CONTENT_FILE)
+ set(arg_PRIVATE_CONTENT_FILE "")
endif()
+ set(generator_command ${CMAKE_COMMAND}
+ "-DIN_FILE=${infile}"
+ "-DPRIVATE_CONTENT_FILE=${arg_PRIVATE_CONTENT_FILE}"
+ "-DOUT_FILE=${outfile}"
+ -P "${QT_CMAKE_DIR}/QtGenerateVersionScript.cmake"
+ )
+ set(generator_dependencies
+ "${arg_PRIVATE_CONTENT_FILE}"
+ "${QT_CMAKE_DIR}/QtGenerateVersionScript.cmake"
+ )
add_custom_command(
OUTPUT "${outfile}"
@@ -94,7 +139,18 @@ function(qt_internal_add_linker_version_script target)
endfunction()
function(qt_internal_add_link_flags_no_undefined target)
- if (NOT QT_BUILD_SHARED_LIBS)
+ 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)
@@ -134,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")
@@ -147,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()
@@ -166,13 +241,17 @@ 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}")
@@ -210,21 +289,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()
@@ -297,14 +376,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)
@@ -324,7 +404,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()
@@ -536,13 +616,11 @@ endfunction()
# LANGUAGES - optional list of languages like 'C', 'CXX', for which to remove the flags
# if not provided, defaults to the list of enabled C-like languages
function(qt_internal_remove_known_optimization_flags)
- qt_parse_all_arguments(
- arg
- "qt_internal_remove_known_optimization_flags"
+ cmake_parse_arguments(PARSE_ARGV 0 arg
"IN_CACHE"
""
- "CONFIGS;LANGUAGES"
- ${ARGN})
+ "CONFIGS;LANGUAGES")
+ _qt_internal_validate_all_args_are_parsed(arg)
if(NOT arg_CONFIGS)
message(FATAL_ERROR
@@ -569,20 +647,27 @@ 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)
- qt_parse_all_arguments(arg
- "qt_internal_remove_compiler_flags"
+ cmake_parse_arguments(PARSE_ARGV 1 arg
"IN_CACHE;REGEX"
""
"CONFIGS;LANGUAGES"
- ${ARGN}
)
+ _qt_internal_validate_all_args_are_parsed(arg)
if("${flags}" STREQUAL "")
message(WARNING "qt_internal_remove_compiler_flags was called without any flags specified.")
@@ -598,8 +683,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)
@@ -637,13 +721,11 @@ endfunction()
# LANGUAGES - optional list of languages like 'C', 'CXX', for which to add the flags
# if not provided, defaults to the list of enabled C-like languages
function(qt_internal_add_compiler_flags)
- qt_parse_all_arguments(
- arg
- "qt_internal_add_compiler_flags"
+ cmake_parse_arguments(PARSE_ARGV 0 arg
"IN_CACHE"
"FLAGS"
- "CONFIGS;LANGUAGES"
- ${ARGN})
+ "CONFIGS;LANGUAGES")
+ _qt_internal_validate_all_args_are_parsed(arg)
if(NOT arg_CONFIGS)
message(FATAL_ERROR
@@ -680,13 +762,11 @@ endfunction()
# LANGUAGES - optional list of languages like 'C', 'CXX', for which to add the flags
# if not provided, defaults to the list of enabled C-like languages
function(qt_internal_add_compiler_flags_for_release_configs)
- qt_parse_all_arguments(
- arg
- "qt_internal_add_compiler_flags_for_release_configs"
+ cmake_parse_arguments(PARSE_ARGV 0 arg
"IN_CACHE"
"FLAGS"
- "LANGUAGES"
- ${ARGN})
+ "LANGUAGES")
+ _qt_internal_validate_all_args_are_parsed(arg)
set(args "")
@@ -726,13 +806,11 @@ endfunction()
# It is meant to be called in a subdirectory scope to enable full optimizations for a particular
# Qt module, like Core or Gui.
function(qt_internal_add_optimize_full_flags)
- qt_parse_all_arguments(
- arg
- "qt_internal_add_optimize_full_flags"
+ cmake_parse_arguments(PARSE_ARGV 0 arg
"IN_CACHE"
""
- ""
- ${ARGN})
+ "")
+ _qt_internal_validate_all_args_are_parsed(arg)
# QT_USE_DEFAULT_CMAKE_OPTIMIZATION_FLAGS disables forced full optimization.
if(QT_USE_DEFAULT_CMAKE_OPTIMIZATION_FLAGS)
@@ -788,13 +866,11 @@ endfunction()
# LANGUAGES - optional list of languages like 'C', 'CXX', for which to replace the flags
# if not provided, defaults to the list of enabled C-like languages
function(qt_internal_replace_compiler_flags match_string replace_string)
- qt_parse_all_arguments(
- arg
- "qt_internal_replace_compiler_flags"
+ cmake_parse_arguments(PARSE_ARGV 2 arg
"IN_CACHE"
""
- "CONFIGS;LANGUAGES"
- ${ARGN})
+ "CONFIGS;LANGUAGES")
+ _qt_internal_validate_all_args_are_parsed(arg)
if(NOT arg_CONFIGS)
message(FATAL_ERROR
@@ -829,13 +905,11 @@ endfunction()
# CMAKE_<LINKER_TYPE>_LINKER_FLAGS_<CONFIG> cache variable.
# e.g EXE, MODULE, SHARED, STATIC.
function(qt_internal_add_linker_flags)
- qt_parse_all_arguments(
- arg
- "qt_internal_add_linker_flags"
+ cmake_parse_arguments(PARSE_ARGV 0 arg
"IN_CACHE"
"FLAGS"
- "CONFIGS;TYPES"
- ${ARGN})
+ "CONFIGS;TYPES")
+ _qt_internal_validate_all_args_are_parsed(arg)
if(NOT arg_TYPES)
message(FATAL_ERROR
@@ -876,13 +950,11 @@ endfunction()
# CMAKE_<LINKER_TYPE>_LINKER_FLAGS_<CONFIG> cache variable.
# e.g EXE, MODULE, SHARED, STATIC.
function(qt_internal_replace_linker_flags match_string replace_string)
- qt_parse_all_arguments(
- arg
- "qt_internal_replace_compiler_flags"
+ cmake_parse_arguments(PARSE_ARGV 2 arg
"IN_CACHE"
""
- "CONFIGS;TYPES"
- ${ARGN})
+ "CONFIGS;TYPES")
+ _qt_internal_validate_all_args_are_parsed(arg)
if(NOT arg_TYPES)
message(FATAL_ERROR
@@ -1017,14 +1089,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 c90e2c1623..750caf2cb8 100644
--- a/cmake/QtFrameworkHelpers.cmake
+++ b/cmake/QtFrameworkHelpers.cmake
@@ -1,10 +1,12 @@
# 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: BSD-3-Clause
macro(qt_find_apple_system_frameworks)
if(APPLE)
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)
@@ -31,6 +33,11 @@ macro(qt_find_apple_system_frameworks)
qt_internal_find_apple_system_framework(FWWatchKit WatchKit)
qt_internal_find_apple_system_framework(FWGameController GameController)
qt_internal_find_apple_system_framework(FWCoreBluetooth CoreBluetooth)
+ qt_internal_find_apple_system_framework(FWAVFoundation AVFoundation)
+ 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()
@@ -53,7 +60,7 @@ function(qt_internal_find_apple_system_framework out_var framework_name)
endif()
endfunction()
-# Copy header files to QtXYZ.framework/Versions/A/Headers/
+# Copy header files to the framework's Headers directory
# Use this function for header files that
# - are not added as source files to the target
# - are not marked as PUBLIC_HEADER
@@ -66,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})
@@ -74,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}"
+ )
+
+ if(CMAKE_GENERATOR MATCHES "^Ninja")
+ add_custom_command(
+ OUTPUT "${output_dir}/${fw_versioned_header_dir}"
+ DEPENDS ${target}_sync_headers
+ COMMAND ${copy_fw_sync_headers_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})
+ 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)
+ # Hack to create the "Headers" symlink in the framework:
+ # Create a fake header file and copy it into the framework by marking it as PUBLIC_HEADER.
+ # CMake now takes care of creating the symlink.
+ set(fake_header "${CMAKE_CURRENT_BINARY_DIR}/${target}_fake_header.h")
+ qt_internal_get_main_cmake_configuration(main_config)
+ file(GENERATE OUTPUT "${fake_header}" CONTENT "// ignore this file\n"
+ CONDITION "$<CONFIG:${main_config}>")
+ target_sources(${target} PRIVATE "${fake_header}")
+ set_source_files_properties("${fake_header}" PROPERTIES GENERATED ON)
+ set_property(TARGET ${target} APPEND PROPERTY PUBLIC_HEADER "${fake_header}")
endfunction()
function(qt_finalize_framework_headers_copy target)
@@ -108,17 +170,7 @@ function(qt_finalize_framework_headers_copy target)
endif()
get_target_property(headers ${target} QT_COPIED_FRAMEWORK_HEADERS)
if(headers)
- # Hack to create the "Headers" symlink in the framework:
- # Create a fake header file and copy it into the framework by marking it as PUBLIC_HEADER.
- # CMake now takes care of creating the symlink.
- set(fake_header ${target}_fake_header.h)
- qt_internal_get_main_cmake_configuration(main_config)
- file(GENERATE OUTPUT ${fake_header} CONTENT "// ignore this file\n"
- CONDITION "$<CONFIG:${main_config}>")
- string(PREPEND fake_header "${CMAKE_CURRENT_BINARY_DIR}/")
- target_sources(${target} PRIVATE ${fake_header})
- set_source_files_properties(${fake_header} PROPERTIES GENERATED ON)
- set_property(TARGET ${target} APPEND PROPERTY PUBLIC_HEADER ${fake_header})
+ qt_internal_generate_fake_framework_header(${target})
# Add a target, e.g. Core_framework_headers, that triggers the header copy.
add_custom_target(${target}_framework_headers DEPENDS ${headers})
@@ -156,8 +208,13 @@ 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")
- set(${out_var}_versioned_header_dir "${${out_var}_dir}/Versions/${${out_var}_version}/Headers")
- set(${out_var}_private_header_dir "${${out_var}_header_dir}/${${out_var}_bundle_version}")
+ if(UIKIT)
+ # iOS frameworks do not version their headers
+ 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")
+ 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}")
set(${out_var}_name "${${out_var}_name}" PARENT_SCOPE)
diff --git a/cmake/QtGenerateExtPri.cmake b/cmake/QtGenerateExtPri.cmake
index c6f41ac809..b79ef2b721 100644
--- a/cmake/QtGenerateExtPri.cmake
+++ b/cmake/QtGenerateExtPri.cmake
@@ -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: BSD-3-Clause
# Generate a qt_ext_XXX.pri file.
#
diff --git a/cmake/QtGenerateLibHelpers.cmake b/cmake/QtGenerateLibHelpers.cmake
index d711574c10..3ffe354fd8 100644
--- a/cmake/QtGenerateLibHelpers.cmake
+++ b/cmake/QtGenerateLibHelpers.cmake
@@ -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: BSD-3-Clause
# Given "/usr/lib/x86_64-linux-gnu/libcups.so"
# Returns "cups" or an empty string if the file is not an absolute library path.
diff --git a/cmake/QtGenerateLibPri.cmake b/cmake/QtGenerateLibPri.cmake
index 309a218fd1..bde42b7723 100644
--- a/cmake/QtGenerateLibPri.cmake
+++ b/cmake/QtGenerateLibPri.cmake
@@ -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: BSD-3-Clause
# Generate a qt_lib_XXX.pri file.
#
diff --git a/cmake/QtGlobalStateHelpers.cmake b/cmake/QtGlobalStateHelpers.cmake
index 43f785c21e..2df89486c8 100644
--- a/cmake/QtGlobalStateHelpers.cmake
+++ b/cmake/QtGlobalStateHelpers.cmake
@@ -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: BSD-3-Clause
function(qt_internal_clear_qt_repo_known_modules)
set(QT_REPO_KNOWN_MODULES "" CACHE INTERNAL "Known current repo Qt modules" FORCE)
diff --git a/cmake/QtHeadersClean.cmake b/cmake/QtHeadersClean.cmake
index f73c7e409c..f47ac1754c 100644
--- a/cmake/QtHeadersClean.cmake
+++ b/cmake/QtHeadersClean.cmake
@@ -1,29 +1,25 @@
# 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: BSD-3-Clause
# Add a custom ${module_target}_headersclean_check target that builds each header in
# ${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_include_name
- module_headers)
- # module_headers is a list of strings of the form
- # <headerfile>[:feature]
+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()
+ endif()
+
set(hclean_headers "")
- foreach(entry ${module_headers})
- string(REPLACE ":" ";" entry_list ${entry})
- list(LENGTH entry_list entry_list_length)
- list(GET entry_list 0 entry_path)
-
- if (${entry_list_length} EQUAL 2)
- list(GET entry_list 1 entry_feature)
- if (NOT QT_FEATURE_${entry_feature})
- message(STATUS "headersclean: Ignoring header ${entry_path} because of missing feature ${entry_feature}")
- continue()
- endif()
+ foreach(header IN LISTS module_headers)
+ get_filename_component(header_name "${header}" NAME)
+ if(header_name MATCHES "^q[^_]+\\.h$" AND NOT header_name MATCHES ".*(global|exports)\\.h")
+ list(APPEND hclean_headers "${header}")
endif()
- list(APPEND hclean_headers ${entry_path})
endforeach()
# Make sure that the header compiles with our strict options
@@ -31,6 +27,7 @@ function(qt_internal_add_headersclean_target
-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
@@ -42,7 +39,7 @@ function(qt_internal_add_headersclean_target
endif()
set(prop_prefix "")
- get_target_property(target_type "${target}" TYPE)
+ get_target_property(target_type "${module_target}" TYPE)
if(target_type STREQUAL "INTERFACE_LIBRARY")
set(prop_prefix "INTERFACE_")
endif()
@@ -53,6 +50,12 @@ function(qt_internal_add_headersclean_target
set(target_includes_joined_genex
"$<${includes_exist_genex}:-I$<JOIN:${target_includes_genex},;-I>>")
+ get_cmake_property(is_multi_config GENERATOR_IS_MULTI_CONFIG)
+ if(is_multi_config)
+ list(GET CMAKE_CONFIGURATION_TYPES 0 first_config_type)
+ set(config_suffix "$<$<NOT:$<CONFIG:${first_config_type}>>:-$<CONFIG>>")
+ endif()
+
# qmake doesn't seem to add the defines that are set by the header_only_module when checking the
# the cleanliness of the module's header files.
# This allows us to bypass an error with CMake 3.18 and lower when trying to evaluate
@@ -102,41 +105,33 @@ function(qt_internal_add_headersclean_target
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
- -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
+ -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)
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)
@@ -152,10 +147,7 @@ function(qt_internal_add_headersclean_target
# 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}")
@@ -165,76 +157,120 @@ function(qt_internal_add_headersclean_target
endforeach()
endif()
- foreach(header ${hclean_headers})
- get_filename_component(input_path "${header}" ABSOLUTE)
- set(artifact_path "header_check/${header}.o")
- get_filename_component(artifact_directory "${artifact_path}" DIRECTORY)
- set(comment_header_path "${CMAKE_CURRENT_SOURCE_DIR}/${header}")
- file(RELATIVE_PATH comment_header_path "${PROJECT_SOURCE_DIR}" "${comment_header_path}")
-
- add_custom_command(
- OUTPUT "${artifact_path}"
- COMMENT "headersclean: Checking header ${comment_header_path}"
- COMMAND ${CMAKE_COMMAND} -E make_directory "${artifact_directory}"
- COMMAND
- ${compiler_to_run} -c ${cxx_flags}
- "${target_compile_flags_joined_genex}"
- "${target_defines_joined_genex}"
- ${hcleanFLAGS}
- "${target_includes_joined_genex}"
- ${framework_includes}
- ${hcleanDEFS}
- -xc++ "${input_path}"
- -o${artifact_path}
- IMPLICIT_DEPENDS CXX
- VERBATIM
- COMMAND_EXPAND_LISTS
- DEPENDS "${input_path}"
- )
- list(APPEND hclean_artifacts "${artifact_path}")
- endforeach()
+ set(compiler_command_line
+ "${compiler_to_run}" "-c" "${cxx_flags}"
+ "${target_compile_flags_joined_genex}"
+ "${target_defines_joined_genex}"
+ "${hcleanFLAGS}"
+ "${target_includes_joined_genex}"
+ "${framework_includes}"
+ "${hcleanDEFS}"
+ )
+ string(JOIN " " compiler_command_line_variables
+ "-xc++"
+ "\${INPUT_HEADER_FILE}"
+ "-o"
+ "\${OUTPUT_ARTIFACT}"
+ )
+ set(input_header_path_type ABSOLUTE)
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
- # -Za would enable strict standards behavior, but we can't add it because
- # <windows.h> and <GL.h> violate the standards.
- set(hcleanFLAGS -std:c++latest -Zc:__cplusplus -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)
- foreach(header ${hclean_headers})
- # We need realpath here to make sure path starts with drive letter
- get_filename_component(input_path "${header}" REALPATH)
- set(artifact_path "header_${header}.o")
- set(comment_header_path "${CMAKE_CURRENT_SOURCE_DIR}/${header}")
- file(RELATIVE_PATH comment_header_path "${PROJECT_SOURCE_DIR}" "${comment_header_path}")
-
- add_custom_command(
- OUTPUT "${artifact_path}"
- COMMENT "headersclean: Checking header ${comment_header_path}"
- COMMAND
- ${compiler_to_run} -nologo -c ${CMAKE_CXX_FLAGS}
- "${target_compile_flags_joined_genex}"
- "${target_defines_joined_genex}"
- ${hcleanFLAGS}
- "${target_includes_joined_genex}"
- ${hcleanDEFS}
- -FI "${input_path}"
- -Fo${artifact_path} "${source_path}"
- IMPLICIT_DEPENDS CXX
- VERBATIM
- COMMAND_EXPAND_LISTS
- DEPENDS "${input_path}"
- )
- list(APPEND hclean_artifacts "${artifact_path}")
- endforeach()
+ set(compiler_command_line
+ "${compiler_to_run}" "-nologo" "-c" "${CMAKE_CXX_FLAGS}"
+ "${target_compile_flags_joined_genex}"
+ "${target_defines_joined_genex}"
+ "${hcleanFLAGS}"
+ "${target_includes_joined_genex}"
+ "${hcleanDEFS}"
+ "${hcleanUDEFS}"
+ )
+ string(JOIN " " compiler_command_line_variables
+ "-FI"
+ "\${INPUT_HEADER_FILE}"
+ "-Fo\${OUTPUT_ARTIFACT}"
+ "${source_path}"
+ )
+
+ set(input_header_path_type REALPATH)
else()
message(FATAL_ERROR "CMAKE_CXX_COMPILER_ID \"${CMAKE_CXX_COMPILER_ID}\" is not supported"
" for the headersclean check.")
endif()
+ qt_internal_module_info(module ${module_target})
+
+ unset(header_check_exceptions)
+ set(header_check_exceptions
+ "${CMAKE_CURRENT_BINARY_DIR}/${module}_header_check_exceptions")
+ set(headers_check_parameters
+ "${CMAKE_CURRENT_BINARY_DIR}/${module_target}HeadersCheckParameters${config_suffix}.cmake")
+ string(JOIN "\n" headers_check_parameters_content
+ "set(HEADER_CHECK_EXCEPTIONS"
+ " \"${header_check_exceptions}\")"
+ "set(HEADER_CHECK_COMPILER_COMMAND_LINE"
+ " \[\[$<JOIN:${compiler_command_line},\]\]\n \[\[>\]\]\n"
+ " ${compiler_command_line_variables}"
+ ")"
+ )
+ file(GENERATE OUTPUT "${headers_check_parameters}"
+ CONTENT "${headers_check_parameters_content}")
+
+ set(sync_headers_dep "${module_target}_sync_headers")
+
+ foreach(header ${hclean_headers})
+ # We need realpath here to make sure path starts with drive letter
+ get_filename_component(input_path "${header}" ${input_header_path_type})
+
+ get_filename_component(input_file_name ${input_path} NAME)
+ set(artifact_path "${CMAKE_CURRENT_BINARY_DIR}/header_check/${input_file_name}.o")
+
+ unset(input_base_dir)
+ if(input_path MATCHES "${CMAKE_BINARY_DIR}")
+ set(input_base_dir "${CMAKE_BINARY_DIR}")
+ elseif(input_path MATCHES "${CMAKE_SOURCE_DIR}")
+ set(input_base_dir "${CMAKE_SOURCE_DIR}")
+ endif()
+
+ if(input_base_dir AND IS_ABSOLUTE "${input_base_dir}" AND IS_ABSOLUTE "${input_path}")
+ file(RELATIVE_PATH comment_header_path "${input_base_dir}" "${input_path}")
+ else()
+ set(comment_header_path "${input_path}")
+ endif()
+
+ add_custom_command(
+ OUTPUT "${artifact_path}"
+ COMMENT "headersclean: Checking header ${comment_header_path}"
+ COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/header_check"
+ COMMAND ${CMAKE_COMMAND}
+ -DINPUT_HEADER_FILE=${input_path}
+ -DOUTPUT_ARTIFACT=${artifact_path}
+ -DPARAMETERS=${headers_check_parameters}
+ -P "${QT_CMAKE_DIR}/QtModuleHeadersCheck.cmake"
+ IMPLICIT_DEPENDS CXX
+ VERBATIM
+ COMMAND_EXPAND_LISTS
+ DEPENDS
+ ${headers_check_parameters}
+ ${sync_headers_dep}
+ ${input_path}
+ ${header_check_exceptions}
+ )
+ list(APPEND hclean_artifacts "${artifact_path}")
+ endforeach()
+
add_custom_target(${module_target}_headersclean_check
- COMMENT "headersclean: Checking headers in ${module_include_name}"
+ COMMENT "headersclean: Checking headers in ${module}"
DEPENDS ${hclean_artifacts}
VERBATIM)
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
new file mode 100644
index 0000000000..a42f59f5c8
--- /dev/null
+++ b/cmake/QtInitProject.cmake
@@ -0,0 +1,214 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+cmake_minimum_required(VERSION 3.16)
+
+if(NOT PROJECT_DIR)
+ set(PROJECT_DIR "${CMAKE_SOURCE_DIR}")
+endif()
+
+get_filename_component(project_name "${PROJECT_DIR}" NAME)
+
+get_filename_component(project_abs_dir "${PROJECT_DIR}" ABSOLUTE)
+if(NOT IS_DIRECTORY "${project_abs_dir}")
+ message(FATAL_ERROR "Unable to scan ${project_abs_dir}. The directory doesn't exist.")
+endif()
+
+set(known_extensions "")
+set(types "")
+
+# The function allows extending the capabilities of this script and establishes simple relation
+# chains between the file types.
+# Option Arguments:
+# EXPERIMENTAL
+# Marks that the support of the following files is experimental and the required Qt modules
+# are in Technical preview state.
+# DEPRECATED
+# Marks that the support of the following files will be discontinued soon and the required
+# Qt modules are deprecated.
+# One-value Arguments:
+# TEMPLATE
+# The CMake code template. Use the '@files@' string for the files substitution.
+# Multi-value Arguments:
+# EXTENSIONS
+# List of the file extensions treated as this source 'type'.
+# MODULES
+# List of Qt modules required for these file types.
+# DEPENDS
+# The prerequisite source 'type' needed by this source 'type'
+macro(handle_type type)
+ cmake_parse_arguments(arg
+ "EXPERIMENTAL;DEPRECATED"
+ "TEMPLATE"
+ "EXTENSIONS;MODULES;DEPENDS"
+ ${ARGN}
+ )
+
+ if(NOT arg_EXTENSIONS)
+ message(FATAL_ERROR "Unexpected call handle_type of with no EXTENSIONS specified."
+ " This is the Qt issue, please report a bug at https://bugreports.qt.io.")
+ endif()
+ set(unique_extensions_subset "${known_extensions}")
+ list(REMOVE_ITEM unique_extensions_subset ${arg_EXTENSIONS})
+ if(NOT "${known_extensions}" STREQUAL "${unique_extensions_subset}")
+ message(FATAL_ERROR "${type} contains duplicated extensions, this is not supported."
+ " This is the Qt issue, please report a bug at https://bugreports.qt.io.")
+ endif()
+ set(${type}_file_extensions "${arg_EXTENSIONS}")
+
+ if(NOT arg_TEMPLATE)
+ message(FATAL_ERROR "Unexpected call handle_type of with no TEMPLATE specified."
+ " This is the Qt issue, please report a bug at https://bugreports.qt.io.")
+ endif()
+ set(${type}_template "${arg_TEMPLATE}")
+
+ if(arg_MODULES)
+ set(${type}_required_modules "${arg_MODULES}")
+ endif()
+
+ list(APPEND types ${type})
+
+ if(arg_EXPERIMENTAL)
+ set(${type}_is_experimental TRUE)
+ else()
+ set(${type}_is_experimental FALSE)
+ endif()
+
+ if(arg_DEPRECATED)
+ set(${type}_is_deprecated TRUE)
+ else()
+ set(${type}_is_deprecated FALSE)
+ endif()
+
+ if(arg_DEPENDS)
+ set(${type}_dependencies ${arg_DEPENDS})
+ endif()
+endmacro()
+
+handle_type(cpp EXTENSIONS .c .cc .cpp .cxx .h .hh .hxx .hpp MODULES Core TEMPLATE
+"\n\nqt_add_executable(${project_name}
+ @files@
+)"
+)
+
+handle_type(qml EXTENSIONS .qml .js .mjs MODULES Gui Qml Quick TEMPLATE
+"\n\nqt_add_qml_module(${project_name}
+ URI ${project_name}
+ OUTPUT_DIRECTORY qml
+ VERSION 1.0
+ RESOURCE_PREFIX /qt/qml
+ QML_FILES
+ @files@
+)"
+)
+
+handle_type(ui EXTENSIONS .ui MODULES Gui Widgets DEPENDS cpp TEMPLATE
+"\n\ntarget_sources(${project_name}
+ PRIVATE
+ @files@
+)"
+)
+
+handle_type(qrc EXTENSIONS .qrc DEPENDS cpp TEMPLATE
+"\n\nqt_add_resources(${project_name}_resources @files@)
+target_sources(${project_name}
+ PRIVATE
+ \\\${${project_name}_resources}
+)"
+)
+
+handle_type(protobuf EXPERIMENTAL EXTENSIONS .proto MODULES Protobuf Grpc TEMPLATE
+"\n\nqt_add_protobuf(${project_name}
+ GENERATE_PACKAGE_SUBFOLDERS
+ PROTO_FILES
+ @files@
+)"
+)
+
+set(extra_packages "")
+file(GLOB_RECURSE files RELATIVE "${project_abs_dir}" "${project_abs_dir}/*")
+foreach(f IN LISTS files)
+ get_filename_component(file_extension "${f}" LAST_EXT)
+ string(TOLOWER "${file_extension}" file_extension)
+
+ foreach(type IN LISTS types)
+ if(file_extension IN_LIST ${type}_file_extensions)
+ list(APPEND ${type}_sources "${f}")
+ list(APPEND packages ${${type}_required_modules})
+ if(${type}_is_experimental)
+ message("We found files with the following extensions in your directory:"
+ " ${${type}_file_extensions}\n"
+ "Note that the modules ${${type}_required_modules} are"
+ " in the technical preview state.")
+ endif()
+ if(${type}_is_deprecated)
+ message("We found files with the following extensions in your directory:"
+ " ${${type}_file_extensions}\n"
+ "Note that the modules ${${type}_required_modules} are deprecated.")
+ endif()
+ break()
+ endif()
+ endforeach()
+endforeach()
+
+if(packages)
+ list(REMOVE_DUPLICATES packages)
+ list(JOIN packages " " packages_string)
+ list(JOIN packages "\n Qt::" deps_string)
+ set(deps_string "Qt::${deps_string}")
+endif()
+
+set(content
+"cmake_minimum_required(VERSION 3.16)
+project(${project_name} LANGUAGES CXX)
+
+find_package(Qt6 REQUIRED COMPONENTS ${packages_string})
+qt_standard_project_setup()"
+)
+
+set(has_useful_sources FALSE)
+foreach(type IN LISTS types)
+ if(${type}_sources)
+ set(skip FALSE)
+ foreach(dep IN LISTS ${type}_dependencies)
+ if(NOT ${dep}_sources)
+ set(skip TRUE)
+ message("Sources of type ${${type}_file_extensions} cannot live in the project"
+ " without ${${dep}_file_extensions} files. Skipping.")
+ break()
+ endif()
+ endforeach()
+ if(skip)
+ continue()
+ endif()
+
+ set(has_useful_sources TRUE)
+ string(REGEX MATCH "( +)@files@" unused "${${type}_template}")
+ list(JOIN ${type}_sources "\n${CMAKE_MATCH_1}" ${type}_sources)
+ string(REPLACE "@files@" "${${type}_sources}" ${type}_content
+ "${${type}_template}")
+ string(APPEND content "${${type}_content}")
+ endif()
+endforeach()
+
+string(APPEND content "\n\ntarget_link_libraries(${project_name}
+ PRIVATE
+ ${deps_string}
+)\n"
+)
+
+if(EXISTS "${project_abs_dir}/CMakeLists.txt")
+ message(FATAL_ERROR "Project is already initialized in current directory."
+ " Please remove CMakeLists.txt if you want to regenerate the project.")
+endif()
+
+if(NOT has_useful_sources)
+ message(FATAL_ERROR "Could not find any files to generate the project.")
+endif()
+file(WRITE "${project_abs_dir}/CMakeLists.txt" "${content}")
+
+message("The project file is successfully generated. To build the project run:"
+ "\nmkdir build"
+ "\ncd build"
+ "\nqt-cmake ${project_abs_dir}"
+ "\ncmake --build ${project_abs_dir}"
+)
diff --git a/cmake/QtInstallHelpers.cmake b/cmake/QtInstallHelpers.cmake
index 38441d828f..deab48cda5 100644
--- a/cmake/QtInstallHelpers.cmake
+++ b/cmake/QtInstallHelpers.cmake
@@ -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: BSD-3-Clause
# Wraps install() command. In a prefix build, simply passes along arguments to install().
# In a non-prefix build, handles association of targets to export names, and also calls export().
@@ -95,12 +95,27 @@ function(qt_copy_or_install)
qt_non_prefix_copy(COPY ${argv_copy} ${copy_arguments})
endfunction()
-# Create a versioned hard-link for the given target.
+# Create a versioned hard-link for the given target, or a program
# E.g. "bin/qmake6" -> "bin/qmake".
-# If no hard link can be created, make a copy instead.
+#
+# One-value Arguments:
+# WORKING_DIRECTORY
+# The directory where the original file is already placed.
+# SUFFIX
+# The program file extension, only used for PROGRAMS
+# Multi-value Arguments:
+# TARGETS
+# List of targets for which the versioned link will be created.
+# If targets are given, BASE_NAME and SUFFIX will be derived from it.
+# PROGRAMS
+# List of program file names for which the versioned link will be created.
+#
+#
+# NOTE: This assumes that TARGETS, or PROGRAMS are already installed in the
+# WORKING_DIRECTORY.
#
# In a multi-config build, create the link for the main config only.
-function(qt_internal_install_versioned_link install_dir target)
+function(qt_internal_install_versioned_link)
if(NOT QT_WILL_INSTALL)
return()
endif()
@@ -109,13 +124,41 @@ function(qt_internal_install_versioned_link install_dir target)
return()
endif()
+ set(options)
+ set(oneValueArgs "WORKING_DIRECTORY;SUFFIX")
+ set(multiValueArgs "TARGETS;PROGRAMS")
+ cmake_parse_arguments(arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+ if(arg_TARGETS)
+ foreach(target "${arg_TARGETS}")
+ _qt_internal_create_versioned_link_or_copy("${arg_WORKING_DIRECTORY}"
+ $<TARGET_FILE_BASE_NAME:${target}>
+ $<TARGET_FILE_SUFFIX:${target}>)
+ endforeach()
+ endif()
+
+ if(arg_PROGRAMS)
+ foreach(program "${arg_PROGRAMS}")
+ _qt_internal_create_versioned_link_or_copy("${arg_WORKING_DIRECTORY}"
+ "${program}"
+ "${arg_SUFFIX}")
+ endforeach()
+ endif()
+endfunction()
+
+# Generate a script for creating a hard-link between the base_name, and
+# base_name${PROJECT_VERSION_MAJOR}.
+#
+# If no hard link can be created, make a copy instead.
+function(_qt_internal_create_versioned_link_or_copy install_dir base_name suffix)
qt_path_join(install_base_file_path "$\{qt_full_install_prefix}"
- "${install_dir}" "$<TARGET_FILE_BASE_NAME:${target}>")
- set(original "${install_base_file_path}$<TARGET_FILE_SUFFIX:${target}>")
- set(linkname "${install_base_file_path}${PROJECT_VERSION_MAJOR}$<TARGET_FILE_SUFFIX:${target}>")
+ "${install_dir}" "${base_name}")
+ set(original "${install_base_file_path}${suffix}")
+ set(linkname "${install_base_file_path}${PROJECT_VERSION_MAJOR}${suffix}")
set(code "set(qt_full_install_prefix \"$\{CMAKE_INSTALL_PREFIX}\")"
" if(NOT \"$ENV\{DESTDIR}\" STREQUAL \"\")"
)
+
if(CMAKE_HOST_WIN32)
list(APPEND code
" if(qt_full_install_prefix MATCHES \"^[a-zA-Z]:\")"
@@ -140,3 +183,67 @@ function(qt_internal_install_versioned_link install_dir target)
list(JOIN code "\n" code)
install(CODE "${code}")
endfunction()
+
+# Use case is copying files or directories in a non-prefix build with each build, so that changes
+# are available each time, this is useful for some Android templates that are needed for building,
+# apks and need to sync changes each time a build is started
+function(qt_internal_copy_at_build_time)
+ set(flags)
+ set(options TARGET DESTINATION)
+ set(multiopts FILES DIRECTORIES)
+ cmake_parse_arguments(arg "${flags}" "${options}" "${multiopts}" ${ARGN})
+
+ file(MAKE_DIRECTORY "${arg_DESTINATION}")
+
+ unset(outputs)
+ foreach(dir_to_copy IN LISTS arg_DIRECTORIES)
+ get_filename_component(file_name "${dir_to_copy}" NAME)
+ set(destination_file_name "${arg_DESTINATION}/${file_name}")
+
+ file(GLOB_RECURSE all_files_in_dir RELATIVE "${dir_to_copy}" "${dir_to_copy}/*")
+ set(dir_outputs ${all_files_in_dir})
+ set(dir_deps ${all_files_in_dir})
+
+ list(TRANSFORM dir_outputs PREPEND "${destination_file_name}/")
+ list(TRANSFORM dir_deps PREPEND "${dir_to_copy}/")
+
+ add_custom_command(OUTPUT ${dir_outputs}
+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${dir_to_copy} "${destination_file_name}"
+ DEPENDS ${dir_deps}
+ COMMENT "Copying directory ${dir_to_copy} to ${arg_DESTINATION}."
+ )
+ list(APPEND outputs ${dir_outputs})
+ endforeach()
+
+ unset(file_outputs)
+ unset(files_to_copy)
+ foreach(path_to_copy IN LISTS arg_FILES)
+ get_filename_component(file_name "${path_to_copy}" NAME)
+ set(destination_file_name "${arg_DESTINATION}/${file_name}")
+
+ list(APPEND file_outputs "${destination_file_name}")
+ list(APPEND files_to_copy "${path_to_copy}")
+ endforeach()
+
+ if(files_to_copy)
+ add_custom_command(OUTPUT ${file_outputs}
+ COMMAND ${CMAKE_COMMAND} -E copy_if_different ${files_to_copy} ${arg_DESTINATION}
+ DEPENDS ${files_to_copy}
+ COMMENT "Copying files ${files_to_copy} to ${arg_DESTINATION}."
+ )
+ list(APPEND outputs ${file_outputs})
+ endif()
+
+ get_property(count GLOBAL PROPERTY _qt_internal_copy_at_build_time_count)
+ if(NOT count)
+ set(count 0)
+ endif()
+
+ add_custom_target(qt_internal_copy_at_build_time_${count} DEPENDS ${outputs})
+ if(arg_TARGET)
+ add_dependencies(${arg_TARGET} qt_internal_copy_at_build_time_${count})
+ endif()
+
+ math(EXPR count "${count} + 1")
+ set_property(GLOBAL PROPERTY _qt_internal_copy_at_build_time_count ${count})
+endfunction()
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 9fcdb37b45..d7eadc1a73 100644
--- a/cmake/QtInternalTargets.cmake
+++ b/cmake/QtInternalTargets.cmake
@@ -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: BSD-3-Clause
function(qt_internal_set_warnings_are_errors_flags target target_scope)
@@ -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,7 +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_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)
@@ -162,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
@@ -199,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
@@ -209,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"
@@ -221,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
@@ -232,21 +277,20 @@ 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)
+ 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)
+ if (MSVC_VERSION GREATER_EQUAL 1919) # MSVC 2019
target_compile_options(PlatformCommonInternal INTERFACE
-Zc:externConstexpr
+ #-Zc:lambda # Buggy. TODO: Enable again when stable enough.
+ #-Zc:preprocessor # breaks build due to bug in default Windows SDK 10.0.19041
)
endif()
@@ -259,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>
)
@@ -273,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()
@@ -304,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 48f056b230..ec9b611c5e 100644
--- a/cmake/QtJavaHelpers.cmake
+++ b/cmake/QtJavaHelpers.cmake
@@ -1,9 +1,13 @@
# 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: BSD-3-Clause
# 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/QtLalrHelpers.cmake b/cmake/QtLalrHelpers.cmake
index f67bbc489f..a63d8e9504 100644
--- a/cmake/QtLalrHelpers.cmake
+++ b/cmake/QtLalrHelpers.cmake
@@ -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: BSD-3-Clause
# Match the pattern 'regex' in 'input_line', replace the match with 'replacement'
# and set that result in 'out_var' in the parent scope.
@@ -35,6 +35,15 @@ function(qt_process_qlalr consuming_target input_file_list flags)
return()
endif()
+ qt_internal_is_skipped_test(skipped ${consuming_target})
+ if(skipped)
+ return()
+ endif()
+ qt_internal_is_in_test_batch(in_batch ${consuming_target})
+ if(in_batch)
+ _qt_internal_test_batch_target_name(consuming_target)
+ endif()
+
foreach(input_file ${input_file_list})
file(STRINGS ${input_file} input_file_lines)
qt_qlalr_find_option_in_list("${input_file_lines}" "^%parser(.+)" "parser")
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 8ea763d86e..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@)
@@ -27,9 +30,8 @@ endif()
if (NOT QT_NO_CREATE_TARGETS AND @INSTALL_CMAKE_NAMESPACE@@target@_FOUND)
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")
- endif()
+ include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target@ExtraProperties.cmake"
+ OPTIONAL)
# DEPRECATED
# Provide old style variables for includes, compile definitions, etc.
@@ -72,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)
@@ -89,12 +101,12 @@ if (NOT QT_NO_CREATE_TARGETS AND @INSTALL_CMAKE_NAMESPACE@@target@_FOUND)
endif()
if (TARGET @QT_CMAKE_EXPORT_NAMESPACE@::@target@)
+ qt_make_features_available(@QT_CMAKE_EXPORT_NAMESPACE@::@target@)
+
foreach(extra_cmake_include @extra_cmake_includes@)
include("${CMAKE_CURRENT_LIST_DIR}/${extra_cmake_include}")
endforeach()
- qt_make_features_available(@QT_CMAKE_EXPORT_NAMESPACE@::@target@)
-
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target@Plugins.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target@Plugins.cmake")
endif()
@@ -116,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..ba5922d1e2 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()
diff --git a/cmake/QtModuleHeadersCheck.cmake b/cmake/QtModuleHeadersCheck.cmake
new file mode 100644
index 0000000000..39053f3e10
--- /dev/null
+++ b/cmake/QtModuleHeadersCheck.cmake
@@ -0,0 +1,34 @@
+cmake_minimum_required(VERSION 3.16)
+# The PARAMETERS file should specify the following variables for the correct work of
+# this script:
+# HEADER_CHECK_EXCEPTIONS - path to file that contains exceptions.
+# The file is created by syncqt.
+#
+# HEADER_CHECK_COMPILER_COMMAND_LINE - compiler command line
+include("${PARAMETERS}")
+
+if(EXISTS ${HEADER_CHECK_EXCEPTIONS})
+ file(READ ${HEADER_CHECK_EXCEPTIONS} header_check_exception_list)
+endif()
+
+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)
+ file(WRITE "${OUTPUT_ARTIFACT}" "skipped")
+ return()
+ endif()
+endforeach()
+
+execute_process(COMMAND ${HEADER_CHECK_COMPILER_COMMAND_LINE}
+ RESULT_VARIABLE result
+ OUTPUT_VARIABLE output
+ ERROR_VARIABLE output
+)
+
+if(NOT result EQUAL 0)
+ message(FATAL_ERROR "${INPUT_HEADER_FILE} header check"
+ " failed: ${HEADER_CHECK_COMPILER_COMMAND_LINE}\n"
+ " ${output}")
+endif()
diff --git a/cmake/QtModuleHelpers.cmake b/cmake/QtModuleHelpers.cmake
index ac6fd8a7f1..ba03173073 100644
--- a/cmake/QtModuleHelpers.cmake
+++ b/cmake/QtModuleHelpers.cmake
@@ -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: BSD-3-Clause
macro(qt_internal_get_internal_add_module_keywords option_args single_args multi_args)
set(${option_args}
@@ -15,9 +15,10 @@ macro(qt_internal_get_internal_add_module_keywords option_args single_args multi
NO_CONFIG_HEADER_FILE
NO_ADDITIONAL_TARGET_INFO
NO_GENERATE_METATYPES
- GENERATE_CPP_EXPORTS # TODO: Rename to NO_GENERATE_CPP_EXPORTS once migration is done
- GENERATE_METATYPES # TODO: Remove once it is not used anymore
- GENERATE_PRIVATE_CPP_EXPORTS
+ NO_HEADERSCLEAN_CHECK
+ GENERATE_CPP_EXPORTS # deprecated
+ NO_GENERATE_CPP_EXPORTS
+ NO_UNITY_BUILD
)
set(${single_args}
MODULE_INCLUDE_NAME
@@ -27,20 +28,43 @@ macro(qt_internal_get_internal_add_module_keywords option_args single_args multi
CONFIGURE_FILE_PATH
CPP_EXPORT_HEADER_BASE_NAME
EXTERNAL_HEADERS_DIR
+ PRIVATE_HEADER_FILTERS
+ QPA_HEADER_FILTERS
+ RHI_HEADER_FILTERS
+ SSG_HEADER_FILTERS
+ HEADER_SYNC_SOURCE_DIRECTORY
${__default_target_info_args}
)
set(${multi_args}
QMAKE_MODULE_CONFIG
EXTRA_CMAKE_FILES
EXTRA_CMAKE_INCLUDES
- NO_PCH_SOURCES
EXTERNAL_HEADERS
+ POLICIES
${__default_private_args}
${__default_public_args}
${__default_private_module_args}
)
endmacro()
+# The function helps to wrap module include paths with the header existence check.
+function(qt_internal_append_include_directories_with_headers_check target list_to_append type)
+ string(TOLOWER "${type}" type)
+ string(JOIN "" has_headers_check
+ "$<BOOL:"
+ "$<TARGET_PROPERTY:"
+ "$<TARGET_NAME:${target}>,"
+ "_qt_module_has_${type}_headers"
+ ">"
+ ">"
+ )
+ foreach(directory IN LISTS ARGN)
+ list(APPEND ${list_to_append}
+ "$<${has_headers_check}:${directory}>")
+ endforeach()
+ set(${list_to_append} "${${list_to_append}}" PARENT_SCOPE)
+endfunction()
+
# This is the main entry function for creating a Qt module, that typically
# consists of a library, public header files, private header files and configurable
# features.
@@ -83,7 +107,28 @@ endmacro()
# A module directory with non qt headers (like 3rdparty) to be installed.
# Note this option overrides install headers used as PUBLIC_HEADER by cmake install(TARGET)
# otherwise set by syncqt.
-
+#
+# PRIVATE_HEADER_FILTERS
+# The regular expressions that filter private header files out of target sources.
+# The value must use the following format 'regex1|regex2|regex3'.
+#
+# QPA_HEADER_FILTERS
+# 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
+# CMAKE_CURRENT_SOURCE_DIR for the header files that needs to be synced and only parse the
+# single subdirectory, that meanwhile can be outside the CMAKE_CURRENT_SOURCE_DIR tree.
function(qt_internal_add_module target)
qt_internal_get_internal_add_module_keywords(
module_option_args
@@ -91,12 +136,12 @@ function(qt_internal_add_module target)
module_multi_args
)
- qt_parse_all_arguments(arg "qt_internal_add_module"
+ cmake_parse_arguments(PARSE_ARGV 1 arg
"${module_option_args}"
"${module_single_args}"
"${module_multi_args}"
- ${ARGN}
)
+ _qt_internal_validate_all_args_are_parsed(arg)
set(is_internal_module FALSE)
if(arg_INTERNAL_MODULE)
@@ -198,6 +243,13 @@ function(qt_internal_add_module target)
set(module_config_header "qt${arg_CONFIG_MODULE_NAME}-config.h")
set(module_config_private_header "qt${arg_CONFIG_MODULE_NAME}-config_p.h")
+ # qt<module>-config.h/-config_p.h header files are not marked as GENERATED automatically
+ # for old CMake versions. Set the property explicitly here.
+ set_source_files_properties("${module_config_header}" "${module_config_private_header}"
+ PROPERTIES
+ GENERATED TRUE
+ SKIP_AUTOGEN TRUE
+ )
# Module define needs to take into account the config module name.
string(TOUPPER "${arg_CONFIG_MODULE_NAME}" module_define_infix)
@@ -284,14 +336,24 @@ function(qt_internal_add_module target)
EXPORT_PROPERTIES "${export_properties}")
endif()
+ # FIXME: This workaround is needed because the deployment logic
+ # for iOS and WASM just copies/embeds the directly linked library,
+ # which will just be a versioned symlink to the actual library.
+ if((UIKIT OR WASM) AND BUILD_SHARED_LIBS)
+ set(version_args "")
+ else()
+ set(version_args
+ VERSION ${PROJECT_VERSION}
+ SOVERSION ${PROJECT_VERSION_MAJOR})
+ endif()
+
if(NOT arg_HEADER_MODULE)
set_target_properties(${target} PROPERTIES
LIBRARY_OUTPUT_DIRECTORY "${QT_BUILD_DIR}/${INSTALL_LIBDIR}"
RUNTIME_OUTPUT_DIRECTORY "${QT_BUILD_DIR}/${INSTALL_BINDIR}"
ARCHIVE_OUTPUT_DIRECTORY "${QT_BUILD_DIR}/${INSTALL_LIBDIR}"
- VERSION ${PROJECT_VERSION}
- SOVERSION ${PROJECT_VERSION_MAJOR}
- )
+ ${version_args}
+ )
qt_set_target_info_properties(${target} ${ARGN})
qt_handle_multi_config_output_dirs("${target}")
@@ -348,84 +410,86 @@ function(qt_internal_add_module target)
else()
set_property(TARGET ${target} APPEND PROPERTY EXPORT_PROPERTIES _qt_module_include_name)
set_target_properties("${target}" PROPERTIES
- _qt_module_include_name "${module_include_name}")
-
- # Use QT_BUILD_DIR for the syncqt call.
- # So we either write the generated files into the qtbase non-prefix build root, or the
- # module specific build root.
- qt_ensure_sync_qt()
- set(syncqt_full_command "${HOST_PERL}" -w "${QT_SYNCQT}"
- -quiet
- -check-includes
- -module "${module_include_name}"
- -version "${PROJECT_VERSION}"
- -outdir "${QT_BUILD_DIR}"
- -builddir "${PROJECT_BINARY_DIR}"
- "${PROJECT_SOURCE_DIR}")
- message(STATUS "Running syncqt for module: '${module_include_name}' ")
- execute_process(COMMAND ${syncqt_full_command} RESULT_VARIABLE syncqt_ret)
- if(NOT syncqt_ret EQUAL 0)
- message(FATAL_ERROR "Failed to run syncqt, return code: ${syncqt_ret}")
- endif()
-
- set_target_properties("${target}" PROPERTIES
- _qt_module_has_headers ON)
-
- ### FIXME: Can we replace headers.pri?
- qt_read_headers_pri("${module_build_interface_include_dir}" "module_headers")
+ _qt_module_include_name "${module_include_name}"
+ _qt_module_has_headers ON
+ )
- if(arg_EXTERNAL_HEADERS)
- set(module_headers_public ${arg_EXTERNAL_HEADERS})
+ set(sync_source_directory "${CMAKE_CURRENT_SOURCE_DIR}")
+ if(arg_HEADER_SYNC_SOURCE_DIRECTORY)
+ set(sync_source_directory "${arg_HEADER_SYNC_SOURCE_DIRECTORY}")
endif()
-
- set_property(TARGET ${target} APPEND PROPERTY
- _qt_module_timestamp_dependencies "${module_headers_public}")
-
+ set_target_properties(${target} PROPERTIES
+ _qt_sync_source_directory "${sync_source_directory}")
# 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()
set(module_depends_header
"${module_build_interface_include_dir}/${module_include_name}Depends")
- if(is_framework)
- if(NOT is_interface_lib)
- qt_copy_framework_headers(${target}
- PUBLIC "${module_headers_public};${module_depends_header}"
- PRIVATE "${module_headers_private}"
- QPA "${module_headers_qpa}"
- )
- endif()
- else()
- set_property(TARGET ${target} APPEND PROPERTY PUBLIC_HEADER "${module_headers_public}")
- set_property(TARGET ${target} APPEND PROPERTY PUBLIC_HEADER ${module_depends_header})
- set_property(TARGET ${target} APPEND PROPERTY PRIVATE_HEADER "${module_headers_private}")
- endif()
- if (NOT ${arg_HEADER_MODULE})
+ set_source_files_properties("${module_depends_header}" PROPERTIES GENERATED TRUE)
+ set_target_properties(${target} PROPERTIES _qt_module_depends_header
+ "${module_depends_header}")
+ if(NOT ${arg_HEADER_MODULE})
+ set(module_header "${module_build_interface_include_dir}/${module_include_name}")
set_property(TARGET "${target}" PROPERTY MODULE_HEADER
- "${module_build_interface_include_dir}/${module_include_name}")
+ "${module_header}")
endif()
- if(module_headers_qpa)
- qt_install(
- FILES ${module_headers_qpa}
- DESTINATION "${module_install_interface_qpa_include_dir}")
+ set(qpa_filter_regex "")
+ if(arg_QPA_HEADER_FILTERS)
+ set(qpa_filter_regex "${arg_QPA_HEADER_FILTERS}")
+ endif()
+ 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}")
+ endif()
+ set_target_properties(${target}
+ PROPERTIES _qt_module_private_headers_filter_regex "${private_filter_regex}")
+
+ # 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}"
+ )
endif()
endif()
+ if(arg_NO_HEADERSCLEAN_CHECK OR arg_NO_MODULE_HEADERS OR arg_NO_SYNC_QT
+ OR NOT INPUT_headersclean)
+ set_target_properties("${target}" PROPERTIES _qt_no_headersclean_check ON)
+ endif()
+
if(NOT arg_HEADER_MODULE)
# Plugin types associated to a module
if(NOT "x${arg_PLUGIN_TYPES}" STREQUAL "x")
@@ -461,15 +525,15 @@ function(qt_internal_add_module target)
# Make sure to create such paths for both the the BUILD_INTERFACE and the INSTALL_INTERFACE.
#
# Only add syncqt headers if they exist.
- # This handles cases like QmlDevToolsPrivate which do not have their own headers, but borrow them
- # from another module.
+ # This handles cases like QmlDevToolsPrivate which do not have their own headers, but borrow
+ # them from another module.
if(NOT arg_NO_SYNC_QT AND NOT arg_NO_MODULE_HEADERS)
# Don't include private headers unless they exist, aka syncqt created them.
- if(module_headers_private)
- list(APPEND private_includes
- "$<BUILD_INTERFACE:${module_build_interface_versioned_include_dir}>"
- "$<BUILD_INTERFACE:${module_build_interface_versioned_inner_include_dir}>")
- endif()
+ qt_internal_append_include_directories_with_headers_check(${target}
+ private_includes PRIVATE
+ "$<BUILD_INTERFACE:${module_build_interface_versioned_include_dir}>"
+ "$<BUILD_INTERFACE:${module_build_interface_versioned_inner_include_dir}>"
+ )
list(APPEND public_includes
# For the syncqt headers
@@ -514,23 +578,12 @@ function(qt_internal_add_module target)
endif()
list(APPEND ${public_headers_list} ${arg_PUBLIC_INCLUDE_DIRECTORIES})
- if(arg_HEADER_MODULE)
- # Provide a *_timestamp target that can be used to trigger the build of custom_commands.
- set(timestamp_file "${CMAKE_CURRENT_BINARY_DIR}/timestamp")
- add_custom_command(OUTPUT "${timestamp_file}"
- COMMAND ${CMAKE_COMMAND} -E touch "${timestamp_file}"
- DEPENDS "$<TARGET_PROPERTY:${target},_qt_module_timestamp_dependencies>"
- VERBATIM)
- add_custom_target(${target}_pri_dep_timestamp ALL DEPENDS "${timestamp_file}")
- endif()
-
set(defines_for_extend_target "")
if(NOT arg_HEADER_MODULE)
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
@@ -541,10 +594,27 @@ function(qt_internal_add_module target)
qt_internal_add_repo_local_defines("${target}")
+ if(arg_NO_UNITY_BUILD)
+ set(arg_NO_UNITY_BUILD "NO_UNITY_BUILD")
+ else()
+ set(arg_NO_UNITY_BUILD "")
+ endif()
+
+ if(NOT arg_EXTERNAL_HEADERS)
+ set(arg_EXTERNAL_HEADERS "")
+ endif()
+
qt_internal_extend_target("${target}"
- SOURCES ${arg_SOURCES}
+ ${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
+ ${arg_SYSTEM_INCLUDE_DIRECTORIES}
PUBLIC_INCLUDE_DIRECTORIES
${public_includes}
PUBLIC_DEFINES
@@ -597,39 +667,13 @@ function(qt_internal_add_module target)
include(${configureFile})
qt_feature_module_end("${target}")
- set_property(TARGET "${target}" APPEND PROPERTY
- PUBLIC_HEADER "${CMAKE_CURRENT_BINARY_DIR}/${module_config_header}"
- )
- set_property(TARGET "${target}" APPEND PROPERTY
- PRIVATE_HEADER "${CMAKE_CURRENT_BINARY_DIR}/${module_config_private_header}"
+ qt_internal_extend_target("${target}"
+ SOURCES
+ "${CMAKE_CURRENT_BINARY_DIR}/${module_config_header}"
+ "${CMAKE_CURRENT_BINARY_DIR}/${module_config_private_header}"
)
endif()
- if(NOT arg_HEADER_MODULE)
- if(DEFINED module_headers_private)
- qt_internal_add_linker_version_script("${target}" PRIVATE_HEADERS ${module_headers_private} ${module_headers_qpa})
- else()
- qt_internal_add_linker_version_script("${target}")
- endif()
- endif()
-
- # Handle injections. Aka create forwarding headers for certain headers that have been
- # automatically generated in the build dir (for example qconfig.h, qtcore-config.h,
- # qvulkanfunctions.h, etc)
- # module_headers_injections come from the qt_read_headers_pri() call.
- # extra_library_injections come from the qt_feature_module_end() call.
- set(final_injections "")
- if(module_headers_injections)
- string(APPEND final_injections "${module_headers_injections} ")
- endif()
- if(extra_library_injections)
- string(APPEND final_injections "${extra_library_injections} ")
- endif()
-
- if(final_injections)
- qt_install_injections(${target} "${QT_BUILD_DIR}" "${QT_INSTALL_DIR}" ${final_injections})
- endif()
-
# Handle creation of cmake files for consumers of find_package().
set(path_suffix "${INSTALL_CMAKE_NAMESPACE}${target}")
qt_path_join(config_build_dir ${QT_CONFIG_BUILD_DIR} ${path_suffix})
@@ -641,8 +685,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)
@@ -654,6 +711,11 @@ set(QT_VISIBILITY_AVAILABLE TRUE)")
set(QT_LIBINFIX \"${QT_LIBINFIX}\")")
endif()
+ # Store whether find_package(Qt6Foo) should succeed if Qt6FooTools is missing.
+ if(QT_ALLOW_MISSING_TOOLS_PACKAGES)
+ string(APPEND qtcore_extra_cmake_code "
+set(QT_ALLOW_MISSING_TOOLS_PACKAGES TRUE)")
+ endif()
endif()
configure_file("${CMAKE_CURRENT_LIST_DIR}/${INSTALL_CMAKE_NAMESPACE}${target}ConfigExtras.cmake.in"
@@ -667,29 +729,40 @@ set(QT_LIBINFIX \"${QT_LIBINFIX}\")")
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})
set(extra_cmake_code "")
- # Generate metatypes
- if(${arg_GENERATE_METATYPES})
- # No mention of NO_GENERATE_METATYPES. You should not use it.
- message(WARNING "GENERATE_METATYPES is on by default for Qt modules. Please remove the manual specification.")
+ if(arg_POLICIES)
+ set(policies "")
+ foreach(policy IN LISTS arg_POLICIES)
+ list(APPEND policies "set(QT_KNOWN_POLICY_${policy} TRUE)")
+
+ # When building Qt, tests and examples might expect a policy to be known, but they
+ # won't be known depending on which scope or when a find_package(Module) with the
+ # respective policy is called. Check the global list of known policies to accommodate
+ # that.
+ set_property(GLOBAL APPEND PROPERTY _qt_global_known_policies "${policy}")
+ endforeach()
+ list(JOIN policies "\n" policies_str)
+ string(APPEND extra_cmake_code "${policies_str}\n")
endif()
- if (NOT ${arg_NO_GENERATE_METATYPES})
- if (NOT target_type STREQUAL "INTERFACE_LIBRARY")
- set(args "")
- if(QT_WILL_INSTALL)
- set(metatypes_install_dir "${INSTALL_LIBDIR}/metatypes")
- list(APPEND args
- __QT_INTERNAL_INSTALL __QT_INTERNAL_INSTALL_DIR "${metatypes_install_dir}")
- endif()
- qt6_extract_metatypes(${target} ${args})
- elseif(${arg_GENERATE_METATYPES})
- message(FATAL_ERROR "Meta types generation does not work on interface libraries")
+
+ # Generate metatypes
+ if (NOT ${arg_NO_GENERATE_METATYPES} AND NOT target_type STREQUAL "INTERFACE_LIBRARY")
+ set(args "")
+ if(QT_WILL_INSTALL)
+ set(metatypes_install_dir "${INSTALL_ARCHDATADIR}/metatypes")
+ list(APPEND args
+ __QT_INTERNAL_INSTALL __QT_INTERNAL_INSTALL_DIR "${metatypes_install_dir}")
endif()
+ qt6_extract_metatypes(${target} ${args})
endif()
+
qt_internal_get_min_new_policy_cmake_version(min_new_policy_version)
qt_internal_get_max_new_policy_cmake_version(max_new_policy_version)
configure_package_config_file(
@@ -729,14 +802,6 @@ set(QT_LIBINFIX \"${QT_LIBINFIX}\")")
list(APPEND exported_targets ${target_private})
endif()
set(export_name "${INSTALL_CMAKE_NAMESPACE}${target}Targets")
- if(arg_EXTERNAL_HEADERS_DIR)
- qt_install(DIRECTORY "${arg_EXTERNAL_HEADERS_DIR}/"
- DESTINATION "${module_install_interface_include_dir}"
- )
- unset(public_header_destination)
- else()
- set(public_header_destination PUBLIC_HEADER DESTINATION "${module_install_interface_include_dir}")
- endif()
qt_install(TARGETS ${exported_targets}
EXPORT ${export_name}
@@ -744,9 +809,7 @@ set(QT_LIBINFIX \"${QT_LIBINFIX}\")")
LIBRARY DESTINATION ${INSTALL_LIBDIR}
ARCHIVE DESTINATION ${INSTALL_LIBDIR}
FRAMEWORK DESTINATION ${INSTALL_LIBDIR}
- PRIVATE_HEADER DESTINATION "${module_install_interface_private_include_dir}"
- ${public_header_destination}
- )
+ )
if(BUILD_SHARED_LIBS)
qt_apply_rpaths(TARGET "${target}" INSTALL_PATH "${INSTALL_LIBDIR}" RELATIVE_RPATH)
@@ -774,7 +837,14 @@ set(QT_LIBINFIX \"${QT_LIBINFIX}\")")
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}
+ CONFIG_INSTALL_DIR "${config_install_dir}"
+ )
### fixme: cmake is missing a built-in variable for this. We want to apply it only to modules and plugins
# that belong to Qt.
@@ -786,39 +856,36 @@ set(QT_LIBINFIX \"${QT_LIBINFIX}\")")
# Handle cases like QmlDevToolsPrivate which do not have their own headers, but rather borrow them
# from another module.
- if(NOT arg_NO_SYNC_QT)
+ 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
# INTERFACE_INCLUDE_DIRECTORIES contains a non-existent path.
- if(NOT arg_NO_MODULE_HEADERS
- AND EXISTS "${module_build_interface_versioned_inner_include_dir}")
- list(APPEND interface_includes
- "$<BUILD_INTERFACE:${module_build_interface_versioned_include_dir}>"
- "$<BUILD_INTERFACE:${module_build_interface_versioned_inner_include_dir}>")
-
- if(is_framework)
- set(fw_install_private_header_dir "${INSTALL_LIBDIR}/${fw_private_header_dir}")
- set(fw_install_private_module_header_dir "${INSTALL_LIBDIR}/${fw_private_module_header_dir}")
- list(APPEND interface_includes
- "$<INSTALL_INTERFACE:${fw_install_private_header_dir}>"
- "$<INSTALL_INTERFACE:${fw_install_private_module_header_dir}>")
- else()
- list(APPEND interface_includes
- "$<INSTALL_INTERFACE:${module_install_interface_versioned_include_dir}>"
- "$<INSTALL_INTERFACE:${module_install_interface_versioned_inner_include_dir}>")
- endif()
- endif()
- endif()
+ qt_internal_append_include_directories_with_headers_check(${target}
+ interface_includes PRIVATE
+ "$<BUILD_INTERFACE:${module_build_interface_versioned_include_dir}>"
+ "$<BUILD_INTERFACE:${module_build_interface_versioned_inner_include_dir}>"
+ )
- if(QT_FEATURE_headersclean AND NOT arg_NO_MODULE_HEADERS)
- qt_internal_add_headersclean_target(
- ${target}
- "${module_include_name}"
- "${module_headers_clean}")
+ if(is_framework)
+ set(fw_install_private_header_dir "${INSTALL_LIBDIR}/${fw_private_header_dir}")
+ set(fw_install_private_module_header_dir
+ "${INSTALL_LIBDIR}/${fw_private_module_header_dir}")
+ qt_internal_append_include_directories_with_headers_check(${target}
+ interface_includes PRIVATE
+ "$<INSTALL_INTERFACE:${fw_install_private_header_dir}>"
+ "$<INSTALL_INTERFACE:${fw_install_private_module_header_dir}>"
+ )
+ else()
+ qt_internal_append_include_directories_with_headers_check(${target}
+ interface_includes PRIVATE
+ "$<INSTALL_INTERFACE:${module_install_interface_versioned_include_dir}>"
+ "$<INSTALL_INTERFACE:${module_install_interface_versioned_inner_include_dir}>"
+ )
+ endif()
endif()
if(arg_INTERNAL_MODULE)
@@ -849,11 +916,46 @@ set(QT_LIBINFIX \"${QT_LIBINFIX}\")")
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)
+ 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})
+
+ # qt_internal_install_module_headers needs to be called before
+ # qt_finalize_framework_headers_copy, because the last uses the QT_COPIED_FRAMEWORK_HEADERS
+ # property which supposed to be updated inside every qt_internal_install_module_headers
+ # call.
+ qt_internal_add_headersclean_target(${target} "${module_headers_public}")
+ qt_internal_target_sync_headers(${target} "${module_headers_all}"
+ "${module_headers_generated}")
+ get_target_property(module_depends_header ${target} _qt_module_depends_header)
+ qt_internal_install_module_headers(${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.
@@ -880,6 +982,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.
#
@@ -902,6 +1006,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
@@ -936,6 +1046,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")
@@ -949,6 +1063,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}")
@@ -962,6 +1080,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)
@@ -975,6 +1097,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
@@ -989,6 +1113,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)
@@ -1002,6 +1130,21 @@ 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)
+ set(result "")
+ foreach(item IN LISTS ${list_var})
+ if(NOT "${result}" STREQUAL "")
+ string(APPEND result ", ")
+ endif()
+ string(APPEND result "\"${item}\"")
+ endforeach()
+ set("${out_var}" "[${result}]" PARENT_SCOPE)
endfunction()
# Generate a module description file based on the template in ModuleDescription.json.in
@@ -1012,10 +1155,41 @@ function(qt_describe_module target)
set(descfile_in "${QT_CMAKE_DIR}/ModuleDescription.json.in")
set(descfile_out "${build_dir}/${target}.json")
+ string(TOLOWER "${PROJECT_NAME}" lower_case_project_name)
set(cross_compilation "false")
if(CMAKE_CROSSCOMPILING)
set(cross_compilation "true")
endif()
+ set(extra_module_information "")
+
+ get_target_property(target_type ${target} TYPE)
+ if(NOT target_type STREQUAL "INTERFACE_LIBRARY")
+ 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},")
+ endif()
+ endif()
+
+ get_target_property(is_internal ${target} _qt_is_internal_module)
+ if(is_internal)
+ string(APPEND extra_module_information "\n \"internal\": true,")
+ endif()
+
+ set(extra_build_information "")
+ if(NOT QT_NAMESPACE STREQUAL "")
+ string(APPEND extra_build_information "
+ \"namespace\": \"${QT_NAMESPACE}\",")
+ endif()
+ if(ANDROID)
+ string(APPEND extra_build_information "
+ \"android\": {
+ \"api_version\": \"${QT_ANDROID_API_VERSION}\",
+ \"ndk\": {
+ \"version\": \"${ANDROID_NDK_REVISION}\"
+ }
+ },")
+ endif()
configure_file("${descfile_in}" "${descfile_out}")
qt_install(FILES "${descfile_out}" DESTINATION "${install_dir}")
@@ -1023,7 +1197,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}
)
@@ -1047,49 +1221,190 @@ 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)
+endfunction()
- if(arg_GENERATE_PRIVATE_CPP_EXPORTS)
- set(generated_private_header_path
- "${module_build_interface_private_include_dir}/${header_base_name}_p.h"
- )
+function(qt_internal_install_module_headers target)
+ set(options)
+ set(one_value_args)
+ set(multi_value_args PUBLIC PRIVATE QPA RHI SSG)
+ cmake_parse_arguments(arg "${options}" "${one_value_args}" "${multi_value_args}" ${ARGN})
- configure_file("${QT_CMAKE_DIR}/modulecppexports_p.h.in"
- "${generated_private_header_path}" @ONLY
- )
+ qt_internal_module_info(module ${target})
- set(${out_private_header} "${generated_private_header_path}" PARENT_SCOPE)
- target_sources(${target} PRIVATE "${generated_private_header_path}")
+ get_target_property(target_type ${target} TYPE)
+ set(is_interface_lib FALSE)
+ if(target_type STREQUAL "INTERFACE_LIBRARY")
+ set(is_interface_lib TRUE)
+ else()
+ get_target_property(is_framework ${target} FRAMEWORK)
endif()
- get_target_property(is_framework ${target} FRAMEWORK)
+
+ foreach(header_type IN LISTS multi_value_args)
+ if(NOT arg_${header_type})
+ set(arg_${header_type} "")
+ endif()
+ endforeach()
+
+ if(is_framework)
+ qt_copy_framework_headers(${target}
+ PUBLIC ${arg_PUBLIC}
+ PRIVATE ${arg_PRIVATE}
+ QPA ${arg_QPA}
+ RHI ${arg_RHI}
+ SSG ${arg_SSG}
+ )
+ else()
+ if(arg_PUBLIC)
+ qt_install(FILES ${arg_PUBLIC}
+ DESTINATION "${module_install_interface_include_dir}")
+ endif()
+ if(arg_PRIVATE)
+ qt_install(FILES ${arg_PRIVATE}
+ DESTINATION "${module_install_interface_private_include_dir}")
+ endif()
+ 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()
+
+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)
- set(is_interface_lib 0)
if(target_type STREQUAL "INTERFACE_LIBRARY")
- set(is_interface_lib 1)
+ 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)
+ get_filename_component(file_name "${file_path}" NAME)
+ if(NOT file_name MATCHES ".+\\.h$")
+ continue()
+ endif()
- set_property(TARGET ${target} APPEND PROPERTY
- _qt_module_timestamp_dependencies "${generated_header_path}")
+ get_source_file_property(non_module_header ${file_path} _qt_non_module_header)
+ if(non_module_header)
+ continue()
+ endif()
- if(is_framework)
- if(NOT is_interface_lib)
- qt_copy_framework_headers(${target} PUBLIC "${generated_header_path}")
+ get_filename_component(file_path "${file_path}" ABSOLUTE)
- if(arg_GENERATE_PRIVATE_CPP_EXPORTS)
- qt_copy_framework_headers(${target} PRIVATE "${generated_private_header_path}")
- endif()
+ 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()
- else()
- set_property(TARGET ${target} APPEND PROPERTY PUBLIC_HEADER "${generated_header_path}")
- qt_install(FILES "${generated_header_path}"
- DESTINATION "${module_install_interface_include_dir}")
-
- if(arg_GENERATE_PRIVATE_CPP_EXPORTS)
- set_property(TARGET ${target} APPEND PROPERTY PRIVATE_HEADER
- "${generated_private_header_path}")
- qt_install(FILES "${generated_private_header_path}"
- DESTINATION "${module_install_interface_private_include_dir}")
+
+ 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)
+ string(APPEND condition_independent_headers_warning
+ "\nFile:\n ${file_path}"
+ "\nCondition:\n ${condition_string}")
+ endif()
+
+ 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}")
+ AND NOT is_3rdparty_header)
+ list(APPEND ${out_var}_public "${file_path}")
+ endif()
+ if(is_generated)
+ list(APPEND ${out_var}_generated "${file_path}")
+ endif()
+ endforeach()
+
+ if(NOT condition_independent_headers_warning STREQUAL "" AND QT_FEATURE_developer_build)
+ message(AUTHOR_WARNING "Condition is ignored when adding the following header file(s) to"
+ " the ${target} module:"
+ "${condition_independent_headers_warning}"
+ "\nThe usage of the file(s) is not properly isolated in this or other modules according"
+ " to the condition. This warning is for the Qt maintainers. Please make sure that file"
+ " include(s) are guarded with the appropriate macros in the Qt code. If files should be"
+ " added to the module unconditionally, please move them to the common SOURCES section"
+ " in the qt_internal_add_module call.")
+ endif()
+
+
+ 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)
+ if(${out_var}_${header_type})
+ list(APPEND has_header_types_properties
+ _qt_module_has_${header_type}_headers TRUE)
+ endif()
+
+ set(${out_var}_${header_type} "${${out_var}_${header_type}}" PARENT_SCOPE)
+ endforeach()
+ set(${out_var}_all "${${out_var}_all}" PARENT_SCOPE)
+ set(${out_var}_generated "${${out_var}_generated}" PARENT_SCOPE)
+
+ if(has_header_types_properties)
+ set_target_properties(${target} PROPERTIES ${has_header_types_properties})
endif()
+ set_property(TARGET ${target} APPEND PROPERTY
+ EXPORT_PROPERTIES
+ _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 fdbc853646..ec447aa55b 100644
--- a/cmake/QtModuleToolsConfig.cmake.in
+++ b/cmake/QtModuleToolsConfig.cmake.in
@@ -1,15 +1,24 @@
+# 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(CMakeFindDependencyMacro)
-if (NOT QT_NO_CREATE_TARGETS)
- # Find required dependencies, if any.
- if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target@Dependencies.cmake")
- include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target@Dependencies.cmake")
- endif()
+# Find required dependencies, if any.
+if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target@Dependencies.cmake")
+ include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@target@Dependencies.cmake")
+endif()
+
+# If *Dependencies.cmake exists, the variable value will be defined there.
+# Don't override it in that case.
+if(NOT DEFINED "@INSTALL_CMAKE_NAMESPACE@@target@_FOUND")
+ set("@INSTALL_CMAKE_NAMESPACE@@target@_FOUND" TRUE)
+endif()
+if (NOT QT_NO_CREATE_TARGETS AND @INSTALL_CMAKE_NAMESPACE@@target@_FOUND)
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)
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/QtNoLinkTargetHelpers.cmake b/cmake/QtNoLinkTargetHelpers.cmake
index 9b82d51434..59dc3ff5ac 100644
--- a/cmake/QtNoLinkTargetHelpers.cmake
+++ b/cmake/QtNoLinkTargetHelpers.cmake
@@ -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: BSD-3-Clause
function(qt_create_nolink_target target dependee_target)
if(NOT TARGET "${target}")
diff --git a/cmake/QtPkgConfigHelpers.cmake b/cmake/QtPkgConfigHelpers.cmake
index 34191c2cf5..dbe736c438 100644
--- a/cmake/QtPkgConfigHelpers.cmake
+++ b/cmake/QtPkgConfigHelpers.cmake
@@ -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: BSD-3-Clause
function(qt_internal_collect_direct_target_dependencies target targets_out_var)
__qt_internal_walk_libs("${target}" "${targets_out_var}" _rcc_objects
@@ -22,7 +22,8 @@ endmacro()
# Create a Qt6*.pc file intended for pkg-config consumption.
function(qt_internal_generate_pkg_config_file module)
# TODO: PkgConfig is supported under MSVC with pkgconf (github.com/pkgconf/pkgconf)
- if((NOT UNIX OR QT_FEATURE_framework) AND NOT MINGW OR CMAKE_VERSION VERSION_LESS "3.20")
+ if((NOT UNIX OR QT_FEATURE_framework)
+ AND NOT MINGW OR CMAKE_VERSION VERSION_LESS "3.20" OR ANDROID)
return()
endif()
if(NOT BUILD_SHARED_LIBS)
@@ -50,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)
diff --git a/cmake/QtPlatformAndroid.cmake b/cmake/QtPlatformAndroid.cmake
index 8077000998..e4253b75d7 100644
--- a/cmake/QtPlatformAndroid.cmake
+++ b/cmake/QtPlatformAndroid.cmake
@@ -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: BSD-3-Clause
#
# Self contained Platform Settings for Android
@@ -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-31")
+set(QT_ANDROID_API_VERSION "android-33")
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,14 +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"
+ "--ndk-stack" "${ANDROID_NDK_ROOT}/ndk-stack"
+ "--timeout" "${timeout}"
"--verbose"
PARENT_SCOPE
)
diff --git a/cmake/QtPlatformSupport.cmake b/cmake/QtPlatformSupport.cmake
index b3176c942c..9f8498e42c 100644
--- a/cmake/QtPlatformSupport.cmake
+++ b/cmake/QtPlatformSupport.cmake
@@ -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: BSD-3-Clause
function(qt_set01 result)
if (${ARGN})
@@ -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?
@@ -20,6 +19,7 @@ qt_set01(OPENBSD CMAKE_SYSTEM_NAME STREQUAL "OpenBSD") # FIXME: How to identify
qt_set01(FREEBSD CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") # FIXME: How to identify this?
qt_set01(NETBSD CMAKE_SYSTEM_NAME STREQUAL "NetBSD") # FIXME: How to identify this?
qt_set01(WASM CMAKE_SYSTEM_NAME STREQUAL "Emscripten" OR EMSCRIPTEN)
+qt_set01(WASM64 QT_QMAKE_TARGET_MKSPEC STREQUAL "wasm-emscripten-64")
qt_set01(SOLARIS CMAKE_SYSTEM_NAME STREQUAL "SunOS")
qt_set01(HURD CMAKE_SYSTEM_NAME STREQUAL "GNU")
@@ -32,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 daca58aabd..f1976b9975 100644
--- a/cmake/QtPlatformTargetHelpers.cmake
+++ b/cmake/QtPlatformTargetHelpers.cmake
@@ -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: BSD-3-Clause
# Defines the public Qt::Platform target, which serves as a dependency for all internal Qt target
# as well as user projects consuming Qt.
@@ -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 84060ae214..9437d4236d 100644
--- a/cmake/QtPluginHelpers.cmake
+++ b/cmake/QtPluginHelpers.cmake
@@ -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: BSD-3-Clause
# Note that these are only the keywords that are unique to qt_internal_add_plugin().
# That function also supports the keywords defined by _qt_internal_get_add_plugin_keywords().
@@ -8,6 +8,7 @@ macro(qt_internal_get_internal_add_plugin_keywords option_args single_args multi
EXCEPTIONS
ALLOW_UNDEFINED_SYMBOLS
SKIP_INSTALL
+ NO_UNITY_BUILD
)
set(${single_args}
OUTPUT_DIRECTORY
@@ -43,12 +44,12 @@ function(qt_internal_add_plugin target)
set(single_args ${public_single_args} ${internal_single_args})
set(multi_args ${public_multi_args} ${internal_multi_args})
- qt_parse_all_arguments(arg "qt_internal_add_plugin"
+ cmake_parse_arguments(PARSE_ARGV 1 arg
"${option_args}"
"${single_args}"
"${multi_args}"
- "${ARGN}"
)
+ _qt_internal_validate_all_args_are_parsed(arg)
# Put this behind a cache option for now. It's too noisy for general use
# until most repos are updated.
@@ -90,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.
@@ -210,6 +216,13 @@ 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}")
@@ -276,6 +289,8 @@ function(qt_internal_add_plugin target)
)
endif()
endif()
+
+ qt_internal_add_autogen_sync_header_dependencies(${target} ${qt_module_target})
endif()
# Change the configuration file install location for qml plugins into the Qml package location.
@@ -293,6 +308,12 @@ function(qt_internal_add_plugin target)
if(TARGET qt_plugins)
add_dependencies(qt_plugins "${target}")
endif()
+
+ # Record plugin for current repo.
+ if(qt_repo_plugins AND TARGET ${qt_repo_plugins})
+ add_dependencies(${qt_repo_plugins} "${target}")
+ endif()
+
if(plugin_type STREQUAL "platforms")
if(TARGET qpa_plugins)
add_dependencies(qpa_plugins "${target}")
@@ -318,10 +339,23 @@ function(qt_internal_add_plugin target)
${arg_PUBLIC_INCLUDE_DIRECTORIES}
)
+ if(arg_NO_UNITY_BUILD)
+ set(arg_NO_UNITY_BUILD "NO_UNITY_BUILD")
+ else()
+ set(arg_NO_UNITY_BUILD "")
+ 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
+ ${arg_SYSTEM_INCLUDE_DIRECTORIES}
PUBLIC_INCLUDE_DIRECTORIES
${public_includes}
LIBRARIES ${arg_LIBRARIES} Qt::PlatformPluginInternal
@@ -332,10 +366,10 @@ function(qt_internal_add_plugin target)
PUBLIC_DEFINES
${arg_PUBLIC_DEFINES}
FEATURE_DEPENDENCIES ${arg_FEATURE_DEPENDENCIES}
- DBUS_ADAPTOR_SOURCES "${arg_DBUS_ADAPTOR_SOURCES}"
- DBUS_ADAPTOR_FLAGS "${arg_DBUS_ADAPTOR_FLAGS}"
- DBUS_INTERFACE_SOURCES "${arg_DBUS_INTERFACE_SOURCES}"
- DBUS_INTERFACE_FLAGS "${arg_DBUS_INTERFACE_FLAGS}"
+ DBUS_ADAPTOR_SOURCES ${arg_DBUS_ADAPTOR_SOURCES}
+ DBUS_ADAPTOR_FLAGS ${arg_DBUS_ADAPTOR_FLAGS}
+ DBUS_INTERFACE_SOURCES ${arg_DBUS_INTERFACE_SOURCES}
+ DBUS_INTERFACE_FLAGS ${arg_DBUS_INTERFACE_FLAGS}
COMPILE_OPTIONS ${arg_COMPILE_OPTIONS}
PUBLIC_COMPILE_OPTIONS ${arg_PUBLIC_COMPILE_OPTIONS}
LINK_OPTIONS ${arg_LINK_OPTIONS}
@@ -361,7 +395,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}")
@@ -505,3 +538,88 @@ function(qt_internal_get_module_for_plugin target target_type out_var)
endforeach()
message(FATAL_ERROR "The plug-in '${target}' does not belong to any Qt module.")
endfunction()
+
+function(qt_internal_add_darwin_permission_plugin permission)
+ string(TOLOWER "${permission}" permission_lower)
+ string(TOUPPER "${permission}" permission_upper)
+ set(permission_source_file "platform/darwin/qdarwinpermissionplugin_${permission_lower}.mm")
+ set(plugin_target "QDarwin${permission}PermissionPlugin")
+ set(plugin_name "qdarwin${permission_lower}permission")
+ qt_internal_add_plugin(${plugin_target}
+ STATIC # Force static, even in shared builds
+ OUTPUT_NAME ${plugin_name}
+ PLUGIN_TYPE permissions
+ DEFAULT_IF FALSE
+ SOURCES
+ ${permission_source_file}
+ DEFINES
+ QT_DARWIN_PERMISSION_PLUGIN=${permission}
+ LIBRARIES
+ 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
+ set_target_properties(${plugin_target} PROPERTIES
+ DISABLE_PRECOMPILE_HEADERS ON
+ )
+
+ # Generate plugin JSON file
+ set(content "{ \"Permissions\": [ \"Q${permission}Permission\" ] }")
+ get_target_property(plugin_build_dir "${plugin_target}" BINARY_DIR)
+ set(output_file "${plugin_build_dir}/${plugin_target}.json")
+ qt_configure_file(OUTPUT "${output_file}" CONTENT "${content}")
+
+ # Associate required usage descriptions
+ set(usage_descriptions_property "_qt_info_plist_usage_descriptions")
+ set_target_properties(${plugin_target} PROPERTIES
+ ${usage_descriptions_property} "NS${permission}UsageDescription"
+ )
+ set_property(TARGET ${plugin_target} APPEND PROPERTY
+ EXPORT_PROPERTIES ${usage_descriptions_property}
+ )
+ set(usage_descriptions_genex "$<JOIN:$<TARGET_PROPERTY:${plugin_target},${usage_descriptions_property}>, >")
+ set(extra_plugin_pri_content
+ "QT_PLUGIN.${plugin_name}.usage_descriptions = ${usage_descriptions_genex}"
+ )
+
+ # Support granular check and request implementations
+ set(separate_request_source_file
+ "${plugin_build_dir}/qdarwinpermissionplugin_${permission_lower}_request.mm")
+ set(separate_request_genex
+ "$<BOOL:$<TARGET_PROPERTY:${plugin_target},_qt_darwin_permissison_separate_request>>")
+ file(GENERATE OUTPUT "${separate_request_source_file}" CONTENT
+ "
+ #define BUILDING_PERMISSION_REQUEST 1
+ #include \"${CMAKE_CURRENT_SOURCE_DIR}/${permission_source_file}\"
+ "
+ CONDITION "${separate_request_genex}"
+ )
+ 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
+ )
+ set(permission_request_symbol "_QDarwin${permission}PermissionRequest")
+ set(permission_request_flag "-Wl,-u,${permission_request_symbol}")
+ set(has_usage_description_property "_qt_has_${plugin_target}_usage_description")
+ set(has_usage_description_genex "$<BOOL:$<TARGET_PROPERTY:${has_usage_description_property}>>")
+ target_link_options(${plugin_target} INTERFACE
+ "$<$<AND:${separate_request_genex},${has_usage_description_genex}>:${permission_request_flag}>")
+ list(APPEND extra_plugin_pri_content
+ "QT_PLUGIN.${plugin_name}.request_flag = $<${separate_request_genex}:${permission_request_flag}>"
+ )
+
+ # Expose properties to qmake
+ set_property(TARGET ${plugin_target} PROPERTY
+ QT_PLUGIN_PRI_EXTRA_CONTENT ${extra_plugin_pri_content}
+ )
+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 718b0cd908..f69448c14a 100644
--- a/cmake/QtPostProcess.cmake
+++ b/cmake/QtPostProcess.cmake
@@ -1,7 +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
-
-include(QtPostProcessHelpers)
+# SPDX-License-Identifier: BSD-3-Clause
qt_internal_create_depends_files()
qt_generate_build_internals_extra_cmake_code()
diff --git a/cmake/QtPostProcessHelpers.cmake b/cmake/QtPostProcessHelpers.cmake
index d334741ecd..0a207f6634 100644
--- a/cmake/QtPostProcessHelpers.cmake
+++ b/cmake/QtPostProcessHelpers.cmake
@@ -1,8 +1,9 @@
# 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: BSD-3-Clause
-function(qt_internal_write_depends_file target module_include_name)
- set(outfile "${QT_BUILD_DIR}/include/${module_include_name}/${module_include_name}Depends")
+function(qt_internal_write_depends_file target)
+ get_target_property(module_depends_header ${target} _qt_module_depends_header)
+ set(outfile "${module_depends_header}")
set(contents "/* This file was generated by cmake with the info from ${target} target. */\n")
string(APPEND contents "#ifdef __cplusplus /* create empty PCH in C mode */\n")
foreach (m ${ARGN})
@@ -249,8 +250,7 @@ function(qt_internal_create_module_depends_file target)
get_target_property(hasModuleHeaders "${target}" _qt_module_has_headers)
if (${hasModuleHeaders})
- get_target_property(module_include_name "${target}" _qt_module_include_name)
- qt_internal_write_depends_file(${target} ${module_include_name} ${qtdeps})
+ qt_internal_write_depends_file(${target} ${qtdeps})
endif()
if(third_party_deps OR main_module_tool_deps OR target_deps)
@@ -446,7 +446,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 +498,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 +577,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 +600,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 +630,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)
@@ -696,7 +710,7 @@ endif()\n")
# find_package(Qt6Core) is called in case if the feature was disabled.
string(APPEND QT_EXTRA_BUILD_INTERNALS_VARS "
if(NOT QT_SKIP_BUILD_INTERNALS_PKG_CONFIG_FEATURE)
- set(FEATURE_pkg_config \"${FEATURE_pkg_config}\" CACHE STRING \"Using pkg-config\" FORCE)
+ set(FEATURE_pkg_config \"${FEATURE_pkg_config}\" CACHE BOOL \"Using pkg-config\" FORCE)
endif()\n")
# The OpenSSL root dir needs to be saved so that repos other than qtbase (like qtopcua) can
@@ -713,17 +727,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
"
@@ -732,6 +735,24 @@ set(OpenGL_GL_PREFERENCE \"${OpenGL_GL_PREFERENCE}\" CACHE STRING \"\")
")
endif()
+ string(APPEND QT_EXTRA_BUILD_INTERNALS_VARS
+ "
+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"
@@ -798,7 +819,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)
@@ -842,8 +863,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/QtPrecompiledHeadersHelpers.cmake b/cmake/QtPrecompiledHeadersHelpers.cmake
index 7cf432ca72..fe38413407 100644
--- a/cmake/QtPrecompiledHeadersHelpers.cmake
+++ b/cmake/QtPrecompiledHeadersHelpers.cmake
@@ -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: BSD-3-Clause
function(qt_update_precompiled_header target precompiled_header)
if (precompiled_header AND BUILD_WITH_PCH)
@@ -19,7 +19,9 @@ endfunction()
function(qt_update_ignore_pch_source target sources)
if (sources)
- set_source_files_properties(${sources} PROPERTIES SKIP_PRECOMPILE_HEADERS ON)
+ set_source_files_properties(${sources} PROPERTIES
+ SKIP_PRECOMPILE_HEADERS ON
+ SKIP_UNITY_BUILD_INCLUSION ON)
endif()
endfunction()
diff --git a/cmake/QtPriHelpers.cmake b/cmake/QtPriHelpers.cmake
index 224eea8afd..f410dc9b2a 100644
--- a/cmake/QtPriHelpers.cmake
+++ b/cmake/QtPriHelpers.cmake
@@ -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: BSD-3-Clause
# Extracts the 3rdparty libraries for the module ${module_name}
# and stores the information in cmake language in
@@ -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")
@@ -323,7 +325,9 @@ function(qt_generate_module_pri_file target)
list(APPEND module_internal_config staticlib)
endif()
- # TODO: Add the value 'ltcg' to module_internal_config if LTCG is turned on.
+ if(QT_FEATURE_ltcg)
+ list(APPEND module_internal_config ltcg)
+ endif()
list(JOIN module_internal_config " " joined_module_internal_config)
@@ -541,12 +545,15 @@ QT.${config_module_name}_private.disabled_features = ${disabled_private_features
"-DIMPLICIT_LINK_DIRECTORIES=${implicit_link_directories}"
-P "${QT_CMAKE_DIR}/QtGenerateLibPri.cmake"
VERBATIM)
- add_custom_target(${target}_lib_pri DEPENDS "${private_pri_file_path}")
+ # add_dependencies has no effect when adding interface libraries. So need to add the
+ # '_lib_pri' targets to ALL to make sure that the related rules executed.
+ unset(add_pri_target_to_all)
if(is_interface_lib)
- add_dependencies(${target}_pri_dep_timestamp ${target}_lib_pri)
- else()
- add_dependencies(${target} ${target}_lib_pri)
+ set(add_pri_target_to_all ALL)
endif()
+ add_custom_target(${target}_lib_pri ${add_pri_target_to_all}
+ DEPENDS "${private_pri_file_path}")
+ add_dependencies(${target} ${target}_lib_pri)
endif()
qt_install(FILES "${pri_files}" DESTINATION ${INSTALL_MKSPECSDIR}/modules)
@@ -771,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}")
@@ -782,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}")
@@ -842,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/QtPrlHelpers.cmake b/cmake/QtPrlHelpers.cmake
index 22d241662d..45bfaedcdf 100644
--- a/cmake/QtPrlHelpers.cmake
+++ b/cmake/QtPrlHelpers.cmake
@@ -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: BSD-3-Clause
# Collects the library dependencies of a target.
# As well as rcc object file dependencies.
@@ -108,7 +108,6 @@ function(qt_generate_prl_file target install_dir)
# whose names we know, and can be used in add_custom_command.
set(prl_step1_content
"RCC_OBJECTS = ${rcc_objects}
-QMAKE_PRL_BUILD_DIR = ${CMAKE_CURRENT_BINARY_DIR}
QMAKE_PRL_TARGET = $<TARGET_LINKER_FILE_NAME:${target}>
QMAKE_PRL_TARGET_PATH_FOR_CMAKE = $<TARGET_LINKER_FILE:${target}>
QMAKE_PRL_CONFIG = ${prl_config}
diff --git a/cmake/QtProcessConfigureArgs.cmake b/cmake/QtProcessConfigureArgs.cmake
index 0830bd8977..53235ee9d9 100644
--- a/cmake/QtProcessConfigureArgs.cmake
+++ b/cmake/QtProcessConfigureArgs.cmake
@@ -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: BSD-3-Clause
# This script reads Qt configure arguments from config.opt,
# translates the arguments to CMake arguments and calls 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,6 +85,7 @@ 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 "")
@@ -106,6 +111,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 +142,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")
@@ -144,6 +165,50 @@ 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")
+ push("--fresh")
+ else()
+ file(REMOVE_RECURSE "${CMAKE_BINARY_DIR}/CMakeCache.txt"
+ "${CMAKE_BINARY_DIR}/CMakeFiles")
+ endif()
+endif()
####################################################################################################
# Define functions/macros that are called in configure.cmake files
@@ -210,16 +275,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()
@@ -230,6 +302,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)
@@ -246,6 +323,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)
@@ -310,6 +389,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)
@@ -326,7 +422,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)
@@ -614,10 +712,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")
@@ -634,7 +742,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}'.")
@@ -655,15 +762,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()
@@ -683,6 +781,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)
@@ -778,7 +879,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()
@@ -810,9 +911,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)
@@ -851,15 +956,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)
@@ -880,10 +981,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.
@@ -914,12 +1038,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()
@@ -968,6 +1100,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/QtProperties.cmake b/cmake/QtProperties.cmake
index 12e0fe6b8b..708b60fe0d 100644
--- a/cmake/QtProperties.cmake
+++ b/cmake/QtProperties.cmake
@@ -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: BSD-3-Clause
define_property(TARGET
PROPERTY
diff --git a/cmake/QtPublicAppleHelpers.cmake b/cmake/QtPublicAppleHelpers.cmake
new file mode 100644
index 0000000000..5f7a7719b5
--- /dev/null
+++ b/cmake/QtPublicAppleHelpers.cmake
@@ -0,0 +1,954 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+function(_qt_internal_handle_ios_launch_screen target)
+ # Check if user provided a launch screen path via a variable.
+ set(launch_screen "")
+
+ # Check if the project provided a launch screen path via a variable.
+ # This variable is currently in Technical Preview.
+ if(QT_IOS_LAUNCH_SCREEN)
+ set(launch_screen "${QT_IOS_LAUNCH_SCREEN}")
+ endif()
+
+ # Check if the project provided a launch screen path via a target property, it takes precedence
+ # over the variable.
+ # This property is currently in Technical Preview.
+ get_target_property(launch_screen_from_prop "${target}" QT_IOS_LAUNCH_SCREEN)
+ if(launch_screen_from_prop)
+ set(launch_screen "${launch_screen_from_prop}")
+ endif()
+
+ # If the project hasn't provided a launch screen file path, use a copy of the template
+ # that qmake uses.
+ # It needs to be a copy because configure_file can't handle all the escaped double quotes
+ # present in the qmake template file.
+ set(is_default_launch_screen FALSE)
+ 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_apple_support_files_path}/LaunchScreen.storyboard")
+ endif()
+
+ # Check that the launch screen exists.
+ if(launch_screen)
+ if(NOT IS_ABSOLUTE "${launch_screen}")
+ message(FATAL_ERROR
+ "Provided launch screen value should be an absolute path: '${launch_screen}'")
+ endif()
+
+ if(NOT EXISTS "${launch_screen}")
+ message(FATAL_ERROR
+ "Provided launch screen file does not exist: '${launch_screen}'")
+ endif()
+ endif()
+
+ if(launch_screen AND NOT QT_NO_ADD_IOS_LAUNCH_SCREEN_TO_BUNDLE)
+ get_filename_component(launch_screen_name "${launch_screen}" NAME)
+
+ # Make a copy of the default launch screen template for this target and replace the
+ # label inside the template with the target name.
+ if(is_default_launch_screen)
+ # Configure our default template and place it in the build dir.
+ set(launch_screen_in_path "${launch_screen}")
+
+ string(MAKE_C_IDENTIFIER "${target}" target_identifier)
+ set(launch_screen_out_dir
+ "${CMAKE_CURRENT_BINARY_DIR}/.qt/launch_screen_storyboards/${target_identifier}")
+
+ set(launch_screen_out_path
+ "${launch_screen_out_dir}/${launch_screen_name}")
+
+ file(MAKE_DIRECTORY "${launch_screen_out_dir}")
+
+ configure_file("${launch_screen_in_path}" "${launch_screen_out_path}" COPYONLY)
+
+ set(final_launch_screen_path "${launch_screen_out_path}")
+ else()
+ set(final_launch_screen_path "${launch_screen}")
+ endif()
+
+ # Add the launch screen storyboard file as a source file, otherwise CMake doesn't consider
+ # it as a resource file and MACOSX_PACKAGE_LOCATION processing will be skipped.
+ target_sources("${target}" PRIVATE "${final_launch_screen_path}")
+
+ # Ensure Xcode compiles the storyboard file and installs the compiled storyboard .nib files
+ # into the app bundle.
+ # We use target_sources and the MACOSX_PACKAGE_LOCATION source file property for that
+ # instead of the RESOURCE target property, becaues the latter could potentially end up
+ # needlessly installing the source storyboard file.
+ #
+ # We can't rely on policy CMP0118 since user project controls it.
+ set(scope_args)
+ if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.18")
+ set(scope_args TARGET_DIRECTORY ${target})
+ endif()
+ set_source_files_properties("${final_launch_screen_path}" ${scope_args}
+ PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
+
+ # Save the launch screen name, so its value is added as an UILaunchStoryboardName entry
+ # in the Qt generated Info.plist file.
+ # Xcode expects an Info.plist storyboard entry without an extension.
+ get_filename_component(launch_screen_base_name "${launch_screen}" NAME_WE)
+ set_target_properties("${target}" PROPERTIES
+ _qt_ios_launch_screen_name "${launch_screen_name}"
+ _qt_ios_launch_screen_base_name "${launch_screen_base_name}"
+ _qt_ios_launch_screen_path "${final_launch_screen_path}")
+ endif()
+endfunction()
+
+function(_qt_internal_find_ios_development_team_id out_var)
+ get_property(team_id GLOBAL PROPERTY _qt_internal_ios_development_team_id)
+ get_property(team_id_computed GLOBAL PROPERTY _qt_internal_ios_development_team_id_computed)
+ if(team_id_computed)
+ # Just in case if the value is non-empty but still booly FALSE.
+ if(NOT team_id)
+ set(team_id "")
+ endif()
+ set("${out_var}" "${team_id}" PARENT_SCOPE)
+ return()
+ endif()
+
+ set_property(GLOBAL PROPERTY _qt_internal_ios_development_team_id_computed "TRUE")
+
+ set(home_dir "$ENV{HOME}")
+ set(xcode_preferences_path "${home_dir}/Library/Preferences/com.apple.dt.Xcode.plist")
+
+ # Extract the first account name (email) from the user's Xcode preferences
+ message(DEBUG "Trying to extract an Xcode development team id from '${xcode_preferences_path}'")
+ execute_process(COMMAND "/usr/libexec/PlistBuddy"
+ -x -c "print IDEProvisioningTeams" "${xcode_preferences_path}"
+ OUTPUT_VARIABLE teams_xml
+ ERROR_VARIABLE plist_error)
+
+ # Parsing state.
+ set(is_free "")
+ set(current_team_id "")
+ set(parsing_is_free FALSE)
+ set(parsing_team_id FALSE)
+ set(first_team_id "")
+
+ # Parse the xml output and return the first encountered non-free team id. If no non-free team id
+ # is found, return the first encountered free team id.
+ # If no team is found, return an empty string.
+ #
+ # Example input:
+ #<plist version="1.0">
+ #<dict>
+ # <key>marty@planet.local</key>
+ # <array>
+ # <dict>
+ # <key>isFreeProvisioningTeam</key>
+ # <false/>
+ # <key>teamID</key>
+ # <string>AAA</string>
+ # ...
+ # </dict>
+ # <dict>
+ # <key>isFreeProvisioningTeam</key>
+ # <true/>
+ # <key>teamID</key>
+ # <string>BBB</string>
+ # ...
+ # </dict>
+ # </array>
+ #</dict>
+ #</plist>
+ if(teams_xml AND NOT plist_error)
+ string(REPLACE "\n" ";" teams_xml_lines "${teams_xml}")
+
+ foreach(xml_line ${teams_xml_lines})
+ string(STRIP "${xml_line}" xml_line)
+ if(xml_line STREQUAL "<dict>")
+ # Clean any previously found values when a new team dict is matched.
+ set(is_free "")
+ set(current_team_id "")
+
+ elseif(xml_line STREQUAL "<key>isFreeProvisioningTeam</key>")
+ set(parsing_is_free TRUE)
+
+ elseif(parsing_is_free)
+ set(parsing_is_free FALSE)
+
+ if(xml_line MATCHES "true")
+ set(is_free TRUE)
+ else()
+ set(is_free FALSE)
+ endif()
+
+ elseif(xml_line STREQUAL "<key>teamID</key>")
+ set(parsing_team_id TRUE)
+
+ elseif(parsing_team_id)
+ set(parsing_team_id FALSE)
+ if(xml_line MATCHES "<string>([^<]+)</string>")
+ set(current_team_id "${CMAKE_MATCH_1}")
+ else()
+ continue()
+ endif()
+
+ string(STRIP "${current_team_id}" current_team_id)
+
+ # If this is the first team id we found so far, remember that, regardless if's free
+ # or not.
+ if(NOT first_team_id AND current_team_id)
+ set(first_team_id "${current_team_id}")
+ endif()
+
+ # Break early if we found a non-free team id and use it, because we prefer
+ # a non-free team for signing, just like qmake.
+ if(NOT is_free AND current_team_id)
+ set(first_team_id "${current_team_id}")
+ break()
+ endif()
+ endif()
+ endforeach()
+ endif()
+
+ if(NOT first_team_id)
+ message(DEBUG "Failed to extract an Xcode development team id.")
+ set("${out_var}" "" PARENT_SCOPE)
+ else()
+ message(DEBUG "Successfully extracted the first encountered Xcode development team id.")
+ set_property(GLOBAL PROPERTY _qt_internal_ios_development_team_id "${first_team_id}")
+ set("${out_var}" "${first_team_id}" PARENT_SCOPE)
+ endif()
+endfunction()
+
+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)
+ if(prefix_computed)
+ # Just in case if the value is non-empty but still booly FALSE.
+ if(NOT prefix)
+ set(prefix "")
+ endif()
+ set("${out_var}" "${prefix}" PARENT_SCOPE)
+ return()
+ endif()
+
+ set_property(GLOBAL PROPERTY _qt_internal_ios_bundle_identifier_prefix_computed "TRUE")
+
+ set(home_dir "$ENV{HOME}")
+ set(xcode_preferences_path "${home_dir}/Library/Preferences/com.apple.dt.Xcode.plist")
+
+ message(DEBUG "Trying to extract the default bundle identifier prefix from Xcode preferences.")
+ execute_process(COMMAND "/usr/libexec/PlistBuddy"
+ -c "print IDETemplateOptions:bundleIdentifierPrefix"
+ "${xcode_preferences_path}"
+ OUTPUT_VARIABLE prefix
+ ERROR_VARIABLE prefix_error)
+ if(prefix AND NOT prefix_error)
+ message(DEBUG "Successfully extracted the default bundle identifier prefix.")
+ string(STRIP "${prefix}" prefix)
+ else()
+ message(DEBUG "Failed to extract the default bundle identifier prefix.")
+ endif()
+
+ if(prefix AND NOT prefix_error)
+ set_property(GLOBAL PROPERTY _qt_internal_ios_bundle_identifier_prefix "${prefix}")
+ set("${out_var}" "${prefix}" PARENT_SCOPE)
+ else()
+ set("${out_var}" "" PARENT_SCOPE)
+ endif()
+endfunction()
+
+function(_qt_internal_escape_rfc_1034_identifier value out_var)
+ # According to https://datatracker.ietf.org/doc/html/rfc1034#section-3.5
+ # we can only use letters, digits, dot (.) and hyphens (-).
+ # Underscores are not allowed.
+ string(REGEX REPLACE "[^A-Za-z0-9.]" "-" value "${value}")
+
+ set("${out_var}" "${value}" PARENT_SCOPE)
+endfunction()
+
+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")
+
+ # For a better out-of-the-box experience, try to create a unique prefix by appending
+ # the sha1 of the team id, if one is found.
+ _qt_internal_find_ios_development_team_id(team_id)
+ if(team_id)
+ string(SHA1 hash "${team_id}")
+ string(SUBSTRING "${hash}" 0 8 infix)
+ string(APPEND prefix ".${infix}")
+ 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 \
+ MACOSX_BUNDLE_GUI_IDENTIFIER or XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER property."
+ )
+ endif()
+ endif()
+
+ # Escape the prefix according to rfc 1034, it's important for code-signing. If an invalid
+ # identifier is used, calling xcodebuild on the command line says that no provisioning profile
+ # could be found, with no additional error message. If one opens the generated project with
+ # Xcode and clicks on 'Try again' to get a new profile, it shows a semi-useful error message
+ # that the identifier is invalid.
+ _qt_internal_escape_rfc_1034_identifier("${prefix}" prefix)
+
+ if(CMAKE_GENERATOR STREQUAL "Xcode")
+ set(identifier "${prefix}.$(PRODUCT_NAME:rfc1034identifier)")
+ else()
+ set(identifier "${prefix}.${target}")
+ endif()
+
+ set("${out_var}" "${identifier}" PARENT_SCOPE)
+endfunction()
+
+function(_qt_internal_set_placeholder_apple_bundle_version target)
+ # If user hasn't provided neither a bundle version nor a bundle short version string for the
+ # app, set a placeholder value for both which will add them to the generated Info.plist file.
+ # This is required so that the app launches in the simulator (but apparently not for running
+ # on-device).
+ get_target_property(bundle_version "${target}" MACOSX_BUNDLE_BUNDLE_VERSION)
+ get_target_property(bundle_short_version "${target}" MACOSX_BUNDLE_SHORT_VERSION_STRING)
+
+ if(NOT MACOSX_BUNDLE_BUNDLE_VERSION AND
+ NOT MACOSX_BUNDLE_SHORT_VERSION_STRING AND
+ NOT bundle_version AND
+ NOT bundle_short_version AND
+ NOT QT_NO_SET_XCODE_BUNDLE_VERSION
+ )
+ get_target_property(version "${target}" VERSION)
+ if(NOT version)
+ set(version "${PROJECT_VERSION}")
+ if(NOT version)
+ set(version "1.0.0")
+ endif()
+ endif()
+
+ # Use x.y for short version and x.y.z for full version
+ # Any versions longer than this will fail App Store
+ # submission.
+ string(REPLACE "." ";" version_list ${version})
+ list(LENGTH version_list version_list_length)
+ list(GET version_list 0 version_major)
+ set(bundle_short_version "${version_major}")
+ if(version_list_length GREATER 1)
+ list(GET version_list 1 version_minor)
+ string(APPEND bundle_short_version ".${version_minor}")
+ endif()
+ set(bundle_version "${bundle_short_version}")
+ if(version_list_length GREATER 2)
+ list(GET version_list 2 version_patch)
+ string(APPEND bundle_version ".${version_patch}")
+ endif()
+
+
+ if(NOT CMAKE_XCODE_ATTRIBUTE_MARKETING_VERSION
+ AND NOT QT_NO_SET_XCODE_ATTRIBUTE_MARKETING_VERSION
+ AND NOT CMAKE_XCODE_ATTRIBUTE_CURRENT_PROJECT_VERSION
+ AND NOT QT_NO_SET_XCODE_ATTRIBUTE_CURRENT_PROJECT_VERSION
+ AND CMAKE_GENERATOR STREQUAL "Xcode")
+ get_target_property(marketing_version "${target}"
+ XCODE_ATTRIBUTE_MARKETING_VERSION)
+ get_target_property(current_project_version "${target}"
+ XCODE_ATTRIBUTE_CURRENT_PROJECT_VERSION)
+ if(NOT marketing_version AND NOT current_project_version)
+ set_target_properties("${target}"
+ PROPERTIES
+ XCODE_ATTRIBUTE_CURRENT_PROJECT_VERSION "${bundle_version}"
+ XCODE_ATTRIBUTE_MARKETING_VERSION "${bundle_short_version}"
+ )
+ set(bundle_version "$(CURRENT_PROJECT_VERSION)")
+ set(bundle_short_version "$(MARKETING_VERSION)")
+ endif()
+ endif()
+
+ set_target_properties("${target}"
+ PROPERTIES
+ MACOSX_BUNDLE_BUNDLE_VERSION "${bundle_version}"
+ MACOSX_BUNDLE_SHORT_VERSION_STRING "${bundle_short_version}"
+ )
+ endif()
+endfunction()
+
+function(_qt_internal_set_xcode_development_team_id target)
+ # If user hasn't provided a development team id, try to find the first one specified
+ # in the Xcode preferences.
+ if(NOT CMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM AND NOT QT_NO_SET_XCODE_DEVELOPMENT_TEAM_ID)
+ get_target_property(existing_team_id "${target}" XCODE_ATTRIBUTE_DEVELOPMENT_TEAM)
+ if(NOT existing_team_id)
+ _qt_internal_find_ios_development_team_id(team_id)
+ set_target_properties("${target}"
+ PROPERTIES XCODE_ATTRIBUTE_DEVELOPMENT_TEAM "${team_id}")
+ endif()
+ endif()
+endfunction()
+
+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 (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(CMAKE_GENERATOR STREQUAL "Xcode")
+ set_target_properties("${target}"
+ PROPERTIES
+ XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "${bundle_id}"
+ MACOSX_BUNDLE_GUI_IDENTIFIER "$(PRODUCT_BUNDLE_IDENTIFIER)")
+ else()
+ set_target_properties("${target}"
+ PROPERTIES
+ MACOSX_BUNDLE_GUI_IDENTIFIER "${bundle_id}")
+ endif()
+endfunction()
+
+function(_qt_internal_set_xcode_targeted_device_family target)
+ if(NOT CMAKE_XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY
+ AND NOT QT_NO_SET_XCODE_TARGETED_DEVICE_FAMILY)
+ get_target_property(existing_device_family
+ "${target}" XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY)
+ if(NOT existing_device_family)
+ set(device_family_iphone_and_ipad "1,2")
+ set_target_properties("${target}"
+ PROPERTIES
+ XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY
+ "${device_family_iphone_and_ipad}")
+ endif()
+ endif()
+endfunction()
+
+function(_qt_internal_set_xcode_code_sign_style target)
+ if(NOT CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_STYLE
+ AND NOT QT_NO_SET_XCODE_CODE_SIGN_STYLE)
+ get_target_property(existing_code_style
+ "${target}" XCODE_ATTRIBUTE_CODE_SIGN_STYLE)
+ if(NOT existing_code_style)
+ set(existing_code_style "Automatic")
+ set_target_properties("${target}"
+ PROPERTIES
+ XCODE_ATTRIBUTE_CODE_SIGN_STYLE
+ "${existing_code_style}")
+ endif()
+ endif()
+endfunction()
+
+# Workaround for https://gitlab.kitware.com/cmake/cmake/-/issues/15183
+function(_qt_internal_set_xcode_install_path target)
+ if(NOT CMAKE_XCODE_ATTRIBUTE_INSTALL_PATH
+ AND NOT QT_NO_SET_XCODE_INSTALL_PATH)
+ get_target_property(existing_install_path
+ "${target}" XCODE_ATTRIBUTE_INSTALL_PATH)
+ if(NOT existing_install_path)
+ set_target_properties("${target}"
+ PROPERTIES
+ XCODE_ATTRIBUTE_INSTALL_PATH
+ "$(inherited)")
+ endif()
+ endif()
+endfunction()
+
+function(_qt_internal_set_xcode_bundle_display_name target)
+ # We want the value of CFBundleDisplayName to be ${PRODUCT_NAME}, but we can't put that
+ # into the Info.plist.in template file directly, because the implicit configure_file(Info.plist)
+ # done by CMake is not using the @ONLY option, so CMake would treat the assignment as
+ # variable expansion. Escaping using backslashes does not help.
+ # Work around it by assigning the dollar char to a separate cache var, and expand it, so that
+ # the final value in the file will be ${PRODUCT_NAME}, to be evaluated at build time by Xcode.
+ set(QT_INTERNAL_DOLLAR_VAR "$" CACHE STRING "")
+endfunction()
+
+# Adds ${PRODUCT_NAME} to the Info.plist file, which is then evaluated by Xcode itself.
+function(_qt_internal_set_xcode_bundle_name target)
+ if(QT_NO_SET_XCODE_BUNDLE_NAME)
+ return()
+ endif()
+
+ get_target_property(existing_bundle_name "${target}" MACOSX_BUNDLE_BUNDLE_NAME)
+ if(NOT MACOSX_BUNDLE_BUNDLE_NAME AND NOT existing_bundle_name)
+ if(CMAKE_GENERATOR STREQUAL Xcode)
+ set_target_properties("${target}"
+ PROPERTIES
+ MACOSX_BUNDLE_BUNDLE_NAME "$(PRODUCT_NAME)")
+ else()
+ set_target_properties("${target}"
+ PROPERTIES
+ MACOSX_BUNDLE_BUNDLE_NAME "${target}")
+ endif()
+ endif()
+endfunction()
+
+function(_qt_internal_set_xcode_bitcode_enablement target)
+ if(CMAKE_XCODE_ATTRIBUTE_ENABLE_BITCODE
+ OR QT_NO_SET_XCODE_ENABLE_BITCODE)
+ return()
+ endif()
+
+ get_target_property(existing_bitcode_enablement
+ "${target}" XCODE_ATTRIBUTE_ENABLE_BITCODE)
+ if(NOT existing_bitcode_enablement MATCHES "-NOTFOUND")
+ return()
+ endif()
+
+ # Disable bitcode to match Xcode 14's new default
+ set_target_properties("${target}"
+ PROPERTIES
+ XCODE_ATTRIBUTE_ENABLE_BITCODE
+ "NO")
+endfunction()
+
+function(_qt_internal_copy_info_plist target)
+ # If the project already specifies a custom file, we don't override it.
+ 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()
+
+ string(MAKE_C_IDENTIFIER "${target}" target_identifier)
+ set(info_plist_out_dir
+ "${CMAKE_CURRENT_BINARY_DIR}/.qt/info_plist/${target_identifier}")
+ set(info_plist_out "${info_plist_out_dir}/Info.plist")
+
+ # Check if we need to specify a custom launch screen storyboard entry.
+ get_target_property(launch_screen_base_name "${target}" _qt_ios_launch_screen_base_name)
+ if(launch_screen_base_name)
+ set(qt_ios_launch_screen_plist_entry "${launch_screen_base_name}")
+ endif()
+
+ # Call configure_file to substitute Qt-specific @FOO@ values, not ${FOO} values.
+ #
+ # The output file will be another template file to be fed to CMake via the
+ # MACOSX_BUNDLE_INFO_PLIST property. CMake will then call configure_file on it to provide
+ # content for regular entries like CFBundleName, etc.
+ #
+ # We require this extra configure_file call so we can create unique Info.plist files for each
+ # target in a project, while also providing a way to add Qt specific entries that CMake
+ # does not support out of the box (e.g. a launch screen name).
+ configure_file(
+ "${info_plist_in}"
+ "${info_plist_out}"
+ @ONLY
+ )
+
+ 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)
+ return()
+ endif()
+
+ get_target_property(existing_archs
+ "${target}" XCODE_ATTRIBUTE_ARCHS)
+ if(NOT existing_archs MATCHES "-NOTFOUND")
+ return()
+ endif()
+
+ if(NOT x86_64 IN_LIST QT_OSX_ARCHITECTURES)
+ return()
+ endif()
+
+ if(CMAKE_OSX_ARCHITECTURES AND NOT x86_64 IN_LIST CMAKE_OSX_ARCHITECTURES)
+ return()
+ endif()
+
+ set_target_properties("${target}"
+ PROPERTIES
+ "XCODE_ATTRIBUTE_ARCHS[sdk=iphonesimulator*]"
+ "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 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_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)
+ # 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_set_ios_simulator_arch("${target}")
+endfunction()
+
+function(_qt_internal_finalize_macos_app target)
+ get_target_property(is_bundle ${target} MACOSX_BUNDLE)
+ if(NOT is_bundle)
+ return()
+ endif()
+
+ _qt_internal_finalize_apple_app("${target}")
+
+ # Make sure the install rpath has at least the minimum needed if the app
+ # has any non-static frameworks. We can't rigorously know if the app will
+ # have any, even with a static Qt, so always add this. If there are no
+ # frameworks, it won't do any harm.
+ get_property(install_rpath TARGET ${target} PROPERTY INSTALL_RPATH)
+ list(APPEND install_rpath "@executable_path/../Frameworks")
+ list(REMOVE_DUPLICATES install_rpath)
+ set_property(TARGET ${target} PROPERTY INSTALL_RPATH "${install_rpath}")
+endfunction()
diff --git a/cmake/QtPublicCMakeHelpers.cmake b/cmake/QtPublicCMakeHelpers.cmake
index 06ce5fbd4c..ca091fcf9a 100644
--- a/cmake/QtPublicCMakeHelpers.cmake
+++ b/cmake/QtPublicCMakeHelpers.cmake
@@ -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: BSD-3-Clause
# copy_if_different works incorrect in Windows if file size if bigger than 2GB.
# See https://gitlab.kitware.com/cmake/cmake/-/issues/23052 and QTBUG-99491 for details.
@@ -25,13 +25,486 @@ 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)
endif()
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".
+function(__qt_internal_collect_additional_prefix_paths out_var prefixes_var)
+ if(DEFINED "${out_var}")
+ return()
+ endif()
+
+ set(additional_packages_prefix_paths "")
+
+ set(additional_packages_prefixes "")
+ if(${prefixes_var})
+ list(APPEND additional_packages_prefixes ${${prefixes_var}})
+ endif()
+ if(DEFINED ENV{${prefixes_var}}
+ AND NOT "$ENV{${prefixes_var}}" STREQUAL "")
+ set(prefixes_from_env "$ENV{${prefixes_var}}")
+ if(NOT CMAKE_HOST_WIN32)
+ string(REPLACE ":" ";" prefixes_from_env "${prefixes_from_env}")
+ endif()
+ list(APPEND additional_packages_prefixes ${prefixes_from_env})
+ endif()
+
+ foreach(additional_path IN LISTS additional_packages_prefixes)
+ file(TO_CMAKE_PATH "${additional_path}" additional_path)
+
+ # The prefix paths need to end with lib/cmake to ensure the packages are found when
+ # cross compiling. Search for REROOT_PATH_ISSUE_MARKER in the qt.toolchain.cmake file for
+ # details.
+ # We must pass the values via the PATHS options because the main find_package call uses
+ # 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.
+ __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()
+ 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)
+ __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()
diff --git a/cmake/QtPublicCMakeVersionHelpers.cmake b/cmake/QtPublicCMakeVersionHelpers.cmake
index 4b6137249e..de896d9d2f 100644
--- a/cmake/QtPublicCMakeVersionHelpers.cmake
+++ b/cmake/QtPublicCMakeVersionHelpers.cmake
@@ -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: BSD-3-Clause
function(__qt_internal_get_supported_min_cmake_version_for_using_qt out_var)
# This is recorded in Qt6ConfigExtras.cmake
diff --git a/cmake/QtPublicDependencyHelpers.cmake b/cmake/QtPublicDependencyHelpers.cmake
index dcf321d501..bd8b4a55c4 100644
--- a/cmake/QtPublicDependencyHelpers.cmake
+++ b/cmake/QtPublicDependencyHelpers.cmake
@@ -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: BSD-3-Clause
# Note that target_dep_list does not accept a list of values, but a var name that contains the
# list of dependencies. See foreach block for reference.
@@ -70,7 +70,7 @@ macro(_qt_internal_find_tool_dependencies target target_dep_list)
"${_qt_cmake_dir}"
${_qt_additional_packages_prefix_paths}
)
- if (NOT ${__qt_${target}_pkg}_FOUND)
+ if (NOT ${__qt_${target}_pkg}_FOUND AND NOT QT_ALLOW_MISSING_TOOLS_PACKAGES)
set(${CMAKE_FIND_PACKAGE_NAME}_FOUND FALSE)
set(${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE
"${CMAKE_FIND_PACKAGE_NAME} could not be found because dependency \
@@ -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/QtPublicFinalizerHelpers.cmake b/cmake/QtPublicFinalizerHelpers.cmake
index d26d81e24f..96b5c6c740 100644
--- a/cmake/QtPublicFinalizerHelpers.cmake
+++ b/cmake/QtPublicFinalizerHelpers.cmake
@@ -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: BSD-3-Clause
# Helper to check if the finalizer mode should be used.
# If true, use finalizer mode.
diff --git a/cmake/QtPublicFindPackageHelpers.cmake b/cmake/QtPublicFindPackageHelpers.cmake
index 9ae24b999e..69f4f69e40 100644
--- a/cmake/QtPublicFindPackageHelpers.cmake
+++ b/cmake/QtPublicFindPackageHelpers.cmake
@@ -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: BSD-3-Clause
function(qt_internal_disable_find_package_global_promotion target)
set_target_properties("${target}" PROPERTIES _qt_no_promote_global TRUE)
diff --git a/cmake/QtPublicPluginHelpers.cmake b/cmake/QtPublicPluginHelpers.cmake
index dec3f15222..7087c31234 100644
--- a/cmake/QtPublicPluginHelpers.cmake
+++ b/cmake/QtPublicPluginHelpers.cmake
@@ -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: BSD-3-Clause
# Gets the qt plugin type of the given plugin into out_var_plugin_type.
# Also sets out_var_has_plugin_type to TRUE or FALSE depending on whether the plugin type was found.
@@ -39,22 +39,32 @@ endfunction()
#
# The conditions are based on the various properties set in qt_import_plugins.
-# All the TARGET_PROPERTY genexes are evaluated in the context of the currently linked target.
+# All the TARGET_PROPERTY genexes are evaluated in the context of the currently linked target,
+# unless the TARGET argument is given.
#
# The genex is saved into out_var.
function(__qt_internal_get_static_plugin_condition_genex
plugin_target_unprefixed
out_var)
+ set(options)
+ set(oneValueArgs TARGET)
+ set(multiValueArgs)
+ cmake_parse_arguments(arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
set(plugin_target "${QT_CMAKE_EXPORT_NAMESPACE}::${plugin_target_unprefixed}")
set(plugin_target_versionless "Qt::${plugin_target_unprefixed}")
get_target_property(_plugin_type "${plugin_target}" QT_PLUGIN_TYPE)
+ set(target_infix "")
+ if(arg_TARGET)
+ set(target_infix "${arg_TARGET},")
+ endif()
+
set(_default_plugins_are_enabled
- "$<NOT:$<STREQUAL:$<GENEX_EVAL:$<TARGET_PROPERTY:QT_DEFAULT_PLUGINS>>,0>>")
- set(_manual_plugins_genex "$<GENEX_EVAL:$<TARGET_PROPERTY:QT_PLUGINS>>")
- set(_no_plugins_genex "$<GENEX_EVAL:$<TARGET_PROPERTY:QT_NO_PLUGINS>>")
+ "$<NOT:$<STREQUAL:$<GENEX_EVAL:$<TARGET_PROPERTY:${target_infix}QT_DEFAULT_PLUGINS>>,0>>")
+ set(_manual_plugins_genex "$<GENEX_EVAL:$<TARGET_PROPERTY:${target_infix}QT_PLUGINS>>")
+ set(_no_plugins_genex "$<GENEX_EVAL:$<TARGET_PROPERTY:${target_infix}QT_NO_PLUGINS>>")
# Plugin genex marker for prl processing.
set(_is_plugin_marker_genex "$<BOOL:QT_IS_PLUGIN_GENEX>")
@@ -81,7 +91,7 @@ function(__qt_internal_get_static_plugin_condition_genex
">,"
# Excludes both plugins targeted by EXCLUDE_BY_TYPE and not included in
# INCLUDE_BY_TYPE.
- "$<STREQUAL:,$<GENEX_EVAL:$<TARGET_PROPERTY:QT_PLUGINS_${_plugin_type}>>>"
+ "$<STREQUAL:,$<GENEX_EVAL:$<TARGET_PROPERTY:${target_infix}QT_PLUGINS_${_plugin_type}>>>"
">"
)
@@ -90,7 +100,7 @@ function(__qt_internal_get_static_plugin_condition_genex
"$<IN_LIST:"
"${plugin_target},"
"$<GENEX_EVAL:"
- "$<TARGET_PROPERTY:QT_PLUGINS_${_plugin_type}>"
+ "$<TARGET_PROPERTY:${target_infix}QT_PLUGINS_${_plugin_type}>"
">"
">"
)
@@ -98,7 +108,7 @@ function(__qt_internal_get_static_plugin_condition_genex
"$<IN_LIST:"
"${plugin_target_versionless},"
"$<GENEX_EVAL:"
- "$<TARGET_PROPERTY:QT_PLUGINS_${_plugin_type}>"
+ "$<TARGET_PROPERTY:${target_infix}QT_PLUGINS_${_plugin_type}>"
">"
">"
)
@@ -106,7 +116,7 @@ function(__qt_internal_get_static_plugin_condition_genex
# No point in linking the plugin initialization source file into static libraries. The
# initialization symbol will be discarded by the linker when the static lib is linked into an
# executable or shared library, because nothing is referencing the global static symbol.
- set(type_genex "$<TARGET_PROPERTY:TYPE>")
+ set(type_genex "$<TARGET_PROPERTY:${target_infix}TYPE>")
set(no_static_genex "$<NOT:$<STREQUAL:${type_genex},STATIC_LIBRARY>>")
# Complete condition that defines whether a static plugin is linked
@@ -177,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)
@@ -308,6 +318,25 @@ function(__qt_internal_collect_plugin_init_libraries plugin_targets out_var)
set("${out_var}" "${plugin_inits_to_link}" PARENT_SCOPE)
endfunction()
+# Collect a list of genexes to deploy plugin libraries.
+function(__qt_internal_collect_plugin_library_files target plugin_targets out_var)
+ set(library_files "")
+
+ foreach(plugin_target ${plugin_targets})
+ set(plugin_target_versioned "${QT_CMAKE_EXPORT_NAMESPACE}::${plugin_target}")
+ __qt_internal_get_static_plugin_condition_genex(
+ "${plugin_target}"
+ plugin_condition
+ TARGET ${target}
+ )
+
+ set(target_genex "$<${plugin_condition}:${plugin_target_versioned}>")
+ list(APPEND library_files "$<$<BOOL:${target_genex}>:$<TARGET_FILE:${target_genex}>>")
+ endforeach()
+
+ set("${out_var}" "${library_files}" PARENT_SCOPE)
+endfunction()
+
# Collects all plugin targets discovered by walking the dependencies of ${target}.
#
# Walks immediate dependencies and their transitive dependencies.
@@ -387,6 +416,46 @@ function(__qt_internal_collect_plugin_targets_from_dependencies_of_plugins targe
set("${out_var}" "${plugin_targets}" PARENT_SCOPE)
endfunction()
+# Generate plugin information files for deployment
+#
+# Arguments:
+# OUT_PLUGIN_TARGETS - Variable name to store the plugin targets that were collected with
+# __qt_internal_collect_plugin_targets_from_dependencies.
+function(__qt_internal_generate_plugin_deployment_info target)
+ set(no_value_options "")
+ set(single_value_options "OUT_PLUGIN_TARGETS")
+ set(multi_value_options "")
+ cmake_parse_arguments(PARSE_ARGV 0 arg
+ "${no_value_options}" "${single_value_options}" "${multi_value_options}"
+ )
+
+ __qt_internal_collect_plugin_targets_from_dependencies("${target}" plugin_targets)
+ if(NOT "${arg_OUT_PLUGIN_TARGETS}" STREQUAL "")
+ set("${arg_OUT_PLUGIN_TARGETS}" "${plugin_targets}" PARENT_SCOPE)
+ endif()
+
+ get_target_property(marked_for_deployment ${target} _qt_marked_for_deployment)
+ if(NOT marked_for_deployment)
+ return()
+ endif()
+
+ __qt_internal_collect_plugin_library_files(${target} "${plugin_targets}" plugins_files)
+ set(plugins_files "$<FILTER:${plugins_files},EXCLUDE,^$>")
+
+ _qt_internal_get_deploy_impl_dir(deploy_impl_dir)
+ set(file_path "${deploy_impl_dir}/${target}-plugins")
+ get_cmake_property(is_multi_config GENERATOR_IS_MULTI_CONFIG)
+ if(is_multi_config)
+ string(APPEND file_path "-$<CONFIG>")
+ endif()
+ string(APPEND file_path ".cmake")
+
+ file(GENERATE
+ OUTPUT ${file_path}
+ CONTENT "set(__QT_DEPLOY_PLUGINS ${plugins_files})"
+ )
+endfunction()
+
# Main logic of finalizer mode.
function(__qt_internal_apply_plugin_imports_finalizer_mode target)
# Process a target only once.
@@ -395,6 +464,9 @@ function(__qt_internal_apply_plugin_imports_finalizer_mode target)
return()
endif()
+ __qt_internal_generate_plugin_deployment_info(${target}
+ OUT_PLUGIN_TARGETS plugin_targets)
+
# By default if the project hasn't explicitly opted in or out, use finalizer mode.
# The precondition for this is that qt_finalize_target was called (either explicitly by the user
# or auto-deferred by CMake 3.19+).
@@ -408,7 +480,6 @@ function(__qt_internal_apply_plugin_imports_finalizer_mode target)
return()
endif()
- __qt_internal_collect_plugin_targets_from_dependencies("${target}" plugin_targets)
__qt_internal_collect_plugin_init_libraries("${plugin_targets}" init_libraries)
__qt_internal_collect_plugin_libraries("${plugin_targets}" plugin_libraries)
diff --git a/cmake/QtPublicTargetHelpers.cmake b/cmake/QtPublicTargetHelpers.cmake
index 554b02fcf5..02d5546560 100644
--- a/cmake/QtPublicTargetHelpers.cmake
+++ b/cmake/QtPublicTargetHelpers.cmake
@@ -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: BSD-3-Clause
function(__qt_internal_strip_target_directory_scope_token target out_var)
# In CMake versions earlier than CMake 3.18, a subdirectory scope id is appended to the
@@ -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 70fa45a898..771911c5d5 100644
--- a/cmake/QtPublicTestHelpers.cmake
+++ b/cmake/QtPublicTestHelpers.cmake
@@ -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: BSD-3-Clause
# This function wraps COMMAND with cmake script, that makes possible standalone run with external
# arguments.
@@ -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,8 +97,12 @@ 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()"
)
endfunction()
+
+function(_qt_internal_test_batch_target_name out)
+ set(${out} "test_batch" PARENT_SCOPE)
+endfunction()
diff --git a/cmake/QtPublicToolHelpers.cmake b/cmake/QtPublicToolHelpers.cmake
index ae5923a37a..031f0a3317 100644
--- a/cmake/QtPublicToolHelpers.cmake
+++ b/cmake/QtPublicToolHelpers.cmake
@@ -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: BSD-3-Clause
# The function returns location of the imported 'tool', returns an empty string if tool is not
# imported.
@@ -44,3 +44,73 @@ function(__qt_internal_get_tool_imported_location out_var tool)
set(${out_var} "${${out_var}}" PARENT_SCOPE)
endfunction()
+
+function(_qt_internal_generate_tool_command_wrapper)
+ get_property(is_called GLOBAL PROPERTY _qt_internal_generate_tool_command_wrapper_called)
+ if(NOT CMAKE_HOST_WIN32 OR is_called)
+ return()
+ endif()
+
+ set(prefixes "")
+
+ # In a prefix build, the just-built tools should pick up libraries from the current repo build
+ # dir.
+ if(QT_BUILD_DIR)
+ list(APPEND prefixes "${QT_BUILD_DIR}")
+ endif()
+
+ # Pick up libraries from the main location where Qt was installed during a Qt build.
+ if(QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX)
+ list(APPEND prefixes "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}")
+ endif()
+
+ # Needed for ExternalProjects examples, where the Qt build dir is passed via this variable
+ # to the example project.
+ if(QT_ADDITIONAL_PACKAGES_PREFIX_PATH)
+ __qt_internal_prefix_paths_to_roots(additional_roots
+ "${QT_ADDITIONAL_PACKAGES_PREFIX_PATH}")
+ list(APPEND prefixes ${QT_ADDITIONAL_PACKAGES_PREFIX_PATH})
+ endif()
+
+ # Fallback to wherever Qt6 package is.
+ if(QT6_INSTALL_PREFIX)
+ list(APPEND prefixes "${QT6_INSTALL_PREFIX}")
+ endif()
+
+ # When building qtbase, QT6_INSTALL_BINS is not set yet.
+ if(INSTALL_BINDIR)
+ set(bin_suffix "${INSTALL_BINDIR}")
+ else()
+ set(bin_suffix "${QT6_INSTALL_BINS}")
+ endif()
+
+ set(path_dirs "")
+ foreach(prefix IN LISTS prefixes)
+ set(bin_dir "${prefix}/${bin_suffix}")
+ if(EXISTS "${bin_dir}")
+ file(TO_NATIVE_PATH "${bin_dir}" path_dir)
+ list(APPEND path_dirs "${path_dir}")
+ endif()
+ endforeach()
+
+ set(tool_command_wrapper_dir "${CMAKE_BINARY_DIR}/.qt/bin")
+ file(MAKE_DIRECTORY "${tool_command_wrapper_dir}")
+ set(tool_command_wrapper_path "${tool_command_wrapper_dir}/qt_setup_tool_path.bat")
+
+ file(WRITE "${tool_command_wrapper_path}" "@echo off
+set PATH=${path_dirs};%PATH%
+%*")
+
+ set(QT_TOOL_COMMAND_WRAPPER_PATH "${tool_command_wrapper_path}"
+ CACHE INTERNAL "Path to the wrapper of the tool commands")
+
+ set_property(GLOBAL PROPERTY _qt_internal_generate_tool_command_wrapper_called TRUE)
+endfunction()
+
+# Gets the path to tool wrapper shell script.
+function(_qt_internal_get_tool_wrapper_script_path out_variable)
+ # Ensure the script wrapper exists.
+ _qt_internal_generate_tool_command_wrapper()
+
+ set(${out_variable} "${QT_TOOL_COMMAND_WRAPPER_PATH}" PARENT_SCOPE)
+endfunction()
diff --git a/cmake/QtPublicWalkLibsHelpers.cmake b/cmake/QtPublicWalkLibsHelpers.cmake
index bf9262992b..f79b70c710 100644
--- a/cmake/QtPublicWalkLibsHelpers.cmake
+++ b/cmake/QtPublicWalkLibsHelpers.cmake
@@ -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: BSD-3-Clause
# Add libraries to variable ${out_libs_var} in a way that duplicates
# are added at the end. This ensures the library order needed for the
@@ -189,7 +189,7 @@ function(__qt_internal_walk_libs
# 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)
+ if(TARGET "${namespaceless_lib_target}")
set(lib_target ${namespaceless_lib_target})
endif()
endif()
@@ -277,6 +277,18 @@ ${target}, but not declared.")
set(${rcc_objects_out_var} ${rcc_objects} PARENT_SCOPE)
endfunction()
+function(__qt_internal_print_missing_dependency_target_warning target dep)
+ if(QT_SILENCE_MISSING_DEPENDENCY_TARGET_WARNING)
+ return()
+ endif()
+ message(WARNING
+ "When trying to collect dependencies of target '${target}', "
+ "the non-existent target '${dep}' was encountered. "
+ "This can likely be fixed by moving the find_package call that pulls in "
+ "'${dep}' to the scope of directory '${CMAKE_CURRENT_LIST_DIR}' or higher. "
+ "This warning can be silenced by setting QT_SILENCE_MISSING_DEPENDENCY_TARGET_WARNING to "
+ "ON.")
+endfunction()
# Given ${target}, collect all its private dependencies that are CMake targets.
#
@@ -303,9 +315,14 @@ function(__qt_internal_collect_all_target_dependencies target out_var)
"qt_private_link_library_targets"
"collect_targets")
- if(lib_walked_targets)
- list(APPEND dep_targets ${lib_walked_targets})
- endif()
+ foreach(lib_target IN LISTS lib_walked_targets)
+ if(NOT TARGET "${lib_target}")
+ __qt_internal_print_missing_dependency_target_warning(${target}
+ ${lib_target})
+ continue()
+ endif()
+ list(APPEND dep_targets ${lib_target})
+ endforeach()
endif()
endforeach()
endif()
diff --git a/cmake/QtPublicWasmToolchainHelpers.cmake b/cmake/QtPublicWasmToolchainHelpers.cmake
index 2a4f459b49..31f6b5aca5 100644
--- a/cmake/QtPublicWasmToolchainHelpers.cmake
+++ b/cmake/QtPublicWasmToolchainHelpers.cmake
@@ -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: BSD-3-Clause
# Assuming EMSDK == /path/emsdk
#
@@ -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.10")
+ set(QT_EMCC_RECOMMENDED_VERSION "3.1.50")
set(${out_var} "${QT_EMCC_RECOMMENDED_VERSION}" PARENT_SCOPE)
endfunction()
@@ -72,3 +72,37 @@ function(__qt_internal_show_error_no_emscripten_toolchain_file_found_when_using_
"or provide a path to a valid emscripten installation via the EMSDK "
"environment variable.")
endfunction()
+
+function(__qt_internal_get_qt_build_emsdk_version out_var)
+ if(QT6_INSTALL_PREFIX)
+ set(WASM_BUILD_DIR "${QT6_INSTALL_PREFIX}")
+ elseif(QT_BUILD_DIR)
+ set(WASM_BUILD_DIR "${QT_BUILD_DIR}")
+ endif()
+ if(EXISTS "${WASM_BUILD_DIR}/src/corelib/global/qconfig.h")
+ file(READ "${WASM_BUILD_DIR}/src/corelib/global/qconfig.h" ver)
+ elseif(EXISTS "${WASM_BUILD_DIR}/include/QtCore/qconfig.h")
+ file(READ "${WASM_BUILD_DIR}/include/QtCore/qconfig.h" ver)
+ else()
+ message("qconfig.h not found, unable to determine Qt build Emscripten version")
+ endif()
+ 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)
+ __qt_internal_get_emcc_recommended_version(_recommended_emver)
+ __qt_internal_get_emroot_path_suffix_from_emsdk_env(emroot_path)
+ __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}")
+ 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}")
+ message("This may not work correctly")
+ endif()
+endfunction()
diff --git a/cmake/QtQmakeHelpers.cmake b/cmake/QtQmakeHelpers.cmake
index a81ba8d4b3..c618fa0510 100644
--- a/cmake/QtQmakeHelpers.cmake
+++ b/cmake/QtQmakeHelpers.cmake
@@ -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: BSD-3-Clause
# Create a QMake list (values space-separated) containing paths.
# Entries that contain whitespace characters are quoted.
@@ -37,8 +37,6 @@ function(qt_generate_qconfig_cpp in_file out_file)
set(QT_SYS_CONF_DIR "${INSTALL_SYSCONFDIR}")
# Compute and set relocation prefixes.
- # TODO: Clean this up, there's a bunch of unrealistic assumptions here.
- # See qtConfOutput_preparePaths in qtbase/configure.pri.
if(WIN32)
set(lib_location_absolute_path
"${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}/${INSTALL_BINDIR}")
@@ -82,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()
@@ -98,7 +96,8 @@ function(qt_generate_qmake_and_qtpaths_wrapper_for_target)
"${host_prefix}")
file(RELATIVE_PATH ext_prefix_relative_to_conf_file "${ext_prefix}/${INSTALL_BINDIR}"
"${ext_prefix}")
- file(RELATIVE_PATH ext_prefix_relative_to_host_prefix "${host_prefix}" "${ext_prefix}")
+ file(RELATIVE_PATH ext_datadir_relative_to_host_prefix "${host_prefix}"
+ "${ext_prefix}/${INSTALL_MKSPECSDIR}/..")
set(content "")
@@ -129,8 +128,24 @@ Prefix=${prefix}
string(APPEND content
"[Paths]
Prefix=${ext_prefix_relative_to_conf_file}
+Documentation=${INSTALL_DOCDIR}
+Headers=${INSTALL_INCLUDEDIR}
+Libraries=${INSTALL_LIBDIR}
+LibraryExecutables=${INSTALL_LIBEXECDIR}
+Binaries=${INSTALL_BINDIR}
+Plugins=${INSTALL_PLUGINSDIR}
+QmlImports=${INSTALL_QMLDIR}
+ArchData=${INSTALL_ARCHDATADIR}
+Data=${INSTALL_DATADIR}
+Translations=${INSTALL_TRANSLATIONSDIR}
+Examples=${INSTALL_EXAMPLESDIR}
+Tests=${INSTALL_TESTSDIR}
+Settings=${INSTALL_SYSCONFDIR}
HostPrefix=${host_prefix_relative_to_conf_file}
-HostData=${ext_prefix_relative_to_host_prefix}
+HostBinaries=${QT${PROJECT_VERSION_MAJOR}_HOST_INFO_BINDIR}
+HostLibraries=${QT${PROJECT_VERSION_MAJOR}_HOST_INFO_LIBDIR}
+HostLibraryExecutables=${QT${PROJECT_VERSION_MAJOR}_HOST_INFO_LIBEXECDIR}
+HostData=${ext_datadir_relative_to_host_prefix}
Sysroot=${sysroot}
SysrootifyPrefix=${sysrootify_prefix}
TargetSpec=${QT_QMAKE_TARGET_MKSPEC}
@@ -155,6 +170,11 @@ HostSpec=${QT_QMAKE_HOST_MKSPEC}
endif()
set(host_qt_bindir "${host_prefix}/${QT${PROJECT_VERSION_MAJOR}_HOST_INFO_BINDIR}")
+ file(TO_NATIVE_PATH "${host_qt_bindir}" host_qt_bindir)
+
+ if(QT_CREATE_VERSIONED_HARD_LINK AND QT_WILL_INSTALL)
+ set(tool_version "${PROJECT_VERSION_MAJOR}")
+ endif()
foreach(host_type ${hosts})
foreach(tool_name qmake qtpaths)
@@ -173,6 +193,14 @@ HostSpec=${QT_QMAKE_HOST_MKSPEC}
configure_file("${wrapper_in_file}" "${wrapper}" @ONLY NEWLINE_STYLE ${newline_style})
qt_copy_or_install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/${wrapper}"
DESTINATION "${INSTALL_BINDIR}")
+
+ # Configuring a new wrapper file, this type setting the tool_version
+ if(QT_CREATE_VERSIONED_HARD_LINK AND QT_WILL_INSTALL)
+ set(versioned_wrapper "preliminary/${wrapper_prefix}${tool_name}${tool_version}${wrapper_extension}")
+ configure_file("${wrapper_in_file}" "${versioned_wrapper}" @ONLY NEWLINE_STYLE ${newline_style})
+ qt_copy_or_install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/${versioned_wrapper}"
+ DESTINATION "${INSTALL_BINDIR}")
+ endif()
endforeach()
endforeach()
endfunction()
@@ -183,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/QtResourceHelpers.cmake b/cmake/QtResourceHelpers.cmake
index 76f423d8b4..2df1fed50f 100644
--- a/cmake/QtResourceHelpers.cmake
+++ b/cmake/QtResourceHelpers.cmake
@@ -1,7 +1,19 @@
# 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: BSD-3-Clause
function(qt_internal_add_resource target resourceName)
+ if(NOT TARGET "${target}")
+ message(FATAL_ERROR "${target} is not a target.")
+ endif()
+ qt_internal_is_skipped_test(skipped ${target})
+ if(skipped)
+ return()
+ endif()
+ qt_internal_is_in_test_batch(in_batch ${target})
+ if(in_batch)
+ _qt_internal_test_batch_target_name(target)
+ endif()
+
# Don't try to add resources when cross compiling, and the target is actually a host target
# (like a tool).
qt_is_imported_target("${target}" is_imported)
@@ -9,7 +21,11 @@ function(qt_internal_add_resource target resourceName)
return()
endif()
- qt_parse_all_arguments(arg "qt_add_resource" "" "PREFIX;LANG;BASE;OUTPUT_TARGETS" "FILES" ${ARGN})
+ cmake_parse_arguments(PARSE_ARGV 2 arg
+ ""
+ "PREFIX;LANG;BASE;OUTPUT_TARGETS"
+ "FILES")
+ _qt_internal_validate_all_args_are_parsed(arg)
_qt_internal_process_resource(${target} ${resourceName}
PREFIX "${arg_PREFIX}"
diff --git a/cmake/QtRpathHelpers.cmake b/cmake/QtRpathHelpers.cmake
index bdc3b89944..da6c8715a8 100644
--- a/cmake/QtRpathHelpers.cmake
+++ b/cmake/QtRpathHelpers.cmake
@@ -1,12 +1,12 @@
# 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: BSD-3-Clause
# Returns the platform-specific relative rpath base token, if it's supported.
# If it's not supported, returns the string NO_KNOWN_RPATH_REL_BASE.
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")
@@ -88,7 +88,12 @@ function(qt_apply_rpaths)
return()
endif()
- qt_parse_all_arguments(arg "qt_apply_rpaths" "RELATIVE_RPATH" "TARGET;INSTALL_PATH" "" ${ARGN})
+ cmake_parse_arguments(PARSE_ARGV 0 arg
+ "RELATIVE_RPATH"
+ "TARGET;INSTALL_PATH"
+ "")
+ _qt_internal_validate_all_args_are_parsed(arg)
+
if(NOT arg_TARGET)
message(FATAL_ERROR "No target given to qt_apply_rpaths.")
else()
@@ -187,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 c4695ac398..2a933b2222 100644
--- a/cmake/QtSanitizerHelpers.cmake
+++ b/cmake/QtSanitizerHelpers.cmake
@@ -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: BSD-3-Clause
# Computes which sanitizer options should be set based on features evaluated in qtbase.
# Sets ECM_ENABLE_SANITIZERS with those options in the function calling scope.
@@ -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/QtScopeFinalizerHelpers.cmake b/cmake/QtScopeFinalizerHelpers.cmake
index 5e1f58fa42..9e13bec26d 100644
--- a/cmake/QtScopeFinalizerHelpers.cmake
+++ b/cmake/QtScopeFinalizerHelpers.cmake
@@ -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: BSD-3-Clause
# Add a finalizer function for the current CMake list file.
# It will be processed just before leaving the current source directory scope.
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 8f670bc197..61f62207fa 100644
--- a/cmake/QtSeparateDebugInfo.cmake
+++ b/cmake/QtSeparateDebugInfo.cmake
@@ -1,7 +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
-
-include(CMakeFindBinUtils)
+# SPDX-License-Identifier: BSD-3-Clause
if(CMAKE_VERSION VERSION_LESS 3.17.0)
set(CMAKE_CURRENT_FUNCTION_LIST_DIR ${CMAKE_CURRENT_LIST_DIR})
@@ -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 95b5e64170..a420495756 100644
--- a/cmake/QtSetup.cmake
+++ b/cmake/QtSetup.cmake
@@ -1,328 +1,6 @@
# 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: 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)
-
-# 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()
-
-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 "")
-
-# 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)
-option(QT_BUILD_MINIMAL_STATIC_TESTS "Build minimal subset of tests for static Qt builds" OFF)
-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()
-
-# 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()
diff --git a/cmake/QtSimdHelpers.cmake b/cmake/QtSimdHelpers.cmake
index 233b99e8ea..1e77bf449f 100644
--- a/cmake/QtSimdHelpers.cmake
+++ b/cmake/QtSimdHelpers.cmake
@@ -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: BSD-3-Clause
# Handle files that need special SIMD-related flags.
#
@@ -16,8 +16,12 @@
# SIMD compiler flags. This is mostly relevant for fat / universal builds
#
function(qt_internal_add_simd_part target)
- qt_parse_all_arguments(arg "qt_add_simd_part" "" "NAME;SIMD"
- "${__default_private_args};COMPILE_FLAGS;EXCLUDE_OSX_ARCHITECTURES" ${ARGN})
+ cmake_parse_arguments(PARSE_ARGV 1 arg
+ ""
+ "NAME;SIMD"
+ "${__default_private_args};COMPILE_FLAGS;EXCLUDE_OSX_ARCHITECTURES")
+ _qt_internal_validate_all_args_are_parsed(arg)
+
if ("x${arg_SIMD}" STREQUAL x)
message(FATAL_ERROR "qt_add_simd_part needs a SIMD type to be set.")
endif()
@@ -94,7 +98,9 @@ function(qt_internal_add_simd_part target)
${arg_COMPILE_FLAGS}
)
endforeach()
- set_source_files_properties(${arg_SOURCES} PROPERTIES SKIP_PRECOMPILE_HEADERS TRUE)
+ set_source_files_properties(${arg_SOURCES} PROPERTIES
+ SKIP_PRECOMPILE_HEADERS TRUE
+ SKIP_UNITY_BUILD_INCLUSION TRUE)
target_sources(${target} PRIVATE ${arg_SOURCES})
else()
if(QT_CMAKE_DEBUG_EXTEND_TARGET)
diff --git a/cmake/QtSingleRepoTargetSetBuildHelpers.cmake b/cmake/QtSingleRepoTargetSetBuildHelpers.cmake
index 245d695079..9a003c62c5 100644
--- a/cmake/QtSingleRepoTargetSetBuildHelpers.cmake
+++ b/cmake/QtSingleRepoTargetSetBuildHelpers.cmake
@@ -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: BSD-3-Clause
# Macro that checks for a single repo target set build, and returns from the current file, directory
# or function. Use this at the top of project files to whitelist the file for the given package.
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 c84dbab40d..0188b87c6a 100644
--- a/cmake/QtSyncQtHelpers.cmake
+++ b/cmake/QtSyncQtHelpers.cmake
@@ -1,206 +1,324 @@
# 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: BSD-3-Clause
-function(qt_ensure_perl)
- find_program(HOST_PERL "perl" DOC "Perl binary")
- if (NOT HOST_PERL)
- message(FATAL_ERROR "Perl needs to be available to build Qt.")
+# The function generates the Qt module header structure in build directory and creates install
+# rules. Apart the lists of header files the function takes into account
+# QT_REPO_PUBLIC_NAMESPACE_REGEX cache variable, that can be set by repository in .cmake.conf file.
+# The variable tells the syncqt program, what namespaces are treated as public. Symbols in public
+# namespaces are considered when generating CaMeL case header files.
+function(qt_internal_target_sync_headers target module_headers module_headers_generated)
+ if(NOT TARGET ${QT_CMAKE_EXPORT_NAMESPACE}::syncqt)
+ message(FATAL_ERROR "${QT_CMAKE_EXPORT_NAMESPACE}::syncqt is not a target.")
endif()
-endfunction()
-
-function(qt_ensure_sync_qt)
- qt_ensure_perl()
- if(DEFINED QT_SYNCQT)
+ get_target_property(has_headers ${target} _qt_module_has_headers)
+ if(NOT has_headers)
return()
endif()
- get_property(QT_SYNCQT GLOBAL PROPERTY _qt_syncqt)
- if(NOT "${QT_SYNCQT}" STREQUAL "")
- set(QT_SYNCQT "${QT_SYNCQT}" PARENT_SCOPE)
- return()
- endif()
+ qt_internal_module_info(module "${target}")
- # When building qtbase, use the source syncqt, otherwise use the installed one.
- set(SYNCQT_FROM_SOURCE "${QtBase_SOURCE_DIR}/libexec/syncqt.pl")
- if(NOT ("${QtBase_SOURCE_DIR}" STREQUAL "") AND EXISTS "${SYNCQT_FROM_SOURCE}")
- set(syncqt_absolute_path "${SYNCQT_FROM_SOURCE}")
- message(STATUS "Using source syncqt found at: ${syncqt_absolute_path}")
-
- qt_path_join(syncqt_install_dir ${QT_INSTALL_DIR} ${INSTALL_LIBEXECDIR})
- qt_copy_or_install(PROGRAMS "${SYNCQT_FROM_SOURCE}"
- DESTINATION "${syncqt_install_dir}")
- elseif(NOT "${QT_HOST_PATH}" STREQUAL "")
- get_filename_component(syncqt_absolute_path
- "${QT_HOST_PATH}/${QT${PROJECT_VERSION_MAJOR}_HOST_INFO_LIBEXECDIR}/syncqt.pl"
- ABSOLUTE)
- message(STATUS "Using host syncqt found at: ${syncqt_absolute_path}")
- else()
- get_filename_component(syncqt_absolute_path
- "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}/${INSTALL_LIBEXECDIR}/syncqt.pl"
- ABSOLUTE)
- message(STATUS "Using installed syncqt found at: ${syncqt_absolute_path}")
+ get_target_property(sync_source_directory ${target} _qt_sync_source_directory)
+ set(syncqt_timestamp "${CMAKE_CURRENT_BINARY_DIR}/${target}_syncqt_timestamp")
+ set(syncqt_outputs "${syncqt_timestamp}")
+
+ set(is_interface_lib FALSE)
+ get_target_property(type ${target} TYPE)
+ if(type STREQUAL "INTERFACE_LIBRARY")
+ set(is_interface_lib TRUE)
endif()
- set(QT_SYNCQT "${syncqt_absolute_path}" PARENT_SCOPE)
- set_property(GLOBAL PROPERTY _qt_syncqt "${syncqt_absolute_path}")
-endfunction()
+ set(version_script_private_content_file "")
+ if(NOT is_interface_lib)
+ list(APPEND syncqt_outputs
+ "${module_build_interface_include_dir}/${module}Version"
+ "${module_build_interface_include_dir}/qt${module_lower}version.h")
+ if(TEST_ld_version_script)
+ set(version_script_private_content_file
+ "${CMAKE_CURRENT_BINARY_DIR}/${target}.version.private_content")
+ set(version_script_args
+ "-versionScript" "${version_script_private_content_file}")
+ list(APPEND syncqt_outputs "${version_script_private_content_file}")
+ qt_internal_add_linker_version_script(${target}
+ PRIVATE_CONTENT_FILE "${version_script_private_content_file}")
+ endif()
+ endif()
-function(qt_install_injections target build_dir install_dir)
- set(injections ${ARGN})
- qt_internal_module_info(module ${target})
- get_target_property(target_type ${target} TYPE)
- if (target_type STREQUAL "INTERFACE_LIBRARY")
- set(is_framework FALSE)
+ # Check for _qt_module_is_3rdparty_header_library flag to detect non-Qt modules and
+ # indicate this to syncqt.
+ get_target_property(is_3rd_party_library ${target} _qt_module_is_3rdparty_header_library)
+ set(non_qt_module_argument "")
+ if(is_3rd_party_library)
+ set(non_qt_module_argument "-nonQt")
else()
+ list(APPEND syncqt_outputs "${module_build_interface_include_dir}/${module}")
+ get_target_property(no_headersclean_check ${target} _qt_no_headersclean_check)
+ if(NOT no_headersclean_check)
+ list(APPEND syncqt_outputs
+ "${CMAKE_CURRENT_BINARY_DIR}/${module}_header_check_exceptions")
+ endif()
+ endif()
+
+ set(is_framework FALSE)
+ if(NOT is_interface_lib)
get_target_property(is_framework ${target} FRAMEWORK)
endif()
- # examples:
- # SYNCQT.INJECTIONS = src/corelib/global/qconfig.h:qconfig.h:QtConfig src/corelib/global/qconfig_p.h:5.12.0/QtCore/private/qconfig_p.h
- # SYNCQT.INJECTIONS = src/gui/vulkan/qvulkanfunctions.h:^qvulkanfunctions.h:QVulkanFunctions:QVulkanDeviceFunctions src/gui/vulkan/qvulkanfunctions_p.h:^5.12.0/QtGui/private/qvulkanfunctions_p.h
- # The are 3 parts to the assignment, divded by colons ':'.
- # The first part contains a path to a generated file in a build folder.
- # The second part contains the file name that the forwarding header should have, which points
- # to the file in the first part.
- # The third part contains multiple UpperCaseFileNames that should be forwarding headers to the
- # header specified in the second part.
- separate_arguments(injections UNIX_COMMAND "${injections}")
- foreach(injection ${injections})
- string(REPLACE ":" ";" injection ${injection})
- # Part 1.
- list(GET injection 0 file)
- # Part 2.
- list(GET injection 1 destination)
- string(REGEX REPLACE "^\\^" "" destination "${destination}")
- list(REMOVE_AT injection 0 1)
- # Part 3.
- set(fwd_hdrs ${injection})
- get_filename_component(destinationdir ${destination} DIRECTORY)
- get_filename_component(destinationname ${destination} NAME)
- get_filename_component(original_file_name ${file} NAME)
-
- # This describes a concrete example for easier comprehension:
- # A file 'qtqml-config.h' is generated by qt_internal_feature_write_file into
- # ${qtdeclarative_build_dir}/src/{module_include_name}/qtqml-config.h (part 1).
- #
- # Generate a lower case forwarding header (part 2) 'qtqml-config.h' at the following
- # location:
- # ${some_prefix}/include/${module_include_name}/qtqml-config.h.
- #
- # Inside this file, we #include the originally generated file,
- # ${qtdeclarative_build_dir}/src/{module_include_name}/qtqml-config.h.
- #
- # ${some_prefix}'s value depends on the build type.
- # If doing a prefix build, it should point to
- # ${current_repo_build_dir} which is ${qtdeclarative_build_dir}.
- # If doing a non-prefix build, it should point to
- # ${qtbase_build_dir}.
- #
- # In the code below, ${some_prefix} == ${build_dir}.
- set(lower_case_forwarding_header_path "${build_dir}/include/${module_include_name}")
- if(destinationdir)
- string(APPEND lower_case_forwarding_header_path "/${destinationdir}")
- endif()
- set(current_repo_build_dir "${PROJECT_BINARY_DIR}")
- file(RELATIVE_PATH relpath
- "${lower_case_forwarding_header_path}"
- "${current_repo_build_dir}/${file}")
- set(main_contents "#include \"${relpath}\"")
+ qt_internal_get_qt_all_known_modules(known_modules)
+
+ get_target_property(is_internal_module ${target} _qt_is_internal_module)
+ set(internal_module_argument "")
+ if(is_internal_module)
+ set(internal_module_argument "-internal")
+ endif()
- qt_configure_file(OUTPUT "${lower_case_forwarding_header_path}/${original_file_name}"
- CONTENT "${main_contents}")
+ 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)
- if(is_framework)
- if(file MATCHES "_p\\.h$")
- set(header_type PRIVATE)
- else()
- set(header_type PUBLIC)
- endif()
- qt_copy_framework_headers(${target} ${header_type}
- ${current_repo_build_dir}/${file})
+ # We need to use the real paths since otherwise it may lead to the invalid work of the
+ # std::filesystem API
+ get_filename_component(source_dir_real "${sync_source_directory}" REALPATH)
+ get_filename_component(binary_dir_real "${CMAKE_CURRENT_BINARY_DIR}" REALPATH)
+
+ if(QT_REPO_PUBLIC_NAMESPACE_REGEX)
+ set(public_namespaces_filter -publicNamespaceFilter "${QT_REPO_PUBLIC_NAMESPACE_REGEX}")
+ endif()
+
+ if(qpa_filter_regex)
+ set(qpa_filter_argument
+ -qpaHeadersFilter "${qpa_filter_regex}"
+ )
+ 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}"
+ -binaryDir "${binary_dir_real}"
+ -privateHeadersFilter "${private_filter_regex}"
+ -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}
+ )
+
+ if(QT_INTERNAL_ENABLE_SYNCQT_DEBUG_OUTPUT)
+ list(APPEND common_syncqt_arguments -debug)
+ endif()
+
+ set(build_time_syncqt_arguments "")
+ if(WARNINGS_ARE_ERRORS)
+ if(is_interface_lib)
+ set(warnings_are_errors_enabled_genex 1)
else()
- # Copy the actual injected (generated) header file (not the just created forwarding one)
- # to its install location when doing a prefix build. In an non-prefix build, the qt_install
- # will be a no-op.
- qt_path_join(install_destination
- ${install_dir} ${INSTALL_INCLUDEDIR}
- ${module_include_name} ${destinationdir})
- qt_install(FILES ${current_repo_build_dir}/${file}
- DESTINATION ${install_destination}
- RENAME ${destinationname} OPTIONAL)
+ set(warnings_are_errors_enabled_genex
+ "$<NOT:$<BOOL:$<TARGET_PROPERTY:${target},QT_SKIP_WARNINGS_ARE_ERRORS>>>")
endif()
+ list(APPEND build_time_syncqt_arguments
+ "$<${warnings_are_errors_enabled_genex}:-warningsAreErrors>")
+ endif()
- # Generate UpperCaseNamed forwarding headers (part 3).
- foreach(fwd_hdr ${fwd_hdrs})
- set(upper_case_forwarding_header_path "include/${module_include_name}")
- if(destinationdir)
- string(APPEND upper_case_forwarding_header_path "/${destinationdir}")
- endif()
+ if(is_framework)
+ list(REMOVE_ITEM module_headers "${CMAKE_CURRENT_BINARY_DIR}/${target}_fake_header.h")
+ endif()
+
+ # Filter the generated ui_ header files and header files located in the 'doc/' subdirectory.
+ list(FILTER module_headers EXCLUDE REGEX
+ "(.+/(ui_)[^/]+\\.h|${CMAKE_CURRENT_SOURCE_DIR}(/.+)?/doc/+\\.h)")
- # Generate upper case forwarding header like QVulkanFunctions or QtConfig.
- qt_configure_file(OUTPUT "${build_dir}/${upper_case_forwarding_header_path}/${fwd_hdr}"
- CONTENT "#include \"${destinationname}\"\n")
-
- if(is_framework)
- # Copy the forwarding header to the framework's Headers directory.
- qt_copy_framework_headers(${target} PUBLIC
- "${build_dir}/${upper_case_forwarding_header_path}/${fwd_hdr}")
- else()
- # Install the forwarding header.
- qt_path_join(install_destination "${install_dir}" "${INSTALL_INCLUDEDIR}"
- ${module_include_name})
- qt_install(FILES "${build_dir}/${upper_case_forwarding_header_path}/${fwd_hdr}"
- DESTINATION ${install_destination} OPTIONAL)
+ set(syncqt_staging_dir "${module_build_interface_include_dir}/.syncqt_staging")
+
+ set(syncqt_args "${common_syncqt_arguments}")
+ list(APPEND syncqt_args
+ -headers ${module_headers}
+ -stagingDir "${syncqt_staging_dir}"
+ -knownModules ${known_modules}
+ ${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}
+ COMMAND
+ ${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
+ # ${target}_sync_all_public_headers is running after ${target}_sync_headers, when building docs.
+ set(syncqt_all_args "${common_syncqt_arguments};-all")
+ list(JOIN syncqt_all_args "\n" syncqt_all_args_string)
+ set(syncqt_all_args_rsp "${binary_dir_real}/${target}_syncqt_all_args")
+ qt_configure_file(OUTPUT "${syncqt_all_args_rsp}" CONTENT "${syncqt_all_args_string}")
+ add_custom_target(${target}_sync_all_public_headers
+ COMMAND
+ ${QT_CMAKE_EXPORT_NAMESPACE}::syncqt
+ "@${syncqt_all_args_rsp}"
+ ${external_headers_dir_copy_cmd}
+ DEPENDS
+ ${module_headers}
+ ${syncqt_all_args_rsp}
+ ${QT_CMAKE_EXPORT_NAMESPACE}::syncqt
+ ${target}_sync_headers
+ VERBATIM
+ )
+
+ if(NOT TARGET sync_all_public_headers)
+ add_custom_target(sync_all_public_headers)
+ endif()
+ add_dependencies(sync_all_public_headers ${target}_sync_all_public_headers)
+
+ 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}"
+ )
+ endif()
+
+ if(NOT is_interface_lib)
+ set_property(TARGET ${target}
+ APPEND PROPERTY AUTOGEN_TARGET_DEPENDS "${target}_sync_headers")
+ endif()
+ add_dependencies(${target} "${target}_sync_headers")
+
+
+ get_target_property(private_module_target ${target} _qt_private_module_target_name)
+ if(private_module_target)
+ add_dependencies(${private_module_target} "${target}_sync_headers")
+ endif()
+
+ # 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 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(
+ COMMAND
+ ${syncqt_location}
+ "@${syncqt_args_rsp}"
+ RESULT_VARIABLE syncqt_result
+ OUTPUT_VARIABLE syncqt_output
+ 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()
- endforeach()
- endforeach()
+ message(FATAL_ERROR
+ "syncqt.cpp failed for module ${module}:\n${syncqt_output}")
+ endif()
+ if(syncqt_output)
+ message(WARNING "${syncqt_output}")
+ endif()
+ set_property(GLOBAL APPEND PROPERTY _qt_synced_modules ${module})
+ endif()
endfunction()
-function(qt_read_headers_pri module_include_dir resultVarPrefix)
- file(STRINGS "${module_include_dir}/headers.pri" headers_pri_contents)
- foreach(line ${headers_pri_contents})
- if("${line}" MATCHES "SYNCQT.HEADER_FILES = (.*)")
- set(public_module_headers "${CMAKE_MATCH_1}")
- separate_arguments(public_module_headers UNIX_COMMAND "${public_module_headers}")
- elseif("${line}" MATCHES "SYNCQT.PRIVATE_HEADER_FILES = (.*)")
- set(private_module_headers "${CMAKE_MATCH_1}")
- separate_arguments(private_module_headers UNIX_COMMAND "${private_module_headers}")
- elseif("${line}" MATCHES "SYNCQT.GENERATED_HEADER_FILES = (.*)")
- set(generated_module_headers "${CMAKE_MATCH_1}")
- separate_arguments(generated_module_headers UNIX_COMMAND "${generated_module_headers}")
- foreach(generated_header ${generated_module_headers})
- list(APPEND public_module_headers "${module_include_dir}/${generated_header}")
- endforeach()
- elseif("${line}" MATCHES "SYNCQT.INJECTIONS = (.*)")
- set(injections "${CMAKE_MATCH_1}")
- elseif("${line}" MATCHES "SYNCQT.([A-Z_]+)_HEADER_FILES = (.+)")
- set(prefix "${CMAKE_MATCH_1}")
- string(TOLOWER "${prefix}" prefix)
- set(entries "${CMAKE_MATCH_2}")
- separate_arguments(entries UNIX_COMMAND "${entries}")
- set("${resultVarPrefix}_${prefix}" "${entries}" PARENT_SCOPE)
+function(qt_internal_collect_sync_header_dependencies out_var skip_non_existing)
+ list(LENGTH ARGN sync_headers_target_count)
+ if(sync_headers_target_count EQUAL 0)
+ message(FATAL_ERROR "Invalid use of qt_internal_collect_sync_header_dependencies,"
+ " dependencies are not specified")
+ endif()
+
+ set(${out_var} "")
+ foreach(sync_headers_target IN LISTS ARGN)
+ set(sync_headers_target "${sync_headers_target}_sync_headers")
+ if(NOT skip_non_existing OR TARGET ${sync_headers_target})
+ list(APPEND ${out_var} ${sync_headers_target})
endif()
endforeach()
- set(${resultVarPrefix}_public "${public_module_headers}" PARENT_SCOPE)
- set(${resultVarPrefix}_private "${private_module_headers}" PARENT_SCOPE)
- set(${resultVarPrefix}_injections "${injections}" PARENT_SCOPE)
-endfunction()
-
-function(qt_compute_injection_forwarding_header target)
- qt_parse_all_arguments(arg "qt_compute_injection_forwarding_header"
- "PRIVATE" "SOURCE;OUT_VAR" "" ${ARGN})
- qt_internal_module_info(module "${target}")
- get_filename_component(file_name "${arg_SOURCE}" NAME)
+ list(REMOVE_DUPLICATES ${out_var})
- set(source_absolute_path "${CMAKE_CURRENT_BINARY_DIR}/${arg_SOURCE}")
- file(RELATIVE_PATH relpath "${PROJECT_BINARY_DIR}" "${source_absolute_path}")
+ set(${out_var} "${${out_var}}" PARENT_SCOPE)
+endfunction()
- if (arg_PRIVATE)
- set(fwd "${PROJECT_VERSION}/${module_include_name}/private/${file_name}")
- else()
- set(fwd "${file_name}")
+function(qt_internal_add_sync_header_dependencies target)
+ qt_internal_collect_sync_header_dependencies(sync_headers_targets FALSE ${ARGN})
+ if(sync_headers_targets)
+ add_dependencies(${target} ${sync_headers_targets})
endif()
+endfunction()
- string(APPEND ${arg_OUT_VAR} " ${relpath}:${fwd}")
- set(${arg_OUT_VAR} ${${arg_OUT_VAR}} PARENT_SCOPE)
+function(qt_internal_add_autogen_sync_header_dependencies target)
+ qt_internal_collect_sync_header_dependencies(sync_headers_targets TRUE ${ARGN})
+ foreach(sync_headers_target IN LISTS sync_headers_targets)
+ set_property(TARGET ${target} APPEND PROPERTY AUTOGEN_TARGET_DEPENDS
+ "${sync_headers_target}")
+ endforeach()
endfunction()
diff --git a/cmake/QtTargetHelpers.cmake b/cmake/QtTargetHelpers.cmake
index 1c9e1247b6..e669047ff1 100644
--- a/cmake/QtTargetHelpers.cmake
+++ b/cmake/QtTargetHelpers.cmake
@@ -1,44 +1,105 @@
# 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: BSD-3-Clause
# This function can be used to add sources/libraries/etc. to the specified CMake target
# if the provided CONDITION evaluates to true.
+# One-value Arguments:
+# PRECOMPILED_HEADER
+# Name of the precompiled header that is used for the target.
+# Multi-value Arguments:
+# CONDITION
+# The condition under which the target will be extended.
+# CONDITION_INDEPENDENT_SOURCES
+# Source files that should be added to the target unconditionally. Note that if target is Qt
+# 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
+# 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.")
+ endif()
+ qt_internal_is_skipped_test(skipped ${target})
+ if(skipped)
+ return()
+ endif()
+ qt_internal_is_in_test_batch(in_batch ${target})
+ if(in_batch)
+ _qt_internal_test_batch_target_name(target)
+ endif()
+
# Don't try to extend_target when cross compiling an imported host target (like a tool).
qt_is_imported_target("${target}" is_imported)
if(is_imported)
return()
endif()
- if (NOT TARGET "${target}")
- message(FATAL_ERROR "Trying to extend non-existing target \"${target}\".")
- endif()
- qt_parse_all_arguments(arg "qt_extend_target" "" "PRECOMPILED_HEADER"
- "CONDITION;${__default_public_args};${__default_private_args};${__default_private_module_args};COMPILE_FLAGS;NO_PCH_SOURCES" ${ARGN})
- if ("x${arg_CONDITION}" STREQUAL x)
+ set(option_args
+ NO_UNITY_BUILD
+ )
+ set(single_args
+ PRECOMPILED_HEADER
+ EXTRA_LINKER_SCRIPT_CONTENT
+ )
+ set(multi_args
+ ${__default_public_args}
+ ${__default_private_args}
+ ${__default_private_module_args}
+ CONDITION
+ CONDITION_INDEPENDENT_SOURCES
+ COMPILE_FLAGS
+ EXTRA_LINKER_SCRIPT_EXPORTS
+ )
+
+ cmake_parse_arguments(PARSE_ARGV 1 arg
+ "${option_args}"
+ "${single_args}"
+ "${multi_args}"
+ )
+ _qt_internal_validate_all_args_are_parsed(arg)
+
+ if("x${arg_CONDITION}" STREQUAL "x")
set(arg_CONDITION ON)
endif()
qt_evaluate_config_expression(result ${arg_CONDITION})
- if (${result})
+ if(${result})
if(QT_CMAKE_DEBUG_EXTEND_TARGET)
message("qt_extend_target(${target} CONDITION ${arg_CONDITION} ...): Evaluated")
endif()
set(dbus_sources "")
foreach(adaptor ${arg_DBUS_ADAPTOR_SOURCES})
- qt_create_qdbusxml2cpp_command("${target}" "${adaptor}" ADAPTOR BASENAME "${arg_DBUS_ADAPTOR_BASENAME}" FLAGS "${arg_DBUS_ADAPTOR_FLAGS}")
+ qt_create_qdbusxml2cpp_command("${target}" "${adaptor}"
+ ADAPTOR
+ BASENAME "${arg_DBUS_ADAPTOR_BASENAME}"
+ FLAGS ${arg_DBUS_ADAPTOR_FLAGS}
+ )
list(APPEND dbus_sources "${adaptor}")
endforeach()
foreach(interface ${arg_DBUS_INTERFACE_SOURCES})
- qt_create_qdbusxml2cpp_command("${target}" "${interface}" INTERFACE BASENAME "${arg_DBUS_INTERFACE_BASENAME}" FLAGS "${arg_DBUS_INTERFACE_FLAGS}")
+ qt_create_qdbusxml2cpp_command("${target}" "${interface}"
+ INTERFACE
+ BASENAME "${arg_DBUS_INTERFACE_BASENAME}"
+ FLAGS ${arg_DBUS_INTERFACE_FLAGS}
+ )
list(APPEND dbus_sources "${interface}")
endforeach()
+ set(all_sources
+ ${arg_SOURCES}
+ ${dbus_sources}
+ )
+
get_target_property(target_type ${target} TYPE)
set(is_library FALSE)
set(is_interface_lib FALSE)
- if (${target_type} STREQUAL "STATIC_LIBRARY" OR ${target_type} STREQUAL "SHARED_LIBRARY")
+ 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)
@@ -55,8 +116,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
@@ -67,14 +147,14 @@ function(qt_internal_extend_target target)
# functions. The property itself is not exported and should only be used in the Qt internal
# build tree.
if(NOT is_interface_lib OR CMAKE_VERSION VERSION_GREATER_EQUAL "3.19")
- target_sources("${target}" PRIVATE ${arg_SOURCES} ${dbus_sources})
- if (arg_COMPILE_FLAGS)
- set_source_files_properties(${arg_SOURCES} PROPERTIES
+ target_sources("${target}" PRIVATE ${all_sources})
+ if(arg_COMPILE_FLAGS)
+ set_source_files_properties(${all_sources} PROPERTIES
COMPILE_FLAGS "${arg_COMPILE_FLAGS}")
endif()
else()
set_property(TARGET ${target} APPEND PROPERTY
- _qt_internal_target_sources ${arg_SOURCES} ${dbus_sources})
+ _qt_internal_target_sources ${all_sources})
endif()
set(public_visibility_option "PUBLIC")
@@ -86,6 +166,8 @@ function(qt_internal_extend_target target)
target_include_directories("${target}"
${public_visibility_option} ${arg_PUBLIC_INCLUDE_DIRECTORIES}
${private_visibility_option} ${arg_INCLUDE_DIRECTORIES})
+ target_include_directories("${target}" SYSTEM
+ ${private_visibility_option} ${arg_SYSTEM_INCLUDE_DIRECTORIES})
target_compile_definitions("${target}"
${public_visibility_option} ${arg_PUBLIC_DEFINES}
${private_visibility_option} ${arg_DEFINES})
@@ -100,7 +182,7 @@ function(qt_internal_extend_target target)
${private_visibility_option} ${arg_LINK_OPTIONS})
if(NOT is_interface_lib)
- set_property (TARGET "${target}" APPEND PROPERTY
+ set_property(TARGET "${target}" APPEND PROPERTY
AUTOMOC_MOC_OPTIONS "${arg_MOC_OPTIONS}"
)
# Plugin types associated to a module
@@ -154,15 +236,252 @@ function(qt_internal_extend_target target)
DISABLE_AUTOGEN_TOOLS ${arg_DISABLE_AUTOGEN_TOOLS})
qt_update_precompiled_header("${target}" "${arg_PRECOMPILED_HEADER}")
+ ## Also exclude them from unity build
qt_update_ignore_pch_source("${target}" "${arg_NO_PCH_SOURCES}")
## Ignore objective-c files for PCH (not supported atm)
qt_ignore_pch_obj_c_sources("${target}" "${arg_SOURCES}")
+ if(arg_NO_UNITY_BUILD)
+ set_target_properties("${target}" PROPERTIES UNITY_BUILD OFF)
+ qt_update_ignore_unity_build_sources("${target}" "${arg_SOURCES}")
+ endif()
+ if(arg_NO_UNITY_BUILD_SOURCES)
+ qt_update_ignore_unity_build_sources("${target}" "${arg_NO_UNITY_BUILD_SOURCES}")
+ endif()
else()
if(QT_CMAKE_DEBUG_EXTEND_TARGET)
message("qt_extend_target(${target} CONDITION ${arg_CONDITION} ...): Skipped")
endif()
endif()
+
+ if(arg_CONDITION_INDEPENDENT_SOURCES)
+ set_source_files_properties(${arg_CONDITION_INDEPENDENT_SOURCES} PROPERTIES
+ _qt_extend_target_condition "${arg_CONDITION}"
+ SKIP_AUTOGEN TRUE
+ )
+
+ qt_internal_get_target_sources_property(sources_property)
+ set_property(TARGET ${target} APPEND PROPERTY
+ ${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()
+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}}" 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)
@@ -235,20 +554,20 @@ 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 "")
- set(arg_TARGET_COPYRIGHT "Copyright (C) 2022 The Qt Company Ltd.")
+ if(NOT arg_TARGET_COPYRIGHT)
+ set(arg_TARGET_COPYRIGHT "${QT_COPYRIGHT}")
endif()
set_target_properties(${target} PROPERTIES
QT_TARGET_VERSION "${arg_TARGET_VERSION}"
@@ -495,56 +814,139 @@ 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()
set(properties_retrieved TRUE)
+ get_target_property(is_configure_time_target ${target} _qt_internal_configure_time_target)
+ if(is_configure_time_target)
+ # 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)
+
+ 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_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\")
+ endif()
+ add_executable(${full_target} IMPORTED)
+ set_property(TARGET ${full_target} APPEND PROPERTY IMPORTED_CONFIGURATIONS ${default_cfg})
+ set_target_properties(${full_target} PROPERTIES IMPORTED_LOCATION_${uc_default_cfg}
+ \"$\{_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()
+ endif()
+
# Non-prefix debug-and-release builds: add check for the existence of the debug binary of
# 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)
-if(NOT EXISTS \"$\\{_qt_imported_location}\")
+if(NOT EXISTS \"$\{_qt_imported_location}\")
get_target_property(_qt_imported_configs ${full_target} IMPORTED_CONFIGURATIONS)
list(REMOVE_ITEM _qt_imported_configs DEBUG)
- set_property(TARGET ${full_target} PROPERTY IMPORTED_CONFIGURATIONS $\\{_qt_imported_configs})
+ set_property(TARGET ${full_target} PROPERTY IMPORTED_CONFIGURATIONS $\{_qt_imported_configs})
set_property(TARGET ${full_target} PROPERTY IMPORTED_LOCATION_DEBUG)
-endif()\n\n")
+endif()\n")
endif()
endif()
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)
+ elseif(WASM)
+ # Keep write_soname at FALSE
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")
+ 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")
+ 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)
@@ -560,20 +962,32 @@ endif()\n\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}}\")
+ 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})
- set_property(TARGET ${full_target} PROPERTY IMPORTED_IMPLIB${property_suffix} \"$\\{_qt_imported_implib${var_suffix}}\")
+ set_property(TARGET ${full_target} PROPERTY IMPORTED_IMPLIB${property_suffix} \"$\{_qt_imported_implib${var_suffix}}\")
endif()")
endif()
if(write_soname)
string(APPEND content "
if(_qt_imported_soname${var_suffix})
- set_property(TARGET ${full_target} PROPERTY IMPORTED_SONAME${property_suffix} \"$\\{_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")
@@ -586,6 +1000,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()
@@ -599,25 +1017,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()
+
+ if("${arg_CONFIG_BUILD_DIR}" STREQUAL "")
+ message(FATAL_ERROR "CONFIG_BUILD_DIR is not specified")
+ 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_INSTALL_DIR}" STREQUAL "")
+ message(FATAL_ERROR "CONFIG_INSTALL_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_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)
@@ -626,20 +1070,22 @@ function(qt_internal_create_tracepoints name tracepoints_file)
set(header_filename "${provider_name}_tracepoints_p.h")
set(header_path "${CMAKE_CURRENT_BINARY_DIR}/${header_filename}")
- if(QT_FEATURE_lttng OR QT_FEATURE_etw)
+ if(QT_FEATURE_lttng OR QT_FEATURE_etw OR QT_FEATURE_ctf)
set(source_path "${CMAKE_CURRENT_BINARY_DIR}/${provider_name}_tracepoints.cpp")
qt_configure_file(OUTPUT "${source_path}"
CONTENT "#define TRACEPOINT_CREATE_PROBES
#define TRACEPOINT_DEFINE
#include \"${header_filename}\"")
target_sources(${name} PRIVATE "${source_path}")
- target_compile_definitions(${name} PRIVATE Q_TRACEPOINT)
+ target_compile_definitions(${name} PUBLIC Q_TRACEPOINT)
if(QT_FEATURE_lttng)
set(tracegen_arg "lttng")
target_link_libraries(${name} PRIVATE LTTng::UST)
elseif(QT_FEATURE_etw)
set(tracegen_arg "etw")
+ elseif(QT_FEATURE_ctf)
+ set(tracegen_arg "ctf")
endif()
if(NOT "${QT_HOST_PATH}" STREQUAL "")
@@ -662,6 +1108,77 @@ function(qt_internal_create_tracepoints name tracepoints_file)
endif()
endfunction()
+function(qt_internal_generate_tracepoints name provider)
+ cmake_parse_arguments(arg "" "" "SOURCES" ${ARGN} )
+ set(provider_name ${provider})
+ string(PREPEND provider_name "qt")
+ set(tracepoint_filename "${provider_name}.tracepoints")
+ set(tracepoints_path "${CMAKE_CURRENT_BINARY_DIR}/${tracepoint_filename}")
+ set(header_filename "${provider_name}_tracepoints_p.h")
+ set(header_path "${CMAKE_CURRENT_BINARY_DIR}/${header_filename}")
+
+ if(QT_FEATURE_lttng OR QT_FEATURE_etw OR QT_FEATURE_ctf)
+
+ set(absolute_file_paths "")
+ foreach(file IN LISTS arg_SOURCES)
+ get_filename_component(absolute_file ${file} ABSOLUTE)
+ list(APPEND absolute_file_paths ${absolute_file})
+ endforeach()
+
+ if(NOT "${QT_HOST_PATH}" STREQUAL "")
+ qt_path_join(tracepointgen
+ "${QT_HOST_PATH}"
+ "${QT${PROJECT_VERSION_MAJOR}_HOST_INFO_LIBEXECDIR}"
+ "tracepointgen")
+ else()
+ set(tracepointgen "${QT_CMAKE_EXPORT_NAMESPACE}::tracepointgen")
+ endif()
+
+ add_custom_command(OUTPUT "${tracepoints_path}"
+ COMMAND ${tracepointgen} ${provider_name} "${tracepoints_path}" "I$<JOIN:$<TARGET_PROPERTY:${name},INCLUDE_DIRECTORIES>,;>" ${absolute_file_paths}
+ DEPENDS ${absolute_file_paths}
+ VERBATIM)
+ add_custom_target(${name}_${provider_name}_tracepoints_file DEPENDS "${tracepoints_path}")
+ add_dependencies(${name} ${name}_${provider_name}_tracepoints_file)
+
+ set(source_path "${CMAKE_CURRENT_BINARY_DIR}/${provider_name}_tracepoints.cpp")
+ qt_configure_file(OUTPUT "${source_path}"
+ CONTENT "#define TRACEPOINT_CREATE_PROBES
+ #define TRACEPOINT_DEFINE
+ #include \"${header_filename}\"")
+ target_sources(${name} PRIVATE "${source_path}")
+ target_compile_definitions(${name} PUBLIC Q_TRACEPOINT)
+
+ if(QT_FEATURE_lttng)
+ set(tracegen_arg "lttng")
+ target_link_libraries(${name} PRIVATE LTTng::UST)
+ elseif(QT_FEATURE_etw)
+ set(tracegen_arg "etw")
+ elseif(QT_FEATURE_ctf)
+ set(tracegen_arg "ctf")
+ endif()
+
+ if(NOT "${QT_HOST_PATH}" STREQUAL "")
+ qt_path_join(tracegen
+ "${QT_HOST_PATH}"
+ "${QT${PROJECT_VERSION_MAJOR}_HOST_INFO_LIBEXECDIR}"
+ "tracegen")
+ else()
+ set(tracegen "${QT_CMAKE_EXPORT_NAMESPACE}::tracegen")
+ endif()
+
+ get_filename_component(tracepoints_filepath "${tracepoints_path}" ABSOLUTE)
+ add_custom_command(OUTPUT "${header_path}"
+ COMMAND ${tracegen} ${tracegen_arg} "${tracepoints_filepath}" "${header_path}"
+ DEPENDS "${tracepoints_path}"
+ VERBATIM)
+ add_custom_target(${name}_${provider_name}_tracepoints_header DEPENDS "${header_path}")
+ add_dependencies(${name} ${name}_${provider_name}_tracepoints_header)
+ else()
+ qt_configure_file(OUTPUT "${header_path}" CONTENT "#include <private/qtrace_p.h>\n")
+ endif()
+endfunction()
+
function(qt_internal_set_compile_pdb_names target)
if(MSVC)
get_target_property(target_type ${target} TYPE)
@@ -819,6 +1336,33 @@ 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
+# ExternalProjects.
+# Needed to create a ${repo}_src global target that examples can depend on in multi-config builds
+# due to a bug in AUTOUIC.
+#
+# See QTBUG-110369.
+function(qt_internal_skip_dependency_for_examples target)
+ set_target_properties(${target} PROPERTIES _qt_skip_dependency_for_examples TRUE)
+endfunction()
+
+function(qt_internal_is_target_skipped_for_examples target out_var)
+ get_property(is_skipped TARGET ${target} PROPERTY _qt_skip_dependency_for_examples)
+ if(NOT is_skipped)
+ set(is_skipped FALSE)
+ endif()
+ set(${out_var} "${is_skipped}" PARENT_SCOPE)
endfunction()
function(qt_internal_link_internal_platform_for_object_library target)
@@ -883,9 +1427,17 @@ endfunction()
# The function disables one or multiple internal global definitions that are defined by the
# qt_internal_add_global_definition function for a specific 'target'.
function(qt_internal_undefine_global_definition target)
- if(NOT TARGET ${target})
+ if(NOT TARGET "${target}")
message(FATAL_ERROR "${target} is not a target.")
endif()
+ qt_internal_is_skipped_test(skipped ${target})
+ if(skipped)
+ return()
+ endif()
+ qt_internal_is_in_test_batch(in_batch ${target})
+ if(in_batch)
+ _qt_internal_test_batch_target_name(target)
+ endif()
if("${ARGN}" STREQUAL "")
message(FATAL_ERROR "The function expects at least one definition as an argument.")
@@ -934,3 +1486,186 @@ function(qt_internal_get_target_sources_property out_var)
endif()
set(${out_var} "${${out_var}}" PARENT_SCOPE)
endfunction()
+
+# This function collects target properties that contain generator expressions and needs to be
+# exported. This function is needed since the CMake EXPORT_PROPERTIES property doesn't support
+# properties that contain generator expressions.
+# Usage: qt_internal_add_genex_properties_export(target properties...)
+function(qt_internal_add_genex_properties_export target)
+ get_cmake_property(is_multi_config GENERATOR_IS_MULTI_CONFIG)
+
+ set(config_check_begin "")
+ set(config_check_end "")
+ if(is_multi_config)
+ list(GET CMAKE_CONFIGURATION_TYPES 0 first_config_type)
+
+ # The genex snippet is evaluated to '$<NOT:$<BOOL:$<CONFIG>>>' in the generated cmake file.
+ # The check is only applicable to the 'main' configuration. If user project doesn't use
+ # multi-config generator, then the check supposed to return true and the value from the
+ # 'main' configuration supposed to be used.
+ string(JOIN "" check_if_config_empty
+ "$<1:$><NOT:"
+ "$<1:$><BOOL:"
+ "$<1:$><CONFIG$<ANGLE-R>"
+ "$<ANGLE-R>"
+ "$<ANGLE-R>"
+ )
+
+ # The genex snippet is evaluated to '$<CONFIG:'Qt config type'>' in the generated cmake
+ # file and checks if the config that user uses matches the generated cmake file config.
+ string(JOIN "" check_user_config
+ "$<1:$><CONFIG:$<CONFIG>$<ANGLE-R>"
+ )
+
+ # The genex snippet is evaluated to '$<$<OR:$<CONFIG:'Qt config type'>>:'Property content'>
+ # for non-main Qt configs and to
+ # $<$<OR:$<CONFIG:'Qt config type'>,$<NOT:$<BOOL:$<CONFIG>>>>:'Property content'> for the
+ # main Qt config. This guard is required to choose the correct value of the property for the
+ # user project according to the user config type.
+ # All genexes need to be escaped properly to protect them from evaluation by the
+ # file(GENERATE call in the qt_internal_export_genex_properties function.
+ string(JOIN "" config_check_begin
+ "$<1:$><"
+ "$<1:$><OR:"
+ "${check_user_config}"
+ "$<$<CONFIG:${first_config_type}>:$<COMMA>${check_if_config_empty}>"
+ "$<ANGLE-R>:"
+ )
+ set(config_check_end "$<ANGLE-R>")
+ endif()
+ set(target_name "${QT_CMAKE_EXPORT_NAMESPACE}::${target}")
+ foreach(property IN LISTS ARGN)
+ set(target_property_genex "$<TARGET_PROPERTY:${target_name},${property}>")
+ # All properties that contain lists need to be protected of processing by JOIN genex calls.
+ # So this escapes the semicolons for these list.
+ set(target_property_list_escape
+ "$<JOIN:$<GENEX_EVAL:${target_property_genex}>,\;>")
+ set(property_value
+ "\"${config_check_begin}${target_property_list_escape}${config_check_end}\"")
+ set_property(TARGET ${target} APPEND PROPERTY _qt_export_genex_properties_content
+ "${property} ${property_value}")
+ endforeach()
+endfunction()
+
+# This function executes generator expressions for the properties that are added by the
+# qt_internal_add_genex_properties_export function and sets the calculated values to the
+# corresponding properties in the generated ExtraProperties.cmake file. The file then needs to be
+# included after the target creation routines in Config.cmake files. It also supports Multi-Config
+# builds.
+# Arguments:
+# EXPORT_NAME_PREFIX:
+# The portion of the file name before ExtraProperties.cmake
+# CONFIG_INSTALL_DIR:
+# Installation location for the file.
+# TARGETS:
+# The internal target names.
+function(qt_internal_export_genex_properties)
+ set(option_args "")
+ set(single_args
+ EXPORT_NAME_PREFIX
+ CONFIG_INSTALL_DIR
+ )
+ set(multi_args TARGETS)
+ cmake_parse_arguments(arg "${option_args}" "${single_args}" "${multi_args}" ${ARGN})
+
+ if(NOT arg_EXPORT_NAME_PREFIX)
+ message(FATAL_ERROR "qt_internal_export_genex_properties: "
+ "Missing EXPORT_NAME_PREFIX argument.")
+ endif()
+
+ if(NOT arg_TARGETS)
+ message(FATAL_ERROR "qt_internal_export_genex_properties: "
+ "TARGETS argument must contain at least one target")
+ endif()
+
+ foreach(target IN LISTS arg_TARGETS)
+ get_cmake_property(is_multi_config GENERATOR_IS_MULTI_CONFIG)
+
+ set(output_file_base_name "${arg_EXPORT_NAME_PREFIX}ExtraProperties")
+ set(should_append "")
+ set(config_suffix "")
+ if(is_multi_config)
+ list(GET CMAKE_CONFIGURATION_TYPES 0 first_config_type)
+ set(config_suffix "$<$<NOT:$<CONFIG:${first_config_type}>>:-$<CONFIG>>")
+ # If the generated file belongs to the 'main' config type, we should set property
+ # but not append it.
+ string(JOIN "" should_append
+ "$<$<NOT:$<CONFIG:${first_config_type}>>: APPEND>")
+ endif()
+ set(file_name "${output_file_base_name}${config_suffix}.cmake")
+
+ qt_path_join(output_file "${arg_CONFIG_INSTALL_DIR}"
+ "${file_name}")
+
+ if(NOT IS_ABSOLUTE "${output_file}")
+ qt_path_join(output_file "${QT_BUILD_DIR}" "${output_file}")
+ endif()
+
+ set(target_name "${QT_CMAKE_EXPORT_NAMESPACE}::${target}")
+
+ string(JOIN "" set_property_begin "set_property(TARGET "
+ "${target_name}${should_append} PROPERTY "
+ )
+ set(set_property_end ")")
+ set(set_property_glue "${set_property_end}\n${set_property_begin}")
+ set(property_list
+ "$<GENEX_EVAL:$<TARGET_PROPERTY:${target},_qt_export_genex_properties_content>>")
+ string(JOIN "" set_property_content "${set_property_begin}"
+ "$<JOIN:${property_list},${set_property_glue}>"
+ "${set_property_end}")
+
+ if(is_multi_config)
+ set(config_includes "")
+ foreach(config IN LISTS CMAKE_CONFIGURATION_TYPES)
+ if(NOT first_config_type STREQUAL config)
+ set(include_file_name
+ "${output_file_base_name}-${config}.cmake")
+ list(APPEND config_includes
+ "include(\"\${CMAKE_CURRENT_LIST_DIR}/${include_file_name}\")")
+ endif()
+ endforeach()
+ list(JOIN config_includes "\n" config_includes_string)
+ set(config_includes_string
+ "\n$<$<CONFIG:${first_config_type}>:${config_includes_string}>")
+ endif()
+
+ file(GENERATE OUTPUT "${output_file}"
+ CONTENT "$<$<BOOL:${property_list}>:${set_property_content}${config_includes_string}>"
+ CONDITION "$<BOOL:${property_list}>"
+ )
+ endforeach()
+
+ qt_install(FILES "$<$<BOOL:${property_list}>:${output_file}>"
+ DESTINATION "${arg_CONFIG_INSTALL_DIR}"
+ 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 78f50a0a06..705de2f739 100644
--- a/cmake/QtTestHelpers.cmake
+++ b/cmake/QtTestHelpers.cmake
@@ -1,17 +1,21 @@
# 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: BSD-3-Clause
# Simple wrapper around qt_internal_add_executable for benchmarks which insure that
# the binary is built under ${CMAKE_CURRENT_BINARY_DIR} and never installed.
# See qt_internal_add_executable() for more details.
function(qt_internal_add_benchmark target)
+ if(QT_BUILD_TESTS_BATCHED)
+ message(WARNING "Benchmarks won't be batched - unsupported (yet)")
+ endif()
- qt_parse_all_arguments(arg "qt_add_benchmark"
+ cmake_parse_arguments(PARSE_ARGV 1 arg
"${__qt_internal_add_executable_optional_args}"
"${__qt_internal_add_executable_single_args}"
"${__qt_internal_add_executable_multi_args}"
- ${ARGN}
)
+ _qt_internal_validate_all_args_are_parsed(arg)
+ _qt_internal_validate_no_unity_build(arg)
qt_remove_args(exec_args
ARGS_TO_REMOVE
@@ -27,14 +31,25 @@ 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
OUTPUT_DIRECTORY "${arg_OUTPUT_DIRECTORY}" # avoid polluting bin directory
${exec_args}
)
+ qt_internal_extend_target(${target}
+ DEFINES
+ ${deprecation_define}
+ )
# Benchmarks on iOS must be app bundles.
if(IOS)
@@ -72,50 +87,18 @@ function(qt_internal_add_benchmark target)
qt_internal_add_test_finalizers("${target}")
endfunction()
+function(qt_internal_add_test_dependencies target)
+ if(QT_BUILD_TESTS_BATCHED)
+ _qt_internal_test_batch_target_name(target)
+ endif()
+ add_dependencies(${target} ${ARGN})
+endfunction()
+
# Simple wrapper around qt_internal_add_executable for manual tests which insure that
# the binary is built under ${CMAKE_CURRENT_BINARY_DIR} and never installed.
# See qt_internal_add_executable() for more details.
function(qt_internal_add_manual_test target)
-
- qt_parse_all_arguments(arg "qt_add_manual_test"
- "${__qt_internal_add_executable_optional_args}"
- "${__qt_internal_add_executable_single_args}"
- "${__qt_internal_add_executable_multi_args}"
- ${ARGN}
- )
-
- qt_remove_args(exec_args
- ARGS_TO_REMOVE
- ${target}
- OUTPUT_DIRECTORY
- INSTALL_DIRECTORY
- ALL_ARGS
- "${__qt_internal_add_executable_optional_args}"
- "${__qt_internal_add_executable_single_args}"
- "${__qt_internal_add_executable_multi_args}"
- ARGS
- ${ARGV}
- )
-
- if(NOT arg_OUTPUT_DIRECTORY)
- set(arg_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
- endif()
-
- qt_internal_add_executable(${target}
- NO_INSTALL # we don't install benchmarks
- OUTPUT_DIRECTORY "${arg_OUTPUT_DIRECTORY}" # avoid polluting bin directory
- ${exec_args}
- )
-
- # Tests on iOS must be app bundles.
- if(IOS)
- set_target_properties(${target} PROPERTIES MACOSX_BUNDLE TRUE)
- endif()
-
- # Disable the QT_NO_NARROWING_CONVERSIONS_IN_CONNECT define for manual tests
- qt_internal_undefine_global_definition(${target} QT_NO_NARROWING_CONVERSIONS_IN_CONNECT)
-
- qt_internal_add_test_finalizers("${target}")
+ qt_internal_add_test(${ARGV} MANUAL)
endfunction()
# This function will configure the fixture for the network tests that require docker network services
@@ -126,6 +109,11 @@ function(qt_internal_setup_docker_test_fixture name)
return()
endif()
+ option(QT_SKIP_DOCKER_COMPOSE "Skip setting up docker on Linux." OFF)
+ if(QT_SKIP_DOCKER_COMPOSE)
+ return()
+ endif()
+
set(QT_TEST_SERVER_LIST ${ARGN})
set(DNSDOMAIN test-net.qt.local)
@@ -192,20 +180,32 @@ function(qt_internal_setup_docker_test_fixture name)
endfunction()
-# This function creates a CMake test target with the specified name for use with CTest.
-#
-# All tests are wrapped with cmake script that supports TESTARGS and TESTRUNNER environment
-# variables handling. Endpoint wrapper may be used standalone as cmake script to run tests e.g.:
-# TESTARGS="-o result.xml,junitxml" TESTRUNNER="testrunner --arg" ./tst_simpleTestWrapper.cmake
-# On non-UNIX machine you may need to use 'cmake -P' explicitly to execute wrapper.
-# You may avoid test wrapping by either passing NO_WRAPPER option or switching QT_NO_TEST_WRAPPERS
-# to ON. This is helpful if you want to use internal CMake tools within tests, like memory or
-# sanitizer checks. See https://cmake.org/cmake/help/v3.19/manual/ctest.1.html#ctest-memcheck-step
-# Arguments:
-# BUILTIN_TESTDATA the option forces adding the provided TESTDATA to resources.
-function(qt_internal_add_test name)
- # EXCEPTIONS is a noop as they are enabled by default.
- set(optional_args
+function(qt_internal_get_test_batch out)
+ get_property(batched_list GLOBAL PROPERTY _qt_batched_test_list_property)
+ set(${out} ${batched_list} PARENT_SCOPE)
+endfunction()
+
+function(qt_internal_prepare_test_target_flags version_arg exceptions_text gui_text)
+ cmake_parse_arguments(arg "EXCEPTIONS;NO_EXCEPTIONS;GUI" "VERSION" "" ${ARGN})
+
+ if (arg_VERSION)
+ set(${version_arg} VERSION "${arg_VERSION}" PARENT_SCOPE)
+ endif()
+
+ # Qt modules get compiled without exceptions enabled by default.
+ # However, testcases should be still built with exceptions.
+ set(${exceptions_text} "EXCEPTIONS" PARENT_SCOPE)
+ if (${arg_NO_EXCEPTIONS} OR WASM)
+ set(${exceptions_text} "" PARENT_SCOPE)
+ endif()
+
+ if (${arg_GUI})
+ set(${gui_text} "GUI" PARENT_SCOPE)
+ endif()
+endfunction()
+
+function(qt_internal_get_test_arg_definitions optional_args single_value_args multi_value_args)
+ set(${optional_args}
RUN_SERIAL
EXCEPTIONS
NO_EXCEPTIONS
@@ -215,45 +215,287 @@ function(qt_internal_add_test name)
LOWDPI
NO_WRAPPER
BUILTIN_TESTDATA
+ MANUAL
+ NO_BATCH
+ NO_INSTALL
+ BUNDLE_ANDROID_OPENSSL_LIBS
+ PARENT_SCOPE
)
- set(single_value_args
+ set(${single_value_args}
OUTPUT_DIRECTORY
WORKING_DIRECTORY
TIMEOUT
VERSION
+ PARENT_SCOPE
)
- set(multi_value_args
+ set(${multi_value_args}
QML_IMPORTPATH
TESTDATA
QT_TEST_SERVER_LIST
${__default_private_args}
${__default_public_args}
+ PARENT_SCOPE
)
- qt_parse_all_arguments(arg "qt_add_test"
+endfunction()
+
+function(qt_internal_add_test_to_batch batch_name name)
+ qt_internal_get_test_arg_definitions(optional_args single_value_args multi_value_args)
+
+ cmake_parse_arguments(
+ arg "${optional_args}" "${single_value_args}" "${multi_value_args}" ${ARGN})
+ qt_internal_prepare_test_target_flags(version_arg exceptions_text gui_text ${ARGN})
+
+ _qt_internal_validate_no_unity_build(arg)
+
+ _qt_internal_test_batch_target_name(target)
+
+ # 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}
+ ${version_arg}
+ NO_INSTALL
+ OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/build_dir"
+ SOURCES "${QT_CMAKE_DIR}/qbatchedtestrunner.in.cpp"
+ DEFINES QTEST_BATCH_TESTS ${deprecation_define}
+ INCLUDE_DIRECTORIES ${private_includes}
+ LIBRARIES ${QT_CMAKE_EXPORT_NAMESPACE}::Core
+ ${QT_CMAKE_EXPORT_NAMESPACE}::Test
+ ${QT_CMAKE_EXPORT_NAMESPACE}::TestPrivate
+ # Add GUI by default so that the plugins link properly with non-standalone
+ # build of tests. Plugin handling is currently only done in
+ # qt_internal_add_executable if Gui is present. This should be reevaluated with
+ # multiple batches.
+ ${QT_CMAKE_EXPORT_NAMESPACE}::Gui
+ )
+
+ set_property(TARGET ${target} PROPERTY _qt_has_exceptions ${arg_EXCEPTIONS})
+ set_property(TARGET ${target} PROPERTY _qt_has_gui ${arg_GUI})
+ set_property(TARGET ${target} PROPERTY _qt_has_lowdpi ${arg_LOWDPI})
+ set_property(TARGET ${target} PROPERTY _qt_version ${version_arg})
+ set_property(TARGET ${target} PROPERTY _qt_is_test_executable TRUE)
+ set_property(TARGET ${target} PROPERTY _qt_is_manual_test ${arg_MANUAL})
+ else()
+ # Check whether the args match with the batch. Some differences between
+ # flags cannot be reconciled - one should not combine these tests into
+ # a single binary.
+ qt_internal_get_target_property(
+ batch_has_exceptions ${target} _qt_has_exceptions)
+ if(NOT ${batch_has_exceptions} STREQUAL ${arg_EXCEPTIONS})
+ qt_internal_get_test_batch(test_batch_contents)
+ message(FATAL_ERROR "Conflicting exceptions declaration between test \
+ batch (${test_batch_contents}) and ${name}")
+ endif()
+ qt_internal_get_target_property(batch_has_gui ${target} _qt_has_gui)
+ if(NOT ${batch_has_gui} STREQUAL ${arg_GUI})
+ qt_internal_get_test_batch(test_batch_contents)
+ message(FATAL_ERROR "Conflicting gui declaration between test batch \
+ (${test_batch_contents}) and ${name}")
+ endif()
+ qt_internal_get_target_property(
+ batch_has_lowdpi ${target} _qt_has_lowdpi)
+ if(NOT ${batch_has_lowdpi} STREQUAL ${arg_LOWDPI})
+ qt_internal_get_test_batch(test_batch_contents)
+ message(FATAL_ERROR "Conflicting lowdpi declaration between test batch \
+ (${test_batch_contents}) and ${name}")
+ endif()
+ qt_internal_get_target_property(batch_version ${target} _qt_version)
+ if(NOT "${batch_version} " STREQUAL " " AND
+ NOT "${version_arg} " STREQUAL " " AND
+ NOT "${batch_version} " STREQUAL "${version_arg} ")
+ qt_internal_get_test_batch(test_batch_contents)
+ message(FATAL_ERROR "Conflicting version declaration between test \
+ batch ${test_batch_contents} (${batch_version}) and ${name} (${version_arg})")
+ endif()
+ endif()
+
+ get_property(batched_test_list GLOBAL PROPERTY _qt_batched_test_list_property)
+ if(NOT batched_test_list)
+ set_property(GLOBAL PROPERTY _qt_batched_test_list_property "")
+ set(batched_test_list "")
+ endif()
+ 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}
+ PUBLIC_LIBRARIES ${arg_PUBLIC_LIBRARIES}
+ LIBRARIES ${arg_LIBRARIES}
+ SOURCES ${arg_SOURCES}
+ COMPILE_OPTIONS ${arg_COMPILE_OPTIONS}
+ COMPILE_FLAGS ${arg_COMPILE_FLAGS}
+ LINK_OPTIONS ${arg_LINK_OPTIONS}
+ MOC_OPTIONS ${arg_MOC_OPTIONS}
+ ENABLE_AUTOGEN_TOOLS ${arg_ENABLE_AUTOGEN_TOOLS}
+ DISABLE_AUTOGEN_TOOLS ${arg_DISABLE_AUTOGEN_TOOLS}
+ NO_UNITY_BUILD # Tests should not be built using UNITY_BUILD
+ )
+
+ set(${batch_name} ${target} PARENT_SCOPE)
+
+ # Add a dummy target so that new tests don't have problems with a nonexistent
+ # target when calling cmake functions.
+ # The batch tests that include this target will compile, but may fail to work.
+ # Manual action is required then.
+ add_custom_target(${name})
+
+ # Add the dependency to the dummy target so that it is indirectly added to the test batch
+ # dependencies.
+ add_dependencies(${target} ${name})
+endfunction()
+
+# Checks whether the test 'name' is present in the test batch. See QT_BUILD_TESTS_BATCHED.
+# The result of the check is placed in the 'out' variable.
+function(qt_internal_is_in_test_batch out name)
+ set(${out} FALSE PARENT_SCOPE)
+ if(QT_BUILD_TESTS_BATCHED)
+ get_property(batched_test_list GLOBAL PROPERTY _qt_batched_test_list_property)
+ if("${name}" IN_LIST batched_test_list)
+ set(${out} TRUE PARENT_SCOPE)
+ endif()
+ endif()
+endfunction()
+
+function(qt_internal_is_skipped_test out name)
+ get_target_property(is_skipped_test ${name} _qt_is_skipped_test)
+ set(${out} ${is_skipped_test} PARENT_SCOPE)
+endfunction()
+
+function(qt_internal_set_skipped_test name)
+ set_target_properties(${name} PROPERTIES _qt_is_skipped_test TRUE)
+endfunction()
+
+function(qt_internal_is_qtbase_test out)
+ get_filename_component(dir "${CMAKE_CURRENT_BINARY_DIR}" ABSOLUTE)
+ set(${out} FALSE PARENT_SCOPE)
+
+ while(TRUE)
+ get_filename_component(filename "${dir}" NAME)
+ if("${filename}" STREQUAL "qtbase")
+ set(${out} TRUE PARENT_SCOPE)
+ break()
+ endif()
+
+ set(prev_dir "${dir}")
+ get_filename_component(dir "${dir}" DIRECTORY)
+ if("${dir}" STREQUAL "${prev_dir}")
+ break()
+ endif()
+ endwhile()
+endfunction()
+
+function(qt_internal_get_batched_test_arguments out testname)
+ if(WASM)
+ # Add a query string to the runner document, so that the script therein
+ # knows which test to run in response to launching the testcase by ctest.
+ list(APPEND args "qbatchedtest")
+ if(CMAKE_BUILD_TYPE STREQUAL "Debug")
+ list(APPEND args "qvisualoutput")
+ endif()
+ else()
+ # Simply add the test name in case of standard executables.
+ list(APPEND args "${testname}")
+ endif()
+ set(${out} ${args} PARENT_SCOPE)
+endfunction()
+
+# This function creates a CMake test target with the specified name for use with CTest.
+#
+# All tests are wrapped with cmake script that supports TESTARGS and TESTRUNNER environment
+# variables handling. Endpoint wrapper may be used standalone as cmake script to run tests e.g.:
+# TESTARGS="-o result.xml,junitxml" TESTRUNNER="testrunner --arg" ./tst_simpleTestWrapper.cmake
+# On non-UNIX machine you may need to use 'cmake -P' explicitly to execute wrapper.
+# You may avoid test wrapping by either passing NO_WRAPPER option or switching QT_NO_TEST_WRAPPERS
+# to ON. This is helpful if you want to use internal CMake tools within tests, like memory or
+# sanitizer checks. See https://cmake.org/cmake/help/v3.19/manual/ctest.1.html#ctest-memcheck-step
+# Arguments:
+# BUILTIN_TESTDATA
+# The option forces adding the provided TESTDATA to resources.
+# MANUAL
+# The option indicates that the test is a manual test.
+function(qt_internal_add_test name)
+ qt_internal_get_test_arg_definitions(optional_args single_value_args multi_value_args)
+
+ cmake_parse_arguments(PARSE_ARGV 1 arg
"${optional_args}"
"${single_value_args}"
"${multi_value_args}"
- ${ARGN}
)
-
- if (NOT arg_OUTPUT_DIRECTORY)
- set(arg_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
+ _qt_internal_validate_all_args_are_parsed(arg)
+ _qt_internal_validate_no_unity_build(arg)
+
+ set(batch_current_test FALSE)
+ if(QT_BUILD_TESTS_BATCHED AND NOT arg_NO_BATCH AND NOT arg_QMLTEST AND NOT arg_MANUAL
+ AND ("${QT_STANDALONE_TEST_PATH}" STREQUAL ""
+ OR DEFINED ENV{QT_BATCH_STANDALONE_TESTS}))
+ set(batch_current_test TRUE)
endif()
- # Qt modules get compiled without exceptions enabled by default.
- # However, testcases should be still built with exceptions.
- set(exceptions_text "EXCEPTIONS")
- if (${arg_NO_EXCEPTIONS})
- set(exceptions_text "")
+ if(batch_current_test OR (QT_BUILD_TESTS_BATCHED AND arg_QMLTEST))
+ if (QT_SUPERBUILD OR DEFINED ENV{TESTED_MODULE_COIN})
+ set(is_qtbase_test FALSE)
+ if(QT_SUPERBUILD)
+ qt_internal_is_qtbase_test(is_qtbase_test)
+ elseif($ENV{TESTED_MODULE_COIN} STREQUAL "qtbase")
+ set(is_qtbase_test TRUE)
+ endif()
+ if(NOT is_qtbase_test)
+ file(GENERATE OUTPUT "dummy${name}.cpp" CONTENT "int main() { return 0; }")
+ # Add a dummy target to tackle some potential problems
+ qt_internal_add_executable(${name} SOURCES "dummy${name}.cpp")
+ # Batched tests outside of qtbase are unsupported and skipped
+ qt_internal_set_skipped_test(${name})
+ return()
+ endif()
+ endif()
endif()
- if (${arg_GUI})
- set(gui_text "GUI")
+ 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()
- if (arg_VERSION)
- set(version_arg VERSION "${arg_VERSION}")
- endif()
+ set(private_includes
+ "${CMAKE_CURRENT_SOURCE_DIR}"
+ "${CMAKE_CURRENT_BINARY_DIR}"
+ "$<BUILD_INTERFACE:${QT_BUILD_DIR}/include>"
+ )
+
+ set(testname "${name}")
if(arg_PUBLIC_LIBRARIES)
message(WARNING
@@ -261,14 +503,17 @@ function(qt_internal_add_test name)
"removed in a future Qt version. Use the LIBRARIES option instead.")
endif()
- # Handle cases where we have a qml test without source files
- if (arg_SOURCES)
- set(private_includes
- "${CMAKE_CURRENT_SOURCE_DIR}"
- "${CMAKE_CURRENT_BINARY_DIR}"
- "$<BUILD_INTERFACE:${QT_BUILD_DIR}/include>"
- ${arg_INCLUDE_DIRECTORIES}
- )
+ if(batch_current_test)
+ qt_internal_add_test_to_batch(name ${name} ${ARGN})
+ elseif(arg_SOURCES)
+ if(QT_BUILD_TESTS_BATCHED AND arg_QMLTEST)
+ message(WARNING "QML tests won't be batched - unsupported (yet)")
+ endif()
+ # Handle cases where we have a qml test without source files
+ 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}
@@ -281,6 +526,7 @@ function(qt_internal_add_test name)
${private_includes}
DEFINES
${arg_DEFINES}
+ ${deprecation_define}
LIBRARIES
${arg_LIBRARIES}
${arg_PUBLIC_LIBRARIES}
@@ -291,6 +537,7 @@ function(qt_internal_add_test name)
MOC_OPTIONS ${arg_MOC_OPTIONS}
ENABLE_AUTOGEN_TOOLS ${arg_ENABLE_AUTOGEN_TOOLS}
DISABLE_AUTOGEN_TOOLS ${arg_DISABLE_AUTOGEN_TOOLS}
+ NO_UNITY_BUILD # Tests should not be built using UNITY_BUILD
)
qt_internal_add_repo_local_defines(${name})
@@ -298,13 +545,16 @@ function(qt_internal_add_test name)
# Disable the QT_NO_NARROWING_CONVERSIONS_IN_CONNECT define for tests
qt_internal_undefine_global_definition(${name} QT_NO_NARROWING_CONVERSIONS_IN_CONNECT)
- # Tests should not be bundles on macOS even if arg_GUI is true, because some tests make
- # assumptions about the location of helper processes, and those paths would be different
- # if a test is built as a bundle.
- set_property(TARGET "${name}" PROPERTY MACOSX_BUNDLE FALSE)
- # The same goes for WIN32_EXECUTABLE, but because it will detach from the console window
- # and not print anything.
- set_property(TARGET "${name}" PROPERTY WIN32_EXECUTABLE FALSE)
+ # Manual tests can be bundle apps
+ if(NOT arg_MANUAL)
+ # Tests should not be bundles on macOS even if arg_GUI is true, because some tests make
+ # assumptions about the location of helper processes, and those paths would be different
+ # if a test is built as a bundle.
+ set_property(TARGET "${name}" PROPERTY MACOSX_BUNDLE FALSE)
+ # The same goes for WIN32_EXECUTABLE, but because it will detach from the console window
+ # and not print anything.
+ set_property(TARGET "${name}" PROPERTY WIN32_EXECUTABLE FALSE)
+ endif()
# Tests on iOS must be app bundles.
if(IOS)
@@ -330,6 +580,13 @@ function(qt_internal_add_test name)
qt_internal_extend_target("${name}" CONDITION ANDROID
LIBRARIES ${QT_CMAKE_EXPORT_NAMESPACE}::Gui
)
+ 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)
@@ -355,23 +612,80 @@ 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 "")
set(test_executable "${name}")
elseif(WASM)
- # Test script expects html file
- set(test_executable "${name}.html")
+ # The test script expects an html file. In case of batched tests, the
+ # version specialized for running batches has to be supplied.
+ if(batch_current_test)
+ get_target_property(batch_output_dir ${name} RUNTIME_OUTPUT_DIRECTORY)
+ set(test_executable "${batch_output_dir}/${name}.html")
+ else()
+ set(test_executable "${name}.html")
+ endif()
- if(QT6_INSTALL_PREFIX)
- set(QT_WASM_TESTRUNNER "${QT6_INSTALL_PREFIX}/${INSTALL_LIBEXECDIR}/qt-wasmtestrunner.py")
- elseif(QT_BUILD_DIR)
- set(QT_WASM_TESTRUNNER "${QT_BUILD_DIR}/${INSTALL_LIBEXECDIR}/qt-wasmtestrunner.py")
+ list(APPEND extra_test_args "quseemrun")
+ list(APPEND extra_test_args "qtestname=${testname}")
+ list(APPEND extra_test_args "--silence_timeout=60")
+ # TODO: Add functionality to specify browser
+ list(APPEND extra_test_args "--browser=chrome")
+ list(APPEND extra_test_args "--browser_args=\"--password-store=basic\"")
+ list(APPEND extra_test_args "--kill_exit")
+
+ # 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
+ 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 "${QT_WASM_TESTRUNNER}")
+ 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}")
@@ -388,58 +702,79 @@ function(qt_internal_add_test name)
endif()
endif()
- qt_internal_collect_command_environment(test_env_path test_env_plugin_path)
+ if(NOT arg_MANUAL)
+ if(batch_current_test)
+ qt_internal_get_batched_test_arguments(batched_test_args ${testname})
+ list(PREPEND extra_test_args ${batched_test_args})
+ elseif(WASM AND CMAKE_BUILD_TYPE STREQUAL "Debug")
+ list(PREPEND extra_test_args "qvisualoutput")
+ endif()
- if(arg_NO_WRAPPER OR QT_NO_TEST_WRAPPERS)
- add_test(NAME "${name}" COMMAND ${test_executable} ${extra_test_args}
- WORKING_DIRECTORY "${test_working_dir}")
- set_property(TEST "${name}" APPEND PROPERTY
- ENVIRONMENT "PATH=${test_env_path}"
- "QT_TEST_RUNNING_IN_CTEST=1"
- "QT_PLUGIN_PATH=${test_env_plugin_path}"
- )
- else()
- set(test_wrapper_file "${CMAKE_CURRENT_BINARY_DIR}/${name}Wrapper$<CONFIG>.cmake")
- qt_internal_create_test_script(NAME "${name}"
- COMMAND "${test_executable}"
- ARGS "${extra_test_args}"
- WORKING_DIRECTORY "${test_working_dir}"
- OUTPUT_FILE "${test_wrapper_file}"
- ENVIRONMENT "QT_TEST_RUNNING_IN_CTEST" 1
- "PATH" "${test_env_path}"
- "QT_PLUGIN_PATH" "${test_env_plugin_path}"
- )
- endif()
+ qt_internal_collect_command_environment(test_env_path test_env_plugin_path)
- if(arg_QT_TEST_SERVER_LIST AND NOT ANDROID)
- qt_internal_setup_docker_test_fixture(${name} ${arg_QT_TEST_SERVER_LIST})
- endif()
+ if(arg_NO_WRAPPER OR QT_NO_TEST_WRAPPERS)
+ if(QT_BUILD_TESTS_BATCHED)
+ message(FATAL_ERROR "Wrapperless tests are unspupported with test batching")
+ endif()
- set_tests_properties("${name}" PROPERTIES RUN_SERIAL "${arg_RUN_SERIAL}" LABELS "${label}")
- if (arg_TIMEOUT)
- set_tests_properties(${name} PROPERTIES TIMEOUT ${arg_TIMEOUT})
- endif()
+ add_test(NAME "${testname}" COMMAND ${test_executable} ${extra_test_args}
+ WORKING_DIRECTORY "${test_working_dir}")
+ set_property(TEST "${testname}" APPEND PROPERTY
+ ENVIRONMENT "PATH=${test_env_path}"
+ "QT_TEST_RUNNING_IN_CTEST=1"
+ "QT_PLUGIN_PATH=${test_env_plugin_path}"
+ )
+ else()
+ set(test_wrapper_file "${CMAKE_CURRENT_BINARY_DIR}/${testname}Wrapper$<CONFIG>.cmake")
+ qt_internal_create_test_script(NAME "${testname}"
+ COMMAND "${test_executable}"
+ ARGS "${extra_test_args}"
+ WORKING_DIRECTORY "${test_working_dir}"
+ OUTPUT_FILE "${test_wrapper_file}"
+ ENVIRONMENT "QT_TEST_RUNNING_IN_CTEST" 1
+ "PATH" "${test_env_path}"
+ "QT_PLUGIN_PATH" "${test_env_plugin_path}"
+ )
+ endif()
- # Add a ${target}/check makefile target, to more easily test one test.
+ if(arg_QT_TEST_SERVER_LIST AND NOT ANDROID)
+ qt_internal_setup_docker_test_fixture(${testname} ${arg_QT_TEST_SERVER_LIST})
+ endif()
- set(test_config_options "")
- get_cmake_property(is_multi_config GENERATOR_IS_MULTI_CONFIG)
- if(is_multi_config)
- set(test_config_options -C $<CONFIG>)
- endif()
- add_custom_target("${name}_check"
- VERBATIM
- COMMENT "Running ${CMAKE_CTEST_COMMAND} -V -R \"^${name}$\" ${test_config_options}"
- COMMAND "${CMAKE_CTEST_COMMAND}" -V -R "^${name}$" ${test_config_options}
- )
- if(TARGET "${name}")
- add_dependencies("${name}_check" "${name}")
- if(ANDROID)
- add_dependencies("${name}_check" "${name}_make_apk")
+ set_tests_properties("${testname}" PROPERTIES RUN_SERIAL "${arg_RUN_SERIAL}" LABELS "${label}")
+ if(arg_TIMEOUT)
+ 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 "")
+ get_cmake_property(is_multi_config GENERATOR_IS_MULTI_CONFIG)
+ if(is_multi_config)
+ set(test_config_options -C $<CONFIG>)
+ endif()
+ add_custom_target("${testname}_check"
+ VERBATIM
+ COMMENT "Running ${CMAKE_CTEST_COMMAND} -V -R \"^${name}$\" ${test_config_options}"
+ COMMAND "${CMAKE_CTEST_COMMAND}" -V -R "^${name}$" ${test_config_options}
+ )
+ if(TARGET "${name}")
+ add_dependencies("${testname}_check" "${name}")
+ if(ANDROID)
+ add_dependencies("${testname}_check" "${name}_make_apk")
+ endif()
endif()
endif()
- if(ANDROID OR IOS OR INTEGRITY OR arg_BUILTIN_TESTDATA)
+ if(ANDROID OR IOS OR WASM OR INTEGRITY OR arg_BUILTIN_TESTDATA)
set(builtin_testdata TRUE)
endif()
@@ -451,10 +786,29 @@ function(qt_internal_add_test name)
foreach(testdata IN LISTS arg_TESTDATA)
list(APPEND builtin_files ${testdata})
endforeach()
+ foreach(file IN LISTS builtin_files)
+ set_source_files_properties(${file}
+ PROPERTIES QT_SKIP_QUICKCOMPILER TRUE
+ )
+ endforeach()
- set(blacklist_path "BLACKLIST")
- if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${blacklist_path}")
- list(APPEND builtin_files ${blacklist_path})
+ if(batch_current_test)
+ set(blacklist_path "BLACKLIST")
+ if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${blacklist_path}")
+ get_target_property(blacklist_files ${name} _qt_blacklist_files)
+ if(NOT blacklist_files)
+ set_target_properties(${name} PROPERTIES _qt_blacklist_files "")
+ set(blacklist_files "")
+ cmake_language(EVAL CODE "cmake_language(DEFER DIRECTORY \"${CMAKE_SOURCE_DIR}\" CALL \"_qt_internal_finalize_batch\" \"${name}\") ")
+ endif()
+ list(PREPEND blacklist_files "${CMAKE_CURRENT_SOURCE_DIR}/${blacklist_path}")
+ set_target_properties(${name} PROPERTIES _qt_blacklist_files "${blacklist_files}")
+ endif()
+ else()
+ set(blacklist_path "BLACKLIST")
+ if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${blacklist_path}")
+ list(APPEND builtin_files ${blacklist_path})
+ endif()
endif()
list(REMOVE_DUPLICATES builtin_files)
@@ -466,23 +820,35 @@ function(qt_internal_add_test name)
)
endforeach()
- if (builtin_files)
- qt_internal_add_resource(${name} "${name}_testdata_builtin"
+ if(builtin_files)
+ qt_internal_add_resource(${name} "${testname}_testdata_builtin"
PREFIX "/"
FILES ${builtin_files}
BASE ${CMAKE_CURRENT_SOURCE_DIR})
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}"
@@ -499,6 +865,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.
#
@@ -551,6 +946,11 @@ for this function. Will be ignored")
set(executable_file "${arg_COMMAND}")
endif()
+ set(executable_name ${arg_NAME})
+ qt_internal_is_in_test_batch(is_in_batch ${executable_name})
+ if(is_in_batch)
+ _qt_internal_test_batch_target_name(executable_name)
+ endif()
add_test(NAME "${arg_NAME}" COMMAND "${CMAKE_COMMAND}" "-P" "${arg_OUTPUT_FILE}"
WORKING_DIRECTORY "${arg_WORKING_DIRECTORY}")
@@ -559,8 +959,8 @@ for this function. Will be ignored")
# CROSSCOMPILING_EMULATOR don't check if actual cross compilation is configured,
# emulator is prepended independently.
set(crosscompiling_emulator "")
- if(CMAKE_CROSSCOMPILING AND TARGET ${arg_NAME})
- get_target_property(crosscompiling_emulator ${arg_NAME} CROSSCOMPILING_EMULATOR)
+ if(CMAKE_CROSSCOMPILING AND TARGET ${executable_name})
+ get_target_property(crosscompiling_emulator ${executable_name} CROSSCOMPILING_EMULATOR)
if(NOT crosscompiling_emulator)
set(crosscompiling_emulator "")
else()
@@ -592,11 +992,12 @@ function(qt_internal_add_test_helper name)
"OVERRIDE_OUTPUT_DIRECTORY"
)
- qt_parse_all_arguments(arg "qt_add_test_helper"
+ cmake_parse_arguments(PARSE_ARGV 1 arg
"${qt_add_test_helper_optional_args};${__qt_internal_add_executable_optional_args}"
"${__qt_internal_add_executable_single_args}"
"${__qt_internal_add_executable_multi_args}"
- ${ARGN})
+ )
+ _qt_internal_validate_all_args_are_parsed(arg)
qt_remove_args(forward_args
ARGS_TO_REMOVE
@@ -613,10 +1014,19 @@ function(qt_internal_add_test_helper name)
set(extra_args_to_pass)
if(NOT arg_OVERRIDE_OUTPUT_DIRECTORY)
- set(extra_args_to_pass OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/..")
+ _qt_internal_test_batch_target_name(test_batch_target_name)
+ if(QT_BUILD_TESTS_BATCHED AND TARGET ${test_batch_target_name})
+ get_target_property(
+ test_batch_output_dir ${test_batch_target_name} RUNTIME_OUTPUT_DIRECTORY)
+ set(extra_args_to_pass OUTPUT_DIRECTORY "${test_batch_output_dir}")
+ else()
+ set(extra_args_to_pass OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/..")
+ endif()
endif()
- qt_internal_add_executable("${name}" NO_INSTALL ${extra_args_to_pass} ${forward_args})
+ qt_internal_add_executable("${name}" NO_INSTALL
+ NO_UNITY_BUILD # excluded by default
+ ${extra_args_to_pass} ${forward_args})
# Disable the QT_NO_NARROWING_CONVERSIONS_IN_CONNECT define for test helpers
qt_internal_undefine_global_definition(${name} QT_NO_NARROWING_CONVERSIONS_IN_CONNECT)
diff --git a/cmake/QtToolHelpers.cmake b/cmake/QtToolHelpers.cmake
index 421235789c..7dd507c0ee 100644
--- a/cmake/QtToolHelpers.cmake
+++ b/cmake/QtToolHelpers.cmake
@@ -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: BSD-3-Clause
# This function is used to define a "Qt tool", such as moc, uic or rcc.
#
@@ -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
@@ -37,159 +44,35 @@
# linked to the executable target by default.
function(qt_internal_add_tool target_name)
qt_tool_target_to_name(name ${target_name})
- set(option_keywords NO_INSTALL USER_FACING INSTALL_VERSIONED_LINK EXCEPTIONS)
+ set(option_keywords
+ NO_INSTALL
+ USER_FACING
+ INSTALL_VERSIONED_LINK
+ EXCEPTIONS
+ 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
EXTRA_CMAKE_INCLUDES
PUBLIC_LIBRARIES
${__default_private_args})
- qt_parse_all_arguments(arg "qt_internal_add_tool" "${option_keywords}"
- "${one_value_keywords}"
- "${multi_value_keywords}" ${ARGN})
-
- # Handle case when a tool does not belong to a module and it can't be built either (like
- # during a cross-compile).
- if(NOT arg_TOOLS_TARGET AND NOT QT_WILL_BUILD_TOOLS)
- message(FATAL_ERROR "The tool \"${name}\" has not been assigned to a module via"
- " TOOLS_TARGET (so it can't be found) and it can't be built"
- " (QT_WILL_BUILD_TOOLS is ${QT_WILL_BUILD_TOOLS}).")
- 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.")
- endif()
-
- set(full_name "${QT_CMAKE_EXPORT_NAMESPACE}::${name}")
- set(imported_tool_target_already_found FALSE)
-
- # This condition can only be TRUE if a previous find_package(Qt6${arg_TOOLS_TARGET}Tools)
- # was already done. That can happen if QT_FORCE_FIND_TOOLS was ON or we're cross-compiling.
- # In such a case, we need to exit early if we're not going to also build the tools.
- if(TARGET ${full_name})
- get_property(path TARGET ${full_name} PROPERTY LOCATION)
- message(STATUS "Tool '${full_name}' was found at ${path}.")
- set(imported_tool_target_already_found TRUE)
- if(NOT QT_WILL_BUILD_TOOLS)
- return()
- endif()
- endif()
-
- # We need to search for the host Tools package when doing a cross-build
- # or when QT_FORCE_FIND_TOOLS is ON.
- # As an optimiziation, we don't search for the package one more time if the target
- # was already brought into scope from a previous find_package.
- set(search_for_host_package FALSE)
- if(NOT QT_WILL_BUILD_TOOLS OR QT_WILL_RENAME_TOOL_TARGETS)
- set(search_for_host_package TRUE)
- endif()
- if(search_for_host_package AND NOT imported_tool_target_already_found)
- set(tools_package_name "Qt6${arg_TOOLS_TARGET}Tools")
- message(STATUS "Searching for tool '${full_name}' in package ${tools_package_name}.")
-
- # Create the tool targets, even if QT_NO_CREATE_TARGETS is set.
- # Otherwise targets like Qt6::moc are not available in a top-level cross-build.
- set(BACKUP_QT_NO_CREATE_TARGETS ${QT_NO_CREATE_TARGETS})
- set(QT_NO_CREATE_TARGETS OFF)
-
- # When cross-compiling, we want to search for Tools packages in QT_HOST_PATH.
- # To do that, we override CMAKE_PREFIX_PATH and CMAKE_FIND_ROOT_PATH.
- #
- # We don't use find_package + PATHS option because any recursive find_dependency call
- # inside a Tools package would not inherit the initial PATHS value given.
- # TODO: Potentially we could set a global __qt_cmake_host_dir var like we currently
- # do with _qt_cmake_dir in Qt6Config and change all our host tool find_package calls
- # everywhere to specify that var in PATHS.
- #
- # Note though that due to path rerooting issue in
- # https://gitlab.kitware.com/cmake/cmake/-/issues/21937
- # we have to append a lib/cmake suffix to CMAKE_PREFIX_PATH so the value does not get
- # rerooted on top of CMAKE_FIND_ROOT_PATH.
- # Use QT_HOST_PATH_CMAKE_DIR for the suffix when available (it would be set by
- # the qt.toolchain.cmake file when building other repos or given by the user when
- # configuring qtbase) or derive it from from the Qt6HostInfo package which is
- # found in QtSetup.
- set(${tools_package_name}_BACKUP_CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH})
- set(${tools_package_name}_BACKUP_CMAKE_FIND_ROOT_PATH "${CMAKE_FIND_ROOT_PATH}")
- if(QT_HOST_PATH_CMAKE_DIR)
- set(qt_host_path_cmake_dir_absolute "${QT_HOST_PATH_CMAKE_DIR}")
- elseif(Qt${PROJECT_VERSION_MAJOR}HostInfo_DIR)
- get_filename_component(qt_host_path_cmake_dir_absolute
- "${Qt${PROJECT_VERSION_MAJOR}HostInfo_DIR}/.." ABSOLUTE)
- else()
- # This should never happen, serves as an assert.
- message(FATAL_ERROR
- "Neither QT_HOST_PATH_CMAKE_DIR nor "
- "Qt${PROJECT_VERSION_MAJOR}HostInfo_DIR available.")
- endif()
- set(CMAKE_PREFIX_PATH "${qt_host_path_cmake_dir_absolute}")
-
- # Look for tools in additional host Qt installations. This is done for conan support where
- # we have separate installation prefixes per package. For simplicity, we assume here that
- # all host Qt installations use the same value of INSTALL_LIBDIR.
- if(DEFINED QT_ADDITIONAL_HOST_PACKAGES_PREFIX_PATH)
- file(RELATIVE_PATH rel_host_cmake_dir "${QT_HOST_PATH}"
- "${qt_host_path_cmake_dir_absolute}")
- foreach(host_path IN LISTS QT_ADDITIONAL_HOST_PACKAGES_PREFIX_PATH)
- set(host_cmake_dir "${host_path}/${rel_host_cmake_dir}")
- list(PREPEND CMAKE_PREFIX_PATH "${host_cmake_dir}")
- endforeach()
-
- list(PREPEND CMAKE_FIND_ROOT_PATH "${QT_ADDITIONAL_HOST_PACKAGES_PREFIX_PATH}")
- endif()
- list(PREPEND CMAKE_FIND_ROOT_PATH "${QT_HOST_PATH}")
-
- find_package(
- ${tools_package_name}
- ${PROJECT_VERSION}
- NO_PACKAGE_ROOT_PATH
- NO_CMAKE_ENVIRONMENT_PATH
- NO_SYSTEM_ENVIRONMENT_PATH
- NO_CMAKE_PACKAGE_REGISTRY
- NO_CMAKE_SYSTEM_PATH
- NO_CMAKE_SYSTEM_PACKAGE_REGISTRY)
- # Restore backups.
- set(CMAKE_FIND_ROOT_PATH "${${tools_package_name}_BACKUP_CMAKE_FIND_ROOT_PATH}")
- set(CMAKE_PREFIX_PATH "${${tools_package_name}_BACKUP_CMAKE_PREFIX_PATH}")
- set(QT_NO_CREATE_TARGETS ${BACKUP_QT_NO_CREATE_TARGETS})
+ cmake_parse_arguments(PARSE_ARGV 1 arg
+ "${option_keywords}"
+ "${one_value_keywords}"
+ "${multi_value_keywords}")
+ _qt_internal_validate_all_args_are_parsed(arg)
- if(${${tools_package_name}_FOUND} AND TARGET ${full_name})
- # Even if the tool is already visible, make sure that our modules remain associated
- # with the tools.
- qt_internal_append_known_modules_with_tools("${arg_TOOLS_TARGET}")
- get_property(path TARGET ${full_name} PROPERTY LOCATION)
- message(STATUS "${full_name} was found at ${path} using package ${tools_package_name}.")
- if (NOT QT_FORCE_BUILD_TOOLS)
- return()
- endif()
- endif()
- endif()
+ qt_internal_find_tool(will_build_tools ${target_name} "${arg_TOOLS_TARGET}")
- if(NOT QT_WILL_BUILD_TOOLS)
- if(${${tools_package_name}_FOUND})
- set(pkg_found_msg "")
- string(APPEND pkg_found_msg
- "the ${tools_package_name} package, but the package did not contain the tool. "
- "Make sure that the host module ${arg_TOOLS_TARGET} was built with all features "
- "enabled (no explicitly disabled tools).")
- else()
- set(pkg_found_msg "")
- string(APPEND pkg_found_msg
- "the ${tools_package_name} package, but the package could not be found. "
- "Make sure you have built and installed the host ${arg_TOOLS_TARGET} module, "
- "which will ensure the creation of the ${tools_package_name} package.")
- endif()
- message(FATAL_ERROR
- "Failed to find the host tool \"${full_name}\". It is part of "
- ${pkg_found_msg})
- else()
- message(STATUS "Tool '${full_name}' will be built from source.")
+ if(NOT will_build_tools)
+ return()
endif()
set(disable_autogen_tools "${arg_DISABLE_AUTOGEN_TOOLS}")
@@ -217,16 +100,27 @@ 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()
+
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}
LIBRARIES
${arg_LIBRARIES}
@@ -236,16 +130,22 @@ 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}"
+ 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}")
qt_internal_adjust_main_config_runtime_output_dir("${target_name}" "${output_dir}")
+ if (WIN32)
+ _qt_internal_generate_longpath_win32_rc_file_and_manifest("${target_name}")
+ endif()
+
set_target_properties(${target_name} PROPERTIES
_qt_package_version "${PROJECT_VERSION}"
)
@@ -325,17 +225,70 @@ function(qt_internal_add_tool target_name)
endforeach()
if(arg_INSTALL_VERSIONED_LINK)
- qt_internal_install_versioned_link("${install_dir}" "${target_name}")
+ qt_internal_install_versioned_link(WORKING_DIRECTORY "${install_dir}"
+ TARGETS "${target_name}")
endif()
qt_apply_rpaths(TARGET "${target_name}" INSTALL_PATH "${install_dir}" RELATIVE_RPATH)
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)
@@ -395,7 +348,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()
")
@@ -544,25 +497,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)
@@ -589,3 +551,219 @@ function(qt_exclude_tool_directories_from_default_target)
set(__qt_exclude_tool_directories "${absolute_path_directories}" PARENT_SCOPE)
endif()
endfunction()
+
+function(qt_internal_find_tool out_var target_name tools_target)
+ qt_tool_target_to_name(name ${target_name})
+
+ # Handle case when a tool does not belong to a module and it can't be built either (like
+ # during a cross-compile).
+ if(NOT tools_target AND NOT QT_WILL_BUILD_TOOLS)
+ message(FATAL_ERROR "The tool \"${name}\" has not been assigned to a module via"
+ " TOOLS_TARGET (so it can't be found) and it can't be built"
+ " (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.")
+ endif()
+
+ set(full_name "${QT_CMAKE_EXPORT_NAMESPACE}::${name}")
+ set(imported_tool_target_already_found FALSE)
+
+ # This condition can only be TRUE if a previous find_package(Qt6${tools_target}Tools)
+ # was already done. That can happen if QT_FORCE_FIND_TOOLS was ON or we're cross-compiling.
+ # In such a case, we need to exit early if we're not going to also build the tools.
+ if(TARGET ${full_name})
+ get_property(path TARGET ${full_name} PROPERTY LOCATION)
+ message(STATUS "Tool '${full_name}' was found at ${path}.")
+ set(imported_tool_target_already_found TRUE)
+ if(NOT QT_WILL_BUILD_TOOLS)
+ set(${out_var} "FALSE" PARENT_SCOPE)
+ return()
+ endif()
+ endif()
+
+ # We need to search for the host Tools package when doing a cross-build
+ # or when QT_FORCE_FIND_TOOLS is ON.
+ # As an optimiziation, we don't search for the package one more time if the target
+ # was already brought into scope from a previous find_package.
+ set(search_for_host_package FALSE)
+ if(NOT QT_WILL_BUILD_TOOLS OR QT_WILL_RENAME_TOOL_TARGETS)
+ set(search_for_host_package TRUE)
+ endif()
+ if(search_for_host_package AND NOT imported_tool_target_already_found)
+ set(tools_package_name "${INSTALL_CMAKE_NAMESPACE}${tools_target}Tools")
+ message(STATUS "Searching for tool '${full_name}' in package ${tools_package_name}.")
+
+ # Create the tool targets, even if QT_NO_CREATE_TARGETS is set.
+ # Otherwise targets like Qt6::moc are not available in a top-level cross-build.
+ set(BACKUP_QT_NO_CREATE_TARGETS ${QT_NO_CREATE_TARGETS})
+ set(QT_NO_CREATE_TARGETS OFF)
+
+ # When cross-compiling, we want to search for Tools packages in QT_HOST_PATH.
+ # To do that, we override CMAKE_PREFIX_PATH and CMAKE_FIND_ROOT_PATH.
+ #
+ # We don't use find_package + PATHS option because any recursive find_dependency call
+ # inside a Tools package would not inherit the initial PATHS value given.
+ # TODO: Potentially we could set a global __qt_cmake_host_dir var like we currently
+ # do with _qt_cmake_dir in Qt6Config and change all our host tool find_package calls
+ # everywhere to specify that var in PATHS.
+ #
+ # Note though that due to path rerooting issue in
+ # https://gitlab.kitware.com/cmake/cmake/-/issues/21937
+ # we have to append a lib/cmake suffix to CMAKE_PREFIX_PATH so the value does not get
+ # rerooted on top of CMAKE_FIND_ROOT_PATH.
+ # Use QT_HOST_PATH_CMAKE_DIR for the suffix when available (it would be set by
+ # the qt.toolchain.cmake file when building other repos or given by the user when
+ # configuring qtbase) or derive it from from the Qt6HostInfo package which is
+ # found in QtSetup.
+ set(${tools_package_name}_BACKUP_CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH})
+ set(${tools_package_name}_BACKUP_CMAKE_FIND_ROOT_PATH "${CMAKE_FIND_ROOT_PATH}")
+ if(QT_HOST_PATH_CMAKE_DIR)
+ set(qt_host_path_cmake_dir_absolute "${QT_HOST_PATH_CMAKE_DIR}")
+ elseif(Qt${PROJECT_VERSION_MAJOR}HostInfo_DIR)
+ get_filename_component(qt_host_path_cmake_dir_absolute
+ "${Qt${PROJECT_VERSION_MAJOR}HostInfo_DIR}/.." ABSOLUTE)
+ else()
+ # This should never happen, serves as an assert.
+ message(FATAL_ERROR
+ "Neither QT_HOST_PATH_CMAKE_DIR nor "
+ "Qt${PROJECT_VERSION_MAJOR}HostInfo_DIR available.")
+ endif()
+ set(CMAKE_PREFIX_PATH "${qt_host_path_cmake_dir_absolute}")
+
+ # Look for tools in additional host Qt installations. This is done for conan support where
+ # we have separate installation prefixes per package. For simplicity, we assume here that
+ # all host Qt installations use the same value of INSTALL_LIBDIR.
+ if(DEFINED QT_ADDITIONAL_HOST_PACKAGES_PREFIX_PATH)
+ file(RELATIVE_PATH rel_host_cmake_dir "${QT_HOST_PATH}"
+ "${qt_host_path_cmake_dir_absolute}")
+ foreach(host_path IN LISTS QT_ADDITIONAL_HOST_PACKAGES_PREFIX_PATH)
+ set(host_cmake_dir "${host_path}/${rel_host_cmake_dir}")
+ list(PREPEND CMAKE_PREFIX_PATH "${host_cmake_dir}")
+ endforeach()
+
+ list(PREPEND CMAKE_FIND_ROOT_PATH "${QT_ADDITIONAL_HOST_PACKAGES_PREFIX_PATH}")
+ endif()
+ list(PREPEND CMAKE_FIND_ROOT_PATH "${QT_HOST_PATH}")
+
+ find_package(
+ ${tools_package_name}
+ ${PROJECT_VERSION}
+ NO_PACKAGE_ROOT_PATH
+ NO_CMAKE_ENVIRONMENT_PATH
+ NO_SYSTEM_ENVIRONMENT_PATH
+ NO_CMAKE_PACKAGE_REGISTRY
+ NO_CMAKE_SYSTEM_PATH
+ NO_CMAKE_SYSTEM_PACKAGE_REGISTRY)
+
+ # Restore backups.
+ set(CMAKE_FIND_ROOT_PATH "${${tools_package_name}_BACKUP_CMAKE_FIND_ROOT_PATH}")
+ set(CMAKE_PREFIX_PATH "${${tools_package_name}_BACKUP_CMAKE_PREFIX_PATH}")
+ set(QT_NO_CREATE_TARGETS ${BACKUP_QT_NO_CREATE_TARGETS})
+
+ if(${${tools_package_name}_FOUND} AND TARGET ${full_name})
+ # Even if the tool is already visible, make sure that our modules remain associated
+ # with the tools.
+ qt_internal_append_known_modules_with_tools("${tools_target}")
+ get_property(path TARGET ${full_name} PROPERTY LOCATION)
+ message(STATUS "${full_name} was found at ${path} using package ${tools_package_name}.")
+ if (NOT QT_FORCE_BUILD_TOOLS)
+ set(${out_var} "FALSE" PARENT_SCOPE)
+ return()
+ endif()
+ endif()
+ endif()
+
+ 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
+ "the ${tools_package_name} package, but the package did not contain the tool. "
+ "Make sure that the host module ${tools_target} was built with all features "
+ "enabled (no explicitly disabled tools).")
+ else()
+ set(pkg_found_msg "")
+ string(APPEND pkg_found_msg
+ "the ${tools_package_name} package, but the package could not be found. "
+ "Make sure you have built and installed the host ${tools_target} module, "
+ "which will ensure the creation of the ${tools_package_name} package.")
+ endif()
+ message(FATAL_ERROR
+ "Failed to find the host tool \"${full_name}\". It is part of "
+ ${pkg_found_msg})
+ endif()
+
+ if(QT_WILL_BUILD_TOOLS)
+ message(STATUS "Tool '${full_name}' will be built from source.")
+ endif()
+ set(${out_var} "TRUE" PARENT_SCOPE)
+endfunction()
+
+# This function adds an internal tool that should be compiled at configure time.
+# TOOLS_TARGET
+# Specifies the module this tool belongs to. The Qt6${TOOLS_TARGET}Tools module
+# will then expose targets for this tool. Ignored if NO_INSTALL is set.
+function(qt_internal_add_configure_time_tool target_name)
+ set(one_value_args INSTALL_DIRECTORY TOOLS_TARGET CONFIG)
+ set(multi_value_args)
+ set(option_args NO_INSTALL)
+ cmake_parse_arguments(PARSE_ARGV 1 arg
+ "${option_args}" "${one_value_args}" "${multi_value_args}")
+
+ qt_internal_find_tool(will_build_tools ${target_name} "${arg_TOOLS_TARGET}")
+ if(NOT will_build_tools)
+ return()
+ endif()
+
+ qt_tool_target_to_name(name ${target_name})
+ set(extra_args "")
+ if(arg_NO_INSTALL OR NOT arg_TOOLS_TARGET)
+ list(APPEND extra_args "NO_INSTALL")
+ else()
+ set(install_dir "${INSTALL_BINDIR}")
+ if(arg_INSTALL_DIRECTORY)
+ set(install_dir "${arg_INSTALL_DIRECTORY}")
+ endif()
+ set(extra_args "INSTALL_DIRECTORY" "${install_dir}")
+ endif()
+
+ if(arg_CONFIG)
+ set(tool_config "${arg_CONFIG}")
+ elseif(QT_MULTI_CONFIG_FIRST_CONFIG)
+ set(tool_config "${arg_QT_MULTI_CONFIG_FIRST_CONFIG}")
+ else()
+ set(tool_config "${CMAKE_BUILD_TYPE}")
+ endif()
+
+ string(REPLACE "\\\;" "\\\\\\\;" unparsed_arguments "${arg_UNPARSED_ARGUMENTS}")
+ qt_internal_add_configure_time_executable(${target_name}
+ OUTPUT_NAME ${name}
+ CONFIG ${tool_config}
+ ${extra_args}
+ ${unparsed_arguments}
+ )
+
+ if(TARGET host_tools)
+ add_dependencies(host_tools "${target_name}_build")
+ endif()
+
+ if(NOT arg_NO_INSTALL AND arg_TOOLS_TARGET)
+ qt_internal_add_targets_to_additional_targets_export_file(
+ TARGETS ${target_name}
+ TARGET_EXPORT_NAMES ${QT_CMAKE_EXPORT_NAMESPACE}::${name}
+ EXPORT_NAME_PREFIX ${INSTALL_CMAKE_NAMESPACE}${arg_TOOLS_TARGET}Tools
+ )
+ endif()
+endfunction()
diff --git a/cmake/QtToolchainHelpers.cmake b/cmake/QtToolchainHelpers.cmake
index 5f3d2dc4d3..26b44bb10c 100644
--- a/cmake/QtToolchainHelpers.cmake
+++ b/cmake/QtToolchainHelpers.cmake
@@ -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: BSD-3-Clause
# Create a CMake toolchain file for convenient configuration of both internal Qt builds
# as well as CMake application projects.
@@ -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
new file mode 100644
index 0000000000..e804396f59
--- /dev/null
+++ b/cmake/QtUnityBuildHelpers.cmake
@@ -0,0 +1,24 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+# Check whether no unity build is requested where it is disabled by default.
+function(_qt_internal_validate_no_unity_build prefix)
+ if(${prefix}_NO_UNITY_BUILD OR ${prefix}_NO_UNITY_BUILD_SOURCES)
+ message(WARNING
+ "Unity build is disabled by default for this target, and its sources. "
+ "You may remove the NO_UNITY_BUILD and/or NO_UNITY_BUILD_SOURCES arguments.")
+ endif()
+endfunction()
+
+function(qt_update_ignore_unity_build_sources target sources)
+ 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 c41de308af..41ef5cb0ba 100644
--- a/cmake/QtWasmHelpers.cmake
+++ b/cmake/QtWasmHelpers.cmake
@@ -1,45 +1,48 @@
# 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: BSD-3-Clause
# WARNING must keep in sync with wasm-emscripten/qmake.conf!
function (qt_internal_setup_wasm_target_properties wasmTarget)
target_link_options("${wasmTarget}" INTERFACE
- "SHELL:-s ERROR_ON_UNDEFINED_SYMBOLS=1"
"SHELL:-s MAX_WEBGL_VERSION=2"
"SHELL:-s FETCH=1"
- "SHELL:-s WASM_BIGINT=1")
+ "SHELL:-s WASM_BIGINT=1"
+ "SHELL:-s STACK_SIZE=5MB")
target_link_libraries("${wasmTarget}" INTERFACE embind)
- # 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")
+ ## wasm64
+ if (WASM64)
+ target_compile_options("${wasmTarget}" INTERFACE "SHELL:-s MEMORY64=1" )
+ target_link_options("${wasmTarget}" INTERFACE "SHELL:-s MEMORY64=1" -mwasm64)
+ endif()
+ # 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)
+ target_compile_options("${wasmTarget}" INTERFACE -msimd128)
+ endif()
if (QT_FEATURE_sse2)
target_compile_options("${wasmTarget}" INTERFACE -O2 -msimd128 -msse -msse2)
endif()
- set(disable_exceptions_catching 1)
- if (QT_FEATURE_exceptions)
- set(disable_exceptions_catching 0)
+ # wasm exceptions
+ if (QT_FEATURE_wasm_exceptions)
+ target_compile_options("${wasmTarget}" INTERFACE -fwasm-exceptions)
+ target_link_options("${wasmTarget}" INTERFACE -fwasm-exceptions)
endif()
- target_link_options("${wasmTarget}" INTERFACE "SHELL:-s DISABLE_EXCEPTION_CATCHING=${disable_exceptions_catching}")
if (QT_FEATURE_thread)
target_compile_options("${wasmTarget}" INTERFACE "SHELL:-pthread")
target_link_options("${wasmTarget}" INTERFACE "SHELL:-pthread")
- else()
- target_link_options("${wasmTarget}" INTERFACE "SHELL:-s ALLOW_MEMORY_GROWTH=1")
endif()
+ target_link_options("${wasmTarget}" INTERFACE "SHELL:-s ALLOW_MEMORY_GROWTH")
+
# debug add_compile_options
if ("QT_WASM_SOURCE_MAP=1" IN_LIST QT_QMAKE_DEVICE_OPTIONS)
set(WASM_SOURCE_MAP_BASE "http://localhost:8000/")
@@ -58,7 +61,6 @@ function (qt_internal_setup_wasm_target_properties wasmTarget)
# a few good defaults to make console more verbose while debugging
target_link_options("${wasmTarget}" INTERFACE $<$<CONFIG:Debug>:
"SHELL:-s DEMANGLE_SUPPORT=1"
- "SHELL:-s GL_DEBUG=1"
--profiling-funcs>)
# target_link_options("${wasmTarget}" INTERFACE "SHELL:-s LIBRARY_DEBUG=1") # print out library calls, verbose
@@ -67,7 +69,6 @@ function (qt_internal_setup_wasm_target_properties wasmTarget)
# target_link_options("${wasmTarget}" INTERFACE "SHELL:-s SOCKET_DEBUG") # print out socket,network data transfer
if ("QT_EMSCRIPTEN_ASYNCIFY=1" IN_LIST QT_QMAKE_DEVICE_OPTIONS)
-
# Emscripten recommends building with optimizations when using asyncify
# in order to reduce wasm file size, and may also generate broken wasm
# (with "wasm validation error: too many locals" type errors) if optimizations
@@ -82,10 +83,45 @@ function (qt_internal_setup_wasm_target_properties wasmTarget)
# Set ASYNCIFY_IMPORTS unconditionally in order to support enabling asyncify at link time.
target_link_options("${wasmTarget}" INTERFACE "SHELL:-sASYNCIFY_IMPORTS=qt_asyncify_suspend_js,qt_asyncify_resume_js")
+ if(QT_FEATURE_shared)
+
+ set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS TRUE)
+
+ set(side_modules
+ MODULE_LIBRARY SHARED_LIBRARY)
+ set(enable_side_module_if_needed
+ "$<$<IN_LIST:$<TARGET_PROPERTY:TYPE>,${side_modules}>:SHELL:-s SIDE_MODULE=1>")
+ set(enable_main_module_if_needed
+ "$<$<IN_LIST:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:SHELL:-s MAIN_MODULE=1>")
+ set(set_shared_module_type_if_needed
+ "${enable_side_module_if_needed}"
+ "${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}")
+
+ else()
+ target_link_options("${wasmTarget}" INTERFACE "SHELL:-s ERROR_ON_UNDEFINED_SYMBOLS=1")
+ endif()
+
+ # Suppress warnings for known issues for developer builds
+ if(FEATURE_developer_build)
+ target_link_options("${wasmTarget}" INTERFACE "SHELL:-Wno-pthreads-mem-growth")
+ endif()
+
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 21ad62dd92..8eb4416e6d 100644
--- a/cmake/QtWrapperScriptHelpers.cmake
+++ b/cmake/QtWrapperScriptHelpers.cmake
@@ -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: BSD-3-Clause
# Creates and installs the following wrapper CMake scripts:
# qt-make
@@ -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"
@@ -39,21 +44,40 @@ function(qt_internal_create_wrapper_scripts)
DESTINATION "${INSTALL_BINDIR}")
endif()
- # Provide a private convenience wrapper with options which should not be propagated via the
+ if(generate_unix)
+ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/bin/qt-cmake-create.in"
+ "${QT_BUILD_DIR}/${INSTALL_BINDIR}/qt-cmake-create" @ONLY
+ NEWLINE_STYLE LF)
+ qt_install(PROGRAMS "${QT_BUILD_DIR}/${INSTALL_BINDIR}/qt-cmake-create"
+ DESTINATION "${INSTALL_BINDIR}")
+ endif()
+ if(generate_non_unix)
+ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/bin/qt-cmake-create.bat.in"
+ "${QT_BUILD_DIR}/${INSTALL_BINDIR}/qt-cmake-create.bat" @ONLY
+ NEWLINE_STYLE CRLF)
+ qt_install(PROGRAMS "${QT_BUILD_DIR}/${INSTALL_BINDIR}/qt-cmake-create.bat"
+ DESTINATION "${INSTALL_BINDIR}")
+ endif()
+
+ # 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_BINDIR}/qt-cmake-private" @ONLY
+ "${QT_BUILD_DIR}/${INSTALL_LIBEXECDIR}/qt-cmake-private" @ONLY
NEWLINE_STYLE LF)
- qt_install(PROGRAMS "${QT_BUILD_DIR}/${INSTALL_BINDIR}/qt-cmake-private"
- DESTINATION "${INSTALL_BINDIR}")
+ qt_install(PROGRAMS "${QT_BUILD_DIR}/${INSTALL_LIBEXECDIR}/qt-cmake-private"
+ DESTINATION "${INSTALL_LIBEXECDIR}")
endif()
if(generate_non_unix)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/bin/qt-cmake.bat.in"
@@ -95,9 +119,15 @@ function(qt_internal_create_wrapper_scripts)
# find_package(Qt...) to get all dependencies like examples do.
# Instead a template CMakeLists.txt project is used which sets up all the necessary private bits
# and then calls add_subdirectory on the provided project path.
- set(__qt_cmake_standalone_test_bin_name "qt-cmake-standalone-test")
- set(__qt_cmake_standalone_test_bin_path
- "${INSTALL_BINDIR}/${__qt_cmake_standalone_test_bin_name}")
+ set(__qt_cmake_standalone_test_name "qt-cmake-standalone-test")
+ if(generate_unix)
+ set(__qt_cmake_standalone_test_libexec_path
+ "${INSTALL_LIBEXECDIR}/${__qt_cmake_standalone_test_name}")
+ endif()
+ if(generate_non_unix)
+ set(__qt_cmake_standalone_test_bin_path
+ "${INSTALL_BINDIR}/${__qt_cmake_standalone_test_name}")
+ endif()
# Configuring a standalone test on iOS should use the Xcode generator, but qt-cmake-private uses
# the generator that was used to build Qt itself (e.g. Ninja).
@@ -106,16 +136,19 @@ function(qt_internal_create_wrapper_scripts)
set(__qt_cmake_private_path
"${QT_STAGING_PREFIX}/${INSTALL_BINDIR}/qt-cmake")
else()
- set(__qt_cmake_private_path
- "${QT_STAGING_PREFIX}/${INSTALL_BINDIR}/qt-cmake-private")
+ if(generate_unix)
+ set(__qt_cmake_private_path
+ "${QT_STAGING_PREFIX}/${INSTALL_LIBEXECDIR}/qt-cmake-private")
+ endif()
+ if(generate_non_unix)
+ set(__qt_cmake_private_path
+ "${QT_STAGING_PREFIX}/${INSTALL_BINDIR}/qt-cmake-private")
+ endif()
endif()
set(__qt_cmake_standalone_test_path
"${__build_internals_install_dir}/${__build_internals_standalone_test_template_dir}")
- get_filename_component(rel_base_path
- "${QT_STAGING_PREFIX}/${__qt_cmake_standalone_test_bin_path}"
- DIRECTORY)
if(QT_WILL_INSTALL)
# Need to prepend the staging prefix when doing prefix builds, because the build internals
# install dir is relative in that case..
@@ -124,12 +157,16 @@ function(qt_internal_create_wrapper_scripts)
"${__qt_cmake_standalone_test_path}")
endif()
- file(RELATIVE_PATH __qt_cmake_private_relpath "${rel_base_path}"
- "${__qt_cmake_private_path}")
- file(RELATIVE_PATH __qt_cmake_standalone_test_relpath "${rel_base_path}"
- "${__qt_cmake_standalone_test_path}")
-
if(generate_unix)
+ get_filename_component(rel_base_path
+ "${QT_STAGING_PREFIX}/${__qt_cmake_standalone_test_libexec_path}"
+ DIRECTORY)
+
+ file(RELATIVE_PATH __qt_cmake_private_relpath "${rel_base_path}"
+ "${__qt_cmake_private_path}")
+ file(RELATIVE_PATH __qt_cmake_standalone_test_relpath "${rel_base_path}"
+ "${__qt_cmake_standalone_test_path}")
+
set(__qt_cmake_standalone_test_os_prelude "#!/bin/sh")
set(__qt_cmake_standalone_test_script_relpath "SCRIPT_DIR=`dirname $0`")
string(PREPEND __qt_cmake_private_relpath "exec $SCRIPT_DIR/")
@@ -137,12 +174,21 @@ function(qt_internal_create_wrapper_scripts)
set(__qt_cmake_standalone_passed_args "\"$@\" -DPWD=\"$PWD\"")
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/bin/qt-cmake-standalone-test.in"
- "${QT_BUILD_DIR}/${__qt_cmake_standalone_test_bin_path}"
+ "${QT_BUILD_DIR}/${__qt_cmake_standalone_test_libexec_path}"
NEWLINE_STYLE LF)
- qt_install(PROGRAMS "${QT_BUILD_DIR}/${__qt_cmake_standalone_test_bin_path}"
- DESTINATION "${INSTALL_BINDIR}")
+ qt_install(PROGRAMS "${QT_BUILD_DIR}/${__qt_cmake_standalone_test_libexec_path}"
+ DESTINATION "${INSTALL_LIBEXECDIR}")
endif()
if(generate_non_unix)
+ get_filename_component(rel_base_path
+ "${QT_STAGING_PREFIX}/${__qt_cmake_standalone_test_bin_path}"
+ DIRECTORY)
+
+ file(RELATIVE_PATH __qt_cmake_private_relpath "${rel_base_path}"
+ "${__qt_cmake_private_path}")
+ file(RELATIVE_PATH __qt_cmake_standalone_test_relpath "${rel_base_path}"
+ "${__qt_cmake_standalone_test_path}")
+
set(__qt_cmake_standalone_test_os_prelude "@echo off")
set(__qt_cmake_standalone_test_script_relpath "set SCRIPT_DIR=%~dp0")
string(APPEND __qt_cmake_standalone_test_bin_path ".bat")
@@ -166,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_BINDIR}/${__qt_cmake_install_script_name}" @ONLY)
- qt_install(FILES "${QT_BUILD_DIR}/${INSTALL_BINDIR}/${__qt_cmake_install_script_name}"
- DESTINATION "${INSTALL_BINDIR}")
+ "${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)
@@ -185,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.
+
+ 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()
- set(script_passed_args "-DQT_BUILD_STANDALONE_TESTS=ON")
+ 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}
@@ -213,16 +286,48 @@ function(qt_internal_create_qt_configure_tests_wrapper_script)
endif()
if(generate_non_unix)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/libexec/${script_name}.bat.in"
- "${QT_BUILD_DIR}/${INSTALL_LIBEXECDIR}/${script_name}.bat" @ONLY
+ "${QT_BUILD_DIR}/${INSTALL_BINDIR}/${script_name}.bat" @ONLY
NEWLINE_STYLE CRLF)
- qt_install(PROGRAMS "${QT_BUILD_DIR}/${INSTALL_LIBEXECDIR}/${script_name}.bat"
- DESTINATION "${INSTALL_LIBEXECDIR}")
+ qt_install(PROGRAMS "${QT_BUILD_DIR}/${INSTALL_BINDIR}/${script_name}.bat"
+ DESTINATION "${INSTALL_BINDIR}")
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 c03834edc9..77a9eb2463 100644
--- a/cmake/QtWriteArgsFile.cmake
+++ b/cmake/QtWriteArgsFile.cmake
@@ -1,22 +1,79 @@
# 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: BSD-3-Clause
# This script writes its arguments to the file determined by OUT_FILE.
# Each argument appears on a separate line.
# This is used for writing the config.opt file.
#
# This script takes the following arguments:
-# IN_FILE: The input file. The whole command line as one string.
+# IN_FILE: The input file. The whole command line as one string, or one argument per line.
+# REDO_FILE: A file containing extra commands to be joined with IN_FILE.
# OUT_FILE: The output file. One argument per line.
# SKIP_ARGS: Number of arguments to skip from the front of the arguments list.
# IGNORE_ARGS: List of arguments to be ignored, i.e. that are not written.
+#
+# If the REDO_FILE is given, its parameters will be merged with IN_FILE parameters
+# and be written into the OUT_FILE.
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}")
+
+ if(args)
+ list(FIND args "--" args_ddash_loc)
+ list(FIND redo_args "--" redo_ddash_loc)
+ if("${redo_ddash_loc}" STREQUAL "-1")
+ if("${args_ddash_loc}" STREQUAL "-1")
+ list(LENGTH args args_ddash_loc)
+ endif()
+ # Avoid adding an empty line for an empty -redo
+ if(NOT "${redo_args}" STREQUAL "")
+ list(INSERT args ${args_ddash_loc} "${redo_args}")
+ endif()
+ else()
+ # Handling redo's configure options
+ list(SUBLIST redo_args 0 ${redo_ddash_loc} redo_config_args)
+ if(redo_config_args)
+ if("${args_ddash_loc}" STREQUAL "-1")
+ list(APPEND args "${redo_config_args}")
+ else()
+ list(INSERT args ${args_ddash_loc} "${redo_config_args}")
+ endif()
+ endif()
+
+ # Handling redo's CMake options
+ list(LENGTH redo_args redo_args_len)
+ math(EXPR redo_ddash_loc "${redo_ddash_loc} + 1")
+ # Catch an unlikely case of -redo being called with an empty --, ie., `-redo --`
+ if(NOT ${redo_ddash_loc} STREQUAL ${redo_args_len})
+ list(SUBLIST redo_args ${redo_ddash_loc} -1 redo_cmake_args)
+ endif()
+
+ if(DEFINED redo_cmake_args)
+ if("${args_ddash_loc}" STREQUAL "-1")
+ list(APPEND args "--")
+ endif()
+ list(APPEND args "${redo_cmake_args}")
+ endif()
+ endif()
+ else()
+ list(APPEND args "${redo_args}")
+ endif()
+endif()
+
# Skip arguments if requested
if(DEFINED SKIP_ARGS)
foreach(i RANGE 1 ${SKIP_ARGS})
diff --git a/cmake/README.md b/cmake/README.md
index 64b4321189..9d0743566d 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).
@@ -48,7 +53,9 @@ You may use brew to install dependencies needed to build QtBase.
`/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"`
* Build Qt dependencies: ``brew install pcre2 harfbuzz freetype``
* Install cmake: ``brew install cmake``
- * When running cmake in qtbase, pass ``-DCMAKE_PREFIX_PATH=/usr/local``
+ * When running cmake in qtbase, pass ``-DFEATURE_pkg_config=ON`` together with
+ ``-DCMAKE_PREFIX_PATH=/usr/local``, or ``-DCMAKE_PREFIX_PATH=/opt/homebrew`` if you have a Mac
+ with Apple Silicon.
# Building
@@ -193,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``
@@ -311,3 +318,16 @@ $ cd some/empty/directory
$ ~/Qt/6.0.0/bin/qt-cmake-standalone-test ~/source/of/qtbase/test/auto/corelib/io/qprocess
$ cmake --build .
```
+
+## qt-cmake-create
+
+Generates a simple CMakeLists.txt based on source files in specified project directory.
+
+Example:
+
+```
+$ cd some/source/directory/
+$ qt-cmake-create
+$ qt-cmake -S . -B /build/directory
+$ cmake --build /build/directory
+```
diff --git a/cmake/configure-cmake-mapping.md b/cmake/configure-cmake-mapping.md
index ade65ed5de..d504bd8d4b 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 |
@@ -60,6 +61,7 @@ The following table describes the mapping of configure options to CMake argument
| -R <string> | -DQT_EXTRA_RPATHS=path1;path2 | |
| -rpath | negative CMAKE_SKIP_BUILD_RPATH | |
| | negative CMAKE_SKIP_INSTALL_RPATH | |
+| | negative CMAKE_MACOSX_RPATH | |
| -reduce-exports | -DFEATURE_reduce_exports=ON | |
| -reduce-relocations | -DFEATURE_reduce_relocations=ON | |
| -plugin-manifests | | |
@@ -73,21 +75,16 @@ The following table describes the mapping of configure options to CMake argument
| | | custom build steps for moc, uic, and rcc. |
| | | This lacks support in CMake. |
| -ccache | -DQT_USE_CCACHE=ON | |
-| -make-tool <tool> | n/a | |
-| -mp | n/a | |
+| -unity-build | -DQT_UNITY_BUILD=ON | |
+| -unity-build-batch-size <int> | -DQT_UNITY_BUILD_BATCH_SIZE=<int> | |
| -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> | |
@@ -98,7 +95,9 @@ The following table describes the mapping of configure options to CMake argument
| -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> | -QT_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 |
@@ -108,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 | |
@@ -118,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 | |
@@ -165,8 +164,10 @@ 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> | |
+| -mimetype-database-compression <type> | -DINPUT_mimetype_database_compression=<type> | Sets the compression type for mime type database. Supported |
+| | | types: gzip, zstd, none. |
diff --git a/cmake/ios/Info.plist.app.in b/cmake/ios/Info.plist.app.in
index f2cbe593b2..2f13828213 100644
--- a/cmake/ios/Info.plist.app.in
+++ b/cmake/ios/Info.plist.app.in
@@ -2,54 +2,53 @@
<!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>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
- <key>CFBundlePackageType</key>
- <string>APPL</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
- <key>CFBundleName</key>
- <string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
+ <key>CFBundleName</key>
+ <string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
- <key>CFBundleDisplayName</key>
- <string>${QT_INTERNAL_DOLLAR_VAR}{PRODUCT_NAME}</string>
+ <key>CFBundleDisplayName</key>
+ <string>${QT_INTERNAL_DOLLAR_VAR}{PRODUCT_NAME}</string>
- <key>CFBundleIdentifier</key>
- <string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
+ <key>CFBundleIdentifier</key>
+ <string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
- <key>CFBundleExecutable</key>
- <string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
+ <key>CFBundleExecutable</key>
+ <string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
- <key>CFBundleVersion</key>
- <string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
+ <key>CFBundleVersion</key>
+ <string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
- <key>CFBundleShortVersionString</key>
- <string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
+ <key>CFBundleShortVersionString</key>
+ <string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
- <key>NSHumanReadableCopyright</key>
- <string>${MACOSX_BUNDLE_COPYRIGHT}</string>
+ <key>CFBundleIconFile</key>
+ <string>${MACOSX_BUNDLE_ICON_FILE}</string>
- <key>CFBundleIconFile</key>
- <string>${MACOSX_BUNDLE_ICON_FILE}</string>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>$(DEVELOPMENT_LANGUAGE)</string>
+ <key>CFBundleAllowMixedLocalizations</key>
+ <true/>
- <key>CFBundleDevelopmentRegion</key>
- <string>English</string>
+ <key>LSRequiresIPhoneOS</key>
+ <true/>
- <key>LSRequiresIPhoneOS</key>
- <true/>
+ <key>NOTE</key>
+ <string>This file was generated by Qt's default CMake support.</string>
- <key>NOTE</key>
- <string>This file was generated by Qt's default CMake support.</string>
+ <key>UILaunchStoryboardName</key>
+ <string>@qt_ios_launch_screen_plist_entry@</string>
- <key>UILaunchStoryboardName</key>
- <string>@qt_ios_launch_screen_plist_entry@</string>
-
- <key>UISupportedInterfaceOrientations</key>
- <array>
- <string>UIInterfaceOrientationPortrait</string>
- <string>UIInterfaceOrientationPortraitUpsideDown</string>
- <string>UIInterfaceOrientationLandscapeLeft</string>
- <string>UIInterfaceOrientationLandscapeRight</string>
- </array>
+ <key>UISupportedInterfaceOrientations</key>
+ <array>
+ <string>UIInterfaceOrientationPortrait</string>
+ <string>UIInterfaceOrientationPortraitUpsideDown</string>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ </array>
</dict>
</plist>
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 2ead02b7d5..c791521655 100644
--- a/cmake/macos/MacOSXBundleInfo.plist.in
+++ b/cmake/macos/Info.plist.app.in
@@ -29,7 +29,9 @@
<string>${MACOSX_BUNDLE_ICON_FILE}</string>
<key>CFBundleDevelopmentRegion</key>
- <string>English</string>
+ <string>en</string>
+ <key>CFBundleAllowMixedLocalizations</key>
+ <true/>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
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 f4e976b540..4d41a3a2a2 100644
--- a/cmake/modulecppexports.h.in
+++ b/cmake/modulecppexports.h.in
@@ -4,7 +4,9 @@
#ifndef @header_base_name_upper@_H
#define @header_base_name_upper@_H
-#include <QtCore/qglobal.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)
@@ -16,22 +18,23 @@
# define Q_@module_define_infix@_EXPORT
#endif
-#if !defined(QT_BUILD_@module_define_infix@_LIB) || defined(QT_STATIC)
-/* outside library → inline decl + defi */
+#if !defined(QT_BUILD_@module_define_infix@_LIB) && !defined(QT_STATIC)
+/* 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/platforms/FindIntegrityPlatformGraphics.cmake b/cmake/platforms/FindIntegrityPlatformGraphics.cmake
index 3bc266649b..7b03d7ae89 100644
--- a/cmake/platforms/FindIntegrityPlatformGraphics.cmake
+++ b/cmake/platforms/FindIntegrityPlatformGraphics.cmake
@@ -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: BSD-3-Clause
#.rst:
# IntegrityPlatformGraphics
diff --git a/cmake/platforms/Platform/Integrity.cmake b/cmake/platforms/Platform/Integrity.cmake
index d742bf2544..0ad7fd1099 100644
--- a/cmake/platforms/Platform/Integrity.cmake
+++ b/cmake/platforms/Platform/Integrity.cmake
@@ -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: BSD-3-Clause
# Custom platform module file for INTEGRITY.
#
diff --git a/cmake/qbatchedtestrunner.in.cpp b/cmake/qbatchedtestrunner.in.cpp
new file mode 100644
index 0000000000..cc49b77e0a
--- /dev/null
+++ b/cmake/qbatchedtestrunner.in.cpp
@@ -0,0 +1,18 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QList>
+#include <QString>
+#include <QtTest/private/qtestcase_p.h>
+
+int main(int argc, char **argv)
+{
+ if (argc == 1) {
+ printf("%s\n", QTest::qGetTestCaseNames().join(
+ QStringLiteral(" ")).toStdString().c_str());
+ return 0;
+ }
+
+ const auto entryFunction = QTest::qGetTestCaseEntryFunction(QString::fromUtf8(argv[1]));
+ return entryFunction ? entryFunction(argc - 1, argv + 1) : -1;
+}
diff --git a/cmake/tests/CMakeLists.txt b/cmake/tests/CMakeLists.txt
index 5ee20fbf15..45523c2195 100644
--- a/cmake/tests/CMakeLists.txt
+++ b/cmake/tests/CMakeLists.txt
@@ -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: BSD-3-Clause
# These macros are inspired by ECM:
diff --git a/cmake/tests/features/CMakeLists.txt b/cmake/tests/features/CMakeLists.txt
index 8ff854ad59..415accb04e 100644
--- a/cmake/tests/features/CMakeLists.txt
+++ b/cmake/tests/features/CMakeLists.txt
@@ -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: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
diff --git a/cmake/tests/features/configure.cmake b/cmake/tests/features/configure.cmake
index 4dc8f8208e..fa68d8596e 100644
--- a/cmake/tests/features/configure.cmake
+++ b/cmake/tests/features/configure.cmake
@@ -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: BSD-3-Clause
#### Features
diff --git a/cmake/tests/features/src/CMakeLists.txt b/cmake/tests/features/src/CMakeLists.txt
index 927b093d4b..a02fb1f581 100644
--- a/cmake/tests/features/src/CMakeLists.txt
+++ b/cmake/tests/features/src/CMakeLists.txt
@@ -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: BSD-3-Clause
## Features from parent scope were inherited:
assert(QT_FEATURE_top_a STREQUAL "ON")
diff --git a/cmake/tests/qt_make_output_file/CMakeLists.txt b/cmake/tests/qt_make_output_file/CMakeLists.txt
index 83de59da2e..5beecc6ec3 100644
--- a/cmake/tests/qt_make_output_file/CMakeLists.txt
+++ b/cmake/tests/qt_make_output_file/CMakeLists.txt
@@ -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: BSD-3-Clause
cmake_minimum_required(VERSION 3.16)
diff --git a/cmake/tests/test.cmake b/cmake/tests/test.cmake
index 9087c4a274..db55cc8842 100644
--- a/cmake/tests/test.cmake
+++ b/cmake/tests/test.cmake
@@ -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: BSD-3-Clause
# FAKE moc-ing:
set(QT_MOCSCANNER /usr/bin/true)
diff --git a/cmake/visionos/Info.plist.app.in b/cmake/visionos/Info.plist.app.in
new file mode 100644
index 0000000000..7aa4698649
--- /dev/null
+++ b/cmake/visionos/Info.plist.app.in
@@ -0,0 +1,42 @@
+<?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>
+</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>