2016-09-12 3 views
7

С CMake, как я могу получить список всех исходных файлов, которые входят в исполняемую цель, включая все источники во всех целях, от которых зависит этот исполняемый файл?Получить все исходные файлы, от которых зависит цель в CMake

У нас есть шаблон в базе кода, где вызывающие абоненты инициализатора генерируются системой сборки на основе имен файлов и путей в исходном дереве. Поэтому мне нужен полный путь (или относительно исходного корня) ко всем исходным файлам, от которых зависит исполняемая цель.

+2

Вы можете использовать [ 'SOURCES'] (https://cmake.org/cmake/help/latest/prop_tgt/SOURCES.html) предназначаться недвижимость и можно найти [здесь] (http://stackoverflow.com/questions/32756195/recursive-list-of-link-libraries-in-cmake) образцы кода, которые перебирают зависимые цели. Не могли бы вы описать, что вы пробовали до сих пор? – Florian

+0

Я не понимал, что могу перебирать подобные цели. Я думаю, что могу заставить его работать с свойством SOURCES. –

+0

Я написал что-то подобное, перезаписав функции CMake и мог бы представить пример кода, если вы заинтересованы (в качестве отправной точки). Это какой-то внешний код библиотеки CMake, о котором мы говорим здесь, или вы хотите использовать его на свой собственный код? – Florian

ответ

5

Вот мой кусок кода, чтобы получить зависимости ссылку одного целевого объекта:

function(target_link_libraries _target) 
    set(_mode "PUBLIC") 
    foreach(_arg IN LISTS ARGN) 
     if (_arg MATCHES "INTERFACE|PUBLIC|PRIVATE|LINK_PRIVATE|LINK_PUBLIC|LINK_INTERFACE_LIBRARIES") 
      set(_mode "${_arg}") 
     else() 
      if (NOT _arg MATCHES "debug|optimized|general") 
       set_property(GLOBAL APPEND PROPERTY GlobalTargetDepends${_target} ${_arg}) 
      endif() 
     endif() 
    endforeach() 
    _target_link_libraries(${_target} ${ARGN}) 
endfunction() 

function(get_link_dependencies _target _listvar) 
    set(_worklist ${${_listvar}}) 
    if (TARGET ${_target}) 
     list(APPEND _worklist ${_target}) 
     get_property(_dependencies GLOBAL PROPERTY GlobalTargetDepends${_target}) 
     foreach(_dependency IN LISTS _dependencies) 
      if (NOT _dependency IN_LIST _worklist) 
       get_link_dependencies(${_dependency} _worklist) 
      endif() 
     endforeach() 
     set(${_listvar} "${_worklist}" PARENT_SCOPE) 
    endif() 
endfunction() 

Для более старых версий CMake (до 3.4), вам нужно будет заменить IN_LIST чек с list(FIND ...) вызова:

[...] 
     list(FIND _worklist ${_dependency} _idx) 
     if (${_idx} EQUAL -1) 
      get_link_dependencies(${_dependency} _worklist) 
     endif() 
[...] 

А вот тест код, который я использовал:

cmake_minimum_required(VERSION 3.4) 

project(GetSources) 

cmake_policy(SET CMP0057 NEW) 

[... include functions posted above ...] 

file(WRITE a.cc "") 
add_library(A STATIC a.cc) 

file(WRITE b.cc "") 
add_library(B STATIC b.cc) 

file(WRITE main.cc "int main() { return 0; }") 
add_executable(${PROJECT_NAME} main.cc) 

target_link_libraries(B A) 
target_link_libraries(${PROJECT_NAME} B) 

get_link_dependencies(${PROJECT_NAME} _deps) 
foreach(_dep IN LISTS _deps) 
    get_target_property(_srcs ${_dep} SOURCES) 
    get_target_property(_src_dir ${_dep} SOURCE_DIR) 
    foreach(_src IN LISTS _srcs) 
     message("${_src_dir}/${_src}") 
    endforeach() 
endforeach() 

Ссылки

+0

Отлично подходит для исполняемых целей. По какой-то причине мне понадобилось 'cmake_policy (SET CMP0057 NEW)' для 'IN_LIST' работать внутри оператора' if' при запуске этого на второй целевой библиотеке. –

+0

@PetterKvalvaag Спасибо за подсказку. Я фактически представил 'IN_LIST' код для этого ответа и не знал о политике' CMP0057' (CMake 3.4, который я использовал для тестирования, не выдает предупреждение/ошибку). Я соответствующим образом обновил свой ответ и добавил вариант, который у меня был до (тестировался с CMake версии 2.8). – Florian

Смежные вопросы