2016-09-12 20 views
7

Với CMake, làm cách nào để có danh sách tất cả các tệp nguồn đi vào một mục tiêu thực thi, bao gồm tất cả các nguồn trong tất cả các mục tiêu mà tệp thực thi này phụ thuộc?Lấy tất cả các tệp nguồn mà một mục tiêu phụ thuộc vào CMake

Chúng tôi có một mẫu trong cơ sở mã nơi người gọi khởi tạo được tạo bởi hệ thống xây dựng dựa trên tên tệp và đường dẫn trong cây nguồn. Vì vậy, tôi cần đường dẫn đầy đủ (hoặc liên quan đến nguồn gốc) cho tất cả các tệp nguồn một mục tiêu thực thi phụ thuộc vào.

+2

Bạn có thể sử dụng [ 'SOURCES'] (https://cmake.org/cmake/help/latest/prop_tgt/SOURCES.html) nhắm mục tiêu bất động sản và bạn có thể tìm thấy các mẫu mã [ở đây] (http://stackoverflow.com/questions/32756195/recursive-list-of-link-libraries-in-cmake) lặp lại các mục tiêu phụ thuộc. Bạn có thể mô tả những gì bạn đã thử cho đến nay không? – Florian

+0

Tôi không nhận ra rằng tôi có thể lặp lại các mục tiêu phụ thuộc như thế. Tôi nghĩ tôi có thể làm cho nó hoạt động với thuộc tính SOURCES. –

+0

Tôi đã viết một cái gì đó tương tự bằng cách ghi đè các chức năng CMake và có thể cung cấp một ví dụ mã nếu bạn quan tâm (như là một điểm khởi đầu). Đây có phải là một số mã CMake của thư viện bên ngoài mà chúng ta đang nói đến ở đây hoặc bạn có muốn sử dụng nó trên mã của riêng mình không? – Florian

Trả lời

5

Đây là mảnh của tôi về mã để nhận được liên kết phụ thuộc một mục tiêu:

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

Đối với các phiên bản cũ CMake (trước 3.4), bạn sẽ cần phải thay thế việc kiểm tra IN_LIST với một cuộc gọi list(FIND ...):

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

Và đây là các mã kiểm tra tôi đã sử dụng:

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

Tài liệu tham khảo

+0

Hoạt động tốt cho các mục tiêu thực thi. Vì lý do nào đó, tôi cần 'cmake_policy (SET CMP0057 NEW)' cho 'IN_LIST' để làm việc bên trong câu lệnh' if' khi chạy nó trên một thư mục thứ hai. –

+0

@PetterKvalvaag Cảm ơn gợi ý. Tôi thực sự giới thiệu 'IN_LIST' cho mã cho câu trả lời này và không biết về chính sách' CMP0057' (CMake 3.4 tôi được sử dụng để kiểm tra không ném một cảnh báo/lỗi). Tôi đã cập nhật câu trả lời của tôi cho phù hợp và thêm các biến thể tôi đã có trước đó (thử nghiệm với CMake phiên bản 2.8). – Florian

Các vấn đề liên quan