以编程方式获取CMake项目中的所有目标

以编程方式获取CMake项目中的所有目标,cmake,Cmake,我希望有一个特定的目标依赖于我的项目中所有其他添加的目标。换一种说法——我希望这个目标(比如lint)在所有库和应用程序构建完成后运行 在顶部的CMakeLists.txt文件中,指定了项目,是否有办法获取其他CMakeLists.txt文件在使用添加的目录中添加的所有目标的列表?然后我可以使用指定顺序。有一个属性,但它只在目录级别工作 如果有其他方法来实现这一点,请让我知道。我使用的是CMake 3.14。您没有提到您的CMake版本,因此我将假设此解决方案已经过测试的是3.8或更高版本 一种

我希望有一个特定的目标依赖于我的项目中所有其他添加的目标。换一种说法——我希望这个目标(比如
lint
)在所有库和应用程序构建完成后运行

在顶部的
CMakeLists.txt
文件中,指定了
项目
,是否有办法获取其他
CMakeLists.txt
文件在使用添加的目录中添加的所有目标的列表?然后我可以使用指定顺序。有一个属性,但它只在目录级别工作


如果有其他方法来实现这一点,请让我知道。我使用的是CMake 3.14。

您没有提到您的CMake版本,因此我将假设此解决方案已经过测试的是
3.8
或更高版本

一种可能的解决方案是迭代项目中的所有子目录,然后对每个子目录应用
BUILDSYSTEM\u目标。为了简单易读,我将其分为三个不同的宏

