Salin file dari direktori sumber ke direktori biner menggunakan CMake

103

Saya mencoba membuat proyek sederhana di CLion. Ini menggunakan CMake (saya baru di sini) untuk menghasilkan Makefiles untuk membangun proyek (atau semacamnya)

Yang saya perlukan hanyalah mentransfer beberapa file non-proyek (semacam file sumber daya) ke direktori biner setiap kali saya menjalankan kode saya.

File tersebut berisi data uji dan aplikasi membukanya untuk membacanya. Saya mencoba beberapa cara untuk melakukannya:

  • Melalui file(COPY ...

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

    Terlihat bagus tetapi berfungsi hanya sekali dan tidak menyalin ulang file setelah proses berikutnya.

  • Melalui add_custom_command

    • OUTPUT Versi: kapan

      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 Versi: kapan

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

    Tapi tidak ada yang berhasil.

Apa yang saya lakukan salah?

mongolrgata
sumber

Jawaban:

129

Anda dapat mempertimbangkan untuk menggunakan configure_file dengan COPYONLYopsi:

configure_file(<input> <output> COPYONLY)

Tidak seperti file(COPY ...)itu menciptakan ketergantungan tingkat file antara input dan output, yaitu:

Jika file masukan diubah, sistem build akan menjalankan ulang CMake untuk mengonfigurasi ulang file dan membuat sistem build lagi.

tamas.kenez
sumber
12
Harap dicatat bahwa configure_fileini tidak akan berfungsi dengan sub-direktori, meskipun Anda menggunakan GLOB untuk membuat daftar file.
Tarantula
63

kedua opsi tersebut valid dan menargetkan dua langkah berbeda dari build Anda:

  1. file(COPY ...menyalin file pada langkah konfigurasi dan hanya pada langkah ini. Ketika Anda membangun kembali proyek Anda tanpa mengubah konfigurasi cmake Anda, perintah ini tidak akan dijalankan.
  2. add_custom_command adalah pilihan yang lebih disukai ketika Anda ingin menyalin file pada setiap langkah pembuatan.

Versi yang tepat untuk tugas Anda adalah:

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

Anda dapat memilih antara PRE_BUILD, PRE_LINK, POST_BUILD yang terbaik adalah Anda membaca dokumentasi add_custom_command

contoh tentang cara menggunakan versi pertama dapat ditemukan di sini: Gunakan CMake add_custom_command untuk menghasilkan sumber untuk target lain

jenseb.dll
sumber
1
Apakah CMAKE_SOURCE_DIR atau CMAKE_CURRENT_SOURCE_DIR?
Syaiful Nizam Yahya
1
@SyaifulNizamYahya gunakan CMAKE_CURRENT_SOURCE_DIRjika test/input.txtfile tersebut relatif terhadap CMakeLists.txtfile saat ini . Jika itu relatif terhadap root CMakeLists.txt, maka gunakan CMAKE_SOURCE_DIR.
Tandai Ingram
16

Opsi pertama yang Anda coba tidak berfungsi karena dua alasan.

Pertama, Anda lupa menutup tanda kurung.

Kedua, DESTINATIONharus berupa direktori, bukan nama file. Dengan asumsi Anda menutup tanda kurung, file tersebut akan berakhir di folder bernama input.txt.

Untuk membuatnya berhasil, ubah saja menjadi

file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/input.txt
     DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
Capuano Jerman
sumber
4

Saya akan menyarankan TARGET_FILE_DIRjika Anda ingin file tersebut disalin ke folder yang sama dengan file .exe Anda.

$ Direktori file utama (.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}>)

Di VS, skrip cmake ini akan menyalin input.txt ke file yang sama dengan exe akhir Anda, tidak peduli itu debug atau rilis.

Felix Xu
sumber
3

Inilah yang saya gunakan untuk menyalin beberapa file sumber daya: file salinan adalah target kosong untuk mengabaikan kesalahan

 add_custom_target(copy-files ALL
    COMMAND ${CMAKE_COMMAND} -E copy_directory
    ${CMAKE_BINARY_DIR}/SOURCEDIRECTORY
    ${CMAKE_BINARY_DIR}/DESTINATIONDIRECTORY
    )
Cory Lewis
sumber
Saya juga akan menambahkan add_dependencies(MainTarget copy-files)untuk membuatnya berjalan secara otomatis ketika saya membangun MainTarget
Herrgott
Ini sepertinya jawaban terbaik (+ komentar Herrgott) karena ini benar-benar memastikan bahwa versi sumber saat ini selalu dalam pembuatan posting tujuan. Untuk pekerjaan salin kecil, ini berfungsi dengan baik, terima kasih. Menempatkan file add_dependencies(MainTarget copy-files)root CMakeLists.txtberarti ini dapat digunakan di seluruh proyek.
satnhak
1

jika Anda ingin menyalin folder dari direktori saat ini ke folder biner (folder build)

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

maka syntexe-nya adalah:

file(COPY pathSource DESTINATION pathDistination)
Amirouche Zeggagh
sumber
0

Configur_file yang disarankan mungkin merupakan solusi termudah. Namun, itu tidak akan menjalankan kembali perintah salin jika Anda menghapus file secara manual dari direktori build. Untuk menangani kasus ini juga, berikut ini berfungsi untuk saya:

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)
ar31
sumber