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这实际上是我试图实现的。这可能是个人的,但我不喜欢手动为库头维护一个独立的位置(除非我误解了你的意思),这就是为什么我想要一个脚本自动完成它。然而,这个难题让我重新组织了我的整个代码,这样“在编译任何东西之前复制所有东西”部分就不再是一个要求了。不管怎样,公认的答案提供了一个很好的方法来完成它。:)太好了,谢谢你。