CMake: Deduce install prefix of example in qt_internal_add_example

We want to get rid of the INSTALL_EXAMPLEDIR and INSTALL_EXAMPLESDIR
code in each example project.

This was an internal workaround to ensure examples are installed into
a relative path somewhere under $qt_prefix/examples and not in
$qt_prefix/bin or similar.

To achieve that we do two things.

First, deduce the install prefix for each example in the
implementation of qt_internal_add_example (our add_subdirectory
wrapper) and assign it to CMAKE_INSTALL_PREFIX before calling
add_subdirectory. We need to make sure to remove the default
value of CMAKE_INSTALL_PREFIX in the generated
cmake_install.cmake file.

Second, we set an internal variable called
QT_INTERNAL_SET_EXAMPLE_INSTALL_DIR_TO_DOT before the add_subdirectory
call, which will be checked whenever find_package(Qt6Core) is called
in an example project. If the variable is set, the
INSTALL_EXAMPLEDIR var is set to "." in the scope of where Qt6Core
is found.

This ensures that the hardcoded INSTALL_EXAMPLEDIR values in our
example projects are changed to ".".

With both changes, our example project install(TARGET DESTINATION)
calls will now install to
"${CMAKE_INSTALL_PREFIX}/examples/${example_relative_dir}/."

Once all repositories are updated to use qt_internal_add_example
instead of add_subdirectory, we can get rid of the
QT_INTERNAL_SET_EXAMPLE_INSTALL_DIR_TO_DOT workaround.

For repositories that still don't use qt_internal_add_example,
the install prefix rewriting will not happen, but the examples will
still be installed to the proper place because they use their own
hardcoded INSTALL_EXAMPLEDIR value.

Amends d97fd7af2b

Pick-to: 6.2 6.3
Task-number: QTBUG-96232
Task-number: QTBUG-98545
Change-Id: I78c118e10c41b519c570c7d87529afd15aeed900
Reviewed-by: Jörg Bornemann <joerg.bornemann@qt.io>
This commit is contained in:
Alexandru Croitor 2021-12-14 16:27:58 +01:00
parent 1a103beff6
commit ac4a913f33
3 changed files with 55 additions and 2 deletions

View File

@ -730,6 +730,9 @@ macro(qt_examples_build_begin)
cmake_parse_arguments(arg "${options}" "${singleOpts}" "${multiOpts}" ${ARGN})
# Use by qt_internal_add_example.
set(QT_EXAMPLE_BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
# FIXME: Support prefix builds as well QTBUG-96232
if(arg_EXTERNAL_BUILD AND QT_BUILD_EXAMPLES_AS_EXTERNAL)
# Examples will be built using ExternalProject.
@ -750,7 +753,6 @@ macro(qt_examples_build_begin)
list(APPEND QT_EXAMPLE_DEPENDENCIES ${qt_repo_targets_name}_tools)
endif()
set(QT_EXAMPLE_BASE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(QT_IS_EXTERNAL_EXAMPLES_BUILD TRUE)
string(TOLOWER ${PROJECT_NAME} project_name_lower)
@ -802,6 +804,13 @@ macro(qt_examples_build_begin)
# seems there's no way to query such information from CMake itself.
set(CMAKE_INSTALL_RPATH "${_default_install_rpath}")
set(QT_DISABLE_QT_ADD_PLUGIN_COMPATIBILITY TRUE)
install(CODE "
# Backup CMAKE_INSTALL_PREFIX because we're going to change it in each example subdirectory
# and restore it after all examples are processed so that QtFooToolsAdditionalTargetInfo.cmake
# files are installed into the original install prefix.
set(_qt_internal_examples_cmake_install_prefix_backup \"\${CMAKE_INSTALL_PREFIX}\")
")
endmacro()
macro(qt_examples_build_end)
@ -839,6 +848,11 @@ macro(qt_examples_build_end)
endforeach()
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ${BACKUP_CMAKE_FIND_ROOT_PATH_MODE_PACKAGE})
install(CODE "
# Restore backed up CMAKE_INSTALL_PREFIX.
set(CMAKE_INSTALL_PREFIX \"\${_qt_internal_examples_cmake_install_prefix_backup}\")
")
endmacro()
function(qt_internal_add_example subdir)
@ -849,8 +863,35 @@ function(qt_internal_add_example subdir)
endif()
endfunction()
# Use old non-ExternalProject approach, aka build in-tree with the Qt build.
function(qt_internal_add_example_in_tree subdir)
# Use old non-ExternalProject approach, aka build in-tree with the Qt build.
file(RELATIVE_PATH example_rel_path
"${QT_EXAMPLE_BASE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/${subdir}")
# Unset the default CMAKE_INSTALL_PREFIX that's generated in
# ${CMAKE_CURRENT_BINARY_DIR}/cmake_install.cmake
# so we can override it with a different value in
# ${CMAKE_CURRENT_BINARY_DIR}/${subdir}/cmake_install.cmake
#
install(CODE "
# Unset the CMAKE_INSTALL_PREFIX in the current cmake_install.cmake file so that it can be
# overridden in the included add_subdirectory-specific cmake_install.cmake files instead.
unset(CMAKE_INSTALL_PREFIX)
")
# Override the install prefix in the subdir cmake_install.cmake, so that
# relative install(TARGETS DESTINATION) calls in example projects install where we tell them to.
set(CMAKE_INSTALL_PREFIX
"${CMAKE_INSTALL_PREFIX}/${INSTALL_EXAMPLESDIR}/${example_rel_path}")
# Make sure unclean example projects have their INSTALL_EXAMPLEDIR set to "."
# Won't have any effect on example projects that don't use INSTALL_EXAMPLEDIR.
# This plus the install prefix above takes care of installing examples where we want them to
# be installed, while allowing us to remove INSTALL_EXAMPLEDIR code in each example
# incrementally.
# TODO: Remove once all repositories use qt_internal_add_example instead of add_subdirectory.
set(QT_INTERNAL_SET_EXAMPLE_INSTALL_DIR_TO_DOT ON)
add_subdirectory(${subdir} ${ARGN})
endfunction()

View File

@ -55,3 +55,5 @@ endif()
if(EMSCRIPTEN)
include("${CMAKE_CURRENT_LIST_DIR}/@QT_CMAKE_EXPORT_NAMESPACE@WasmMacros.cmake")
endif()
_qt_internal_override_example_install_dir_to_dot()

View File

@ -2205,6 +2205,16 @@ if(NOT QT_NO_CREATE_VERSIONLESS_FUNCTIONS)
endfunction()
endif()
# TODO: Remove once all repositories use qt_internal_add_example instead of add_subdirectory.
macro(_qt_internal_override_example_install_dir_to_dot)
# Set INSTALL_EXAMPLEDIR to ".".
# This overrides the install destination of unclean Qt example projects to install directly
# to CMAKE_INSTALL_PREFIX.
if(QT_INTERNAL_SET_EXAMPLE_INSTALL_DIR_TO_DOT)
set(INSTALL_EXAMPLEDIR ".")
endif()
endmacro()
function(qt6_allow_non_utf8_sources target)
set_target_properties("${target}" PROPERTIES QT_NO_UTF8_SOURCE TRUE)
endfunction()