使用CMake GLOB_递归查找目录

使用CMake GLOB_递归查找目录,cmake,glob,Cmake,Glob,我有以下目录结构: . ├── CMakeLists.txt └── deps ├── eigen │   └── include │   ├── Eigen │   └── eigen.h └── osg ├── include │   └── Osg └── lib └── libosg.so 我正在尝试获取部署软件所不需要的最大数量的文件,即库。 我试图创建一个

我有以下目录结构:

.
├── 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\u FILES
包含
deps/osg/lib
。关于
GLOB\u 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\u RECURSE
筛选目录时,CMake似乎会删除globbing表达式的最后一个组件。这就是为什么CMake不进一步过滤示例中的
include
目录的原因。这可能是目录的CMake
GLOB_RECURSE
实现中的错误,也可能是CMake中的疏忽

编辑:解决方案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
  ...
)

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

当使用
GLOB\u RECURSE
筛选目录时,CMake似乎会删除globbing表达式的最后一个组件。这就是为什么CMake不进一步过滤示例中的
include
目录的原因。这可能是目录的CMake
GLOB_RECURSE
实现中的错误,也可能是CMake中的疏忽

编辑:解决方案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
  ...
)

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

我认为这可能是一个解决方案:

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\u RECURSE
LIST\u目录true
一起使用时,如果表达式的
*
不在路径的最后一个条目上,我猜这是一个错误。一旦包含匹配项的目录在中匹配,下一个目录将无条件地递归添加到输出中。因此,一旦
${CMAKE\u SOURCE\u DIR}/deps/*
目录中有一个
include
目录或文件,所有从
${CMAKE\u SOURCE\u DIR}/deps/
递归而来的目录都被添加到输出中。文件不会被添加,因为它们是根据regex进行检查的。

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

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\u RECURSE
LIST\u目录true
一起使用时,如果表达式的
*
不在路径的最后一个条目上,我猜这是一个错误。一旦包含匹配项的目录在中匹配,下一个目录将无条件地递归添加到输出中。因此,一旦
${CMAKE\u SOURCE\u DIR}/deps/*
目录中有一个
include
目录或文件,所有从
${CMAKE\u SOURCE\u DIR}/deps/
递归而来的目录都被添加到输出中。不会添加文件,因为它们会根据您请求的regex进行检查。

。从文档中:默认情况下,GLOB_RECURSE忽略结果列表中的目录-将list_directories设置为true会将目录添加到结果列表中。是的,但osg/lib中的任何内容都不匹配全局表达式good point。我一定错过了,抱歉吵闹。是的,
deps/*.h
确实足够了。我可以用simple
mkdir-p./source/deps/osg/{include,lib}./source/deps/eigen/include
文件(全局递归找到的文件列表目录真${CMAKE\u当前的列表目录目录}/source deps/*/include)foreach(我在找到的文件列表中)消息(状态“${i}”)endforeach()
cmake脚本..:/你在请求它。从文档中:默认情况下,GLOB_RECURSE忽略结果列表中的目录-将list_directories设置为true会将目录添加到结果列表中。是的,但osg/lib中的任何内容都不匹配全局表达式good point。我一定错过了,抱歉吵闹。是的,
deps/*.h
确实足够了。我可以用simple
mkdir-p./source/deps/osg/{include,lib}./source/deps/eigen/include
文件(全局递归找到的文件列表目录真${CMAKE\u当前的列表目录目录}/source deps/*/include)foreach(我在找到的文件列表中)消息(状态“${i}”)endforeach()
cmake脚本..:/不幸的是,CMake似乎不支持
***
全局模式,因此不匹配
*。h
包括
目录和deps下的两个目录。“与
全局递归使用的全局模式似乎匹配星号(
*
)后的任何目录在模式中,并且不会进一步过滤
include
目录”-在搜索目录时,无论是否包含星号,CMake似乎只会删除全局表达式的最后一个路径组件。例如,此全局表达式
${CMAKE\u SOURCE\u DIR}/deps/NonExistentFile
将“匹配”到
${CMAKE\u SOURCE\u DIR}/deps/
下的所有目录,但不匹配到任何文件。这的确是一个有趣的行为。@Hugal31你是对的;CMake似乎不支持
**
全局模式。我在回复中添加了一个潜在的解决方法,但它不是很好移植。几乎可以肯定有一个更强大的解决方案(可能是使用
GLOB
收集目录列表,然后使用regex将其过滤到以
/include
结尾的目录列表)!我修改了文件