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,我有以下项目布局: project/ ├─ CMakeLists.txt ├─ main.cpp ╘═ my_lib/ ├─ CMakeLists.txt ╞═ some_package1/ │ ├── header.hpp │ └── impl.cpp ╘═ some_package2/ ├── header.hpp └── impl.cpp my_lib由CMakeLists.txt从项目添加为子目录 我想要的是my_libCMak

我有以下项目布局:

project/
├─ CMakeLists.txt
├─ main.cpp
╘═ my_lib/
   ├─ CMakeLists.txt
   ╞═ some_package1/
   │  ├── header.hpp
   │  └── impl.cpp
   ╘═ some_package2/
      ├── header.hpp
      └── impl.cpp
my_lib
CMakeLists.txt
项目添加为子目录
我想要的是
my_lib
CMakeLists.txt
中的目标,它在构建时执行一个命令,将
my_lib
中的所有头复制到目标目录,同时保留目录结构。目标目录将由
项目
CMakeLists.txt
定义

基本上,如果我能以某种方式获得
add_custom_命令
来执行此操作:

file(COPY ${CMAKE_SOURCE_DIR}/my_lib DESTINATION ${COPY_DEST_DIR} FILES_MATCHING PATTERN "*.hpp")
我会非常高兴的。但我还没有找到一种方法来做到这一点。这与安装目标非常相似,只是我需要在编译任何东西之前完成它

我试着做了以下几点:

set(MY_LIB_HEADER_FILES
    some_package1/header.hpp
    some_package2/header.hpp
)

add_custom_target(copy_headers)
add_custom_command(
    TARGET copy_headers
    COMMAND ${CMAKE_COMMAND} -E copy "${MY_LIB_HEADER_FILES}" ${COPY_DEST_DIR}
    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/my_lib
)
但这并没有保留目录结构,在本例中,这将导致一个头被另一个头覆盖。我还没有找到解决这个问题的办法

我能想到的唯一解决方案是一种黑客攻击,我在
${MY_LIB_HEADER_FILES}
中循环每个文件,删除最后一个正斜杠后面的内容,创建该目录,然后将文件复制到该目录。但我真的不想求助于它,也不想去想它,考虑到它必须在
add\u custom\u命令
调用中完成,我甚至不知道该怎么做


当然有一个解决方案,对吗?

实现这一点的方法之一是编写一个“CMake脚本”文件,该文件将包含
文件(复制)
命令,并在
添加自定义\u命令
中执行它。简而言之,您的代码片段如下所示:

#create script file during configure phase...
file(WRITE ${CMAKE_BINARY_DIR}/cp.cmake
  "file(COPY ${CMAKE_SOURCE_DIR}/my_lib DESTINATION ${COPY_DEST_DIR} FILES_MATCHING PATTERN *.hpp)\n"
)

#execute the script during the build phase...
add_custom_command(
  TARGET my_lib
  POST_BUILD
  COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/cp.cmake
)

file(WRITE…
语句将在名为
cp.cmake
的根生成文件夹中创建一个新的cmake脚本文件

注1:
$
前面的变量
CMAKE\u SOURCE\u DIR
COPY\u DEST\u DIR
未转义的,这意味着
cp.CMAKE
将包含其评估值

注2: 假设您的库创建了一个名为
my_lib
的目标,并且
add_custom_命令
作为该目标的
POST_BUILD
事件添加


最后,这里是关于cmake的文档,您是否尝试了
${cmake_COMMAND}-E copy_directories
而不是
copy
?我最终会复制源文件和标题,因为
copy_directories
不提供任何匹配文件的选项。但是,正如一个似乎不再在这里的答案所建议的,我可以使用
文件(GLOB_RECURSE)在目的目录中找到源文件并删除它们。这远不是理想的,但是缺少更好的解决方案,这可能是我最终要做的。我希望你能找到一个好的解决方案。但是你也可以考虑重新组织目录结构。我发现有用“外部”头文件是有用的。(最终用户需要使用编译代码的文件)在一个独立于源文件和内部头文件的目录中。这使得使用类似于
copy\u目录
的东西来安装它们更加容易。@EricBackus这实际上是我试图实现的。这可能是个人的,但我不喜欢手动为库头维护一个独立的位置(除非我误解了你的意思),这就是为什么我想要一个脚本自动完成它。然而,这个难题让我重新组织了我的整个代码,这样“在编译任何东西之前复制所有东西”部分就不再是一个要求了。不管怎样,公认的答案提供了一个很好的方法来完成它。:)太好了,谢谢你。