Sao chép tệp từ thư mục nguồn sang thư mục nhị phân bằng CMake


98

Tôi đang cố gắng tạo một dự án đơn giản trên CLion. Nó sử dụng CMake (tôi là người mới ở đây) để tạo các tệp Makefiles để xây dựng dự án (hoặc một số loại nó)

Tất cả những gì tôi cần là chuyển một số tệp không thuộc dự án (một số loại tệp tài nguyên) sang thư mục nhị phân mỗi khi tôi chạy mã của mình.

Tệp đó chứa dữ liệu thử nghiệm và ứng dụng mở nó để đọc chúng. Tôi đã thử một số cách để làm như vậy:

  • Thông qua file(COPY ...

    file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/input.txt
            DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/input.txt
    

    Trông đẹp nhưng nó chỉ hoạt động một lần và không sao chép lại tệp sau lần chạy tiếp theo.

  • Thông qua add_custom_command

    • OUTPUT phiên bản

      add_custom_command(
              OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/input.txt
              COMMAND ${CMAKE_COMMAND} -E copy
                      ${CMAKE_CURRENT_SOURCE_DIR}/input.txt
                      ${CMAKE_CURRENT_BINARY_DIR}/input.txt)
      
    • TARGET phiên bản

      add_custom_target(foo)
      add_custom_command(
              TARGET foo
              COMMAND ${CMAKE_COMMAND} copy
                      ${CMAKE_CURRENT_BINARY_DIR}/test/input.txt
                      ${CMAKE_SOURCE_DIR})
      

    Nhưng không ai trong số nó hoạt động.

Tôi đang làm gì sai?

Câu trả lời:


126

Bạn có thể cân nhắc sử dụng config_file với COPYONLYtùy chọn:

configure_file(<input> <output> COPYONLY)

Không giống như file(COPY ...)nó tạo ra sự phụ thuộc cấp độ tệp giữa đầu vào và đầu ra, đó là:

Nếu tệp đầu vào được sửa đổi, hệ thống xây dựng sẽ chạy lại CMake để định cấu hình lại tệp và tạo lại hệ thống xây dựng.


12
Xin lưu ý rằng điều đó configure_filesẽ không hoạt động với các thư mục con, ngay cả khi bạn sử dụng GLOB để tạo danh sách tệp.
Tarantula

63

cả hai tùy chọn đều hợp lệ và nhắm mục tiêu hai bước khác nhau trong quá trình xây dựng của bạn:

  1. file(COPY ...sao chép tệp trong bước cấu hình và chỉ trong bước này. Khi bạn xây dựng lại dự án của mình mà không thay đổi cấu hình cmake, lệnh này sẽ không được thực thi.
  2. add_custom_command là lựa chọn ưu tiên khi bạn muốn sao chép tệp xung quanh mỗi bước xây dựng.

Phiên bản phù hợp cho nhiệm vụ của bạn sẽ là:

add_custom_command(
        TARGET foo POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E copy
                ${CMAKE_SOURCE_DIR}/test/input.txt
                ${CMAKE_CURRENT_BINARY_DIR}/input.txt)

bạn có thể lựa chọn giữa PRE_BUILD, PRE_LINK, POST_BUILD tốt nhất là bạn đọc tài liệu của add_custom_command

có thể tìm thấy ví dụ về cách sử dụng phiên bản đầu tiên tại đây: Sử dụng CMake add_custom_command để tạo nguồn cho một mục tiêu khác


1
Đó là CMAKE_SOURCE_DIR hay CMAKE_CURRENT_SOURCE_DIR?
Syaiful Nizam Yahya

1
@SyaifulNizamYahya sử dụng CMAKE_CURRENT_SOURCE_DIRnếu test/input.txttệp có liên quan đến CMakeLists.txttệp hiện tại . Nếu nó liên quan đến gốc CMakeLists.txt, thì hãy sử dụng CMAKE_SOURCE_DIR.
Mark Ingram

16

Tùy chọn đầu tiên bạn đã thử không hoạt động vì hai lý do.

Đầu tiên, bạn quên đóng dấu ngoặc đơn.

Thứ hai, DESTINATIONphải là một thư mục, không phải là một tên tệp. Giả sử rằng bạn đã đóng dấu ngoặc, tệp sẽ kết thúc trong một thư mục có tên input.txt.

Để làm cho nó hoạt động, chỉ cần thay đổi nó thành

file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/input.txt
     DESTINATION ${CMAKE_CURRENT_BINARY_DIR})

4

Tôi sẽ đề xuất TARGET_FILE_DIRnếu bạn muốn tệp được sao chép vào cùng thư mục với tệp .exe của bạn.

$ Thư mục của tệp chính (.exe, .so.1.2, .a).

add_custom_command(
  TARGET ${PROJECT_NAME} POST_BUILD
  COMMAND ${CMAKE_COMMAND} -E copy 
    ${CMAKE_CURRENT_SOURCE_DIR}/input.txt 
    $<TARGET_FILE_DIR:${PROJECT_NAME}>)

Trong VS, tập lệnh cmake này sẽ sao chép input.txt vào cùng một tệp như exe cuối cùng của bạn, bất kể đó là gỡ lỗi hoặc phát hành.


3

Đây là những gì tôi đã sử dụng để sao chép một số tệp tài nguyên: các tệp sao chép là một mục tiêu trống để bỏ qua lỗi

 add_custom_target(copy-files ALL
    COMMAND ${CMAKE_COMMAND} -E copy_directory
    ${CMAKE_BINARY_DIR}/SOURCEDIRECTORY
    ${CMAKE_BINARY_DIR}/DESTINATIONDIRECTORY
    )

Tôi cũng xin thêm add_dependencies(MainTarget copy-files)để làm cho nó chạy tự động khi tôi xây dựng MainTarget
Herrgott

Đây có vẻ là câu trả lời hay nhất (+ Nhận xét của Herrgott) vì nó thực sự đảm bảo rằng phiên bản hiện tại của nguồn luôn ở trong bản dựng bài đăng đích. Đối với các công việc sao chép nhỏ, điều này hoạt động tốt, cảm ơn. Đặt add_dependencies(MainTarget copy-files)vào CMakeLists.txttệp gốc có nghĩa là tệp này có thể được sử dụng trong toàn bộ dự án.
satnhak

1

nếu bạn muốn sao chép thư mục từ thư mục nho sang thư mục nhị phân (thư mục xây dựng)

file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/yourFolder/ DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/yourFolder/)

thì syntexe là:

file(COPY pathSource DESTINATION pathDistination)

0

Cấu hình cấu hình được đề xuất có lẽ là giải pháp dễ dàng nhất. Tuy nhiên, nó sẽ không chạy lại lệnh sao chép nếu bạn xóa tệp khỏi thư mục xây dựng theo cách thủ công. Để xử lý trường hợp này, tôi sẽ làm như sau:

add_custom_target(copy-test-makefile ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/input.txt)
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/input.txt
                   COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/input.txt
                                                    ${CMAKE_CURRENT_BINARY_DIR}/input.txt
                   DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/input.txt)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.