CMake: Work around upstream AUTOGEN issue with discarded dependencies

Upstream CMake has a nasty bug where AUTOGEN dependencies are
discarded if a library is added as a dependency more than once (or
rather the number of times it is added is not equal to the number of
configured build configs).

This can result in racy build failures, where a <module>_autogen
target is supposed to depend on some <other_module>_sync_headers
target, but doesn't, and thus moc generates empty metatypes files
because it can't find a synced header.

To avoid the AUTOGEN dependencies from being discarded, manually
add all dependencies passed to qt_internal_extend_target to the
AUTOGEN_TARGET_DEPENDS property.

The issue is fixed in CMake 4.0, so the workaround is gated on the
cmake version used. Add a flag called
QT_NO_AUTOGEN_DISCARDED_DEPENDENCIES_WORKAROUND to disable the
workaround, in case the fix gets reverted upstream.

Pick-to: 6.8 6.5
Fixes: QTBUG-133725
Change-Id: I857d7e774fc9f9f5203a58311daea5e7177e0d67
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
(cherry picked from commit fcb20586316aff2ccc39e2ae840b79f8b0e904a7)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Alexandru Croitor 2025-02-14 22:11:28 +01:00 committed by Qt Cherry-pick Bot
parent ac0e10db65
commit 71130a16f8
2 changed files with 53 additions and 0 deletions

View File

@ -214,3 +214,53 @@ function(qt_make_output_file infile prefix suffix source_dir binary_dir result)
file(MAKE_DIRECTORY "${outpath}")
set("${result}" "${outpath}/${prefix}${outfilename}${suffix}" PARENT_SCOPE)
endfunction()
# Work around AUTOGEN issue when a library is added as a dependency more than once, and the autogen
# library dependency results in being discarded. To mitigate that, add all autogen dependencies
# manually, based on the passed in dependencies.
# CMake 4.0+ has a fix, so we don't need the extra logic.
# See https://gitlab.kitware.com/cmake/cmake/-/issues/26700
function(qt_internal_work_around_autogen_discarded_dependencies target)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 4.0
OR QT_NO_AUTOGEN_DISCARDED_DEPENDENCIES_WORKAROUND)
return()
endif()
set(libraries ${ARGN})
set(final_libraries "")
foreach(lib IN LISTS libraries)
# Skip non-target dependencies.
if(NOT TARGET "${lib}")
continue()
endif()
# Resolve alias targets, because AUTOGEN_TARGET_DEPENDS doesn't seem to handle them.
get_target_property(aliased_target "${lib}" ALIASED_TARGET)
if(aliased_target)
set(lib "${aliased_target}")
endif()
# Skip imported targets, they don't have sync_headers targets.
get_target_property(imported "${lib}" IMPORTED)
if(imported)
continue()
endif()
# Resolve Qt private modules to their public counterparts.
get_target_property(is_private_module "${lib}" _qt_is_private_module)
get_target_property(public_module_target "${lib}" _qt_public_module_target_name)
if(is_private_module AND public_module_target)
set(lib "${public_module_target}")
endif()
# Another TARGET check, just in case.
if(TARGET "${lib}")
list(APPEND final_libraries "${lib}")
endif()
endforeach()
if(final_libraries)
set_property(TARGET ${target} APPEND PROPERTY AUTOGEN_TARGET_DEPENDS "${final_libraries}")
endif()
endfunction()

View File

@ -232,6 +232,9 @@ function(qt_internal_extend_target target)
)
endif()
set(all_libraries ${arg_LIBRARIES} ${arg_PUBLIC_LIBRARIES})
qt_internal_work_around_autogen_discarded_dependencies(${target} ${all_libraries})
if(QT_GENERATE_SBOM)
set(sbom_args "")
_qt_internal_forward_function_args(