Программно получить все цели в проекте CMake - PullRequest
1 голос
/ 13 февраля 2020

Я бы хотел, чтобы одна конкретная цель c зависела от всех других добавленных целей в моем проекте. Чтобы сказать это по-другому - я бы хотел, чтобы эта цель (скажем, lint) работала после того, как все библиотеки и приложения были созданы.

Есть ли способ в верхнем файле CMakeLists.txt, где указано project, получить список всех целей, добавленных другими файлами CMakeLists.txt в каталогах, добавленных с использованием add_subdirectory? Тогда я могу использовать add_dependencies, чтобы указать порядок. Существует свойство BUILDSYSTEM_TARGETS, но оно работает только на уровне каталогов.

Если есть другой способ добиться этого, пожалуйста, сообщите мне. Я использую CMake 3.14.

Ответы [ 2 ]

4 голосов
/ 14 февраля 2020

Вы не упомянули свою версию CMake, поэтому я предполагаю, что 3.8 или лучше, для которого это решение было проверено.

Одним из возможных решений является перебор всех подкаталогов в вашем проекте, и затем примените BUILDSYSTEM_TARGETS к каждому из них. Ради простоты и читабельности я разделил это на три разных макроса.

Во-первых, нам нужен способ рекурсивного получения всех подкаталогов в проекте. Для этого мы можем использовать file(GLOB_RECURSE ...) с LIST_DIRECTORIES, установленным на 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()

Во-вторых, нам нужен способ получить все цели на определенном уровне каталога. DIRECTORY принимает необязательный параметр, а именно каталог, который вы запрашиваете sh, что является ключом для этого:

#
# 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()

В-третьих, нам нужен еще один макрос для t ie всего этого вместе :

#
# 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_targets_by_directory(ALL_TARGETS ${CMAKE_CURRENT_LIST_DIR}).

2 голосов
/ 14 февраля 2020

Для дальнейшего использования я написал собственную функцию вместо макроса. Но концепция такая же, как принятый ответ @ 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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...