27

tl;博士版本:

是否可以使用 CMake (>= 2.8) 从某些文件生成 zip 文件并将打包的 zip 文件放在特定位置?

更长的版本:

我有一个 CMakeLists.txt,它将我的项目构建成一个 .exe 文件,这个 exe 文件将从 zip 文件中读取数据。要打包到 zip 文件中的内容在我的 git 存储库中,因此也可以对其进行编辑。但是,该程序需要 zip 文件中的这些数据。因此,如果 CMake 脚本可以获取数据,将其放入 zip 文件中,并将其放在 exe 旁边,那就太好了。我已经听说过 CPack,但我没有找到任何简单的示例,并且不确定这是否是适合我任务的工具。

这可能吗?如果是,如何?

4

6 回答 6

32

从 3.2 版开始,CMake 具有生成内置 zip 文件的功能。CMake命令行模式子命令tar支持创建 zip 和 7zip 存档。

例如,如果当前 CMake 源目录包含 filetestfile.txt和 directory testdir,您可以使用以下 CMake 命令创建包含这两个项目的 zip 文件:

add_custom_target(create_zip COMMAND
    ${CMAKE_COMMAND} -E tar "cfv" "archive.zip" --format=zip
       "${CMAKE_CURRENT_SOURCE_DIR}/testfile.txt"
       "${CMAKE_CURRENT_SOURCE_DIR}/testdir")

作为早期 CMake 版本的解决方法,您可以使用作为标准 Java JRE 安装一部分的jar命令。

find_package(Java)

execute_process(
    COMMAND
        "${Java_JAR_EXECUTABLE}" "cfM" "archive.zip" 
        "-C" "${CMAKE_CURRENT_SOURCE_DIR}" "testfile.txt" 
        "-C" "${CMAKE_CURRENT_SOURCE_DIR}" "testdir"
    RESULT_VARIABLE _result
)

zip 文件将在当前 CMake 二进制目录 ( CMAKE_CURRENT_BINARY_DIR) 中生成。

于 2011-08-13T17:12:42.647 回答
11

显示真正的答案永远不会迟到:

function(create_zip output_file input_files working_dir)
    add_custom_command(
        COMMAND ${CMAKE_COMMAND} -E tar "cf" "${output_file}" --format=zip -- ${input_files}
        WORKING_DIRECTORY "${working_dir}"
        OUTPUT  "${output_file}"
        DEPENDS ${input_files}
        COMMENT "Zipping to ${output_file}."
    )
endfunction()

使用喜欢

file(GLOB ZIP_FILES "${CMAKE_CURRENT_SOURCE_DIR}/zip/*")
create_zip("${CMAKE_CURRENT_BINARY_DIR}/native_data.zip" "${ZIP_FILES}" "${CMAKE_CURRENT_SOURCE_DIR}/zip")

zip/这会将子目录中的所有文件打包到native_data.zip(在构建目录中)。然后将您的存档(路径会有所不同CMakeLists.txt!)作为源文件包含在内,或者将其添加为目标:

