2016-09-12 12 views
7

Z CMake, w jaki sposób mogę uzyskać listę wszystkich plików źródłowych, które trafiają do wykonywalnych celów, w tym wszystkie źródła we wszystkich celach, od których ten plik wykonywalny jest zależny?Uzyskaj wszystkie pliki źródłowe, których cel zależy od CMake

Mamy wzorzec w bazie kodu, w którym wywołujący inicjatory są generowani przez system kompilacji na podstawie nazw plików i ścieżek w drzewie źródłowym. Potrzebuję więc pełnej ścieżki (lub źródła względem root) do wszystkich plików źródłowych, od których zależy wykonywany cel.

+2

można użyć [ 'SOURCES'] (https://cmake.org/cmake/help/latest/prop_tgt/SOURCES.html) kierowanie i mienia można znaleźć próbki kodu [here] (http://stackoverflow.com/questions/32756195/recursive-list-of-link-libraries-in-cmake), które są iteracyjne w zależności od celów docelowych. Czy możesz opisać to, co dotychczas próbowałeś? – Florian

+0

Nie zdawałem sobie sprawy, że mogę wykonać iterację w zależności od takich celów. Myślę, że mogę sprawić, by działała z własnością SOURCES. –

+0

Napisałem coś podobnego przez nadpisanie funkcji CMake i mogłem podać przykład kodu, jeśli jesteś zainteresowany (jako punkt wyjścia). Czy jest to jakiś kod CMake biblioteki zewnętrznej, o którym tu mówimy, czy też chcesz go użyć na swoim własnym kodzie? – Florian

Odpowiedz

5

Oto mój kawałek kodu, aby uzyskać link zależności jeden cel to:

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

Dla starszych wersjach CUpewnij (przed 3.4), trzeba będzie wymienić czek IN_LIST z list(FIND ...) rozmowy:

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

A oto kod testu użyłem:

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

Referencje

+0

Działa doskonale w przypadku wykonywalnych obiektów docelowych. Z jakiegoś powodu potrzebowałem 'cmake_policy (SET CMP0057 NEW)' dla 'IN_LIST' do pracy wewnątrz instrukcji' if' podczas uruchamiania tego na drugim obiekcie bibliotecznym. –

+0

@PetterKvalvaag Dzięki za podpowiedź. Właściwie wprowadziłem 'IN_LIST' do kodu dla tej odpowiedzi i nie wiedziałem o polityce' CMP0057' (CMake 3.4, której użyłem do testowania, nie generuje ostrzeżenia/błędu). Odpowiednio zaktualizowałem swoją odpowiedź i dodałem wariant, który miałem wcześniej (przetestowany przy użyciu CMake w wersji 2.8). – Florian

Powiązane problemy