首先,我们需要一种递归获取项目中所有子目录的方法。为此,我们可以使用
文件(GLOB\u RECURSE…
,将
列表目录设置为
ON

#
# Get all directories below the specified root directory.
#   _result     : The variable in which to store the resulting directory list
#   _root       : The root directory, from which to start.
#
macro(get_directories _result _root)
    file(GLOB_RECURSE dirs RELATIVE ${_root} LIST_DIRECTORIES ON ${_root}/*)
    foreach(dir ${dirs})
        if(IS_DIRECTORY ${dir})
            list(APPEND ${_result} ${dir})
        endif()
    endforeach()
endmacro()
其次,我们需要一种在特定目录级别获取所有目标的方法<代码>目录
采用一个可选参数,即您希望查询的目录,这是此项工作的关键:

#
# Get all targets defined at the specified directory (level).
#   _result     : The variable in which to store the resulting list of targets.
#   _dir        : The directory to query for targets.
#
macro(get_targets_by_directory _result _dir)
    get_property(_target DIRECTORY ${_dir} PROPERTY BUILDSYSTEM_TARGETS)
    set(_result ${_target})
endmacro()
第三,我们需要另一个宏观层面来将所有这些联系在一起:

#
# Get all targets defined below the specified root directory.
#   _result     : The variable in which to store the resulting list of targets.
#   _root_dir   : The root project root directory
#
macro(get_all_targets _result _root_dir)
    get_directories(_all_directories ${_root_dir})
    foreach(_dir ${_all_directories})
        get_targets_by_directory(_target ${_dir})
        if(_target)
            list(APPEND ${_result} ${_target})
        endif()
    endforeach()
endmacro()
最后,以下是如何使用它:

get_all_targets(ALL_TARGETS ${CMAKE_CURRENT_LIST_DIR})

ALL_TARGETS
现在应该是一个列表,其中包含调用方目录级别下创建的每个目标的名称。请注意,它不包括在当前
CMakeLists.txt
中创建的任何目标。为此,您可以额外调用
get\u targets\u by\u directory(ALL\u targets${CMAKE\u CURRENT\u LIST\u DIR})
您没有提到您的CMAKE版本,因此我将假设
3.8
或更高版本,此解决方案已经过测试

一种可能的解决方案是迭代项目中的所有子目录,然后对每个子目录应用
BUILDSYSTEM\u目标。为了简单易读,我将其分为三个不同的宏

首先,我们需要一种递归获取项目中所有子目录的方法。为此,我们可以使用
文件(GLOB\u RECURSE…
,将
列表目录设置为
ON

#
# Get all directories below the specified root directory.
#   _result     : The variable in which to store the resulting directory list
#   _root       : The root directory, from which to start.
#
macro(get_directories _result _root)
    file(GLOB_RECURSE dirs RELATIVE ${_root} LIST_DIRECTORIES ON ${_root}/*)
    foreach(dir ${dirs})
        if(IS_DIRECTORY ${dir})
            list(APPEND ${_result} ${dir})
        endif()
    endforeach()
endmacro()
其次,我们需要一种在特定目录级别获取所有目标的方法<代码>目录
采用一个可选参数,即您希望查询的目录,这是此项工作的关键:

#
# Get all targets defined at the specified directory (level).
#   _result     : The variable in which to store the resulting list of targets.
#   _dir        : The directory to query for targets.
#
macro(get_targets_by_directory _result _dir)
    get_property(_target DIRECTORY ${_dir} PROPERTY BUILDSYSTEM_TARGETS)
    set(_result ${_target})
endmacro()
第三,我们需要另一个宏观层面来将所有这些联系在一起:

#
# Get all targets defined below the specified root directory.
#   _result     : The variable in which to store the resulting list of targets.
#   _root_dir   : The root project root directory
#
macro(get_all_targets _result _root_dir)
    get_directories(_all_directories ${_root_dir})
    foreach(_dir ${_all_directories})
        get_targets_by_directory(_target ${_dir})
        if(_target)
            list(APPEND ${_result} ${_target})
        endif()
    endforeach()
endmacro()
最后,以下是如何使用它:

get_all_targets(ALL_TARGETS ${CMAKE_CURRENT_LIST_DIR})

ALL_TARGETS
现在应该是一个列表,其中包含调用方目录级别下创建的每个目标的名称。请注意,它不包括在当前
CMakeLists.txt
中创建的任何目标。为此,您可以额外调用
get\u targets\u by\u directory(ALL\u targets${CMAKE\u CURRENT\u LIST\u DIR})

作为将来的参考,我最终编写了自己的函数,而不是宏。但这个概念与@thomas_f接受的答案相同

代码如下:

# Collect all currently added targets in all subdirectories
#
# Parameters:
# - _result the list containing all found targets
# - _dir root directory to start looking from
function(get_all_targets _result _dir)
    get_property(_subdirs DIRECTORY "${_dir}" PROPERTY SUBDIRECTORIES)
    foreach(_subdir IN LISTS _subdirs)
        get_all_targets(${_result} "${_subdir}")
    endforeach()

    get_directory_property(_sub_targets DIRECTORY "${_dir}" BUILDSYSTEM_TARGETS)
    set(${_result} ${${_result}} ${_sub_targets} PARENT_SCOPE)
endfunction()

作为将来的参考,我最终编写了自己的函数,而不是宏。但这个概念与@thomas_f接受的答案相同

代码如下:

# Collect all currently added targets in all subdirectories
#
# Parameters:
# - _result the list containing all found targets
# - _dir root directory to start looking from
function(get_all_targets _result _dir)
    get_property(_subdirs DIRECTORY "${_dir}" PROPERTY SUBDIRECTORIES)
    foreach(_subdir IN LISTS _subdirs)
        get_all_targets(${_result} "${_subdir}")
    endforeach()

    get_directory_property(_sub_targets DIRECTORY "${_dir}" BUILDSYSTEM_TARGETS)
    set(${_result} ${${_result}} ${_sub_targets} PARENT_SCOPE)
endfunction()

你检查了第二个答案和两个答案了吗?谢谢你的分数。是的。这里提到了
BUILDSYSTEM\u TARGETS
,但它只适用于当前目录,而不适用于整个目录树。您是否检查了第二个答案以及两个答案?谢谢您的回答。是的。这里提到了
BUILDSYSTEM\u目标
,但它只适用于当前目录,而不适用于完整的目录树。为什么要检查
是否(IS_DIRECTORY${dir})
file()
不是只返回目录吗?@ilya1725不,它也列出了文件。@ilya1725
LIST\u目录在
上仅仅指示
file()
也包括目录,在使用
GLOB\u RECURSE
时默认关闭目录。为什么要检查
是否(IS_DIRECTORY${dir})
file()
不是只返回目录吗?@ilya1725不,它也列出了文件。@ilya1725
LIST\u目录在
上仅仅指示
file()
也包括目录,在使用
全局递归时默认关闭。