Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
CMake自定义命令复制多个文件_Cmake - Fatal编程技术网

CMake自定义命令复制多个文件

CMake自定义命令复制多个文件,cmake,Cmake,我试图使用${CMAKE_COMMAND}-E copy格式复制多个文件,但我想知道是否有办法提供大量文件以复制到特定目录。似乎cmake copy一次只允许复制一个文件。我真的不想重复使用copy命令,因为我宁愿提供要复制的文件列表作为第一个参数 我认为最简单的解决方案是使用依赖于平台的“cp”命令。虽然这显然不利于可移植性,但我们的系统保证构建在Linux上。一个简单的、独立于平台的解决方案会更好。一个相对简单的解决方法是使用${CMAKE_COMMAND}-E tar捆绑源代码,移动tar

我试图使用
${CMAKE_COMMAND}-E copy
格式复制多个文件,但我想知道是否有办法提供大量文件以复制到特定目录。似乎cmake copy一次只允许复制一个文件。我真的不想重复使用copy命令,因为我宁愿提供要复制的文件列表作为第一个参数


我认为最简单的解决方案是使用依赖于平台的“cp”命令。虽然这显然不利于可移植性,但我们的系统保证构建在Linux上。一个简单的、独立于平台的解决方案会更好。

一个相对简单的解决方法是使用
${CMAKE_COMMAND}-E tar
捆绑源代码,移动tarball并在目标目录中提取它

如果您的源代码分散在许多不同的目录中,那么这可能会带来更多麻烦,因为提取将保留原始目录结构(与使用
cp
)。但是,如果所有文件都在一个目录中,则只需调用2个
add\u custom\u命令即可实现复制

假设您要移动的源都在
${CMAKE\u SOURCE\u DIR}/SOURCE\u DIR
中,目标是
${CMAKE\u SOURCE\u DIR}/destination\u DIR
并且您的文件名列表(非完整路径)在
${FileList}
中。你可以做:

add_custom_command(
    TARGET MyExe POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E tar cfj ${CMAKE_BINARY_DIR}/temp.tar ${FileList}
    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/source_dir)

add_custom_command(
    TARGET MyExe POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E rename ${CMAKE_BINARY_DIR}/temp.tar temp.tar
    COMMAND ${CMAKE_COMMAND} -E tar xfj temp.tar ${FileList}
    COMMAND ${CMAKE_COMMAND} -E remove temp.tar
    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/destination_dir)
我打了个圈

# create a list of files to copy
set( THIRD_PARTY_DLLS
   C:/DLLFOLDER/my_dll_1.dll
   C:/DLLFOLDER/my_dll_2.dll
)

# do the copying
foreach( file_i ${THIRD_PARTY_DLLS})
    add_custom_command(
    TARGET ${VIEWER_NAME}
    POST_BUILD
    COMMAND ${CMAKE_COMMAND}
    ARGS -E copy ${file_i} "C:/TargetDirectory"
)
endforeach( file_i )

可从CMake 3.5复制多个文件

cmake -E copy <file>... <destination>
cmake-E复制。。。


由于我或多或少都遇到了同样的问题,并且不喜欢上面的解决方案,我最终想出了这个办法。它不仅仅是复制文件,但我想我会发布整个内容,因为它显示了该技术的灵活性,并结合生成器表达式,根据构建变量允许不同的文件和目录。我相信命令\u EXPAND\u LISTS对于这里的功能至关重要。 此函数不仅可以将某些文件复制到新目录,还可以对每个文件运行命令。在这种情况下,它使用microsoft signtool程序向每个文件添加数字签名

cmake_minimum_required (VERSION 3.12)

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)

