以编程方式获取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不,它也列出了文件。@ilya1725LIST\u目录在
上仅仅指示file()
也包括目录,在使用GLOB\u RECURSE
时默认关闭目录。为什么要检查是否(IS_DIRECTORY${dir})
?file()
不是只返回目录吗?@ilya1725不,它也列出了文件。@ilya1725LIST\u目录在上仅仅指示file()
也包括目录,在使用全局递归时默认关闭。