Commit 681f3a2f authored by Domen Vrankar's avatar Domen Vrankar Committed by Brad King

CPackRPM: Add basic symlink support (#15209)

RPM packages can contain symbolic links to relative paths - including
support for multiple relocation paths through generation of post install
relocation scripts.  Add basic support with limitations described in
documentation.
parent c1f8c6cd
This diff is collapsed.
......@@ -991,6 +991,7 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
${build_generator_args}
--build-project CPackComponentsForAll
--build-options ${build_options}
-DCPACK_GENERATOR:STRING=${CPackGen}
-DCPACK_BINARY_${CPackGen}:BOOL=ON
${CPackRun_CPackComponentWay}
${CPackComponentsForAll_BUILD_OPTIONS}
......
......@@ -49,6 +49,44 @@ install(FILES mylib.h
DESTINATION include
COMPONENT headers)
if("${CPACK_GENERATOR}" MATCHES "RPM")
# Package symbolic links
install(DIRECTORY DESTINATION ${CMAKE_INSTALL_LIBDIR}/inside_relocatable_one/depth_two/depth_three COMPONENT libraries)
install(DIRECTORY DESTINATION ${CMAKE_INSTALL_LIBDIR}/inside_relocatable_two/depth_two/different_relocatable/bar COMPONENT libraries)
install(DIRECTORY DESTINATION other_relocatable/depth_two COMPONENT libraries)
install(DIRECTORY DESTINATION non_relocatable/depth_two COMPONENT libraries)
# test symbolic links to same dir
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink depth_three symlink_samedir_path)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/symlink_samedir_path DESTINATION ${CMAKE_INSTALL_LIBDIR}/inside_relocatable_one/depth_two COMPONENT libraries)
# test symbolic links to same dir with current dir ./ prefix
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink ./depth_three symlink_samedir_path_current_dir)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/symlink_samedir_path_current_dir DESTINATION ${CMAKE_INSTALL_LIBDIR}/inside_relocatable_one/depth_two COMPONENT libraries)
# test symbolic links to same dir with longer relative path
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink ../../../${CMAKE_INSTALL_LIBDIR}/.././${CMAKE_INSTALL_LIBDIR}/inside_relocatable_one/./depth_two/depth_three symlink_samedir_path_longer)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/symlink_samedir_path_longer DESTINATION ${CMAKE_INSTALL_LIBDIR}/inside_relocatable_one/depth_two COMPONENT libraries)
# test symbolic links to sub dir
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink ../../${CMAKE_INSTALL_LIBDIR}/inside_relocatable_one/depth_two/depth_three symlink_subdir_path)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/symlink_subdir_path DESTINATION ${CMAKE_INSTALL_LIBDIR}/inside_relocatable_one COMPONENT libraries)
# test symbolic links to parent dir
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink .././../../../${CMAKE_INSTALL_LIBDIR}/inside_relocatable_one/./depth_two symlink_parentdir_path)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/symlink_parentdir_path DESTINATION ${CMAKE_INSTALL_LIBDIR}/inside_relocatable_one/depth_two/depth_three COMPONENT libraries)
# test symbolic link to another relocatable path
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink .././.././../other_relocatable/./depth_two symlink_other_relocatable_path)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/symlink_other_relocatable_path DESTINATION ${CMAKE_INSTALL_LIBDIR}/inside_relocatable_two/depth_two COMPONENT libraries)
# test symbolic link to non relocatable path
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink .././../../non_relocatable/./depth_two symlink_to_non_relocatable_path)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/symlink_to_non_relocatable_path DESTINATION ${CMAKE_INSTALL_LIBDIR}/inside_relocatable_two/depth_two COMPONENT libraries)
# test symbolic link from non relocatable path
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink .././../${CMAKE_INSTALL_LIBDIR}/inside_relocatable_two/depth_two symlink_from_non_relocatable_path)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/symlink_from_non_relocatable_path DESTINATION non_relocatable/depth_two COMPONENT libraries)
# test symbolic link relocatable path to its relocatable subpath
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink ../../inside_relocatable_two/depth_two/different_relocatable/bar symlink_relocatable_subpath)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/symlink_relocatable_subpath DESTINATION ${CMAKE_INSTALL_LIBDIR}/inside_relocatable_one/depth_two COMPONENT libraries)
# test symbolic link to location outside package
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink ./outside_package symlink_outside_package)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/symlink_outside_package DESTINATION ${CMAKE_INSTALL_LIBDIR}/inside_relocatable_one/depth_two COMPONENT libraries)
endif()
# CPack boilerplate for this project
set(CPACK_PACKAGE_NAME "MyLib")
set(CPACK_PACKAGE_CONTACT "None")
......@@ -114,7 +152,8 @@ set(CPACK_COMPONENT_APPLICATIONS_INSTALL_TYPES Full)
# can not be used in CPack scripts due to CMAKE_SIZEOF_VOID_P
# variable not being set
set(CPACK_RPM_RELOCATION_PATHS "${CMAKE_INSTALL_INCLUDEDIR}"
"${CMAKE_INSTALL_LIBDIR}" "${CMAKE_INSTALL_BINDIR}")
"${CMAKE_INSTALL_LIBDIR}" "${CMAKE_INSTALL_BINDIR}" "other_relocatable"
"${CMAKE_INSTALL_LIBDIR}/inside_relocatable_two/depth_two/different_relocatable")
# We may use the CPack specific config file in order
# to tailor CPack behavior on a CPack generator specific way
......
# prevent older policies from interfearing with this script
cmake_policy(PUSH)
cmake_policy(VERSION ${CMAKE_VERSION})
message(STATUS "=============================================================================")
message(STATUS "CTEST_FULL_OUTPUT (Avoid ctest truncation of output)")
message(STATUS "")
......@@ -138,6 +142,7 @@ if(CPackGen MATCHES "RPM")
"An extremely useful application that makes use of MyLib")
set(CPACK_COMPONENT_LIBRARIES_DESCRIPTION
"Static libraries used to build programs with MyLib")
set(LIB_SUFFIX "6?4?")
# test package info
if(${CPackComponentWay} STREQUAL "IgnoreGroup")
......@@ -174,10 +179,32 @@ if(CPackGen MATCHES "RPM")
if(check_file_libraries_match)
set(check_file_match_expected_summary ".*${CPACK_RPM_PACKAGE_SUMMARY}.*")
set(check_file_match_expected_description ".*${CPACK_COMPONENT_LIBRARIES_DESCRIPTION}.*")
set(check_file_match_expected_relocation_path "Relocations${whitespaces}:${whitespaces}${CPACK_PACKAGING_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
set(check_file_match_expected_relocation_path "Relocations${whitespaces}:${whitespaces}${CPACK_PACKAGING_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}${LIB_SUFFIX}${whitespaces}${CPACK_PACKAGING_INSTALL_PREFIX}/other_relocatable${whitespaces}${CPACK_PACKAGING_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}${LIB_SUFFIX}/inside_relocatable_two/depth_two/different_relocatable")
set(check_file_match_expected_architecture "") # we don't explicitly set this value so it is different on each platform - ignore it
set(spec_regex "*libraries*")
set(check_content_list "^/usr/foo/bar/lib.*\n/usr/foo/bar/lib.*/libmylib.a$")
set(check_content_list "^/usr/foo/bar/lib${LIB_SUFFIX}
/usr/foo/bar/lib${LIB_SUFFIX}/inside_relocatable_one
/usr/foo/bar/lib${LIB_SUFFIX}/inside_relocatable_one/depth_two
/usr/foo/bar/lib${LIB_SUFFIX}/inside_relocatable_one/depth_two/depth_three
/usr/foo/bar/lib${LIB_SUFFIX}/inside_relocatable_one/depth_two/depth_three/symlink_parentdir_path
/usr/foo/bar/lib${LIB_SUFFIX}/inside_relocatable_one/depth_two/symlink_outside_package
/usr/foo/bar/lib${LIB_SUFFIX}/inside_relocatable_one/depth_two/symlink_relocatable_subpath
/usr/foo/bar/lib${LIB_SUFFIX}/inside_relocatable_one/depth_two/symlink_samedir_path
/usr/foo/bar/lib${LIB_SUFFIX}/inside_relocatable_one/depth_two/symlink_samedir_path_current_dir
/usr/foo/bar/lib${LIB_SUFFIX}/inside_relocatable_one/depth_two/symlink_samedir_path_longer
/usr/foo/bar/lib${LIB_SUFFIX}/inside_relocatable_one/symlink_subdir_path
/usr/foo/bar/lib${LIB_SUFFIX}/inside_relocatable_two
/usr/foo/bar/lib${LIB_SUFFIX}/inside_relocatable_two/depth_two
/usr/foo/bar/lib${LIB_SUFFIX}/inside_relocatable_two/depth_two/different_relocatable
/usr/foo/bar/lib${LIB_SUFFIX}/inside_relocatable_two/depth_two/different_relocatable/bar
/usr/foo/bar/lib${LIB_SUFFIX}/inside_relocatable_two/depth_two/symlink_other_relocatable_path
/usr/foo/bar/lib${LIB_SUFFIX}/inside_relocatable_two/depth_two/symlink_to_non_relocatable_path
/usr/foo/bar/lib${LIB_SUFFIX}/libmylib.a
/usr/foo/bar/non_relocatable
/usr/foo/bar/non_relocatable/depth_two
/usr/foo/bar/non_relocatable/depth_two/symlink_from_non_relocatable_path
/usr/foo/bar/other_relocatable
/usr/foo/bar/other_relocatable/depth_two$")
elseif(check_file_headers_match)
set(check_file_match_expected_summary ".*${CPACK_RPM_headers_PACKAGE_SUMMARY}.*")
set(check_file_match_expected_description ".*${CPACK_RPM_headers_PACKAGE_DESCRIPTION}.*")
......@@ -188,10 +215,12 @@ if(CPackGen MATCHES "RPM")
elseif(check_file_applications_match)
set(check_file_match_expected_summary ".*${CPACK_RPM_PACKAGE_SUMMARY}.*")
set(check_file_match_expected_description ".*${CPACK_COMPONENT_APPLICATIONS_DESCRIPTION}.*")
set(check_file_match_expected_relocation_path "Relocations${whitespaces}:${whitespaces}${CPACK_PACKAGING_INSTALL_PREFIX}${whitespaces}${CPACK_PACKAGING_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}.*")
set(check_file_match_expected_relocation_path "Relocations${whitespaces}:${whitespaces}${CPACK_PACKAGING_INSTALL_PREFIX}${whitespaces}${CPACK_PACKAGING_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}")
set(check_file_match_expected_architecture "armv7hf")
set(spec_regex "*applications*")
set(check_content_list "^/usr/foo/bar\n/usr/foo/bar/bin\n/usr/foo/bar/bin/mylibapp$")
set(check_content_list "^/usr/foo/bar
/usr/foo/bar/bin
/usr/foo/bar/bin/mylibapp$")
elseif(check_file_Unspecified_match)
set(check_file_match_expected_summary ".*${CPACK_RPM_PACKAGE_SUMMARY}.*")
set(check_file_match_expected_description ".*DESCRIPTION.*")
......@@ -269,5 +298,59 @@ if(CPackGen MATCHES "RPM")
message(FATAL_ERROR "error: '${check_file}' rpm package content does not match expected value - regex '${check_content_list}'; RPM output: '${check_package_content}'; generated spec file: '${spec_file_content}'")
endif()
endforeach()
#######################
# verify generated symbolic links
#######################
file(GLOB_RECURSE symlink_files RELATIVE "${CPackComponentsForAll_BINARY_DIR}" "${CPackComponentsForAll_BINARY_DIR}/*/symlink_*")
foreach(check_symlink IN LISTS symlink_files)
get_filename_component(symlink_name "${check_symlink}" NAME)
execute_process(COMMAND ls -la "${check_symlink}"
WORKING_DIRECTORY "${CPackComponentsForAll_BINARY_DIR}"
OUTPUT_VARIABLE SYMLINK_POINT_
OUTPUT_STRIP_TRAILING_WHITESPACE)
if("${symlink_name}" STREQUAL "symlink_samedir_path"
OR "${symlink_name}" STREQUAL "symlink_samedir_path_current_dir"
OR "${symlink_name}" STREQUAL "symlink_samedir_path_longer")
string(REGEX MATCH "^.*${whitespaces}->${whitespaces}depth_three$" check_symlink "${SYMLINK_POINT_}")
elseif("${symlink_name}" STREQUAL "symlink_subdir_path")
string(REGEX MATCH "^.*${whitespaces}->${whitespaces}depth_two/depth_three$" check_symlink "${SYMLINK_POINT_}")
elseif("${symlink_name}" STREQUAL "symlink_parentdir_path")
string(REGEX MATCH "^.*${whitespaces}->${whitespaces}../$" check_symlink "${SYMLINK_POINT_}")
elseif("${symlink_name}" STREQUAL "symlink_to_non_relocatable_path")
string(REGEX MATCH "^.*${whitespaces}->${whitespaces}${CPACK_PACKAGING_INSTALL_PREFIX}/non_relocatable/depth_two$" check_symlink "${SYMLINK_POINT_}")
elseif("${symlink_name}" STREQUAL "symlink_outside_package")
string(REGEX MATCH "^.*${whitespaces}->${whitespaces}outside_package$" check_symlink "${SYMLINK_POINT_}")
elseif("${symlink_name}" STREQUAL "symlink_other_relocatable_path"
OR "${symlink_name}" STREQUAL "symlink_from_non_relocatable_path"
OR "${symlink_name}" STREQUAL "symlink_relocatable_subpath")
# these links were not canged - post install script only - ignore them
else()
message(FATAL_ERROR "error: unexpected rpm symbolic link '${check_symlink}'")
endif()
if(NOT check_symlink)
message(FATAL_ERROR "symlink points to unexpected location '${SYMLINK_POINT_}'")
endif()
endforeach()
# verify post install symlink relocation script
file(GLOB_RECURSE spec_file "${CPackComponentsForAll_BINARY_DIR}/*libraries*.spec")
file(READ ${spec_file} spec_file_content)
file(READ "${CMAKE_CURRENT_LIST_DIR}/symlink_postinstall_expected.txt" symlink_postinstall_expected)
# prepare regex
string(STRIP "${symlink_postinstall_expected}" symlink_postinstall_expected)
string(REPLACE "[" "\\[" symlink_postinstall_expected "${symlink_postinstall_expected}")
string(REPLACE "$" "\\$" symlink_postinstall_expected "${symlink_postinstall_expected}")
string(REPLACE "lib" "lib${LIB_SUFFIX}" symlink_postinstall_expected "${symlink_postinstall_expected}")
# compare
string(REGEX MATCH ".*${symlink_postinstall_expected}.*" symlink_postinstall_expected_matches "${spec_file_content}")
if(NOT symlink_postinstall_expected_matches)
message(FATAL_ERROR "error: unexpected rpm symbolic link postinstall script! generated spec file: '${spec_file_content}'")
endif()
endif()
endif()
cmake_policy(POP)
if [ "$RPM_INSTALL_PREFIX0" != "/usr/foo/bar/lib" ]; then
if [ "$RPM_INSTALL_PREFIX1" != "/usr/foo/bar/other_relocatable" ]; then
if [ -z "$CPACK_RPM_RELOCATED_SYMLINK_1" ]; then
ln -s "$RPM_INSTALL_PREFIX1/depth_two" "$RPM_INSTALL_PREFIX0/inside_relocatable_two/depth_two/symlink_other_relocatable_path"
CPACK_RPM_RELOCATED_SYMLINK_1=true
fi
fi
if [ "$RPM_INSTALL_PREFIX2" != "/usr/foo/bar/lib/inside_relocatable_two/depth_two/different_relocatable" ]; then
if [ -z "$CPACK_RPM_RELOCATED_SYMLINK_0" ]; then
ln -s "$RPM_INSTALL_PREFIX2/bar" "$RPM_INSTALL_PREFIX0/inside_relocatable_one/depth_two/symlink_relocatable_subpath"
CPACK_RPM_RELOCATED_SYMLINK_0=true
fi
fi
if [ -z "$CPACK_RPM_RELOCATED_SYMLINK_0" ]; then
ln -s "$RPM_INSTALL_PREFIX0/inside_relocatable_two/depth_two/different_relocatable/bar" "$RPM_INSTALL_PREFIX0/inside_relocatable_one/depth_two/symlink_relocatable_subpath"
CPACK_RPM_RELOCATED_SYMLINK_0=true
fi
if [ -z "$CPACK_RPM_RELOCATED_SYMLINK_0" ]; then
ln -s "/usr/foo/bar/lib/inside_relocatable_two/depth_two/different_relocatable/bar" "$RPM_INSTALL_PREFIX0/inside_relocatable_one/depth_two/symlink_relocatable_subpath"
CPACK_RPM_RELOCATED_SYMLINK_0=true
fi
if [ -z "$CPACK_RPM_RELOCATED_SYMLINK_1" ]; then
ln -s "/usr/foo/bar/other_relocatable/depth_two" "$RPM_INSTALL_PREFIX0/inside_relocatable_two/depth_two/symlink_other_relocatable_path"
CPACK_RPM_RELOCATED_SYMLINK_1=true
fi
fi
if [ "$RPM_INSTALL_PREFIX1" != "/usr/foo/bar/other_relocatable" ]; then
if [ -z "$CPACK_RPM_RELOCATED_SYMLINK_1" ]; then
ln -s "$RPM_INSTALL_PREFIX1/depth_two" "/usr/foo/bar/lib/inside_relocatable_two/depth_two/symlink_other_relocatable_path"
CPACK_RPM_RELOCATED_SYMLINK_1=true
fi
fi
if [ "$RPM_INSTALL_PREFIX2" != "/usr/foo/bar/lib/inside_relocatable_two/depth_two/different_relocatable" ]; then
if [ -z "$CPACK_RPM_RELOCATED_SYMLINK_0" ]; then
ln -s "$RPM_INSTALL_PREFIX2/bar" "/usr/foo/bar/lib/inside_relocatable_one/depth_two/symlink_relocatable_subpath"
CPACK_RPM_RELOCATED_SYMLINK_0=true
fi
fi
if [ "$RPM_INSTALL_PREFIX0" != "/usr/foo/bar/lib" ]; then
if [ -z "$CPACK_RPM_RELOCATED_SYMLINK_0" ]; then
ln -s "$RPM_INSTALL_PREFIX0/inside_relocatable_two/depth_two/different_relocatable/bar" "/usr/foo/bar/lib/inside_relocatable_one/depth_two/symlink_relocatable_subpath"
CPACK_RPM_RELOCATED_SYMLINK_0=true
fi
if [ -z "$CPACK_RPM_RELOCATED_SYMLINK_2" ]; then
ln -s "$RPM_INSTALL_PREFIX0/inside_relocatable_two/depth_two" "/usr/foo/bar/non_relocatable/depth_two/symlink_from_non_relocatable_path"
CPACK_RPM_RELOCATED_SYMLINK_2=true
fi
fi
if [ -z "$CPACK_RPM_RELOCATED_SYMLINK_0" ]; then
ln -s "/usr/foo/bar/lib/inside_relocatable_two/depth_two/different_relocatable/bar" "/usr/foo/bar/lib/inside_relocatable_one/depth_two/symlink_relocatable_subpath"
fi
if [ -z "$CPACK_RPM_RELOCATED_SYMLINK_1" ]; then
ln -s "/usr/foo/bar/other_relocatable/depth_two" "/usr/foo/bar/lib/inside_relocatable_two/depth_two/symlink_other_relocatable_path"
fi
if [ -z "$CPACK_RPM_RELOCATED_SYMLINK_2" ]; then
ln -s "/usr/foo/bar/lib/inside_relocatable_two/depth_two" "/usr/foo/bar/non_relocatable/depth_two/symlink_from_non_relocatable_path"
fi
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment