【问题标题】:Using CMake GLOB_RECURSE to find directories使用 CMake GLOB_RECURSE 查找目录
【发布时间】:2020-05-27 14:22:51
【问题描述】:

我的目录结构如下:

.
├── CMakeLists.txt
└── deps
    ├── eigen
    │   └── include
    │       ├── Eigen
    │       └── eigen.h
    └── osg
        ├── include
        │   └── Osg
        └── lib
            └── libosg.so

我正在尝试获取最多的我不需要部署我的软件的文件,即库。 我试图创建一个匹配*.h 文件和include 目录的通配符:

file(GLOB_RECURSE
  FOUND_FILES
  LIST_DIRECTORIES true
  ${CMAKE_SOURCE_DIR}/deps/*/include
  ${CMAKE_SOURCE_DIR}/deps/*/*.h)
message(STATUS "Files are ${FOUND_FILES}")

但是,由于某种原因,变量FOUND_FILES 包含deps/osg/libGLOB_RECURSE 函数我有什么不明白的地方?

- deps/eigen/include
- deps/eigen/include/eigen.h
- deps/osg/include
- deps/osg/lib
- deps/eigen/include
- deps/osg/include
- deps/osg/lib

【问题讨论】:

  • 您正在请求它。来自文档:默认情况下 GLOB_RECURSE 从结果列表中省略目录 - 将 LIST_DIRECTORIES 设置为 true 会将目录添加到结果列表中。
  • 是的,但 osg/lib 中没有任何内容与全局表达式匹配
  • 好点。一定是错过了,抱歉打扰了。
  • 是的,deps/*.h 确实足够了。
  • 我可以用简单的mkdir -p ./source/deps/osg/{include,lib} ./source/deps/eigen/includefile(GLOB_RECURSE FOUND_FILES LIST_DIRECTORIES true ${CMAKE_CURRENT_LIST_DIR}/source/deps/*/include ) foreach(i IN LISTS FOUND_FILES) message(STATUS "${i}") endforeach() cmake 脚本重现.. :/

标签: cmake glob


【解决方案1】:

我认为这可能是一种解决方法:

file(GLOB_RECURSE
    FOUND_FILES
    LIST_DIRECTORIES true
    ${CMAKE_SOURCE_DIR}/deps/*/include
)
list(FILTER FOUND_FILES INCLUDE REGEX "^${CMAKE_SOURCE_DIR}/deps/.*/include$")
file(GLOB_RECURSE
    tmp
    ${CMAKE_BINARY_DIR}/deps/*/*.h
)
list(APPEND FOUND_FILES ${tmp})

我猜这是一个错误,当GLOB_RECURSELIST_DIRECTORIES true 一起使用时,* 的表达式不在路径的最后一个条目上。一旦包含匹配条目的目录在cmake:Glob.cxx#L404 中匹配,下一个目录将无条件地递归添加到输出this add_file() in cmake Glob.cxx#L316。因此,一旦${CMAKE_SOURCE_DIR}/deps/* 目录中包含include 目录或文件,所有从${CMAKE_SOURCE_DIR}/deps/ 递归的目录都将添加到输出中。未添加文件,因为它们是在 cmake Glob.cxx:#L326 处针对正则表达式进行检查的。

【讨论】:

  • 这不适用于查找较低的包含目录。它并没有真正回答我的问题,但它适合我的需要。我不确定是否应该将答案标记为已接受。
  • Ooooch,对,因为例如${CMAKE_SOURCE_DIR}/deps/a/b/include 将找不到:/所以后过滤是一个选项。用list(FILTER REGEX 编辑了答案
【解决方案2】:

在使用GLOB_RECURSE 过滤目录时,CMake 似乎删除了通配表达式的最后一个组件。这就是为什么 CMake 不会在您的示例中进一步过滤 include 目录的原因。这可能是 CMake GLOB_RECURSE 目录实现中的错误,或者是 CMake documentation 中的疏忽。

编辑:解决方案 1(不起作用):

您可以改为模拟使用通配模式本身的递归。请改用 CMake 的 GLOB,并在 globbing 模式中使用 ** 来匹配 deps//include 之间的一个或多个字符的任何内容:

file(GLOB
  FOUND_FILES
  LIST_DIRECTORIES true
  ${CMAKE_SOURCE_DIR}/deps/**/include
  ${CMAKE_BINARY_DIR}/deps/**/*.h)
)
message(STATUS "Files are ${FOUND_FILES}")

解决方案2(丑陋):

您可以为 CMake 手动添加目录级别以搜索 include 文件夹:

file(GLOB
  FOUND_FILES
  LIST_DIRECTORIES true
  ${CMAKE_SOURCE_DIR}/deps/*/include
  ${CMAKE_SOURCE_DIR}/deps/*/*/include
  ...
)

但是,这不是一个非常可扩展的解决方案。

【讨论】:

  • 不幸的是,CMake 似乎不支持 ** 通配模式,因此与 deps 下的 *.hinclude 两个目录不匹配。
  • “与GLOB_RECURSE 一起使用的通配模式似乎与模式中星号 (*) 之后的任何目录匹配,并且不会进一步过滤 include 目录” - 似乎在搜索目录时,无论是否包含星号,CMake 都会简单地删除通配表达式的 last path component。例如,这个通配表达式${CMAKE_SOURCE_DIR}/deps/NonExistentFile 将“匹配”到${CMAKE_SOURCE_DIR}/deps/ 下的所有目录,但不匹配任何文件。真是个有趣的行为。
  • @Hugal31 你是对的; CMake 似乎不支持** globbing 模式。我在回复中添加了一个潜在的解决方法,但它不是很便携。几乎可以肯定有一个更强大的解决方案(也许,使用GLOB 收集目录列表,然后使用正则表达式将其过滤到以/include 结尾的那些)。
  • @Tsyvarev 好收获!我修改了响应以反映您的观察。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-31
  • 1970-01-01
  • 2017-11-25
  • 1970-01-01
  • 1970-01-01
  • 2017-07-19
相关资源
最近更新 更多