Commit 3ec02547 authored by Domen Vrankar's avatar Domen Vrankar Committed by Brad King

CPackRPM: Allow multiple path relocation prefixes for one package

parent 8c4b7c56
rpm_multi_prefix
----------------
* The :module:`CPackRPM` module learned a new
:variable:`CPACK_RPM_<COMPONENT>_PACKAGE_PREFIX` variable to
specify a component-specific value to use instead of
:variable:`CPACK_PACKAGING_INSTALL_PREFIX`.
* The :module:`CPackRPM` module learned a new
:variable:`CPACK_RPM_RELOCATION_PATHS` variable to
specify multiple relocation prefixes for a single rpm package.
......@@ -379,6 +379,34 @@
#
# May be used to add more exclude path (directories or files) from the initial
# default list of excluded paths. See CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST.
#
# .. variable:: CPACK_RPM_RELOCATION_PATHS
#
# * Mandatory : NO
# * Default : -
#
# May be used to specify more than one relocation path per relocatable RPM.
# Variable contains a list of relocation paths that if relative are prefixed
# by the value of CPACK_RPM_<COMPONENT>_PACKAGE_PREFIX or by the value of
# CPACK_PACKAGING_INSTALL_PREFIX if the component version is not provided.
# Variable is not component based as its content can be used to set a different
# path prefix for e.g. binary dir and documentation dir at the same time.
# Only prefixes that are required by a certain component are added to that
# component - component must contain at least one file/directory/symbolic link
# with CPACK_RPM_RELOCATION_PATHS prefix for a certain relocation path
# to be added. Package will not contain any relocation paths if there are no
# files/directories/symbolic links on any of the provided prefix locations.
# Packages that either do not contain any relocation paths or contain
# files/directories/symbolic links that are outside relocation paths print
# out an AUTHOR_WARNING that RPM will be partially relocatable.
#
# .. variable:: CPACK_RPM_<COMPONENT>_PACKAGE_PREFIX
#
# * Mandatory : NO
# * Default : CPACK_PACKAGING_INSTALL_PREFIX
#
# May be used to set per component CPACK_PACKAGING_INSTALL_PREFIX for
# relocatable RPM packages.
#=============================================================================
# Copyright 2007-2009 Kitware, Inc.
......@@ -395,6 +423,62 @@
# Author: Eric Noulard with the help of Alexander Neundorf.
function(cpack_rpm_prepare_relocation_paths)
# set appropriate prefix, remove possible trailing slash and convert backslashes to slashes
if(CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_PREFIX)
file(TO_CMAKE_PATH "${CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_PREFIX}" PATH_PREFIX)
else()
file(TO_CMAKE_PATH "${CPACK_PACKAGING_INSTALL_PREFIX}" PATH_PREFIX)
endif()
set(RPM_RELOCATION_PATHS "${CPACK_RPM_RELOCATION_PATHS}")
list(REMOVE_DUPLICATES RPM_RELOCATION_PATHS)
# set base path prefix
if(EXISTS "${WDIR}/${PATH_PREFIX}")
set(TMP_RPM_PREFIXES "${TMP_RPM_PREFIXES}Prefix: ${PATH_PREFIX}\n")
list(APPEND RPM_USED_PACKAGE_PREFIXES "${PATH_PREFIX}")
endif()
# set other path prefixes
foreach(RELOCATION_PATH ${RPM_RELOCATION_PATHS})
if(IS_ABSOLUTE "${RELOCATE_PATH}")
set(PREPARED_RELOCATION_PATH "${RELOCATION_PATH}")
else()
set(PREPARED_RELOCATION_PATH "${PATH_PREFIX}/${RELOCATION_PATH}")
endif()
if(EXISTS "${WDIR}/${PREPARED_RELOCATION_PATH}")
set(TMP_RPM_PREFIXES "${TMP_RPM_PREFIXES}Prefix: ${PREPARED_RELOCATION_PATH}\n")
list(APPEND RPM_USED_PACKAGE_PREFIXES "${PREPARED_RELOCATION_PATH}")
endif()
endforeach()
# warn about all the paths that are not relocatable
file(GLOB_RECURSE FILE_PATHS_ "${WDIR}/*")
foreach(TMP_PATH ${FILE_PATHS_})
string(LENGTH "${WDIR}" WDIR_LEN)
string(SUBSTRING "${TMP_PATH}" ${WDIR_LEN} -1 TMP_PATH)
unset(TMP_PATH_FOUND_)
foreach(RELOCATION_PATH ${RPM_USED_PACKAGE_PREFIXES})
file(RELATIVE_PATH REL_PATH_ "${RELOCATION_PATH}" "${TMP_PATH}")
string(SUBSTRING "${REL_PATH_}" 0 2 PREFIX_)
if(NOT "${PREFIX_}" STREQUAL "..")
set(TPM_PATH_FOUND_ TRUE)
break()
endif()
endforeach()
if(NOT TPM_PATH_FOUND_)
message(AUTHOR_WARNING "CPackRPM:Warning: Path ${TMP_PATH} is not on one of the relocatable paths! Package will be partially relocatable.")
endif()
endforeach()
set(TMP_RPM_PREFIXES "${TMP_RPM_PREFIXES}" PARENT_SCOPE)
endfunction()
if(CMAKE_BINARY_DIR)
message(FATAL_ERROR "CPackRPM.cmake may only be used by CPack internally.")
endif()
......@@ -636,13 +720,16 @@ if(CPACK_PACKAGE_RELOCATABLE)
set(CPACK_RPM_PACKAGE_RELOCATABLE TRUE)
endif()
if(CPACK_RPM_PACKAGE_RELOCATABLE)
unset(TMP_RPM_PREFIXES)
if(CPACK_RPM_PACKAGE_DEBUG)
message("CPackRPM:Debug: Trying to build a relocatable package")
endif()
if(CPACK_SET_DESTDIR AND (NOT CPACK_SET_DESTDIR STREQUAL "I_ON"))
message("CPackRPM:Warning: CPACK_SET_DESTDIR is set (=${CPACK_SET_DESTDIR}) while requesting a relocatable package (CPACK_RPM_PACKAGE_RELOCATABLE is set): this is not supported, the package won't be relocatable.")
else()
set(CPACK_RPM_PACKAGE_PREFIX ${CPACK_PACKAGING_INSTALL_PREFIX})
set(CPACK_RPM_PACKAGE_PREFIX ${CPACK_PACKAGING_INSTALL_PREFIX}) # kept for back compatibility (provided external RPM spec files)
cpack_rpm_prepare_relocation_paths()
endif()
endif()
......@@ -856,15 +943,21 @@ if(CPACK_RPM_PACKAGE_RELOCATABLE)
# get a list of the elements in CPACK_RPM_PACKAGE_PREFIX and remove
# the final element (so the install-prefix dir itself is not omitted
# from the RPM's content-list)
string(REPLACE "/" ";" _CPACK_RPM_PACKAGE_PREFIX_ELEMS ".${CPACK_RPM_PACKAGE_PREFIX}")
list(REMOVE_AT _CPACK_RPM_PACKAGE_PREFIX_ELEMS -1)
# Now generate all of the parent dirs of CPACK_RPM_PACKAGE_PREFIX
foreach(_ELEM ${_CPACK_RPM_PACKAGE_PREFIX_ELEMS})
list(APPEND _TMP_LIST "${_ELEM}")
string(REPLACE ";" "/" _OMIT_DIR "${_TMP_LIST}")
set(_OMIT_DIR "-o -path ${_OMIT_DIR}")
separate_arguments(_OMIT_DIR)
list(APPEND _RPM_DIRS_TO_OMIT ${_OMIT_DIR})
foreach(CPACK_RPM_PACKAGE_PREFIX ${RPM_PACKAGE_PREFIXES})
string(REPLACE "/" ";" _CPACK_RPM_PACKAGE_PREFIX_ELEMS ".${CPACK_RPM_PACKAGE_PREFIX}")
list(REMOVE_AT _CPACK_RPM_PACKAGE_PREFIX_ELEMS -1)
unset(_TMP_LIST)
# Now generate all of the parent dirs of CPACK_RPM_PACKAGE_PREFIX
foreach(_ELEM ${_CPACK_RPM_PACKAGE_PREFIX_ELEMS})
list(APPEND _TMP_LIST "${_ELEM}")
string(REPLACE ";" "/" _OMIT_DIR "${_TMP_LIST}")
list(FIND _RPM_DIRS_TO_OMIT "${_OMIT_DIR}" _DUPLICATE_FOUND)
if(_DUPLICATE_FOUND EQUAL -1)
set(_OMIT_DIR "-o -path ${_OMIT_DIR}")
separate_arguments(_OMIT_DIR)
list(APPEND _RPM_DIRS_TO_OMIT ${_OMIT_DIR})
endif()
endforeach()
endforeach()
endif()
......@@ -1101,7 +1194,7 @@ Vendor: \@CPACK_RPM_PACKAGE_VENDOR\@
\@TMP_RPM_AUTOREQ\@
\@TMP_RPM_AUTOREQPROV\@
\@TMP_RPM_BUILDARCH\@
\@TMP_RPM_PREFIX\@
\@TMP_RPM_PREFIXES\@
%define _rpmdir \@CPACK_RPM_DIRECTORY\@
%define _rpmfilename \@CPACK_RPM_FILE_NAME\@
......
......@@ -110,6 +110,12 @@ set(CPACK_COMPONENT_LIBRARIES_INSTALL_TYPES Developer Full)
set(CPACK_COMPONENT_HEADERS_INSTALL_TYPES Developer Full)
set(CPACK_COMPONENT_APPLICATIONS_INSTALL_TYPES Full)
# set CPACK_RPM_RELOCATION_PATHS here as GNUInstallDirs script
# 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}")
# We may use the CPack specific config file in order
# to tailor CPack behavior on a CPack generator specific way
# (Behavior would be different for RPM or TGZ or DEB ...)
......
......@@ -6,15 +6,17 @@ if(CPACK_GENERATOR MATCHES "ZIP")
endif()
if(CPACK_GENERATOR MATCHES "RPM")
set(CPACK_RPM_COMPONENT_INSTALL "ON")
set(CPACK_RPM_applications_PACKAGE_REQUIRES "mylib-libraries")
set(CPACK_PACKAGING_INSTALL_PREFIX "/usr")
# test package summary override
set(CPACK_RPM_PACKAGE_SUMMARY "default summary")
set(CPACK_RPM_libraries_PACKAGE_SUMMARY "libraries summary")
set(CPACK_RPM_COMPONENT_INSTALL "ON")
set(CPACK_RPM_applications_PACKAGE_REQUIRES "mylib-libraries")
# test package description override
set(CPACK_RPM_libraries_PACKAGE_DESCRIPTION "libraries description")
# test package summary override
set(CPACK_RPM_PACKAGE_SUMMARY "default summary")
set(CPACK_RPM_libraries_PACKAGE_SUMMARY "libraries summary")
# test package description override
set(CPACK_RPM_libraries_PACKAGE_DESCRIPTION "libraries description")
endif()
if(CPACK_GENERATOR MATCHES "DEB")
......
......@@ -140,6 +140,12 @@ if(CPackGen MATCHES "RPM")
"C/C\\+\\+ header files for use with MyLib")
if(${CPackComponentWay} STREQUAL "IgnoreGroup")
# set gnu install prefixes to what they are set during rpm creation
# CMAKE_SIZEOF_VOID_P is not set here but lib is prefix of lib64 so
# relocation path test won't fail on OSes with lib64 library location
include(GNUInstallDirs)
set(CPACK_PACKAGING_INSTALL_PREFIX "/usr")
foreach(check_file ${expected_file})
string(REGEX MATCH ".*libraries.*" check_file_libraries_match ${check_file})
string(REGEX MATCH ".*headers.*" check_file_headers_match ${check_file})
......@@ -154,15 +160,23 @@ if(CPackGen MATCHES "RPM")
if(check_file_libraries_match)
set(check_file_match_expected_summary ".*${CPACK_RPM_libraries_PACKAGE_SUMMARY}.*")
set(check_file_match_expected_description ".*${CPACK_RPM_libraries_PACKAGE_DESCRIPTION}.*")
set(check_file_match_expected_relocation_path "Relocations : ${CPACK_PACKAGING_INSTALL_PREFIX} ${CPACK_PACKAGING_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
set(spec_regex "*libraries*")
elseif(check_file_headers_match)
set(check_file_match_expected_summary ".*${CPACK_RPM_PACKAGE_SUMMARY}.*")
set(check_file_match_expected_description ".*${CPACK_COMPONENT_HEADERS_DESCRIPTION}.*")
set(check_file_match_expected_relocation_path "Relocations : ${CPACK_PACKAGING_INSTALL_PREFIX} ${CPACK_PACKAGING_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}")
set(spec_regex "*headers*")
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 : ${CPACK_PACKAGING_INSTALL_PREFIX} ${CPACK_PACKAGING_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}")
set(spec_regex "*applications*")
elseif(check_file_Unspecified_match)
set(check_file_match_expected_summary ".*${CPACK_RPM_PACKAGE_SUMMARY}.*")
set(check_file_match_expected_description ".*DESCRIPTION.*")
set(check_file_match_expected_relocation_path "Relocations : ${CPACK_PACKAGING_INSTALL_PREFIX} ${CPACK_PACKAGING_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}")
set(spec_regex "*Unspecified*")
else()
message(FATAL_ERROR "error: unexpected rpm package '${check_file}'")
endif()
......@@ -170,13 +184,25 @@ if(CPackGen MATCHES "RPM")
string(REGEX MATCH ${check_file_match_expected_summary} check_file_match_summary ${check_file_content})
if(NOT check_file_match_summary)
message(FATAL_ERROR "error: '${check_file}' rpm package summary does not match expected value - regex '${check_file_match_expected_summary}'")
message(FATAL_ERROR "error: '${check_file}' rpm package summary does not match expected value - regex '${check_file_match_expected_summary}'; RPM output: '${check_file_content}'")
endif()
string(REGEX MATCH ${check_file_match_expected_description} check_file_match_description ${check_file_content})
if(NOT check_file_match_description)
message(FATAL_ERROR "error: '${check_file}' rpm package description does not match expected value - regex '${check_file_match_expected_description}'")
message(FATAL_ERROR "error: '${check_file}' rpm package description does not match expected value - regex '${check_file_match_expected_description}'; RPM output: '${check_file_content}'")
endif()
string(REGEX MATCH ${check_file_match_expected_relocation_path} check_file_match_relocation_path ${check_file_content})
if(NOT check_file_match_relocation_path)
file(GLOB_RECURSE spec_file "${CPackComponentsForAll_BINARY_DIR}/${spec_regex}.spec")
if(spec_file)
file(READ ${spec_file} spec_file_content)
endif()
message(FATAL_ERROR "error: '${check_file}' rpm package relocation path does not match expected value - regex '${check_file_match_expected_relocation_path}'; RPM output: '${check_file_content}'; generated spec file: '${spec_file_content}'")
endif()
endforeach()
elseif(${CPackComponentWay} STREQUAL "IgnoreGroup")
......
......@@ -173,3 +173,7 @@ add_RunCMake_test(CommandLine)
add_RunCMake_test(install)
add_RunCMake_test(CPackInstallProperties)
add_RunCMake_test(ExternalProject)
if(RPMBUILD)
add_RunCMake_test(CPackRPM)
endif()
cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)
set(CPACK_GENERATOR "RPM")
include(CPack)
CPackRPM:Warning: Path /not_relocatable/CMakeLists.txt is not on one of the.*relocatable paths! Package will be partially relocatable.
install(FILES CMakeLists.txt DESTINATION /not_relocatable COMPONENT static)
install(FILES CMakeLists.txt DESTINATION relocatable COMPONENT relocatable)
set(CPACK_PACKAGE_RELOCATABLE TRUE)
set(CPACK_PACKAGING_INSTALL_PREFIX "/opt")
set(CPACK_RPM_COMPONENT_INSTALL ON)
include(RunCMake)
function(run_cpack_rpm_test TEST_NAME)
set(RunCMake_TEST_NO_CLEAN TRUE)
set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/${TEST_NAME}-build")
file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
execute_process(
COMMAND "${CMAKE_COMMAND}" -D RunCMake_TEST=${TEST_NAME} "${RunCMake_SOURCE_DIR}"
WORKING_DIRECTORY "${RunCMake_TEST_BINARY_DIR}"
OUTPUT_QUIET
ERROR_QUIET
)
run_cmake_command(${TEST_NAME} ${CMAKE_CPACK_COMMAND})
endfunction()
run_cpack_rpm_test(CPackRPM_PARTIALLY_RELOCATABLE_WARNING)
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