SET(ALL_3RD_PARTY_DLLS_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/file1.dll" "${CMAKE_CURRENT_SOURCE_DIR}/file2.dll")
SET(ALL_3RD_PARTY_DLLS_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/file3.dll" "${CMAKE_CURRENT_SOURCE_DIR}/file4.dll")

STRING(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}" ";${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug" ALL_OUTPUT_3RD_PARTY_DLLS_DEBUG ${ALL_3RD_PARTY_DLLS_DEBUG})
LIST(REMOVE_AT ALL_OUTPUT_3RD_PARTY_DLLS_DEBUG 0)
STRING(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}" ";${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release" ALL_OUTPUT_3RD_PARTY_DLLS_RELEASE ${ALL_3RD_PARTY_DLLS_RELEASE})
LIST(REMOVE_AT ALL_OUTPUT_3RD_PARTY_DLLS_RELEASE 0)

FILE(TO_NATIVE_PATH "C:\\Program\ Files\ (x86)\\Windows\ Kits\\10\\bin\\10.0.17763.0\\x86\\signtool.exe" SIGNTOOL_COMMAND)

add_custom_target(Copy3rdPartyDLLs ALL
                COMMENT "Copying and signing 3rd Party DLLs"
                VERBATIM
                COMMAND_EXPAND_LISTS
                COMMAND ${CMAKE_COMMAND} -E
                    make_directory "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$<$<CONFIG:Release>:Release>$<$<CONFIG:Debug>:Debug>/"
                COMMAND ${CMAKE_COMMAND} -E
                    copy_if_different 
                            "$<$<CONFIG:Release>:${ALL_3RD_PARTY_DLLS_RELEASE}>" 
                            "$<$<CONFIG:Debug>:${ALL_3RD_PARTY_DLLS_DEBUG}>"
                            "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$<$<CONFIG:Release>:Release>$<$<CONFIG:Debug>:Debug>/"
                COMMAND ${SIGNTOOL_COMMAND} sign 
                            "$<$<CONFIG:Release>:${ALL_OUTPUT_3RD_PARTY_DLLS_RELEASE}>" 
                            "$<$<CONFIG:Debug>:${ALL_OUTPUT_3RD_PARTY_DLLS_DEBUG}>"
)
cmake_最低要求(3.12版)
集合(CMAKE_运行时_输出_目录${CMAKE_二进制_目录}/bin)
设置(所有第三方dll调试“${CMAKE\u CURRENT\u SOURCE\u DIR}/file1.dll”“${CMAKE\u CURRENT\u SOURCE\u DIR}/file2.dll”)
设置(所有第三方dll发布“${CMAKE\u CURRENT\u SOURCE\u DIR}/file3.dll”“${CMAKE\u CURRENT\u SOURCE\u DIR}/file4.dll”)
字符串(替换“${CMAKE_CURRENT_SOURCE_DIR}”;${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug”所有输出第三方DLL调试${ALL第三方DLL调试})
列表(删除所有\u输出\u第三方\u DLL\u调试0)
字符串(替换“${CMAKE_CURRENT_SOURCE_DIR}”;${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release”所有输出第三方DLL发布${ALL第三方DLL发布})
列表(删除所有\u输出\u第三方\u DLL\u版本0中的\u)
文件(指向路径“C:\\Program\Files\(x86)\\Windows\Kits\\10\\bin\\10.0.17763.0\\x86\\signtool.exe”signtool\u命令)
添加自定义目标(COPY3RDPARTYDLS ALL
注释“复制和签署第三方DLL”
逐字的
命令\u展开\u列表
命令${CMAKE_COMMAND}-E
生成目录“${CMAKE\U运行时\U输出\U目录}/$$/”
命令${CMAKE_COMMAND}-E
如果不同,请复制
"$" 
"$"
“${CMAKE_运行时_输出_目录}/$$/”
命令${SIGNTOOL_COMMAND}符号
"$" 
"$"
)

我希望这可以节省我花了一天左右的时间来解决这个问题。

虽然我喜欢你的方法,但我仍然在寻找比使用tar更简单的方法。现在,也许把它放进CMake函数中,可能会有用。是的,我希望其他人会有更好的答案。您确实可以创建一个CMake函数,该函数可以在内部执行此操作,包括仅获取每个源文件路径的最终组件(使用),以更好地模拟
cp
的行为。这会起作用,但在尝试复制数百个文件时,这不会创建一个大型makefile吗?我想是这样,但是你没有写你有大量的文件。很抱歉,我无法帮助您。如果您的文件位于源目录中,您应该将每个文件名命名为${CMAKE\u CURRENT\u source\u DIR}。如果要复制到当前的bin dir,也可以。例如,ARGS-E copy${CMAKE\u CURRENT\u SOURCE\u DIR}/${file\u i}${CMAKE\u CURRENT\u BINARY\u DIR}在Windows上(至少)这实际上被连接到一个非常长的命令行中,足够长,以至于cmd.exe实际上可以抱怨并拒绝执行它。“CMake真的需要一种更好的方法。我喜欢你的例子,@David。但我还没有摸索。您将
$
语法称为什么,以便可以不断搜索有关其功能的文档?我知道,
${ALL\u third\u PARTY\u DLLS\u RELEASE}
是要迭代通过的文件路径列表。但是,我不明白在那之前,代币中应该包含什么。