tl; dr版本: 是否可以使用CMake(> = 2.8)从某些文件生成zip文件并将打包的zip文件放在特定位置?
较长版本 我有一个CMakeLists.txt将我的项目构建到.exe文件。此exe文件将从zip文件中读取数据。现在,要在zip文件中打包的内容在我的git存储库中,以便它也可以编辑。但程序需要这个数据在一个zip文件中。因此,如果cmake脚本可以获取数据,将其放在zip文件中并将其放在exe旁边,那将是很好的。我已经听说过CPack,但我没有找到简单的例子,也不确定这是否适合我的工作。
这可能吗?如果是的话:怎么样?
答案 0 :(得分:24)
从版本3.2开始,CMake具有生成内置zip文件的功能。 CMake command-line mode子命令tar
支持zip和7zip档案的创建。
例如,如果当前CMake源目录包含文件testfile.txt
和目录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
)
将在当前CMake二进制目录(CMAKE_CURRENT_BINARY_DIR
)中生成zip文件。
答案 1 :(得分:6)
我假设你已经安装了一个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的回答
答案 2 :(得分:2)
显示真实答案永远不会晚:
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)
答案 3 :(得分:2)
从3.18版本开始,CMake现在直接支持使用file()
命令和ARCHIVE_CREATE
创建zip或存档文件:
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
)
答案 4 :(得分: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
将复制并压缩我需要的所有内容
答案 5 :(得分:1)
由于这是使用CMake创建zip文件的顶部搜索结果,因此这里提供了一种CPack解决方案,以确保完整性。基本思想是调用install()
,然后告诉它如何命名生成的zip文件。它将被放置在构建目录中,尽管可能有一种更改方法。然后,您可以使用make package
或cpack
创建zip文件。
# 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)