> In my experience, I found that many projects install files using
> absolute paths, even when they should be installed using a path relative
> to the CMAKE_INSTALL_PREFIX. This makes it impossible to package them
> using CPack without large modification of the cmake code.

Maybe others will disagree but to be quite honest I myself don't think
that CMAKE_INSTALL_RELATIVE variable would be the right solution... I
myself prefer to write install commands with relative paths and I
guess that something like that should be fixed in CMakeLists.txt and
contributed to projects that use absolute paths and not add a new
variable for doing this... (maybe someone decided to leave some paths
absolute for a reason e.g. symlinks or system/program requirements for
certain files).

> Moreover it makes it hard to install only one component in a different
> prefix, for example using:
>
>   cmake -DCMAKE_PREFIX_PATH=/new/prefix -DCOMPONENT=foo \
>     -P cmake_install.cmake

This is again something that can be solved by using for e.g.
GNUInstallDirs.cmake module and adding the paths set in this module to
paths provided to install commands.

As for CPack and different locations... I don't know about other
packagers but for RPM packages I wrote a patch a few weeks ago that
uses GNUInstallDirs.cmake and provides option to have more than one
relocation path per RPM package. The reason that I haven't contributed
it yet is that I still have to write tests for the code (I'll do this
in the following days) before submitting the patch for review.

Preview patch is attached.

Regards,
Domen
From 2d5289559527371e3fce555d49b20e6789d1324c Mon Sep 17 00:00:00 2001
From: Domen Vrankar <[email protected]>
Date: Mon, 22 Dec 2014 21:22:34 +0100
Subject: [PATCH] multiple path relocation prefixes

Allow multiple path relocation prefixes for a single rpm package.
---
 Modules/CPackRPM.cmake       | 108 ++++++++++++++++++++++++++++++++++++++-----
 Modules/GNUInstallDirs.cmake |   2 +
 2 files changed, 99 insertions(+), 11 deletions(-)

diff --git a/Modules/CPackRPM.cmake b/Modules/CPackRPM.cmake
index d2cb2ee..cf058c5 100644
--- a/Modules/CPackRPM.cmake
+++ b/Modules/CPackRPM.cmake
@@ -395,6 +395,83 @@
 
 # Author: Eric Noulard with the help of Alexander Neundorf.
 
