summaryrefslogtreecommitdiffstats
path: root/cmake/QtFindPackageHelpers.cmake
diff options
context:
space:
mode:
authorAlexandru Croitor <alexandru.croitor@qt.io>2022-05-17 08:44:43 +0200
committerAlexandru Croitor <alexandru.croitor@qt.io>2022-07-01 10:50:57 +0200
commitdd1030a4501ca067e96f50085c8cfda19d85afd4 (patch)
tree02e6aa5ca6cf2f384a4684c2108c29172322ff26 /cmake/QtFindPackageHelpers.cmake
parent74d832177169dd24ff06c9a584d0dc0f4f35d31b (diff)
CMake: Record used package version for each target dependency
When recording which package version to look for in QtFooModuleDependencies.cmake and other files like it, instead of using PROJECT_VERSION, use the version of the package that contains the dependency. For example if we're hypothetically building the qtdeclarative repo from the 6.4 branch, against an installed 6.2 qtbase, then the Qt6QmlModuleDependencies.cmake file will have a find_package(Qt6Core 6.2) call because qtdeclarative's find_package(Qt6Core) call found a 6.2 Core when it was configured. This allows switching the versioning scheme of specific Qt modules that might not want to follow the general Qt versioning scheme. The first candidate would be QtWebEngine which might want to follow the Chromium versioning scheme, something like Qt 6.94.0 where 94 is the Chromium major version. Implementation notes. We now record the package version of a target in a property called _qt_package_version. We do it for qt modules, plugins, 3rd party libraries, tools and the Platform target. When we try to look up which version to write into the QtFooModuleDependencies.cmake file (or the equivalent Plugins and Tools file), we try to find the version from a few sources: the property mentioned above, then the Qt6{target}_VERSION variable, and finally PROJECT_VERSION. In the latter case, we issue a warning because technically that should never have to happen, and it's a bug or an unforeseen case if it does. A few more places also need adjustments: - package versions to look for when configuring standalone tests and generating standalone tests Config files - handling of tools packages - The main Qt6 package lookup in each Dependencies.cmake files Note that there are some requirements and consequences in case a module wants to use a different versioning scheme like 6.94.0. Requirements. - The root CMakeLists.txt file needs to call find_package with a version different from the usual PROJECT_VERSION. Ideally it should look for a few different Qt versions which are known to be compatible, for example the last stable and LTS versions, or just the lowest supported Qt version, e.g. 6.2.6 or whenever this change would land in the 6.2 branch. - If the repository has multiple modules, some of which need to follow the Qt versioning scheme and some not, project(VERSION x.y.z) calls need to be carefully placed in subdirectory scopes with appropriate version numbers, so that qt_internal_add_module / _tool / _plugin pick up the correct version. Consequences. - The .so / .dylib names will contain the new version, e.g. .so.6.94 - Linux ELF symbols will contain the new versions - syncqt private headers will now exist under a include/QtFoo/6.94.0/QtFoo/private folder - pri and prl files will also contain the new version numbers - pkg-config .pc files contain the new version numbers - It won't be possible to write find_package(Qt6 6.94 COMPONENTS WebEngineWidgets) in user code. One would have to write find_package(Qt6WebEngineWidgets 6.94) otherwise CMake will try to look for Qt6Config 6.94 which won't exist. - Similarly, a find_package(Qt6 6.4 COMPONENTS Widgets WebEngineWidgets) call would always find any kind of WebEngine package that is higher than 6.4, which might be 6.94, 6.95, etc. - In the future, if we fix Qt6Config to pass EXACT to its subcomponent find_package calls, a find_package(Qt6 6.5.0 EXACT COMPONENTS Widgets WebEngineWidgets) would fail to find WebEngineWidgets, because its 6.94.0 version will not be equal to 6.5.0. Currently we don't pass through EXACT, so it's not an issue. Augments 5ffc744b791a114a3180a425dd26e298f7399955 Task-number: QTBUG-103500 Change-Id: I8bdb56bfcbc7f7f6484d1e56651ffc993fd30bab Reviewed-by: Michal Klocek <michal.klocek@qt.io> Reviewed-by: Alexey Edelev <alexey.edelev@qt.io> Reviewed-by: Jörg Bornemann <joerg.bornemann@qt.io>
Diffstat (limited to 'cmake/QtFindPackageHelpers.cmake')
-rw-r--r--cmake/QtFindPackageHelpers.cmake71
1 files changed, 68 insertions, 3 deletions
diff --git a/cmake/QtFindPackageHelpers.cmake b/cmake/QtFindPackageHelpers.cmake
index 07749ebf10..ae581fd75d 100644
--- a/cmake/QtFindPackageHelpers.cmake
+++ b/cmake/QtFindPackageHelpers.cmake
@@ -314,6 +314,68 @@ function(qt_internal_is_lib_part_of_qt6_package lib out_var)
endif()
endfunction()
+# Try to get the CMake package version of a Qt target.
+#
+# Query the target's _qt_package_version property, or try to read it from the CMake package version
+# variable set from calling find_package(Qt6${target}).
+# Not all targets will have a find_package _VERSION variable, for example if the target is an
+# executable.
+# A heuristic is used to handle QtFooPrivate module targets.
+# If no version can be found, fall back to ${PROJECT_VERSION} and issue a warning.
+function(qt_internal_get_package_version_of_target target package_version_out_var)
+ qt_internal_is_lib_part_of_qt6_package("${target}" is_part_of_qt6)
+
+ if(is_part_of_qt6)
+ # When building qtbase, Qt6_VERSION is not set (unless examples are built in-tree,
+ # non-ExternalProject). Use the Platform target's version instead which would be the
+ # equivalent.
+ if(TARGET "${QT_CMAKE_EXPORT_NAMESPACE}::Platform")
+ get_target_property(package_version
+ "${QT_CMAKE_EXPORT_NAMESPACE}::Platform" _qt_package_version)
+ endif()
+ if(NOT package_version)
+ set(package_version "${${QT_CMAKE_EXPORT_NAMESPACE}_VERSION}")
+ endif()
+ else()
+ # Try to get the version from the target.
+ # Try the Private target first and if it doesn't exist, try the non-Private target later.
+ if(TARGET "${QT_CMAKE_EXPORT_NAMESPACE}::${target}")
+ get_target_property(package_version
+ "${QT_CMAKE_EXPORT_NAMESPACE}::${target}" _qt_package_version)
+ endif()
+
+ # Try to get the version from the corresponding package version variable.
+ if(NOT package_version)
+ set(package_version "${${QT_CMAKE_EXPORT_NAMESPACE}${target}_VERSION}")
+ endif()
+
+ # Try non-Private target.
+ if(NOT package_version AND target MATCHES "(.*)Private$")
+ set(target "${CMAKE_MATCH_1}")
+ endif()
+
+ if(NOT package_version AND TARGET "${QT_CMAKE_EXPORT_NAMESPACE}::${target}")
+ get_target_property(package_version
+ "${QT_CMAKE_EXPORT_NAMESPACE}::${target}" _qt_package_version)
+ endif()
+
+ if(NOT package_version)
+ set(package_version "${${QT_CMAKE_EXPORT_NAMESPACE}${target}_VERSION}")
+ endif()
+ endif()
+
+ if(NOT package_version)
+ set(package_version "${PROJECT_VERSION}")
+ if(FEATURE_developer_build)
+ message(WARNING
+ "Could not determine package version of target ${target}. "
+ "Defaulting to project version ${PROJECT_VERSION}.")
+ endif()
+ endif()
+
+ set(${package_version_out_var} "${package_version}" PARENT_SCOPE)
+endfunction()
+
# This function stores the list of Qt targets a library depend on,
# along with their version info, for usage in ${target}Depends.cmake file
function(qt_register_target_dependencies target public_libs private_libs)
@@ -346,10 +408,12 @@ function(qt_register_target_dependencies target public_libs private_libs)
if ("${lib}" MATCHES "^Qt::(.*)")
set(lib "${CMAKE_MATCH_1}")
qt_internal_is_lib_part_of_qt6_package("${lib}" is_part_of_qt6)
+
+ qt_internal_get_package_version_of_target("${lib}" package_version)
if (is_part_of_qt6)
- list(APPEND target_deps "Qt6\;${PROJECT_VERSION}")
+ list(APPEND target_deps "Qt6\;${package_version}")
else()
- list(APPEND target_deps "${INSTALL_CMAKE_NAMESPACE}${lib}\;${PROJECT_VERSION}")
+ list(APPEND target_deps "${INSTALL_CMAKE_NAMESPACE}${lib}\;${package_version}")
endif()
endif()
endforeach()
@@ -370,7 +434,8 @@ function(qt_register_target_dependencies target public_libs private_libs)
qt_internal_is_lib_part_of_qt6_package("${lib}" is_part_of_qt6)
get_target_property(lib_type "${lib_namespaced}" TYPE)
if(NOT lib_type STREQUAL "STATIC_LIBRARY" AND NOT is_part_of_qt6)
- list(APPEND target_deps "${INSTALL_CMAKE_NAMESPACE}${lib}\;${PROJECT_VERSION}")
+ qt_internal_get_package_version_of_target("${lib}" package_version)
+ list(APPEND target_deps "${INSTALL_CMAKE_NAMESPACE}${lib}\;${package_version}")
endif()
endif()
endforeach()