瀏覽代碼

CPack/DEB: Add option to select archive type

Add a `CPACK_DEBIAN_ARCHIVE_TYPE` option that can be used to select an
archive type that supports long file names.

Closes: #14332
Domen Vrankar 9 年之前
父節點
當前提交
4ffdd564eb

+ 6 - 0
Help/release/dev/cpack-deb-long-filenames.rst

@@ -0,0 +1,6 @@
+cpack-deb-long-filenames
+------------------------
+
+* The :module:`CPackDeb` module learned to support long file names
+  when archive format is set to GNU tar.
+  See :variable:`CPACK_DEBIAN_ARCHIVE_TYPE`

+ 32 - 1
Modules/CPackDeb.cmake

@@ -177,6 +177,24 @@
 #
 #  See https://www.debian.org/doc/debian-policy/ch-archive.html#s-subsections
 #
+# .. variable:: CPACK_DEBIAN_ARCHIVE_TYPE
+#
+#  The archive format used for creating the Debian package.
+#
+#  * Mandatory : YES
+#  * Default   : "paxr"
+#
+#  Possible values are:
+#
+#  - paxr
+#  - gnutar
+#
+#  .. note::
+#
+#    Default pax archive format is the most portable format and generates
+#    packages that do not treat sparse files specially.
+#    GNU tar format on the other hand supports longer filenames.
+#
 # .. variable:: CPACK_DEBIAN_COMPRESSION_TYPE
 #
 #  The compression used for creating the Debian package.
@@ -842,12 +860,24 @@ function(cpack_deb_prepare_package_vars)
     set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
   endif()
 
+  if(CPACK_DEBIAN_ARCHIVE_TYPE)
+    set(archive_types_ "paxr;gnutar")
+    cmake_policy(PUSH)
+      cmake_policy(SET CMP0057 NEW)
+      if(NOT CPACK_DEBIAN_ARCHIVE_TYPE IN_LIST archive_types_)
+        message(FATAL_ERROR "CPACK_DEBIAN_ARCHIVE_TYPE set to unsupported"
+          "type ${CPACK_DEBIAN_ARCHIVE_TYPE}")
+      endif()
+    cmake_policy(POP)
+  else()
+    set(CPACK_DEBIAN_ARCHIVE_TYPE "paxr")
+  endif()
+
   # Compression: (recommended)
   if(NOT CPACK_DEBIAN_COMPRESSION_TYPE)
     set(CPACK_DEBIAN_COMPRESSION_TYPE "gzip")
   endif()
 
-
   # Recommends:
   # You should set: CPACK_DEBIAN_PACKAGE_RECOMMENDS
 
@@ -1000,6 +1030,7 @@ function(cpack_deb_prepare_package_vars)
   set(GEN_CPACK_DEBIAN_PACKAGE_MAINTAINER "${CPACK_DEBIAN_PACKAGE_MAINTAINER}" PARENT_SCOPE)
   set(GEN_CPACK_DEBIAN_PACKAGE_DESCRIPTION "${CPACK_DEBIAN_PACKAGE_DESCRIPTION}" PARENT_SCOPE)
   set(GEN_CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}" PARENT_SCOPE)
+  set(GEN_CPACK_DEBIAN_ARCHIVE_TYPE "${CPACK_DEBIAN_ARCHIVE_TYPE}" PARENT_SCOPE)
   set(GEN_CPACK_DEBIAN_COMPRESSION_TYPE "${CPACK_DEBIAN_COMPRESSION_TYPE}" PARENT_SCOPE)
   set(GEN_CPACK_DEBIAN_PACKAGE_RECOMMENDS "${CPACK_DEBIAN_PACKAGE_RECOMMENDS}" PARENT_SCOPE)
   set(GEN_CPACK_DEBIAN_PACKAGE_SUGGESTS "${CPACK_DEBIAN_PACKAGE_SUGGESTS}" PARENT_SCOPE)

+ 10 - 2
Source/CPack/cmCPackDebGenerator.cxx

@@ -419,6 +419,12 @@ int cmCPackDebGenerator::createDeb()
                     << debian_compression_type << std::endl);
   }
 
+  const char* debian_archive_type =
+    this->GetOption("GEN_CPACK_DEBIAN_ARCHIVE_TYPE");
+  if (!debian_archive_type) {
+    debian_archive_type = "paxr";
+  }
+
   std::string filename_data_tar =
     strGenWDIR + "/data.tar" + compression_suffix;
 
@@ -431,7 +437,8 @@ int cmCPackDebGenerator::createDeb()
                       << filename_data_tar << "\" for writing" << std::endl);
       return 0;
     }
-    cmArchiveWrite data_tar(fileStream_data_tar, tar_compression_type, "paxr");
+    cmArchiveWrite data_tar(fileStream_data_tar, tar_compression_type,
+                            debian_archive_type);
 
     // uid/gid should be the one of the root user, and this root user has
     // always uid/gid equal to 0.
@@ -535,7 +542,8 @@ int cmCPackDebGenerator::createDeb()
       return 0;
     }
     cmArchiveWrite control_tar(fileStream_control_tar,
-                               cmArchiveWrite::CompressGZip, "paxr");
+                               cmArchiveWrite::CompressGZip,
+                               debian_archive_type);
 
     // sets permissions and uid/gid for the files
     control_tar.SetUIDAndGID(0u, 0u);