add_custom_target("project-data" ALL DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/native_data.zip")

安装与平常没有太大区别:

install(FILES "${CMAKE_CURRENT_BINARY_DIR}/native_data.zip" DESTINATION ${DATADIR} RENAME "data000.zip") # Install our zip (as data000.zip)
于 2018-10-29T18:40:44.900 回答
7

我假设您已经安装了 zip 工具(WinZip 或 7z 等)。您可以编写一个 find_zip-tool 脚本来搜索 WinZip 或 7Z 等...

WinZip 的片段:

FIND_PROGRAM(ZIP_EXECUTABLE wzzip PATHS "$ENV{ProgramFiles}/WinZip")
IF(ZIP_EXECUTABLE)
  SET(ZIP_COMMAND "\"${ZIP_EXECUTABLE}\" -P \"<ARCHIVE>\" @<FILELIST>")
ENDIF(ZIP_EXECUTABLE)

7-zip 的片段:

  FIND_PROGRAM(ZIP_EXECUTABLE 7z PATHS "$ENV{ProgramFiles}/7-Zip") 
  IF(ZIP_EXECUTABLE)
    SET(ZIP_COMMAND "\"${ZIP_EXECUTABLE}\" a -tzip \"<ARCHIVE>\" @<FILELIST>")
  ENDIF(ZIP_EXECUTABLE)

看一下文件

<cmake-install-dir>\share\cmake-2.8\Modules\CPackZIP.cmake

它显示了 CPack 如何搜索 Zip_Executable 并准备一些“有用的”默认标志。

之后,我会建议execute_process,类似于sakra的回答

于 2011-08-31T06:56:24.780 回答
5

file()从 3.18 版开始,CMake 现在直接支持使用以下命令创建 zip 或存档文件ARCHIVE_CREATE

file(ARCHIVE_CREATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/MyData.zip
    PATHS ${CMAKE_CURRENT_SOURCE_DIR}/data
    FORMAT zip
)

请务必指定压缩文件名的完整路径OUTPUT,否则可能无法生成文件。此外,该PATHS选项接受要放置在 zip 文件中的文件目录,但在撰写本文时它接受通配符。

此命令支持多种存档格式和压缩风格。因此,您也可以使用相同的命令来创建 tarball:

file(ARCHIVE_CREATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/MyData.tar.gz
    PATHS ${CMAKE_CURRENT_SOURCE_DIR}/data
    FORMAT gnutar
    COMPRESSION GZip
)
于 2020-07-15T13:45:39.060 回答
3

由于这是使用 CMake 创建 zip 文件的热门搜索结果,因此这里有一个 CPack 解决方案以确保完整性。基本的想法是你调用install()然后告诉它如何命名生成的 zip 文件。它将被放置在构建目录中,尽管可能有一种方法可以改变它。make package然后,您可以使用或创建 zip 文件cpack

# Version 1: Subtractive
# Include everything in the project source directory.
# Put it at the top level of the zip via `DESTINATION .`
# Subtract things we don't want.
# The trailing slash after "${PROJECT_SOURCE_DIR}/" prevents
# an extra layer of directories.
install(DIRECTORY "${PROJECT_SOURCE_DIR}/"
    DESTINATION .
    PATTERN ".git*" EXCLUDE
    PATTERN ".DS_Store" EXCLUDE
    PATTERN "examples" EXCLUDE
    PATTERN "docs" EXCLUDE
    PATTERN "README.md" EXCLUDE
)

# Version 2: Additive
# Include only the list of things we specify.
# Put it at the top level of the zip via `DESTINATION .`
# install(FILES
#     ${SRCS}
#     "Notes.txt"
#     DESTINATION .
# )

# Tell CPack to create a zip file.
set(CPACK_GENERATOR "ZIP")
# Tell CPack what to name the zip file. It will append `.zip`.
set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}")
# Tell CPack not to put everything inside an enclosing directory.
set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY OFF)
# Apparently this should be always on but isn't for backwards compatibility.
set(CPACK_VERBATIM_VARIABLES YES)
include(CPack)
于 2020-10-12T09:29:46.103 回答
1

基本上我所做的是创建自定义目标

add_custom_target(STAGE_FILES)

有了这个目标,我将文件和目录复制到CMAKE_CURRENT_BINARY_DIR

add_custom_command( 
  TARGET STAGE_FILES 
  COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/assets/video ${CMAKE_CURRENT_BINARY_DIR}/video
  COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/assets/data ${CMAKE_CURRENT_BINARY_DIR}/data
  COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/assets/strings_en.csv ${CMAKE_CURRENT_BINARY_DIR}/
  COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/assets/strings_rules_en.csv ${CMAKE_CURRENT_BINARY_DIR}/
  COMMAND ${CMAKE_COMMAND} -E tar "cfv" "data.zip" --format=zip  --files-from=${CMAKE_SOURCE_DIR}/assets/to_zip.txt
  COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_CURRENT_BINARY_DIR}/data
  COMMAND ${CMAKE_COMMAND} -E rename  ${CMAKE_CURRENT_BINARY_DIR}/data.zip ${CMAKE_CURRENT_BINARY_DIR}/data
)

重要的线路

COMMAND ${CMAKE_COMMAND} -E tar "cfv" "data.zip" --format=zip  --files-from=${CMAKE_SOURCE_DIR}/assets/to_zip.txt

在我的里面

to_zip.txt

我指定了我想要包含在我的 zip 中的所有文件

data/
video/
...

我现在可以执行命令

make STAGE_FILES

这将复制和压缩我需要的一切

于 2018-01-11T01:14:48.117 回答