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.

Pick-to: dev
Task-number: QTBUG-89170
Change-Id: Id32d6055544c475166f4d854aaeb6292fbb5fbb5
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
This commit is contained in:
Joerg Bornemann 2021-02-26 11:04:00 +01:00
parent 74b7d5643f
commit c19d957f45
5 changed files with 69 additions and 3 deletions

View File

@ -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()

View File

@ -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}")

View File

@ -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}" "$<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}>")
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()

View File

@ -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_QT 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_QT;NO_INSTALL;USER_FACING"
qt_parse_all_arguments(arg "qt_internal_add_tool" "${option_keywords}"
"${one_value_keywords}"
"${__default_private_args}" ${ARGN})
@ -238,6 +244,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()

View File

@ -9,6 +9,7 @@ qt_internal_add_tool(${target_name}
NO_QT # special case
TOOLS_TARGET Core # special case
USER_FACING
INSTALL_VERSIONED_LINK
SOURCES
../src/3rdparty/pcre2/src/config.h
../src/3rdparty/pcre2/src/pcre2.h