CMake: Properly handle CONFIG += thread aka Threads::Threads
mkspecs/features/qt.prf adds a dependency on the system threading library if the Qt Core thread feature is enabled. Because qt.prf is loaded by any public or internal Qt project, it's essentially a public dependency for any Qt consumer. To mimic that in CMake, we check if the thread feature is enabled, and and set the Threads::Threads library as a dependency of Qt6::Platform, which is a public target used by all Qt modules and plugins and Qt consumers. We also need to create a Qt6Dependencies.cmake file so we find_package(Threads) every time find_package(Qt6) is called. For the .prl files to be usable, we have to filter out some CMake implementation specific directory separator tokens 'CMAKE_DIRECTORY_ID_SEP' aka '::@', which are added because we call target_link_libraries() with a target created in a different scope (I think). As a result of this change, we shouldn't have to hardcode Threads::Threads in other projects, because it's now a global public dependency. Task-number: QTBUG-85801 Task-number: QTBUG-85877 Change-Id: Ib5d662c43b28e63f7da49d3bd77d0ad751220b31 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Cristian Adam <cristian.adam@qt.io>
This commit is contained in:
parent
bd2bcd4e1d
commit
92ee9bd6b8
@ -353,6 +353,7 @@ qt_copy_or_install(FILES
|
||||
cmake/QtBuildInformation.cmake
|
||||
cmake/QtCompilerFlags.cmake
|
||||
cmake/QtCompilerOptimization.cmake
|
||||
cmake/QtConfigDependencies.cmake.in
|
||||
cmake/QtFeature.cmake
|
||||
cmake/QtFinishPrlFile.cmake
|
||||
cmake/QtFindWrapHelper.cmake
|
||||
|
@ -3256,7 +3256,12 @@ function(qt_internal_walk_libs target out_var dict_name operation)
|
||||
set(lib_target ${lib})
|
||||
endif()
|
||||
|
||||
if(TARGET ${lib_target})
|
||||
# Skip CMAKE_DIRECTORY_ID_SEP. If a target_link_libraries is applied to a target
|
||||
# that was defined in a different scope, CMake appends and prepends a special directory
|
||||
# id separator. Filter those out.
|
||||
if(lib_target MATCHES "^::@")
|
||||
continue()
|
||||
elseif(TARGET ${lib_target})
|
||||
if ("${lib_target}" MATCHES "^Qt::(.*)")
|
||||
# If both, Qt::Foo and Foo targets exist, prefer the target name without
|
||||
# namespace. Which one is preferred doesn't really matter. This code exists to
|
||||
|
@ -49,6 +49,19 @@ if(APPLE AND (NOT CMAKE_SYSTEM_NAME OR CMAKE_SYSTEM_NAME STREQUAL "Darwin"))
|
||||
list(APPEND CMAKE_MODULE_PATH "${_qt_import_prefix}/macos")
|
||||
endif()
|
||||
|
||||
# Find required dependencies, if any.
|
||||
include(CMakeFindDependencyMacro)
|
||||
set(@INSTALL_CMAKE_NAMESPACE@_DEPENDENCIES_FOUND TRUE)
|
||||
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@Dependencies.cmake")
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@Dependencies.cmake")
|
||||
endif()
|
||||
if(NOT @INSTALL_CMAKE_NAMESPACE@_DEPENDENCIES_FOUND)
|
||||
set(@INSTALL_CMAKE_NAMESPACE@_FOUND False)
|
||||
message(FATAL_ERROR
|
||||
"Failed to find Qt Platform dependency:
|
||||
${@INSTALL_CMAKE_NAMESPACE@_DEPENDENCY_NOT_FOUND_MESSAGE}")
|
||||
endif()
|
||||
|
||||
foreach(module ${@INSTALL_CMAKE_NAMESPACE@_FIND_COMPONENTS})
|
||||
find_package(@INSTALL_CMAKE_NAMESPACE@${module}
|
||||
${_@INSTALL_CMAKE_NAMESPACE@_FIND_PARTS_QUIET}
|
||||
|
35
cmake/QtConfigDependencies.cmake.in
Normal file
35
cmake/QtConfigDependencies.cmake.in
Normal file
@ -0,0 +1,35 @@
|
||||
# note: _third_party_deps example: "ICU\\;1.0\\;i18n uc data;ZLIB\\;\\;"
|
||||
set(_third_party_deps "@third_party_deps@")
|
||||
|
||||
@third_party_extra@
|
||||
|
||||
foreach(_target_dep ${_third_party_deps})
|
||||
list(GET _target_dep 0 pkg)
|
||||
list(GET _target_dep 1 version)
|
||||
list(GET _target_dep 2 components)
|
||||
set(find_package_args "${pkg}")
|
||||
if(version)
|
||||
list(APPEND find_package_args "${version}")
|
||||
endif()
|
||||
|
||||
if(components)
|
||||
string(REPLACE " " ";" components "${components}")
|
||||
find_dependency(${find_package_args} COMPONENTS ${components})
|
||||
else()
|
||||
find_dependency(${find_package_args})
|
||||
endif()
|
||||
|
||||
if (NOT ${pkg}_FOUND)
|
||||
set(@INSTALL_CMAKE_NAMESPACE@_DEPENDENCIES_FOUND FALSE)
|
||||
set(__@INSTALL_CMAKE_NAMESPACE@_message "\nPackage: ${pkg}")
|
||||
if(version)
|
||||
string(APPEND __@INSTALL_CMAKE_NAMESPACE@_message "\nVersion: ${version}")
|
||||
endif()
|
||||
if(components)
|
||||
string(APPEND __@INSTALL_CMAKE_NAMESPACE@_message "\nComponents: ${components}")
|
||||
endif()
|
||||
set(@INSTALL_CMAKE_NAMESPACE@_DEPENDENCY_NOT_FOUND_MESSAGE
|
||||
"${__@INSTALL_CMAKE_NAMESPACE@_message}")
|
||||
return()
|
||||
endif()
|
||||
endforeach()
|
@ -262,10 +262,57 @@ function(qt_internal_create_plugin_depends_file target)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(qt_internal_create_qt6_dependencies_file)
|
||||
# This is used for substitution in the configured file.
|
||||
set(target "${INSTALL_CMAKE_NAMESPACE}")
|
||||
|
||||
# This is the actual target we're querying.
|
||||
set(actual_target Platform)
|
||||
get_target_property(public_depends "${actual_target}" INTERFACE_LINK_LIBRARIES)
|
||||
|
||||
# We need to collect third party deps that are set on the public Platform target,
|
||||
# like Threads::Threads.
|
||||
# This mimics find_package part of the CONFIG += thread assignment in mkspecs/features/qt.prf.
|
||||
qt_collect_third_party_deps(${actual_target})
|
||||
|
||||
# For Threads we also need to write an extra variable assignment.
|
||||
set(third_party_extra "")
|
||||
if(third_party_deps MATCHES "Threads")
|
||||
string(APPEND third_party_extra "if(NOT QT_NO_THREADS_PREFER_PTHREAD_FLAG)
|
||||
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
|
||||
endif()")
|
||||
endif()
|
||||
|
||||
if(third_party_deps)
|
||||
# Setup build and install paths.
|
||||
set(path_suffix "${INSTALL_CMAKE_NAMESPACE}")
|
||||
|
||||
qt_path_join(config_build_dir ${QT_CONFIG_BUILD_DIR} ${path_suffix})
|
||||
qt_path_join(config_install_dir ${QT_CONFIG_INSTALL_DIR} ${path_suffix})
|
||||
|
||||
# Configure and install QtDependencies file.
|
||||
configure_file(
|
||||
"${QT_CMAKE_DIR}/QtConfigDependencies.cmake.in"
|
||||
"${config_build_dir}/${target}Dependencies.cmake"
|
||||
@ONLY
|
||||
)
|
||||
|
||||
qt_install(FILES
|
||||
"${config_build_dir}/${target}Dependencies.cmake"
|
||||
DESTINATION "${config_install_dir}"
|
||||
COMPONENT Devel
|
||||
)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Create Depends.cmake & Depends.h files for all modules and plug-ins.
|
||||
function(qt_internal_create_depends_files)
|
||||
qt_internal_get_qt_repo_known_modules(repo_known_modules)
|
||||
|
||||
if(PROJECT_NAME STREQUAL "QtBase")
|
||||
qt_internal_create_qt6_dependencies_file()
|
||||
endif()
|
||||
|
||||
foreach (target ${repo_known_modules})
|
||||
qt_internal_create_module_depends_file(${target})
|
||||
endforeach()
|
||||
|
@ -249,7 +249,6 @@ qt_add_module(Core
|
||||
../3rdparty/tinycbor/src
|
||||
LIBRARIES
|
||||
Qt::GlobalConfigPrivate # special case
|
||||
Threads::Threads # special case
|
||||
PRECOMPILED_HEADER
|
||||
"global/qt_pch.h"
|
||||
NO_PCH_SOURCES
|
||||
@ -276,6 +275,13 @@ endif()
|
||||
|
||||
qt_generate_qconfig_cpp()
|
||||
|
||||
# Handle qtConfig(thread): CONFIG += thread like in qt.prf.
|
||||
# Aka if the feature is enabled, publically link against the threading library.
|
||||
# This also ensures the link flag is in the .prl file.
|
||||
if(QT_FEATURE_thread)
|
||||
target_link_libraries(Platform INTERFACE Threads::Threads)
|
||||
endif()
|
||||
|
||||
# Handle QObject: Automoc does not work for this as it would
|
||||
# require to spill internals into users:
|
||||
qt_add_module(Core_qobject STATIC
|
||||
|
@ -33,7 +33,6 @@ qt_extend_target(QSQLiteDriverPlugin CONDITION QT_FEATURE_system_sqlite
|
||||
|
||||
# special case begin
|
||||
if (NOT QT_FEATURE_system_sqlite)
|
||||
qt_find_package(Threads REQUIRED PROVIDED_TARGETS Threads::Threads)
|
||||
# On newer compilers compiling sqlite.c produces warnings
|
||||
qt_disable_warnings(QSQLiteDriverPlugin)
|
||||
endif()
|
||||
@ -52,8 +51,6 @@ qt_extend_target(QSQLiteDriverPlugin CONDITION NOT QT_FEATURE_system_sqlite
|
||||
SQLITE_OMIT_COMPLETE
|
||||
INCLUDE_DIRECTORIES
|
||||
../../../3rdparty/sqlite
|
||||
PUBLIC_LIBRARIES # special case
|
||||
Threads::Threads # special case
|
||||
)
|
||||
|
||||
qt_extend_target(QSQLiteDriverPlugin CONDITION CMAKE_BUILD_TYPE STREQUAL Release AND NOT QT_FEATURE_system_sqlite
|
||||
|
@ -62,7 +62,6 @@ qt_add_module(Test
|
||||
QT_BUILD_TESTLIB_LIB # special case
|
||||
LIBRARIES
|
||||
Qt::CorePrivate
|
||||
Threads::Threads # special case
|
||||
PUBLIC_LIBRARIES
|
||||
Qt::Core
|
||||
PRIVATE_MODULE_INTERFACE
|
||||
|
@ -6,7 +6,6 @@ if(QT_BUILD_STANDALONE_TESTS)
|
||||
# special case begin
|
||||
qt_find_package(WrapDBus1 PROVIDED_TARGETS dbus-1)
|
||||
qt_find_package(ICU COMPONENTS i18n uc data PROVIDED_TARGETS ICU::i18n ICU::uc ICU::data)
|
||||
qt_find_package(Threads PROVIDED_TARGETS Threads::Threads)
|
||||
qt_find_package(WrapOpenSSL PROVIDED_TARGETS WrapOpenSSL::WrapOpenSSL)
|
||||
qt_find_package(WrapOpenSSLHeaders PROVIDED_TARGETS WrapOpenSSLHeaders::WrapOpenSSLHeaders)
|
||||
# special case end
|
||||
|
@ -16,7 +16,6 @@ qt_add_test(tst_qmetatype
|
||||
../../../other/qvariant_common
|
||||
PUBLIC_LIBRARIES
|
||||
Qt::CorePrivate
|
||||
Threads::Threads # special case
|
||||
TESTDATA ${test_data}
|
||||
)
|
||||
|
||||
|
@ -9,6 +9,4 @@ qt_add_test(tst_qpromise
|
||||
tst_qpromise.cpp
|
||||
PUBLIC_LIBRARIES
|
||||
Qt::CorePrivate
|
||||
LIBRARIES # special case
|
||||
Threads::Threads # solves issue with libpthread linkage # special case
|
||||
)
|
||||
|
@ -10,8 +10,6 @@ qt_add_test(tst_qthread
|
||||
tst_qthread.cpp
|
||||
INCLUDE_DIRECTORIES
|
||||
../../../../shared
|
||||
LIBRARIES # special case
|
||||
Threads::Threads # special case
|
||||
)
|
||||
|
||||
## Scopes:
|
||||
|
@ -8,9 +8,6 @@
|
||||
add_qt_test(tst_qthreadstorage
|
||||
SOURCES
|
||||
tst_qthreadstorage.cpp
|
||||
LIBRARIES # special case
|
||||
Threads::Threads # special case
|
||||
|
||||
)
|
||||
|
||||
## Scopes:
|
||||
|
@ -28,7 +28,6 @@ qt_add_test(tst_qguiapplication
|
||||
PUBLIC_LIBRARIES
|
||||
Qt::CorePrivate
|
||||
Qt::GuiPrivate
|
||||
Threads::Threads # special case
|
||||
)
|
||||
|
||||
# Resources:
|
||||
|
@ -10,5 +10,4 @@ qt_add_test(tst_qguitimer
|
||||
PUBLIC_LIBRARIES
|
||||
Qt::CorePrivate
|
||||
Qt::Gui
|
||||
Threads::Threads # special case
|
||||
)
|
||||
|
@ -21,12 +21,6 @@ qt_extend_target(tst_qtcpsocket CONDITION WIN32
|
||||
ws2_32
|
||||
)
|
||||
|
||||
# special case begin
|
||||
set(THREADS_PREFER_PTHREAD_FLAG 1)
|
||||
find_package(Threads)
|
||||
target_link_libraries(tst_qtcpsocket PRIVATE Threads::Threads)
|
||||
# special case end
|
||||
|
||||
#### Keys ignored in scope 4:.:.:test.pro:(CMAKE_BUILD_TYPE STREQUAL Debug):
|
||||
# DESTDIR = "../debug"
|
||||
|
||||
|
@ -11,7 +11,6 @@ qt_add_benchmark(qtimer_vs_qmetaobject
|
||||
.
|
||||
PUBLIC_LIBRARIES
|
||||
Qt::Test
|
||||
Threads::Threads # special case
|
||||
)
|
||||
|
||||
#### Keys ignored in scope 1:.:.:qtimer_vs_qmetaobject.pro:<TRUE>:
|
||||
|
Loading…
Reference in New Issue
Block a user