+function(cpack_rpm_prepare_relocation_paths)
+  set(RPM_RELOCATION_PATH_VARS
+      CPACK_PACKAGING_INSTALL_FULL_BINDIR CPACK_PACKAGING_INSTALL_FULL_SBINDIR
+      CPACK_PACKAGING_INSTALL_FULL_LIBEXECDIR CPACK_PACKAGING_INSTALL_FULL_SYSCONFDIR
+      CPACK_PACKAGING_INSTALL_FULL_SHAREDSTATEDIR CPACK_PACKAGING_INSTALL_FULL_LOCALSTATEDIR
+      CPACK_PACKAGING_INSTALL_FULL_LIBDIR CPACK_PACKAGING_INSTALL_FULL_INCLUDEDIR
+      CPACK_PACKAGING_INSTALL_FULL_OLDINCLUDEDIR CPACK_PACKAGING_INSTALL_FULL_DATAROOTDIR
+      CPACK_PACKAGING_INSTALL_FULL_DATADIR CPACK_PACKAGING_INSTALL_FULL_INFODIR
+      CPACK_PACKAGING_INSTALL_FULL_LOCALEDIR CPACK_PACKAGING_INSTALL_FULL_MANDIR
+      CPACK_PACKAGING_INSTALL_FULL_DOCDIR)
+  file(TO_CMAKE_PATH "${CPACK_PACKAGING_INSTALL_PREFIX}" RPM_PACKAGE_PREFIX_PART)
+
+  if(CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_PREFIX)
+    # remove possible trailing slash and convert backslashes to slashes
+    file(TO_CMAKE_PATH "${CPACK_RPM_${CPACK_RPM_PACKAGE_COMPONENT}_PACKAGE_PREFIX}" RPM_COMPONENT_PREFIX_)
+    string(LENGTH "${RPM_PACKAGE_PREFIX_PART}" RPM_PACKAGE_PREFIX_PART_LEN)
+    set(RPM_PACKAGE_PREFIXES "${RPM_COMPONENT_PREFIX_}")
+
+    foreach(RELOCATE_PATH_VAR ${RPM_RELOCATION_PATH_VARS})
+      if(${RELOCATE_PATH_VAR})
+        # check if path is a subpath of CPACK_PACKAGING_INSTALL_PREFIX
+        file(RELATIVE_PATH REL_PATH_ "${RPM_PACKAGE_PREFIX_PART}" "${${RELOCATE_PATH_VAR}}")
+        string(SUBSTRING "${REL_PATH_}" 0 2 PREFIX_)
+
+        if("${PREFIX_}" STREQUAL "..") # not a subpath - leave it as is
+          file(TO_CMAKE_PATH "${${RELOCATE_PATH_VAR}}" RELOCATE_PATH)
+          list(APPEND RPM_PACKAGE_PREFIXES "${RELOCATE_PATH}")
+        else() # a subpath - it should be replaced with component path
+          list(APPEND RPM_PACKAGE_PREFIXES "${RPM_COMPONENT_PREFIX_}/${REL_PATH_}")
+        endif()
+      endif()
+    endforeach()
+  else()
+    set(RPM_PACKAGE_PREFIXES "${RPM_PACKAGE_PREFIX_PART}")
+    foreach(RELOCATE_PATH_VAR ${RPM_RELOCATION_PATH_VARS})
+      if(${RELOCATE_PATH_VAR})
+        file(TO_CMAKE_PATH "${${RELOCATE_PATH_VAR}}" RELOCATE_PATH)
+        list(APPEND RPM_PACKAGE_PREFIXES "${RELOCATE_PATH}")
+      endif()
+    endforeach()
+  endif()
+
+  list(REMOVE_DUPLICATES RPM_PACKAGE_PREFIXES)
+
+  # remove all the paths that are not used
+  foreach(RELOCATION_PATH ${RPM_PACKAGE_PREFIXES})
+    if(EXISTS "${WDIR}/${RELOCATION_PATH}")
+      set(TMP_RPM_PREFIXES "${TMP_RPM_PREFIXES}Prefix: ${RELOCATION_PATH}\n")
+      list(APPEND RPM_USED_PACKAGE_PREFIXES "${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 +713,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
+    cpack_rpm_prepare_relocation_paths()
   endif()
 endif()
 
@@ -856,15 +936,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 +1187,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\@
diff --git a/Modules/GNUInstallDirs.cmake b/Modules/GNUInstallDirs.cmake
index c61e7e9..75c6081 100644
--- a/Modules/GNUInstallDirs.cmake
+++ b/Modules/GNUInstallDirs.cmake
@@ -276,7 +276,9 @@ foreach(dir
     )
   if(NOT IS_ABSOLUTE ${CMAKE_INSTALL_${dir}})
     set(CMAKE_INSTALL_FULL_${dir} "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_${dir}}")
+    set(CPACK_PACKAGING_INSTALL_FULL_${dir} "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_${dir}}")
   else()
     set(CMAKE_INSTALL_FULL_${dir} "${CMAKE_INSTALL_${dir}}")
+    set(CPACK_PACKAGING_INSTALL_FULL_${dir} "${CMAKE_INSTALL_${dir}}")
   endif()
 endforeach()
-- 
2.1.0

-- 

Powered by www.kitware.com

Please keep messages on-topic and check the CMake FAQ at: 
http://www.cmake.org/Wiki/CMake_FAQ

Kitware offers various services to support the CMake community. For more 
information on each offering, please visit:

CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html

Visit other Kitware open-source projects at 
http://www.kitware.com/opensource/opensource.html

Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake-developers

Reply via email to