CMake: Warn when examples are not added via qt_internal_add_example

To ensure examples can be built as ExternalProjects, the example
subdirectories need to be added via qt_internal_add_example rather
than just add_subdirectory.
qt_internal_add_example is also needed for correct installation of
example sources.

To catch examples that are still not added via
qt_internal_add_example, set a QT_WARN_ABOUT_EXAMPLE_ADD_SUBDIRECTORY
variable at the top of the examples/CMakeLists.txt directory scope
and show a warning in qt_add_executable whenever that variable is
TRUE.

Calls of qt_internal_add_example will set the variable to FALSE,
making sure the warning is not shown for properly added examples.

This is limited to developer builds and can be opted out of via the
QT_NO_WARN_ABOUT_EXAMPLE_ADD_SUBDIRECTORY_WARNING variable.

qt_add_executable is used as the 'hook' for showing the error, because
that is the most likely function to be used in examples.
We don't use qt_standard_project_setup in all projects yet, so we
don't want to use that one.

Task-number: QTBUG-90820
Task-number: QTBUG-123096
Change-Id: I7a0b0b2cc60c70903db03b56c06494c127a62420
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
This commit is contained in:
Alexandru Croitor 2024-03-07 15:32:17 +01:00
parent 06fef6219e
commit dd052a0a01
4 changed files with 32 additions and 1 deletions

View File

@ -135,6 +135,13 @@ 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}")

View File

@ -447,7 +447,15 @@ macro(qt_build_repo_impl_examples)
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})
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()

View File

@ -321,3 +321,17 @@ function(_qt_internal_set_up_static_runtime_library target)
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()

View File

@ -617,6 +617,8 @@ set(_Qt6_COMPONENT_PATH "${CMAKE_CURRENT_LIST_DIR}/..")
function(qt6_add_executable target)
cmake_parse_arguments(PARSE_ARGV 1 arg "MANUAL_FINALIZATION" "" "")
_qt_internal_warn_about_example_add_subdirectory()
_qt_internal_create_executable("${target}" ${arg_UNPARSED_ARGUMENTS})
target_link_libraries("${target}" PRIVATE Qt6::Core)
set_property(TARGET ${target} PROPERTY _qt_expects_finalization TRUE)