CMakeを使用してソースディレクトリからバイナリディレクトリにファイルをコピーする


98

CLionで簡単なプロジェクトを作成しようとしています。CMake(ここでは新しい)を使用して、プロジェクト(またはなんらかの種類)をビルドするためのMakefileを生成します。

コードを実行するたびに、非プロジェクトファイル(ある種のリソースファイル)をバイナリディレクトリに転送するだけです。

そのファイルにはテストデータが含まれており、アプリケーションはそれを開いて読み取ります。私はそうするためにいくつかの方法を試しました:

  • 経由 file(COPY ...

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

    見栄えは良いですが、それは一度だけ動作し、次の実行後にファイルを再コピーしません。

  • 経由 add_custom_command

    • OUTPUT バージョン

      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 バージョン

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

    しかし、どれも機能しません。

何が悪いのですか?

回答:


126

あなたはオプションでconfigure_fileを使うことを考えるかもしれませんCOPYONLY

configure_file(<input> <output> COPYONLY)

file(COPY ...)それとは異なり、入力と出力の間にファイルレベルの依存関係を作成します。

入力ファイルが変更されると、ビルドシステムはCMakeを再実行してファイルを再構成し、ビルドシステムを再度生成します。


12
configure_fileGLOBを使用してファイルのリストを作成する場合でも、サブディレクトリでは機能しないことに注意してください。
タランチュラ

63

どちらのオプションも有効で、ビルドの2つの異なるステップを対象としています。

  1. file(COPY ...構成ステップで、このステップでのみファイルをコピーします。cmake構成を変更せずにプロジェクトを再ビルドすると、このコマンドは実行されません。
  2. add_custom_command 各ビルドステップでファイルをコピーする場合は、これが推奨される選択です。

タスクに適したバージョンは次のとおりです。

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

あなたがから選ぶことができPRE_BUILDPRE_LINKPOST_BUILD 最高のは、あなたがのドキュメント読んでadd_custom_commandを

最初のバージョンを使用する方法の例はここにあります:CMake add_custom_commandを使用して別のターゲットのソースを生成します


1
CMAKE_SOURCE_DIRまたはCMAKE_CURRENT_SOURCE_DIRですか?
Syaiful Nizam Yahya

1
@SyaifulNizamYahya ファイルが現在のファイルに関連しているCMAKE_CURRENT_SOURCE_DIR場合に使用します。ルートを基準にした場合は、を使用します。test/input.txtCMakeLists.txtCMakeLists.txtCMAKE_SOURCE_DIR
Mark Ingram

16

最初に試したオプションは、2つの理由で機能しません。

まず、括弧を閉じるのを忘れました。

次に、はDESTINATIONファイル名ではなくディレクトリでなければなりません。かっこを閉じたとすると、ファイルはというフォルダに移動しますinput.txt

機能させるには、次のように変更します

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

4

TARGET_FILE_DIRファイルを.exeファイルと同じフォルダにコピーするかどうかをお勧めします。

$メインファイルのディレクトリ(.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では、このcmakeスクリプトは、デバッグまたはリリースに関係なく、input.txtを最終的なexeファイルと同じファイルにコピーします。


3

これは私がいくつかのリソースファイルをコピーするために使用したものです:コピーファイルはエラーを無視するための空のターゲットです

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

また、add_dependencies(MainTarget copy-files)MainTargetをビルドするときに自動的に実行されるように追加します
Herrgott

これは、ソースの現在のバージョンが常に宛先のポストビルドにあることを実際に保証するため、最良の回答(+ Herrgottのコメント)のようです。小さなコピージョブの場合、これはうまく機能します。置くadd_dependencies(MainTarget copy-files)ルートにCMakeLists.txtファイルすることは、これはプロジェクト全体で使用できることを意味します。
satnhak

1

フォルダーをカラントディレクトリからバイナリ(ビルドフォルダー)フォルダーにコピーする場合

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

次に、syntexeは次のとおりです。

file(COPY pathSource DESTINATION pathDistination)

0

推奨されるconfigure_fileはおそらく最も簡単なソリューションです。ただし、ビルドディレクトリから手動でファイルを削除した場合、copyコマンドは再実行されません。このケースも処理するために、私は次のように機能します:

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)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.