2012-06-19 22 views
25

tôi đã tạo ra một danh sách các tập tin sử dụng:Làm cách nào để cài đặt phân cấp tệp bằng cmake?

file(GLOB_RECURSE DEPLOY_FILES "${PROJECT_SOURCE_DIR}/install/*") 

tôi muốn cài đặt tất cả các file trong/usr/myproject/nhưng tôi muốn duy trì cây tập tin vào thư mục cài đặt:

install/junk 
install/other/junk2 
install/other/junk3 

Nếu tôi sử dụng:

install(FILES ${DEPLOY_FILES} DESTINATION "usr/myproject") 

Tất cả các tập tin kết thúc trong/usr/myproject như:

/usr/myproject/junk 
/usr/myproject/junk2 
/usr/myproject/junk3 

Tôi làm cách nào để lệnh cài đặt theo dõi đường dẫn tương đối?

Tôi đã làm việc xung quanh vấn đề này bằng cách thực hiện nó bằng tay trong một vòng lặp for:

set(BASE "${PROJECT_SOURCE_DIR}/install") 
foreach(ITEM ${DEPLOY_FILES}) 
    get_filename_component(ITEM_PATH ${ITEM} PATH) 
    string(REPLACE ${BASE} "" ITEM_PATH ${ITEM_PATH}) 
    install(FILES ${ITEM} DESTINATION "usr/myproject${ITEM_PATH}") 
endforeach() 

... nhưng điều này là gây phiền nhiễu để làm. Chắc chắn có một cách dễ dàng hơn?

(Cant thấy bất cứ điều gì trong tài liệu cài đặt mặc dù ...)

+1

Nó chỉ đơn giản là thú vị như thế nào f * & ing khó khăn họ có thể thực hiện một hoạt động ** cp -r' ** tầm thường. – ulidtko

Trả lời

23

Sử dụng:

INSTALL(DIRECTORY <directory> DESTINATION usr/myproject) 

(xem tại đây để biết chi tiết: http://www.cmake.org/cmake/help/v2.8.8/cmake.html#command:install)

INSTALL(DIRECTORY .... ) bảo tồn cấu trúc thư mục. Tuy nhiên, nếu bạn sử dụng install<directory>, bạn sẽ kết thúc với usr/myproject/install/.... mà không phải là những gì bạn muốn.

Có hai cách để làm điều này:

  1. Sử dụng INSTALL(FILES .... DESTINATION usr/myproject) để cài đặt các tập tin nằm trực tiếp trong install/, sau đó sử dụng INSTALL(DIRECTORY .... DESTINATION usr/myproject) và bằng tay danh sách các thư mục để cài đặt.

  2. Sử dụng lệnh globbing của bạn trong bài đăng gốc, sau đó xác định mục nhập là tệp, là thư mục, ´di chuyển các mục nhập thư mục vào danh sách riêng và cung cấp danh sách lần lượt là INSTALL(FILES ...)INSTALL(DIRECTORY ...).

    file(GLOB DEPLOY_FILES_AND_DIRS "${PROJECT_SOURCE_DIR}/install/*") 
    foreach(ITEM ${DEPLOY_FILES_AND_DIRS}) 
        IF(IS_DIRECTORY "${ITEM}") 
         LIST(APPEND DIRS_TO_DEPLOY "${ITEM}") 
        ELSE() 
         LIST(APPEND FILES_TO_DEPLOY "${ITEM}") 
        ENDIF() 
    endforeach() 
    INSTALL(FILES ${FILES_TO_DEPLOY} DESTINATION usr/myproject) 
    INSTALL(DIRECTORY ${DIRS_TO_DEPLOY} DESTINATION usr/myproject) 
    

Lưu ý: Tùy thuộc vào loại dữ liệu mà bạn cài đặt, INSTALL(...) lệnh khác có thể thích hợp hơn (ví dụ INSTALL(TARGETS ....) để cài đặt thư viện của bạn/thực thi

+0

@Fraser Cảm ơn bạn đã chỉnh sửa, tôi đã bỏ lỡ định dạng sai. –

40

Cách đơn giản nhất để cài đặt.. mọi thứ từ một thư mục cụ thể là:

install(DIRECTORY mydir/ DESTINATION dir/newname) 

Trailing '/' là quan trọng. Nếu không có mydir sẽ được cài đặt thành newname/mydir.

Từ docs cmake:

Thành phần cuối cùng của mỗi tên thư mục được thêm vào thư mục đích nhưng một gạch chéo có thể được sử dụng để tránh điều này vì nó rời khỏi thành phần cuối cùng trống rỗng.

+0

Đây là một giải pháp đơn giản hơn nhiều mà globbing vv Cảm ơn. –

+4

Cảm ơn bằng "Trailing"/'là đáng kể. " – fechidal89

18

Nếu bạn có một danh sách các tập tin, bạn có thể chỉ đơn giản là vòng qua chúng và sử dụng get_filename_component() để trích xuất các phần thư mục:

foreach (file ${INCLUDE_FILES}) 
    get_filename_component(dir ${file} DIRECTORY) 
    install(FILES ${file} DESTINATION include/${dir}) 
endforeach() 

Done. ;-)

+0

Đây là một câu trả lời thực sự tốt và đơn giản. Không cần phải thực hiện các thủ thuật khác ngoài việc phân tích cú pháp danh sách tệp và cài đặt chúng một lần. +1 – bartgol

+0

Đẹp đơn giản. – Gallaecio

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