+ 5 - 0
Tests/RunCMake/CPack/DEB/LONG_FILENAMES-ExpectedFiles.cmake

@@ -0,0 +1,5 @@
+set(whitespaces_ "[\t\n\r ]*")
+
+set(EXPECTED_FILES_COUNT "1")
+set(EXPECTED_FILE_1 "long_filenames_0.1.1-1_*.deb")
+set(EXPECTED_FILE_CONTENT_1 "^.*/usr/${whitespaces_}.*/usr/foo/${whitespaces_}.*/usr/foo/llllllllll_oooooooooo_nnnnnnnnnn_gggggggggg_ffffffffff_iiiiiiiiii_llllllllll_eeeeeeeeee_nnnnnnnnnn_aaaaaaaaaa_mmmmmmmmmm_eeeeeeeeee.txt$")

+ 7 - 0
Tests/RunCMake/CPack/DEB/LONG_FILENAMES-Prerequirements.cmake

@@ -0,0 +1,7 @@
+function(get_test_prerequirements found_var)
+  find_program(FAKEROOT_EXECUTABLE NAMES fakeroot)
+
+  if(FAKEROOT_EXECUTABLE)
+    set(${found_var} true PARENT_SCOPE)
+  endif()
+endfunction()

+ 26 - 0
Tests/RunCMake/CPack/DEB/LONG_FILENAMES-VerifyResult.cmake

@@ -0,0 +1,26 @@
+# create structure required by non root dpkg install
+file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/root_dir")
+file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/root_dir/admindir")
+file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/root_dir/admindir/updates")
+file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/root_dir/admindir/info")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/root_dir/admindir/available" "")
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/root_dir/admindir/status" "")
+
+# some programs used by fakeroot require sbin in path so we should not
+# leave this to chance (programs: ldconfig and start-stop-daemon)
+set(ENV{PATH} "$ENV{PATH}:/usr/local/sbin:/usr/sbin:/sbin")
+
+execute_process(COMMAND ${FAKEROOT_EXECUTABLE} ${DPKG_EXECUTABLE}
+      -i --force-not-root --root=${CMAKE_CURRENT_BINARY_DIR}/root_dir
+      --admindir=${CMAKE_CURRENT_BINARY_DIR}/root_dir/admindir
+      --log=${CMAKE_CURRENT_BINARY_DIR}/root_dir/dpkg.log
+      ${FOUND_FILE_1}
+    RESULT_VARIABLE install_result_
+    ERROR_VARIABLE install_error_
+    OUTPUT_QUIET
+  )
+
+if(install_result_)
+  message(FATAL_ERROR "LONG_FILENAMES package error -  result:"
+    " '${install_result_}'; text: '${install_error_}'")
+endif()

+ 3 - 0
Tests/RunCMake/CPack/DEB/LONG_FILENAMES-specifics.cmake

@@ -0,0 +1,3 @@
+set(CPACK_PACKAGE_CONTACT "someone")
+set(CPACK_DEBIAN_FILE_NAME "DEB-DEFAULT")
+set(CPACK_DEBIAN_ARCHIVE_TYPE "gnutar")

+ 7 - 0
Tests/RunCMake/CPack/DEB/Prerequirements.cmake

@@ -5,4 +5,11 @@ function(get_test_prerequirements found_var config_file)
     file(WRITE "${config_file}" "set(DPKG_EXECUTABLE \"${DPKG_EXECUTABLE}\")")
     set(${found_var} true PARENT_SCOPE)
   endif()
+
+  # optional tool for some tests
+  find_program(FAKEROOT_EXECUTABLE fakeroot)
+  if(FAKEROOT_EXECUTABLE)
+    file(APPEND "${config_file}"
+      "\nset(FAKEROOT_EXECUTABLE \"${FAKEROOT_EXECUTABLE}\")")
+  endif()
 endfunction()

+ 10 - 0
Tests/RunCMake/CPack/LONG_FILENAMES.cmake

@@ -0,0 +1,10 @@
+set(LONG_FILENAME
+  "${CMAKE_CURRENT_BINARY_DIR}/llllllllll_oooooooooo_nnnnnnnnnn_gggggggggg_ffffffffff_iiiiiiiiii_llllllllll_eeeeeeeeee_nnnnnnnnnn_aaaaaaaaaa_mmmmmmmmmm_eeeeeeeeee.txt")
+
+file(WRITE
+  "${LONG_FILENAME}"
+  "long_filename_test")
+
+install(FILES ${LONG_FILENAME} DESTINATION foo)
+
+set(CPACK_PACKAGE_NAME "long_filenames")

+ 1 - 0
Tests/RunCMake/CPack/RunCMakeTest.cmake

@@ -17,3 +17,4 @@ run_cpack_test(INSTALL_SCRIPTS "RPM" false)
 run_cpack_test(DEB_GENERATE_SHLIBS "DEB" true)
 run_cpack_test(DEB_GENERATE_SHLIBS_LDCONFIG "DEB" true)
 run_cpack_test(DEBUGINFO "RPM" true)
+run_cpack_test(LONG_FILENAMES "DEB" false)