From 5b87a5d53e20849f89ce9b8372a6a9a688318c4b Mon Sep 17 00:00:00 2001 From: AJIOB Date: Mon, 1 Dec 2025 08:40:46 +0300 Subject: [PATCH] cli tar: implement LZMA support Fixes: #27433 --- Help/command/file.rst | 18 +++++- Help/manual/cmake.1.rst | 6 ++ Help/release/dev/cli-tar-lzma.rst | 12 ++++ Modules/CTestCoverageCollectGCOV.cmake | 64 ++++++++++++++++--- Source/cmFileCommand.cxx | 2 + Source/cmSystemTools.cxx | 3 + Source/cmSystemTools.h | 1 + Source/cmcmd.cxx | 3 + Tests/CTestCoverageCollectGCOV/test.cmake.in | 62 ++++++++++++++++++ .../CommandLineTar/RunCMakeTest.cmake | 1 + Tests/RunCMake/CommandLineTar/pax-lzma.cmake | 10 +++ .../RunCMake/File_Archive/RunCMakeTest.cmake | 2 + Tests/RunCMake/File_Archive/pax-lzma.cmake | 8 +++ Tests/RunCMake/File_Archive/pax-lzma2.cmake | 8 +++ 14 files changed, 190 insertions(+), 10 deletions(-) create mode 100644 Help/release/dev/cli-tar-lzma.rst create mode 100644 Tests/RunCMake/CommandLineTar/pax-lzma.cmake create mode 100644 Tests/RunCMake/File_Archive/pax-lzma.cmake create mode 100644 Tests/RunCMake/File_Archive/pax-lzma2.cmake diff --git a/Help/command/file.rst b/Help/command/file.rst index 52725902c2..f439b4fab9 100644 --- a/Help/command/file.rst +++ b/Help/command/file.rst @@ -938,7 +938,23 @@ Archiving The ``7zip`` and ``zip`` archive formats already imply a specific type of compression. The other formats use no compression by default, but can be directed to do so with the ``COMPRESSION`` option. Valid values for - ```` are ``None``, ``BZip2``, ``GZip``, ``XZ``, and ``Zstd``. + ```` are: + + * ``None`` + * ``BZip2`` + * ``GZip`` + * ``LZMA`` + + .. versionadded:: 4.3 + + * ``LZMA2`` + + .. versionadded:: 4.3 + + This is an alias for ``XZ``. + + * ``XZ`` + * ``Zstd`` .. note:: With ``FORMAT`` set to ``raw``, only one file will be compressed diff --git a/Help/manual/cmake.1.rst b/Help/manual/cmake.1.rst index 437440c140..d5d5c74e72 100644 --- a/Help/manual/cmake.1.rst +++ b/Help/manual/cmake.1.rst @@ -1468,6 +1468,12 @@ Available commands are: Compress the resulting archive with Zstandard. + .. option:: --lzma + + .. versionadded:: 4.3 + + Compress the resulting archive with LZMA algorithm. + .. option:: --files-from= .. versionadded:: 3.1 diff --git a/Help/release/dev/cli-tar-lzma.rst b/Help/release/dev/cli-tar-lzma.rst new file mode 100644 index 0000000000..c5a75cd980 --- /dev/null +++ b/Help/release/dev/cli-tar-lzma.rst @@ -0,0 +1,12 @@ +cli-tar-lzma +------------ + +* The :manual:`cmake(1)` ``-E tar`` tool supports support ``LZMA`` compression + via ``--lzma`` option. +* The :command:`file(ARCHIVE_CREATE)` command's ``COMPRESSION`` option, + supports ``LZMA`` and ``LZMA2`` compression. The ``LZMA2`` compression is + an alias for ``XZ``. +* The :module:`CTestCoverageCollectGCOV` supports ``LZMA`` and ``LZMA2`` compression. + The ``LZMA2`` compression is an alias for ``XZ``. +* The :module:`CTestCoverageCollectGCOV` supports ``LZMA`` and ``ZSTD`` compression + file extensions for ``FROM_EXT`` compression mode. diff --git a/Modules/CTestCoverageCollectGCOV.cmake b/Modules/CTestCoverageCollectGCOV.cmake index 4c1211f5db..f36c0222d8 100644 --- a/Modules/CTestCoverageCollectGCOV.cmake +++ b/Modules/CTestCoverageCollectGCOV.cmake @@ -65,14 +65,53 @@ This module provides the following command: Specify a compression algorithm for the ``TARBALL`` data file. Using this option reduces the size of the data file - before it is submitted to CDash. ```` must be one of ``GZIP``, - ``BZIP2``, ``XZ``, ``ZSTD``, ``FROM_EXT``, or an expression that CMake - evaluates as ``FALSE``. The default value is ``BZIP2``. + before it is submitted to CDash. + ```` should be one of the following: + + * ``GZIP`` + * ``BZIP2`` + * ``LZMA`` + + .. versionadded:: 4.3 + + * ``LZMA2`` + + .. versionadded:: 4.3 + + This is an alias for ``XZ``. + + * ``XZ`` + * ``ZSTD`` + * ``FROM_EXT`` + * An expression that CMake evaluates as ``FALSE`` + + The default value is ``BZIP2``. If ``FROM_EXT`` is specified, the resulting file will be compressed based on the file extension of the ```` (i.e. ``.tar.gz`` will use ``GZIP`` - compression). File extensions that will produce compressed output include - ``.tar.gz``, ``.tgz``, ``.tar.bzip2``, ``.tbz``, ``.tar.xz``, and ``.txz``. + compression). File extensions that will produce compressed output include: + + * ``.tar.gz`` + * ``.tgz`` + * ``.tar.bzip2`` + * ``.tbz`` + * ``.tar.xz`` + * ``.txz`` + * ``.tar.lzma`` + + .. versionadded:: 4.3 + + * ``.tlzma`` + + .. versionadded:: 4.3 + + * ``.tar.zst`` + + .. versionadded:: 4.3 + + * ``.tzst`` + + .. versionadded:: 4.3 ``SOURCE `` Specify the top-level source directory for the build. @@ -152,12 +191,12 @@ function(ctest_coverage_collect_gcov) else() set(gcov_command "${GCOV_GCOV_COMMAND}") endif() + set(supported_compressions "GZIP" "BZIP2" "LZMA" "LZMA2" "XZ" "ZSTD" "FROM_EXT") if(NOT DEFINED GCOV_TARBALL_COMPRESSION) set(GCOV_TARBALL_COMPRESSION "BZIP2") elseif( GCOV_TARBALL_COMPRESSION AND - NOT GCOV_TARBALL_COMPRESSION MATCHES "^(GZIP|BZIP2|XZ|ZSTD|FROM_EXT)$") - message(FATAL_ERROR "TARBALL_COMPRESSION must be one of OFF, GZIP, " - "BZIP2, XZ, ZSTD, or FROM_EXT for ctest_coverage_collect_gcov") + NOT GCOV_TARBALL_COMPRESSION IN_LIST supported_compressions) + message(FATAL_ERROR "TARBALL_COMPRESSION must be OFF or one of ${supported_compressions} for ctest_coverage_collect_gcov") endif() # run gcov on each gcda file in the binary tree set(gcda_files) @@ -341,6 +380,7 @@ ${uncovered_files_for_tar} # Prepare tar command line arguments set(tar_opts "") + set(zstd_tar_opt "") # Select data compression mode if( GCOV_TARBALL_COMPRESSION STREQUAL "FROM_EXT") if( GCOV_TARBALL MATCHES [[\.(tgz|tar.gz)$]] ) @@ -349,15 +389,21 @@ ${uncovered_files_for_tar} string(APPEND tar_opts "J") elseif( GCOV_TARBALL MATCHES [[\.(tbz|tar.bz)$]] ) string(APPEND tar_opts "j") + elseif( GCOV_TARBALL MATCHES [[\.(tlzma|tar.lzma)$]] ) + set(zstd_tar_opt "--lzma") + elseif( GCOV_TARBALL MATCHES [[\.(tzst|tar.zst)$]] ) + set(zstd_tar_opt "--zstd") endif() elseif(GCOV_TARBALL_COMPRESSION STREQUAL "GZIP") string(APPEND tar_opts "z") - elseif(GCOV_TARBALL_COMPRESSION STREQUAL "XZ") + elseif((GCOV_TARBALL_COMPRESSION STREQUAL "XZ") OR (GCOV_TARBALL_COMPRESSION STREQUAL "LZMA2")) string(APPEND tar_opts "J") elseif(GCOV_TARBALL_COMPRESSION STREQUAL "BZIP2") string(APPEND tar_opts "j") elseif(GCOV_TARBALL_COMPRESSION STREQUAL "ZSTD") set(zstd_tar_opt "--zstd") + elseif(GCOV_TARBALL_COMPRESSION STREQUAL "LZMA") + set(zstd_tar_opt "--lzma") endif() # Verbosity options if(NOT GCOV_QUIET AND NOT tar_opts MATCHES v) diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 1f4a6f8e47..2d68d3183c 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -3723,6 +3723,8 @@ bool HandleArchiveCreateCommand(std::vector const& args, compressionTypeMap = { { "None", cmSystemTools::TarCompressNone }, { "BZip2", cmSystemTools::TarCompressBZip2 }, { "GZip", cmSystemTools::TarCompressGZip }, + { "LZMA", cmSystemTools::TarCompressLZMA }, + { "LZMA2", cmSystemTools::TarCompressXZ }, { "XZ", cmSystemTools::TarCompressXZ }, { "Zstd", cmSystemTools::TarCompressZstd } }; diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index ee1dba4731..7009868480 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -2408,6 +2408,9 @@ bool cmSystemTools::CreateTar(std::string const& outFileName, case TarCompressZstd: compress = cmArchiveWrite::CompressZstd; break; + case TarCompressLZMA: + compress = cmArchiveWrite::CompressLZMA; + break; case TarCompressNone: compress = cmArchiveWrite::CompressNone; break; diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 946dea93c2..359bf41826 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -547,6 +547,7 @@ public: { TarCompressGZip, TarCompressBZip2, + TarCompressLZMA, TarCompressXZ, TarCompressZstd, TarCompressNone diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 09c35c0c96..b18995bd52 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -1595,6 +1595,9 @@ int cmcmd::ExecuteCMakeCommand(std::vector const& args, } else if (arg == "--zstd") { compress = cmSystemTools::TarCompressZstd; ++nCompress; + } else if (arg == "--lzma") { + compress = cmSystemTools::TarCompressLZMA; + ++nCompress; } else if (cmHasLiteralPrefix(arg, "--mtime=")) { mtime = arg.substr(8); } else if (cmHasLiteralPrefix(arg, "--files-from=")) { diff --git a/Tests/CTestCoverageCollectGCOV/test.cmake.in b/Tests/CTestCoverageCollectGCOV/test.cmake.in index c19c5c232a..66f1703bf2 100644 --- a/Tests/CTestCoverageCollectGCOV/test.cmake.in +++ b/Tests/CTestCoverageCollectGCOV/test.cmake.in @@ -197,3 +197,65 @@ if("${out}" STREQUAL "${expected_out}") else() message(FATAL_ERROR "FAILED: expected:\n${expected_out}\nGot:\n${out}") endif() + +#------------------------------------------------------------------------------# +# Test 6: with optional argument: TARBALL_COMPRESSION "LZMA" +#------------------------------------------------------------------------------# + +set(tar_file ${CTEST_BINARY_DIRECTORY}/gcov.lzma) +ctest_coverage_collect_gcov( + TARBALL "${tar_file}" + TARBALL_COMPRESSION "LZMA" + SOURCE "${CTEST_SOURCE_DIRECTORY}" + BUILD "${CTEST_BINARY_DIRECTORY}" + GCOV_COMMAND "${CMAKE_COMMAND}" + GCOV_OPTIONS -P "@CMake_SOURCE_DIR@/Tests/CTestCoverageCollectGCOV/fakegcov.cmake") +file(REMOVE_RECURSE "${CTEST_BINARY_DIRECTORY}/uncovered") + +execute_process(COMMAND + ${CMAKE_COMMAND} -E tar tf ${tar_file} + OUTPUT_VARIABLE out + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} + OUTPUT_STRIP_TRAILING_WHITESPACE +) + +string(REPLACE "\n" ";" out "${out}") +to_relative_paths(out "${out}") +list(SORT out) + +if("${out}" STREQUAL "${expected_out}") + message("PASSED with correct output: ${out}") +else() + message(FATAL_ERROR "FAILED: expected:\n${expected_out}\nGot:\n${out}") +endif() + +#------------------------------------------------------------------------------# +# Test 7: with optional argument: TARBALL_COMPRESSION "LZMA2" +#------------------------------------------------------------------------------# + +set(tar_file ${CTEST_BINARY_DIRECTORY}/gcov-lzma2.txz) +ctest_coverage_collect_gcov( + TARBALL "${tar_file}" + TARBALL_COMPRESSION "LZMA2" + SOURCE "${CTEST_SOURCE_DIRECTORY}" + BUILD "${CTEST_BINARY_DIRECTORY}" + GCOV_COMMAND "${CMAKE_COMMAND}" + GCOV_OPTIONS -P "@CMake_SOURCE_DIR@/Tests/CTestCoverageCollectGCOV/fakegcov.cmake") +file(REMOVE_RECURSE "${CTEST_BINARY_DIRECTORY}/uncovered") + +execute_process(COMMAND + ${CMAKE_COMMAND} -E tar tf ${tar_file} + OUTPUT_VARIABLE out + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} + OUTPUT_STRIP_TRAILING_WHITESPACE +) + +string(REPLACE "\n" ";" out "${out}") +to_relative_paths(out "${out}") +list(SORT out) + +if("${out}" STREQUAL "${expected_out}") + message("PASSED with correct output: ${out}") +else() + message(FATAL_ERROR "FAILED: expected:\n${expected_out}\nGot:\n${out}") +endif() diff --git a/Tests/RunCMake/CommandLineTar/RunCMakeTest.cmake b/Tests/RunCMake/CommandLineTar/RunCMakeTest.cmake index a487f372dc..316c0a894b 100644 --- a/Tests/RunCMake/CommandLineTar/RunCMakeTest.cmake +++ b/Tests/RunCMake/CommandLineTar/RunCMakeTest.cmake @@ -26,6 +26,7 @@ run_cmake(7zip) run_cmake(gnutar) run_cmake(gnutar-gz) run_cmake(pax) +run_cmake(pax-lzma) run_cmake(pax-xz) run_cmake(pax-zstd) run_cmake(paxr) diff --git a/Tests/RunCMake/CommandLineTar/pax-lzma.cmake b/Tests/RunCMake/CommandLineTar/pax-lzma.cmake new file mode 100644 index 0000000000..5b716c68ec --- /dev/null +++ b/Tests/RunCMake/CommandLineTar/pax-lzma.cmake @@ -0,0 +1,10 @@ +set(OUTPUT_NAME "test.tar.xz") + +set(COMPRESSION_FLAGS cvf) +set(COMPRESSION_OPTIONS --format=pax --lzma) + +set(DECOMPRESSION_FLAGS xvf) + +include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake) + +check_magic("5d00008000" LIMIT 5 HEX) diff --git a/Tests/RunCMake/File_Archive/RunCMakeTest.cmake b/Tests/RunCMake/File_Archive/RunCMakeTest.cmake index c50476c550..3edba005cd 100644 --- a/Tests/RunCMake/File_Archive/RunCMakeTest.cmake +++ b/Tests/RunCMake/File_Archive/RunCMakeTest.cmake @@ -4,6 +4,8 @@ run_cmake(7zip) run_cmake(gnutar) run_cmake(gnutar-gz) run_cmake(pax) +run_cmake(pax-lzma) +run_cmake(pax-lzma2) run_cmake(pax-xz) run_cmake(pax-zstd) run_cmake(paxr) diff --git a/Tests/RunCMake/File_Archive/pax-lzma.cmake b/Tests/RunCMake/File_Archive/pax-lzma.cmake new file mode 100644 index 0000000000..1cc82cd92a --- /dev/null +++ b/Tests/RunCMake/File_Archive/pax-lzma.cmake @@ -0,0 +1,8 @@ +set(OUTPUT_NAME "test.tar.lzma") + +set(ARCHIVE_FORMAT pax) +set(COMPRESSION_TYPE LZMA) + +include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake) + +check_magic("5d00008000" LIMIT 5 HEX) diff --git a/Tests/RunCMake/File_Archive/pax-lzma2.cmake b/Tests/RunCMake/File_Archive/pax-lzma2.cmake new file mode 100644 index 0000000000..f679b5c428 --- /dev/null +++ b/Tests/RunCMake/File_Archive/pax-lzma2.cmake @@ -0,0 +1,8 @@ +set(OUTPUT_NAME "test.tar.xz") + +set(ARCHIVE_FORMAT pax) +set(COMPRESSION_TYPE LZMA2) + +include(${CMAKE_CURRENT_LIST_DIR}/roundtrip.cmake) + +check_magic("fd377a585a00" LIMIT 6 HEX)