CMake: Make WrapVulkanHeaders target optional for QtGui consumers
If Vulkan headers are present on the system when qtbase is configured, QtGui and QtOpenGL should be compiled with Vulkan support. If a user project uses a Qt built with Vulkan support, but their system is missing Vulkan headers, the project configuration needs to succeed. The project will get compilation errors if it uses Vulkan headers, but that's intended. This use case was broken when fixing Vulkan to be found when building Qt for Android. Fix the regression with a combination of things 1) Mark the WrapVulkanHeaders package as optional (already the case) 2) Use the include directories directly when compiling Gui and OpenGL 3) Propagate WrapVulkanHeaders::WrapVulkanHeaders link requirement to consumers only if the target exists. It won't exist if Vulkan include dirs are not found This also requires some changes in pri and prl file generation. For prl file generation, we don't want to link to the WrapVulkanHeaders target, so we filter out all dependencies that use TARGET_NAME_IF_EXISTS for anything that calls __qt_internal_walk_libs which includes qt_collect_libs. For pri files, we make sure to generate a uses=vulkan/nolink clause by inspecting a new _qt_is_nolink_target property on the target. We also don't add include dirs to the pri file if the new _qt_skip_include_dir_for_pri property is set. This is intended for Vulkan, because there is separate qmake logic to try and find the include dirs when configuring a user project. As a drive-by, fix nolink handling for WrapOpenSSLHeaders. Amendsbb25536a3d
Amends7b9904849f
Pick-to: 6.2 Fixes: QTBUG-95391 Change-Id: I21e2f4be5c386f9e40033e4691f4786a91ba0e2d Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Alexey Edelev <alexey.edelev@qt.io> Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
This commit is contained in:
parent
3b2157ed9e
commit
3c23317552
@ -28,6 +28,9 @@ if(OPENSSL_INCLUDE_DIR)
|
||||
add_library(WrapOpenSSLHeaders::WrapOpenSSLHeaders INTERFACE IMPORTED)
|
||||
target_include_directories(WrapOpenSSLHeaders::WrapOpenSSLHeaders INTERFACE
|
||||
${OPENSSL_INCLUDE_DIR})
|
||||
|
||||
set_target_properties(WrapOpenSSLHeaders::WrapOpenSSLHeaders PROPERTIES
|
||||
_qt_is_nolink_target TRUE)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
@ -18,6 +18,12 @@ if(Vulkan_INCLUDE_DIR)
|
||||
target_include_directories(WrapVulkanHeaders::WrapVulkanHeaders INTERFACE
|
||||
${Vulkan_INCLUDE_DIR})
|
||||
|
||||
set_target_properties(WrapVulkanHeaders::WrapVulkanHeaders PROPERTIES
|
||||
_qt_is_nolink_target TRUE)
|
||||
|
||||
set_target_properties(WrapVulkanHeaders::WrapVulkanHeaders PROPERTIES
|
||||
_qt_skip_include_dir_for_pri TRUE)
|
||||
|
||||
# Also propagate MoltenVK include directory on Apple platforms if found.
|
||||
# Assumes the folder structure of the LunarG Vulkan SDK.
|
||||
if(APPLE)
|
||||
|
@ -269,6 +269,29 @@ function(qt_record_extra_qt_main_tools_package_dependency main_target_name
|
||||
"${main_target_name}" "${qtfied_package_name_versioned}" "${dep_package_version}")
|
||||
endfunction()
|
||||
|
||||
# Record an extra 3rd party target as a dependency for ${main_target_name}.
|
||||
#
|
||||
# Adds a find_package(${dep_target_package_name}) in ${main_target_name}Dependencies.cmake.
|
||||
#
|
||||
# Needed to record a dependency on the package that provides WrapVulkanHeaders::WrapVulkanHeaders.
|
||||
# The package version, components, whether the package is optional, etc, are queried from the
|
||||
# ${dep_target} target properties.
|
||||
function(qt_record_extra_third_party_dependency main_target_name dep_target)
|
||||
if(NOT TARGET "${main_target_name}")
|
||||
qt_get_tool_target_name(main_target_name "${main_target_name}")
|
||||
endif()
|
||||
if(TARGET "${main_target_name}")
|
||||
get_target_property(extra_deps "${main_target_name}" _qt_extra_third_party_dep_targets)
|
||||
if(NOT extra_deps)
|
||||
set(extra_deps "")
|
||||
endif()
|
||||
|
||||
list(APPEND extra_deps "${dep_target}")
|
||||
set_target_properties("${main_target_name}" PROPERTIES _qt_extra_third_party_dep_targets
|
||||
"${extra_deps}")
|
||||
endif()
|
||||
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)
|
||||
|
@ -25,7 +25,7 @@ macro(qt_collect_third_party_deps target)
|
||||
endif()
|
||||
unset(_target_is_static)
|
||||
|
||||
foreach(dep ${${depends_var}} ${optional_public_depends})
|
||||
foreach(dep ${${depends_var}} ${optional_public_depends} ${extra_third_party_deps})
|
||||
# Gather third party packages that should be found when using the Qt module.
|
||||
# Also handle nolink target dependencies.
|
||||
string(REGEX REPLACE "_nolink$" "" base_dep "${dep}")
|
||||
@ -138,6 +138,12 @@ function(qt_internal_create_module_depends_file target)
|
||||
list(APPEND target_deps "${extra_depends}")
|
||||
endif()
|
||||
|
||||
# Extra 3rd party targets who's packages should be considered dependencies.
|
||||
get_target_property(extra_third_party_deps "${target}" _qt_extra_third_party_dep_targets)
|
||||
if(NOT extra_third_party_deps)
|
||||
set(extra_third_party_deps "")
|
||||
endif()
|
||||
|
||||
# Used for assembling the content of an include/Module/ModuleDepends.h header.
|
||||
set(qtdeps "")
|
||||
|
||||
|
@ -36,7 +36,16 @@ function(qt_generate_qmake_libraries_pri_content module_name output_root_dir out
|
||||
list(APPEND lib_libs "$<TARGET_LINKER_FILE:${lib_target}>")
|
||||
endif()
|
||||
list(APPEND lib_libdir "$<TARGET_PROPERTY:${lib_target},INTERFACE_LINK_DIRECTORIES>")
|
||||
list(APPEND lib_incdir "$<TARGET_PROPERTY:${lib_target},INTERFACE_INCLUDE_DIRECTORIES>")
|
||||
|
||||
get_target_property(skip_include_dir "${lib_target}" _qt_skip_include_dir_for_pri)
|
||||
if(skip_include_dir)
|
||||
set(target_include_dir "")
|
||||
else()
|
||||
set(target_include_dir
|
||||
"$<TARGET_PROPERTY:${lib_target},INTERFACE_INCLUDE_DIRECTORIES>")
|
||||
endif()
|
||||
|
||||
list(APPEND lib_incdir "${target_include_dir}")
|
||||
list(APPEND lib_defines "$<TARGET_PROPERTY:${lib_target},INTERFACE_COMPILE_DEFINITIONS>")
|
||||
else()
|
||||
if(lib_target MATCHES "/([^/]+).framework$")
|
||||
@ -120,14 +129,35 @@ function(qt_get_direct_module_dependencies target out_var)
|
||||
endfunction()
|
||||
|
||||
# Return a list of qmake library names for a given list of targets.
|
||||
# For example, Vulkan::Vulkan_nolink is mapped to vulkan/nolink.
|
||||
# For example, Foo::Foo_nolink is mapped to foo/nolink.
|
||||
# Also targets with the _qt_is_nolink_target property are mapped to nolink as well.
|
||||
function(qt_internal_map_targets_to_qmake_libs out_var)
|
||||
set(result "")
|
||||
foreach(target ${ARGN})
|
||||
# Unwrap optional targets. Needed for Vulkan.
|
||||
if(target MATCHES "^\\$<TARGET_NAME_IF_EXISTS:(.*)>$")
|
||||
set(target ${CMAKE_MATCH_1})
|
||||
endif()
|
||||
|
||||
set(is_no_link_target FALSE)
|
||||
|
||||
# First case of detecting nolink targets (possibly not needed anymore)
|
||||
string(REGEX REPLACE "_nolink$" "" stripped_target "${target}")
|
||||
if(NOT target STREQUAL stripped_target)
|
||||
set(is_no_link_target TRUE)
|
||||
endif()
|
||||
|
||||
# Second case of detecting nolink targets.
|
||||
if(TARGET "${target}")
|
||||
get_target_property(marked_as_no_link_target "${target}" _qt_is_nolink_target)
|
||||
if(marked_as_no_link_target)
|
||||
set(is_no_link_target TRUE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
qt_internal_map_target_to_qmake_lib(${stripped_target} qmake_lib)
|
||||
if(NOT "${qmake_lib}" STREQUAL "")
|
||||
if(NOT target STREQUAL stripped_target)
|
||||
if(is_no_link_target)
|
||||
string(APPEND qmake_lib "/nolink")
|
||||
endif()
|
||||
list(APPEND result "${qmake_lib}")
|
||||
|
@ -148,6 +148,13 @@ function(__qt_internal_walk_libs
|
||||
continue()
|
||||
endif()
|
||||
|
||||
# Skip optional dependencies for now. They are likely to be handled manually for prl
|
||||
# file purposes (like nolink handling). And for one of the other operations, we don't
|
||||
# have a use case yet. This might be revisited.
|
||||
if(lib MATCHES "^\\$<TARGET_NAME_IF_EXISTS:")
|
||||
continue()
|
||||
endif()
|
||||
|
||||
# Strip any directory scope tokens.
|
||||
__qt_internal_strip_target_directory_scope_token("${lib}" lib)
|
||||
|
||||
|
@ -772,3 +772,40 @@ function(qt_internal_link_internal_platform_for_object_library target)
|
||||
# Achieve this by compiling the cpp files with the PlatformModuleInternal compile flags.
|
||||
target_link_libraries("${target}" PRIVATE Qt::PlatformModuleInternal)
|
||||
endfunction()
|
||||
|
||||
|
||||
# Use ${dep_target}'s include dirs when building ${target} and optionally propagate the include
|
||||
# dirs to consumers of ${target}.
|
||||
|
||||
# Assumes ${dep_target} is an INTERFACE_LIBRARY that only propagates include dirs and ${target}
|
||||
# is a Qt module / plugin.
|
||||
#
|
||||
# Building ${target} requires ${dep_target}'s include dirs.
|
||||
#
|
||||
# User projects that don't have ${dep_target}'s headers installed in their system should still
|
||||
# configure successfully.
|
||||
#
|
||||
# To achieve that, consumers of ${target} will only get the include directories of ${dep_target}
|
||||
# if the latter package and target exists.
|
||||
#
|
||||
# A find_package(dep_target) dependency is added to ${target}'s ModuleDependencies.cmake file.
|
||||
#
|
||||
# We use target_include_directories(PRIVATE) instead of target_link_libraries(PRIVATE) because the
|
||||
# latter would propagate a mandatory LINK_ONLY dependency on the ${dep_target} in a static Qt build.
|
||||
#
|
||||
# The main use case is for propagating WrapVulkanHeaders::WrapVulkanHeaders.
|
||||
function(qt_internal_add_target_include_dirs_and_optionally_propagate target dep_target)
|
||||
if(NOT TARGET "${target}")
|
||||
message(FATAL_ERROR "${target} is not a valid target.")
|
||||
endif()
|
||||
if(NOT TARGET "${dep_target}")
|
||||
message(FATAL_ERROR "${dep_target} is not a valid target.")
|
||||
endif()
|
||||
|
||||
target_include_directories("${target}" PRIVATE
|
||||
"$<TARGET_PROPERTY:${dep_target},INTERFACE_INCLUDE_DIRECTORIES>")
|
||||
|
||||
target_link_libraries("${target}" INTERFACE "$<TARGET_NAME_IF_EXISTS:${dep_target}>")
|
||||
|
||||
qt_record_extra_third_party_dependency("${target}" "${dep_target}")
|
||||
endfunction()
|
||||
|
@ -869,9 +869,11 @@ qt_internal_extend_target(Gui CONDITION QT_FEATURE_vulkan
|
||||
vulkan/qvulkanfunctions.cpp
|
||||
vulkan/qvulkaninstance.cpp vulkan/qvulkaninstance.h
|
||||
vulkan/qvulkanwindow.cpp vulkan/qvulkanwindow.h vulkan/qvulkanwindow_p.h
|
||||
PUBLIC_LIBRARIES
|
||||
WrapVulkanHeaders::WrapVulkanHeaders
|
||||
)
|
||||
if(QT_FEATURE_vulkan)
|
||||
qt_internal_add_target_include_dirs_and_optionally_propagate(
|
||||
Gui WrapVulkanHeaders::WrapVulkanHeaders)
|
||||
endif()
|
||||
|
||||
#### Keys ignored in scope 111:.:vulkan:vulkan/vulkan.pri:QT_FEATURE_vkgen:
|
||||
# special case begin
|
||||
|
@ -90,9 +90,11 @@ qt_internal_extend_target(OpenGL CONDITION NOT QT_FEATURE_opengles2
|
||||
qt_internal_extend_target(OpenGL CONDITION QT_FEATURE_vulkan
|
||||
SOURCES
|
||||
qvkconvenience.cpp qvkconvenience_p.h
|
||||
PUBLIC_LIBRARIES
|
||||
WrapVulkanHeaders::WrapVulkanHeaders
|
||||
)
|
||||
if(QT_FEATURE_vulkan)
|
||||
qt_internal_add_target_include_dirs_and_optionally_propagate(
|
||||
OpenGL WrapVulkanHeaders::WrapVulkanHeaders)
|
||||
endif()
|
||||
|
||||
qt_internal_extend_target(OpenGL CONDITION QT_FEATURE_egl
|
||||
SOURCES
|
||||
|
Loading…
Reference in New Issue
Block a user