CMake kullanarak dosyayı kaynak dizinden ikili dizine kopyalayın


108

CLion hakkında basit bir proje oluşturmaya çalışıyorum. Proje (veya bir çeşit) oluşturmak için Makefiles oluşturmak için CMake (burada yeniyim) kullanıyor

Tek ihtiyacım olan proje dışı bir dosyayı (bir çeşit kaynak dosyası), kodumu her çalıştırdığımda ikili dizine aktarmak.

Bu dosya test verilerini içerir ve uygulama onları okumak için açar. Bunu yapmanın birkaç yolunu denedim:

  • Üzerinden file(COPY ...

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

    İyi görünüyor, ancak yalnızca bir kez çalışıyor ve bir sonraki çalıştırmadan sonra dosyayı yeniden kopyalamıyor.

  • Üzerinden add_custom_command

    • OUTPUT versiyon

      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 versiyon

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

    Ama hiçbiri işe yaramıyor.

Neyi yanlış yapıyorum?

Yanıtlar:


137

Configure_file dosyasını şu COPYONLYseçenekle kullanmayı düşünebilirsiniz :

configure_file(<input> <output> COPYONLY)

Bunun aksine file(COPY ...), girdi ve çıktı arasında dosya düzeyinde bir bağımlılık yaratır, yani:

Girdi dosyası değiştirilirse, derleme sistemi dosyayı yeniden yapılandırmak ve derleme sistemini yeniden oluşturmak için CMake'yi yeniden çalıştırır.


13
configure_fileBir dosya listesi oluşturmak için GLOB kullansanız bile, bunun alt dizinlerle çalışmayacağını lütfen unutmayın .
Tarantula

67

her iki seçenek de geçerlidir ve derlemenizin iki farklı adımını hedeflemektedir:

  1. file(COPY ...dosyayı yapılandırma adımında ve yalnızca bu adımda kopyalar. Cmake yapılandırmanızı değiştirmeden projenizi yeniden oluşturduğunuzda, bu komut çalıştırılmayacaktır.
  2. add_custom_command dosyayı her derleme adımında kopyalamak istediğinizde tercih edilen seçimdir.

Göreviniz için doğru sürüm şöyle olacaktır:

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

Eğer arasında seçim yapabilirsiniz PRE_BUILD, PRE_LINK, POST_BUILD en iyi sen belgelerine okunan add_custom_command

İlk sürümün nasıl kullanılacağına dair bir örnek burada bulunabilir: Başka bir hedef için kaynak oluşturmak için CMake add_custom_command kullanın


1
CMAKE_SOURCE_DIR mi yoksa CMAKE_CURRENT_SOURCE_DIR mı?
Syaiful Nizam Yahya

2
@SyaifulNizamYahya CMAKE_CURRENT_SOURCE_DIR, test/input.txtdosya mevcut CMakeLists.txtdosyayla ilgiliyse kullanın . Kök ile ilgiliyse CMakeLists.txt, kullanın CMAKE_SOURCE_DIR.
Mark Ingram

Hedeflerin dosya adını cmake'de almanın bir yolu var mı? dosya adını kodlamadan mı? Örneğin, bir lib dosyası oluşturuyorum, cmake'nin targte dosya adını almak için bir değişkeni var mı? gibi libSomething.so?
Rika

16

Denediğiniz ilk seçenek iki nedenden dolayı işe yaramıyor.

Önce parantezi kapatmayı unuttunuz.

İkinci olarak, DESTINATIONdosya adı değil, dizin olmalıdır. Parantezi kapattığınızı varsayarsak, dosya adlı bir klasörde son bulacaktır input.txt.

Çalışmasını sağlamak için şu şekilde değiştirin:

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

4

Öneririm TARGET_FILE_DIRsize dosya .exe dosyası ile aynı klasöre kopyalanması istiyorum.

$ Ana dosyanın dizini (.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}>)

VS'de, bu cmake betiği input.txt dosyasını, hata ayıklama veya yayınlama olsun, son exe'nizle aynı dosyaya kopyalayacaktır.


3

Bazı kaynak dosyalarını kopyalamak için kullandığım şey buydu: kopya dosyaları, hataları göz ardı etmek için boş bir hedef

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

Ayrıca add_dependencies(MainTarget copy-files)MainTarget'ı oluşturduğumda otomatik olarak çalışmasını sağlamak için eklerdim
Herrgott

Bu, kaynağın geçerli sürümünün her zaman hedef post build içinde olmasını sağladığından, en iyi yanıt gibi görünüyor (+ Herrgott'un yorumu). Küçük kopyalama işleri için bu iyi çalışıyor, teşekkürler. add_dependencies(MainTarget copy-files)Kök CMakeLists.txtdosyaya koymak , bunun proje boyunca kullanılabileceği anlamına gelir.
satnhak

2

Klasörü frenk üzümü dizininden ikili (yapı klasörü) klasörüne kopyalamak istiyorsanız

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

o zaman sözdizimi:

file(COPY pathSource DESTINATION pathDistination)

0

Önerilen configure_file dosyası muhtemelen en kolay çözümdür. Ancak, dosyayı yapı dizininden elle sildiyseniz, copy komutunu yeniden çalıştırmaz. Bu davayı da ele almak için, aşağıdakiler benim için çalışıyor:

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)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.