From 9f444ce5335d0e7a0978879d9441975de549e20b Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Fri, 26 Feb 2021 11:04:00 +0100 Subject: Add a way to install versioned hard-links for tools Add the option argument INSTALL_VERSIONED_LINK to qt_internal_add_tool and qt_internal_add_app. For tools/apps with this argument we create an install rule that creates a versioned hard link. For example, for bin/qmake we create bin/qmake6. Note that this only applies to prefix builds. Apply this argument to qmake. The qt_internal_add_app change is necessary for qtdiag and in qttools. Task-number: QTBUG-89170 Change-Id: Id32d6055544c475166f4d854aaeb6292fbb5fbb5 Reviewed-by: Alexandru Croitor (cherry picked from commit c19d957f45fa27f61b5ecc566f8dbc19f12a44c3) --- cmake/QtAppHelpers.cmake | 7 ++++++- cmake/QtCMakeHelpers.cmake | 20 ++++++++++++++++++++ cmake/QtInstallHelpers.cmake | 30 ++++++++++++++++++++++++++++++ cmake/QtToolHelpers.cmake | 14 ++++++++++++-- qmake/CMakeLists.txt | 1 + 5 files changed, 69 insertions(+), 3 deletions(-) diff --git a/cmake/QtAppHelpers.cmake b/cmake/QtAppHelpers.cmake index 846a85028f..c40488cc66 100644 --- a/cmake/QtAppHelpers.cmake +++ b/cmake/QtAppHelpers.cmake @@ -3,7 +3,7 @@ function(qt_internal_add_app target) qt_parse_all_arguments(arg "qt_internal_add_app" - "NO_INSTALL" + "NO_INSTALL;INSTALL_VERSIONED_LINK" "${__default_target_info_args}" "${__default_private_args}" ${ARGN}) @@ -52,6 +52,11 @@ function(qt_internal_add_app target) # Consider every app as user facing tool. set_property(GLOBAL APPEND PROPERTY QT_USER_FACING_TOOL_TARGETS ${target}) + # Install versioned link if requested. + if(NOT arg_NO_INSTALL AND arg_INSTALL_VERSIONED_LINK) + qt_internal_install_versioned_link("${INSTALL_BINDIR}" ${target}) + endif() + qt_add_list_file_finalizer(qt_internal_finalize_app ${target}) endfunction() diff --git a/cmake/QtCMakeHelpers.cmake b/cmake/QtCMakeHelpers.cmake index 93513d4369..f9b03d628c 100644 --- a/cmake/QtCMakeHelpers.cmake +++ b/cmake/QtCMakeHelpers.cmake @@ -156,6 +156,26 @@ function(qt_re_escape out_var str) set(${out_var} ${regex} PARENT_SCOPE) endfunction() +# Input: string +# Output: regex string to match the string case insensitively +# Example: "Release" -> "^([Rr][Ee][Ll][Ee][Aa][Ss][Ee])$" +# +# Regular expressions like this are used in cmake_install.cmake files for case-insensitive string +# comparison. +function(qt_create_case_insensitive_regex out_var input) + set(result "^(") + string(LENGTH "${input}" n) + math(EXPR n "${n} - 1") + foreach(i RANGE 0 ${n}) + string(SUBSTRING "${input}" ${i} 1 c) + string(TOUPPER "${c}" uc) + string(TOLOWER "${c}" lc) + string(APPEND result "[${uc}${lc}]") + endforeach() + string(APPEND result ")$") + set(${out_var} "${result}" PARENT_SCOPE) +endfunction() + # Gets a target property, and returns "" if the property was not found function(qt_internal_get_target_property out_var target property) get_target_property(result "${target}" "${property}") diff --git a/cmake/QtInstallHelpers.cmake b/cmake/QtInstallHelpers.cmake index 5832df144c..1f1fb84634 100644 --- a/cmake/QtInstallHelpers.cmake +++ b/cmake/QtInstallHelpers.cmake @@ -125,3 +125,33 @@ function(qt_set_up_nonprefix_build) qt_remove_install_target() endif() endfunction() + +# Create a versioned hard-link for the given target. +# E.g. "bin/qmake6" -> "bin/qmake". +# If no hard link can be created, make a copy instead. +# +# In a multi-config build, create the link for the main config only. +function(qt_internal_install_versioned_link install_dir target) + if(NOT QT_WILL_INSTALL) + return() + endif() + + qt_path_join(install_base_file_path "$ENV\{DESTDIR}$\{CMAKE_INSTALL_PREFIX}" + "${install_dir}" "$") + set(original "${install_base_file_path}$") + set(linkname "${install_base_file_path}${PROJECT_VERSION_MAJOR}$") + set(code + "message(STATUS \"Creating hard link ${original} -> ${linkname}\")" + "file(CREATE_LINK \"${original}\" \"${linkname}\" COPY_ON_ERROR)") + + if(QT_GENERATOR_IS_MULTI_CONFIG) + # Wrap the code in a configuration check, + # because install(CODE) does not support a CONFIGURATIONS argument. + qt_create_case_insensitive_regex(main_config_regex ${QT_MULTI_CONFIG_FIRST_CONFIG}) + list(PREPEND code "if(\"\${CMAKE_INSTALL_CONFIG_NAME}\" MATCHES \"${main_config_regex}\")") + list(APPEND code "endif()") + endif() + + list(JOIN code "\n" code) + install(CODE "${code}") +endfunction() diff --git a/cmake/QtToolHelpers.cmake b/cmake/QtToolHelpers.cmake index 5fcc539b56..21687f5ec1 100644 --- a/cmake/QtToolHelpers.cmake +++ b/cmake/QtToolHelpers.cmake @@ -10,7 +10,12 @@ # qt_get_tool_target_name(target_name my_tool) # qt_internal_add_tool(${target_name}) # -# Arguments: +# Option Arguments: +# INSTALL_VERSIONED_LINK +# Prefix build only. On installation, create a versioned hard-link of the installed file. +# E.g. create a link of "bin/qmake6" to "bin/qmake". +# +# One-value Arguments: # EXTRA_CMAKE_FILES # List of additional CMake files that will be installed alongside the tool's exported CMake # files. @@ -23,9 +28,10 @@ # function(qt_internal_add_tool target_name) qt_tool_target_to_name(name ${target_name}) + set(option_keywords BOOTSTRAP NO_INSTALL USER_FACING INSTALL_VERSIONED_LINK) set(one_value_keywords TOOLS_TARGET EXTRA_CMAKE_FILES INSTALL_DIR ${__default_target_info_args}) - qt_parse_all_arguments(arg "qt_internal_add_tool" "BOOTSTRAP;NO_INSTALL;USER_FACING" + qt_parse_all_arguments(arg "qt_internal_add_tool" "${option_keywords}" "${one_value_keywords}" "${__default_private_args}" ${ARGN}) @@ -224,6 +230,10 @@ function(qt_internal_add_tool target_name) unset(install_initial_call_args) endforeach() + if(arg_INSTALL_VERSIONED_LINK) + qt_internal_install_versioned_link("${install_dir}" "${target_name}") + endif() + qt_apply_rpaths(TARGET "${target_name}" INSTALL_PATH "${install_dir}" RELATIVE_RPATH) endif() diff --git a/qmake/CMakeLists.txt b/qmake/CMakeLists.txt index b89cf25f10..688314b736 100644 --- a/qmake/CMakeLists.txt +++ b/qmake/CMakeLists.txt @@ -47,6 +47,7 @@ qt_get_tool_target_name(target_name qmake) qt_internal_add_tool(${target_name} TOOLS_TARGET Core # special case USER_FACING + INSTALL_VERSIONED_LINK SOURCES cachekeys.h generators/mac/pbuilder_pbx.cpp generators/mac/pbuilder_pbx.h -- cgit v1.2.3