diff options
Diffstat (limited to 'cmake/QtInstallHelpers.cmake')
-rw-r--r-- | cmake/QtInstallHelpers.cmake | 178 |
1 files changed, 127 insertions, 51 deletions
diff --git a/cmake/QtInstallHelpers.cmake b/cmake/QtInstallHelpers.cmake index 9dbb22251d..deab48cda5 100644 --- a/cmake/QtInstallHelpers.cmake +++ b/cmake/QtInstallHelpers.cmake @@ -1,3 +1,6 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + # Wraps install() command. In a prefix build, simply passes along arguments to install(). # In a non-prefix build, handles association of targets to export names, and also calls export(). function(qt_install) @@ -18,14 +21,18 @@ function(qt_install) install(${ARGV}) endif() - # Exit early if this is a prefix build. - if(QT_WILL_INSTALL) - return() - endif() - - # In a non-prefix build, when install(EXPORT) is called, - # also call export(EXPORT) to generate build tree target files. + # When install(EXPORT) is called, also call export(EXPORT) + # to generate build tree target files. if(NOT is_install_targets AND arg_EXPORT) + # For prefixed builds (both top-level and per-repo) export build tree CMake Targets files so + # they can be used in CMake ExternalProjects. One such case is examples built as + # ExternalProjects as part of the Qt build. + # In a top-level build the exported config files are placed under qtbase/lib/cmake. + # In a per-repo build, they will be placed in each repo's build dir/lib/cmake. + if(QT_WILL_INSTALL) + qt_path_join(arg_DESTINATION "${QT_BUILD_DIR}" "${arg_DESTINATION}") + endif() + set(namespace_option "") if(arg_NAMESPACE) set(namespace_option NAMESPACE ${arg_NAMESPACE}) @@ -88,50 +95,27 @@ function(qt_copy_or_install) qt_non_prefix_copy(COPY ${argv_copy} ${copy_arguments}) endfunction() -# Hacky way to remove the install target in non-prefix builds. -# We need to associate targets with export names, and that is only possible to do with the -# install(TARGETS) command. But in a non-prefix build, we don't want to install anything. -# To make sure that developers don't accidentally run make install, replace the generated -# cmake_install.cmake file with an empty file. To do this, always create a new temporary file -# at CMake configuration step, and use it as an input to a custom command that replaces the -# cmake_install.cmake file with an empty one. This means we will always replace the file on -# every reconfiguration, but not when doing null builds. -function(qt_remove_install_target) - # On superbuilds we only do this for qtbase - it will correctly remove the - # cmake_install.cmake at the root of the repository. - if(QT_SUPERBUILD) - if(NOT (PROJECT_NAME STREQUAL "QtBase")) - return() - endif() - endif() - - set(file_in "${CMAKE_BINARY_DIR}/.remove_cmake_install_in.txt") - set(file_generated "${CMAKE_BINARY_DIR}/.remove_cmake_install_generated.txt") - set(cmake_install_file "${CMAKE_BINARY_DIR}/cmake_install.cmake") - file(WRITE ${file_in} "") - - add_custom_command(OUTPUT ${file_generated} - COMMAND ${CMAKE_COMMAND} -E copy ${file_in} ${file_generated} - COMMAND ${CMAKE_COMMAND} -E remove ${cmake_install_file} - COMMAND ${CMAKE_COMMAND} -E touch ${cmake_install_file} - COMMENT "Removing cmake_install.cmake" - MAIN_DEPENDENCY ${file_in}) - - add_custom_target(remove_cmake_install ALL DEPENDS ${file_generated}) -endfunction() - -function(qt_set_up_nonprefix_build) - if(NOT QT_WILL_INSTALL) - qt_remove_install_target() - endif() -endfunction() - -# Create a versioned hard-link for the given target. +# Create a versioned hard-link for the given target, or a program # E.g. "bin/qmake6" -> "bin/qmake". -# If no hard link can be created, make a copy instead. +# +# One-value Arguments: +# WORKING_DIRECTORY +# The directory where the original file is already placed. +# SUFFIX +# The program file extension, only used for PROGRAMS +# Multi-value Arguments: +# TARGETS +# List of targets for which the versioned link will be created. +# If targets are given, BASE_NAME and SUFFIX will be derived from it. +# PROGRAMS +# List of program file names for which the versioned link will be created. +# +# +# NOTE: This assumes that TARGETS, or PROGRAMS are already installed in the +# WORKING_DIRECTORY. # # In a multi-config build, create the link for the main config only. -function(qt_internal_install_versioned_link install_dir target) +function(qt_internal_install_versioned_link) if(NOT QT_WILL_INSTALL) return() endif() @@ -140,13 +124,41 @@ function(qt_internal_install_versioned_link install_dir target) return() endif() + set(options) + set(oneValueArgs "WORKING_DIRECTORY;SUFFIX") + set(multiValueArgs "TARGETS;PROGRAMS") + cmake_parse_arguments(arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(arg_TARGETS) + foreach(target "${arg_TARGETS}") + _qt_internal_create_versioned_link_or_copy("${arg_WORKING_DIRECTORY}" + $<TARGET_FILE_BASE_NAME:${target}> + $<TARGET_FILE_SUFFIX:${target}>) + endforeach() + endif() + + if(arg_PROGRAMS) + foreach(program "${arg_PROGRAMS}") + _qt_internal_create_versioned_link_or_copy("${arg_WORKING_DIRECTORY}" + "${program}" + "${arg_SUFFIX}") + endforeach() + endif() +endfunction() + +# Generate a script for creating a hard-link between the base_name, and +# base_name${PROJECT_VERSION_MAJOR}. +# +# If no hard link can be created, make a copy instead. +function(_qt_internal_create_versioned_link_or_copy install_dir base_name suffix) qt_path_join(install_base_file_path "$\{qt_full_install_prefix}" - "${install_dir}" "$<TARGET_FILE_BASE_NAME:${target}>") - set(original "${install_base_file_path}$<TARGET_FILE_SUFFIX:${target}>") - set(linkname "${install_base_file_path}${PROJECT_VERSION_MAJOR}$<TARGET_FILE_SUFFIX:${target}>") + "${install_dir}" "${base_name}") + set(original "${install_base_file_path}${suffix}") + set(linkname "${install_base_file_path}${PROJECT_VERSION_MAJOR}${suffix}") set(code "set(qt_full_install_prefix \"$\{CMAKE_INSTALL_PREFIX}\")" " if(NOT \"$ENV\{DESTDIR}\" STREQUAL \"\")" ) + if(CMAKE_HOST_WIN32) list(APPEND code " if(qt_full_install_prefix MATCHES \"^[a-zA-Z]:\")" @@ -171,3 +183,67 @@ function(qt_internal_install_versioned_link install_dir target) list(JOIN code "\n" code) install(CODE "${code}") endfunction() + +# Use case is copying files or directories in a non-prefix build with each build, so that changes +# are available each time, this is useful for some Android templates that are needed for building, +# apks and need to sync changes each time a build is started +function(qt_internal_copy_at_build_time) + set(flags) + set(options TARGET DESTINATION) + set(multiopts FILES DIRECTORIES) + cmake_parse_arguments(arg "${flags}" "${options}" "${multiopts}" ${ARGN}) + + file(MAKE_DIRECTORY "${arg_DESTINATION}") + + unset(outputs) + foreach(dir_to_copy IN LISTS arg_DIRECTORIES) + get_filename_component(file_name "${dir_to_copy}" NAME) + set(destination_file_name "${arg_DESTINATION}/${file_name}") + + file(GLOB_RECURSE all_files_in_dir RELATIVE "${dir_to_copy}" "${dir_to_copy}/*") + set(dir_outputs ${all_files_in_dir}) + set(dir_deps ${all_files_in_dir}) + + list(TRANSFORM dir_outputs PREPEND "${destination_file_name}/") + list(TRANSFORM dir_deps PREPEND "${dir_to_copy}/") + + add_custom_command(OUTPUT ${dir_outputs} + COMMAND ${CMAKE_COMMAND} -E copy_directory ${dir_to_copy} "${destination_file_name}" + DEPENDS ${dir_deps} + COMMENT "Copying directory ${dir_to_copy} to ${arg_DESTINATION}." + ) + list(APPEND outputs ${dir_outputs}) + endforeach() + + unset(file_outputs) + unset(files_to_copy) + foreach(path_to_copy IN LISTS arg_FILES) + get_filename_component(file_name "${path_to_copy}" NAME) + set(destination_file_name "${arg_DESTINATION}/${file_name}") + + list(APPEND file_outputs "${destination_file_name}") + list(APPEND files_to_copy "${path_to_copy}") + endforeach() + + if(files_to_copy) + add_custom_command(OUTPUT ${file_outputs} + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${files_to_copy} ${arg_DESTINATION} + DEPENDS ${files_to_copy} + COMMENT "Copying files ${files_to_copy} to ${arg_DESTINATION}." + ) + list(APPEND outputs ${file_outputs}) + endif() + + get_property(count GLOBAL PROPERTY _qt_internal_copy_at_build_time_count) + if(NOT count) + set(count 0) + endif() + + add_custom_target(qt_internal_copy_at_build_time_${count} DEPENDS ${outputs}) + if(arg_TARGET) + add_dependencies(${arg_TARGET} qt_internal_copy_at_build_time_${count}) + endif() + + math(EXPR count "${count} + 1") + set_property(GLOBAL PROPERTY _qt_internal_copy_at_build_time_count ${count}) +endfunction() |