【问题标题】:CMake : How to get the name of all subdirectories of a directory?CMake:如何获取目录的所有子目录的名称?
【发布时间】:2011-12-08 22:11:45
【问题描述】:

我有两个关于 CMake 的问题

  1. 假设我们有一个变量${MY_CURRENT_DIR},其中包含一个目录的路径,该目录包含几个子目录:mydir1、mydir2 和 mydir3。我想检测这些子目录并将它们的名称放入${SUBDIRS}(不是这些目录的完整路径,只有它们的名称)。如何自动做到这一点?

  2. 假设${SUBDIRS} 包含“mydir1 mydir2 mydir3”。如何替换

    ADD_SUBDIRECTORY(mydir1)
    ADD_SUBDIRECTORY(mydir2)
    ADD_SUBDIRECTORY(mydir3)
    

通过${SUBDIRS}的循环?

【问题讨论】:

    标签: cmake


    【解决方案1】:
    1. 使用这个宏:

      MACRO(SUBDIRLIST result curdir)
        FILE(GLOB children RELATIVE ${curdir} ${curdir}/*)
        SET(dirlist "")
        FOREACH(child ${children})
          IF(IS_DIRECTORY ${curdir}/${child})
            LIST(APPEND dirlist ${child})
          ENDIF()
        ENDFOREACH()
        SET(${result} ${dirlist})
      ENDMACRO()
      

      例子:

      SUBDIRLIST(SUBDIRS ${MY_CURRENT_DIR})
      
    2. 使用foreach

      FOREACH(subdir ${SUBDIRS})
        ADD_SUBDIRECTORY(${subdir})
      ENDFOREACH()
      

    【讨论】:

    • 为了提高性能,特别是如果dirlist很长,请使用LIST(APPEND dirlist ${child})而不是SET(dirlist ${dirlist} ${child})see here
    • 重要提示:这不适用于GLOB_RECURSE,仅适用于GLOB
    • GLOB_RECURSE 的默认 LIST_DIRECTORIES 为 false,而 GLOB 的默认 LIST_DIRECTORIES 为 true。如果您使用递归,则必须将其设置为 true
    • 如果文件夹包含CMakeLists.txt 文件以仅添加合适的目录而不是.git 之类的文件,可能需要修改if 条件以检查,这会导致cmake 期间出错:@987654332 @
    【解决方案2】:

    关于上面的答案: 使用这个宏:

    MACRO(SUBDIRLIST result curdir)
      FILE(GLOB children RELATIVE ${curdir} ${curdir}/*)
      SET(dirlist "")
      FOREACH(child ${children})
        IF(IS_DIRECTORY ${curdir}/${child})
          LIST(APPEND dirlist ${child})
        ENDIF()
      ENDFOREACH()
      SET(${result} ${dirlist})
    ENDMACRO()
    

    例子:

    SUBDIRLIST(SUBDIRS ${MY_CURRENT_DIR})
    

    我在使用这个 FILE(GLOB 命令)时遇到了问题。(我使用的是 cmake 3.17.3) 否则宏工作得很好。 我收到了 FILE GLOB 错误,例如“FILE GLOB 在目录之后需要一个 glob 表达式”。 (也许它不喜欢 RELATIVE 和/或只是使用 curdir 作为第四个参数。)

    我不得不使用:

    FILE(GLOB children ${curdir}/*)
    

    (取出 RELATIVE 和第一个 ${curdir} (请注意我上面的 cmake 版本,这可能是我的问题(到目前为止我还不熟悉 glob。)。

    【讨论】:

    • 评论我自己的答案,因为我刚刚意识到 FILE(GLOB 没有扩展我的 ${curdir} 变量,所以这可能是我的错误的原因。所以你可能不需要进行这些更新。
    • 你可以使用 RELATIVE ${CMAKE_SOURCE_DIR}/${curdir} 在相对 Cmake 需要一个绝对路径之后。
    【解决方案3】:

    对于现代更简单的解决方案,试试这个
    对于 cmake 3.7 及更高版本,GLOB 模块有一个 LIST_DIRECTORIES 选项

    This link explains glob patterns

    file(GLOB sources_list LIST_DIRECTORIES true YourGLOBPattern)
    foreach(dir ${sources_list})
        IF(IS_DIRECTORY ${dir})
            add_subdirectory(${dir})
        ELSE()
            CONTINUE()
        ENDIF()
    endforeach()
    

    【讨论】:

    • 我看不出这是一个更简单的版本,对我来说,它与 2011 年接受的答案相同,但有额外的不需要的代码。 LIST_DIRECTORIES 选项是在 cmake 3.3(不是 3.7)中添加的,并增加了在设置为 false 时从输出中省略目录的可能性。它默认为 true(输出目录),因此,没有此选项与将其设置为 true 的行为相同。
    【解决方案4】:

    @refaim 回答不适用于 CMake 3.21.1,我必须做一些小改动:

    MACRO(SUBDIRLIST result curdir)
        FILE(GLOB children ${curdir}/*) # This was changed
        SET(dirlist "")
        FOREACH(child ${children})
            IF(IS_DIRECTORY ${child}) # This was changed
                LIST(APPEND dirlist ${child})
            ENDIF()
        ENDFOREACH()
        SET(${result} ${dirlist})
    ENDMACRO()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-10
      • 2011-02-01
      相关资源
      最近更新 更多